diff options
author | Greg Kroah-Hartman <gregkh@suse.de> | 2012-01-30 17:12:59 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-02-08 17:14:11 -0500 |
commit | b7cdd9e6323af368e26121c5b791eddc78e79fea (patch) | |
tree | 029198d9833036b0a200fe1cc575d6b761be8b11 /drivers/staging | |
parent | 62aa2b537c6f5957afd98e29f96897419ed5ebab (diff) |
staging: delete gma500 driver
It's now "properly" merged into the DRM tree in the kernel, so delete
the staging version of the driver as it is far obsolete and broken.
Requested-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers/staging')
78 files changed, 0 insertions, 30778 deletions
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig index 21e2f4b87f14..b31194c8272d 100644 --- a/drivers/staging/Kconfig +++ b/drivers/staging/Kconfig | |||
@@ -120,8 +120,6 @@ source "drivers/staging/cptm1217/Kconfig" | |||
120 | 120 | ||
121 | source "drivers/staging/ste_rmi4/Kconfig" | 121 | source "drivers/staging/ste_rmi4/Kconfig" |
122 | 122 | ||
123 | source "drivers/staging/gma500/Kconfig" | ||
124 | |||
125 | source "drivers/staging/mei/Kconfig" | 123 | source "drivers/staging/mei/Kconfig" |
126 | 124 | ||
127 | source "drivers/staging/nvec/Kconfig" | 125 | source "drivers/staging/nvec/Kconfig" |
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile index 7c5808d7212d..b5813c46378d 100644 --- a/drivers/staging/Makefile +++ b/drivers/staging/Makefile | |||
@@ -52,7 +52,6 @@ obj-$(CONFIG_FT1000) += ft1000/ | |||
52 | obj-$(CONFIG_SPEAKUP) += speakup/ | 52 | obj-$(CONFIG_SPEAKUP) += speakup/ |
53 | obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ | 53 | obj-$(CONFIG_TOUCHSCREEN_CLEARPAD_TM1217) += cptm1217/ |
54 | obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ | 54 | obj-$(CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4) += ste_rmi4/ |
55 | obj-$(CONFIG_DRM_PSB) += gma500/ | ||
56 | obj-$(CONFIG_INTEL_MEI) += mei/ | 55 | obj-$(CONFIG_INTEL_MEI) += mei/ |
57 | obj-$(CONFIG_MFD_NVEC) += nvec/ | 56 | obj-$(CONFIG_MFD_NVEC) += nvec/ |
58 | obj-$(CONFIG_DRM_OMAP) += omapdrm/ | 57 | obj-$(CONFIG_DRM_OMAP) += omapdrm/ |
diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig deleted file mode 100644 index c7a2b3bc0a18..000000000000 --- a/drivers/staging/gma500/Kconfig +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | config DRM_PSB | ||
2 | tristate "Intel GMA5/600 KMS Framebuffer" | ||
3 | depends on DRM && PCI && X86 && BROKEN | ||
4 | select FB_CFB_COPYAREA | ||
5 | select FB_CFB_FILLRECT | ||
6 | select FB_CFB_IMAGEBLIT | ||
7 | select DRM_KMS_HELPER | ||
8 | select DRM_TTM | ||
9 | help | ||
10 | Say yes for an experimental 2D KMS framebuffer driver for the | ||
11 | Intel GMA500 ('Poulsbo') and other Intel IMG based graphics | ||
12 | devices. | ||
13 | |||
14 | config DRM_PSB_MRST | ||
15 | bool "Intel GMA600 support (Experimental)" | ||
16 | depends on DRM_PSB | ||
17 | help | ||
18 | Say yes to include support for GMA600 (Intel Moorestown/Oaktrail) | ||
19 | platforms with LVDS ports. HDMI and MIPI are not currently | ||
20 | supported. | ||
21 | |||
22 | config DRM_PSB_MFLD | ||
23 | bool "Intel Medfield support (Experimental)" | ||
24 | depends on DRM_PSB | ||
25 | help | ||
26 | Say yes to include support for Intel Medfield platforms with MIPI | ||
27 | interfaces. | ||
28 | |||
29 | config DRM_PSB_CDV | ||
30 | bool "Intel Cedarview support (Experimental)" | ||
31 | depends on DRM_PSB | ||
32 | help | ||
33 | Say yes to include support for Intel Cedarview platforms | ||
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile deleted file mode 100644 index c729868b1b10..000000000000 --- a/drivers/staging/gma500/Makefile +++ /dev/null | |||
@@ -1,52 +0,0 @@ | |||
1 | # | ||
2 | # KMS driver for the GMA500 | ||
3 | # | ||
4 | ccflags-y += -Iinclude/drm | ||
5 | |||
6 | psb_gfx-y += gem_glue.o \ | ||
7 | accel_2d.o \ | ||
8 | backlight.o \ | ||
9 | framebuffer.o \ | ||
10 | gem.o \ | ||
11 | gtt.o \ | ||
12 | intel_bios.o \ | ||
13 | intel_i2c.o \ | ||
14 | intel_opregion.o \ | ||
15 | mmu.o \ | ||
16 | power.o \ | ||
17 | psb_drv.o \ | ||
18 | psb_intel_display.o \ | ||
19 | psb_intel_lvds.o \ | ||
20 | psb_intel_modes.o \ | ||
21 | psb_intel_sdvo.o \ | ||
22 | psb_lid.o \ | ||
23 | psb_irq.o \ | ||
24 | psb_device.o \ | ||
25 | mid_bios.o | ||
26 | |||
27 | psb_gfx-$(CONFIG_DRM_PSB_CDV) += cdv_device.o \ | ||
28 | cdv_intel_crt.o \ | ||
29 | cdv_intel_display.o \ | ||
30 | cdv_intel_hdmi.o \ | ||
31 | cdv_intel_lvds.o | ||
32 | |||
33 | psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \ | ||
34 | mrst_crtc.o \ | ||
35 | mrst_lvds.o \ | ||
36 | mrst_hdmi.o \ | ||
37 | mrst_hdmi_i2c.o | ||
38 | |||
39 | psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \ | ||
40 | mdfld_output.o \ | ||
41 | mdfld_pyr_cmd.o \ | ||
42 | mdfld_tmd_vid.o \ | ||
43 | mdfld_tpo_cmd.o \ | ||
44 | mdfld_tpo_vid.o \ | ||
45 | mdfld_dsi_pkg_sender.o \ | ||
46 | mdfld_dsi_dpi.o \ | ||
47 | mdfld_dsi_output.o \ | ||
48 | mdfld_dsi_dbi.o \ | ||
49 | mdfld_dsi_dbi_dpu.o \ | ||
50 | mdfld_intel_display.o | ||
51 | |||
52 | obj-$(CONFIG_DRM_PSB) += psb_gfx.o | ||
diff --git a/drivers/staging/gma500/TODO b/drivers/staging/gma500/TODO deleted file mode 100644 index fc836158e74c..000000000000 --- a/drivers/staging/gma500/TODO +++ /dev/null | |||
@@ -1,15 +0,0 @@ | |||
1 | - Sort out the power management side. Not important for Poulsbo but | ||
2 | matters for Moorestown/Medfield | ||
3 | - Debug Oaktrail/Moorestown support (single pipe, no BIOS on mrst, | ||
4 | some other differences) | ||
5 | - Add 2D acceleration via console and DRM | ||
6 | - Add scrolling acceleration using the GTT to do remapping on the main | ||
7 | framebuffer. | ||
8 | - HDMI testing | ||
9 | - Oaktrail HDMI and other features | ||
10 | - Oaktrail MIPI | ||
11 | - Medfield needs a lot of further love | ||
12 | |||
13 | As per kernel policy and the in the interest of the safety of various | ||
14 | kittens there is no support or plans to add hooks for the closed user space | ||
15 | stuff. | ||
diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c deleted file mode 100644 index b8f78ebbb145..000000000000 --- a/drivers/staging/gma500/accel_2d.c +++ /dev/null | |||
@@ -1,414 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2007-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 | * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to | ||
19 | * develop this driver. | ||
20 | * | ||
21 | **************************************************************************/ | ||
22 | |||
23 | #include <linux/module.h> | ||
24 | #include <linux/kernel.h> | ||
25 | #include <linux/errno.h> | ||
26 | #include <linux/string.h> | ||
27 | #include <linux/mm.h> | ||
28 | #include <linux/tty.h> | ||
29 | #include <linux/slab.h> | ||
30 | #include <linux/delay.h> | ||
31 | #include <linux/fb.h> | ||
32 | #include <linux/init.h> | ||
33 | #include <linux/console.h> | ||
34 | |||
35 | #include <drm/drmP.h> | ||
36 | #include <drm/drm.h> | ||
37 | #include <drm/drm_crtc.h> | ||
38 | |||
39 | #include "psb_drv.h" | ||
40 | #include "psb_reg.h" | ||
41 | #include "framebuffer.h" | ||
42 | |||
43 | /** | ||
44 | * psb_spank - reset the 2D engine | ||
45 | * @dev_priv: our PSB DRM device | ||
46 | * | ||
47 | * Soft reset the graphics engine and then reload the necessary registers. | ||
48 | * We use this at initialisation time but it will become relevant for | ||
49 | * accelerated X later | ||
50 | */ | ||
51 | void psb_spank(struct drm_psb_private *dev_priv) | ||
52 | { | ||
53 | PSB_WSGX32(_PSB_CS_RESET_BIF_RESET | _PSB_CS_RESET_DPM_RESET | | ||
54 | _PSB_CS_RESET_TA_RESET | _PSB_CS_RESET_USE_RESET | | ||
55 | _PSB_CS_RESET_ISP_RESET | _PSB_CS_RESET_TSP_RESET | | ||
56 | _PSB_CS_RESET_TWOD_RESET, PSB_CR_SOFT_RESET); | ||
57 | PSB_RSGX32(PSB_CR_SOFT_RESET); | ||
58 | |||
59 | msleep(1); | ||
60 | |||
61 | PSB_WSGX32(0, PSB_CR_SOFT_RESET); | ||
62 | wmb(); | ||
63 | PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_CB_CTRL_CLEAR_FAULT, | ||
64 | PSB_CR_BIF_CTRL); | ||
65 | wmb(); | ||
66 | (void) PSB_RSGX32(PSB_CR_BIF_CTRL); | ||
67 | |||
68 | msleep(1); | ||
69 | PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) & ~_PSB_CB_CTRL_CLEAR_FAULT, | ||
70 | PSB_CR_BIF_CTRL); | ||
71 | (void) PSB_RSGX32(PSB_CR_BIF_CTRL); | ||
72 | PSB_WSGX32(dev_priv->gtt.gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); | ||
73 | } | ||
74 | |||
75 | /** | ||
76 | * psb2_2d_wait_available - wait for FIFO room | ||
77 | * @dev_priv: our DRM device | ||
78 | * @size: size (in dwords) of the command we want to issue | ||
79 | * | ||
80 | * Wait until there is room to load the FIFO with our data. If the | ||
81 | * device is not responding then reset it | ||
82 | */ | ||
83 | static int psb_2d_wait_available(struct drm_psb_private *dev_priv, | ||
84 | unsigned size) | ||
85 | { | ||
86 | uint32_t avail = PSB_RSGX32(PSB_CR_2D_SOCIF); | ||
87 | unsigned long t = jiffies + HZ; | ||
88 | |||
89 | while (avail < size) { | ||
90 | avail = PSB_RSGX32(PSB_CR_2D_SOCIF); | ||
91 | if (time_after(jiffies, t)) { | ||
92 | psb_spank(dev_priv); | ||
93 | return -EIO; | ||
94 | } | ||
95 | } | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | /** | ||
100 | * psb_2d_submit - submit a 2D command | ||
101 | * @dev_priv: our DRM device | ||
102 | * @cmdbuf: command to issue | ||
103 | * @size: length (in dwords) | ||
104 | * | ||
105 | * Issue one or more 2D commands to the accelerator. This needs to be | ||
106 | * serialized later when we add the GEM interfaces for acceleration | ||
107 | */ | ||
108 | static int psbfb_2d_submit(struct drm_psb_private *dev_priv, uint32_t *cmdbuf, | ||
109 | unsigned size) | ||
110 | { | ||
111 | int ret = 0; | ||
112 | int i; | ||
113 | unsigned submit_size; | ||
114 | unsigned long flags; | ||
115 | |||
116 | spin_lock_irqsave(&dev_priv->lock_2d, flags); | ||
117 | while (size > 0) { | ||
118 | submit_size = (size < 0x60) ? size : 0x60; | ||
119 | size -= submit_size; | ||
120 | ret = psb_2d_wait_available(dev_priv, submit_size); | ||
121 | if (ret) | ||
122 | break; | ||
123 | |||
124 | submit_size <<= 2; | ||
125 | |||
126 | for (i = 0; i < submit_size; i += 4) | ||
127 | PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i); | ||
128 | |||
129 | (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4); | ||
130 | } | ||
131 | spin_unlock_irqrestore(&dev_priv->lock_2d, flags); | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | |||
136 | /** | ||
137 | * psb_accel_2d_copy_direction - compute blit order | ||
138 | * @xdir: X direction of move | ||
139 | * @ydir: Y direction of move | ||
140 | * | ||
141 | * Compute the correct order setings to ensure that an overlapping blit | ||
142 | * correctly copies all the pixels. | ||
143 | */ | ||
144 | static u32 psb_accel_2d_copy_direction(int xdir, int ydir) | ||
145 | { | ||
146 | if (xdir < 0) | ||
147 | return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL : | ||
148 | PSB_2D_COPYORDER_TR2BL; | ||
149 | else | ||
150 | return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR : | ||
151 | PSB_2D_COPYORDER_TL2BR; | ||
152 | } | ||
153 | |||
154 | /** | ||
155 | * psb_accel_2d_copy - accelerated 2D copy | ||
156 | * @dev_priv: our DRM device | ||
157 | * @src_offset in bytes | ||
158 | * @src_stride in bytes | ||
159 | * @src_format psb 2D format defines | ||
160 | * @dst_offset in bytes | ||
161 | * @dst_stride in bytes | ||
162 | * @dst_format psb 2D format defines | ||
163 | * @src_x offset in pixels | ||
164 | * @src_y offset in pixels | ||
165 | * @dst_x offset in pixels | ||
166 | * @dst_y offset in pixels | ||
167 | * @size_x of the copied area | ||
168 | * @size_y of the copied area | ||
169 | * | ||
170 | * Format and issue a 2D accelerated copy command. | ||
171 | */ | ||
172 | static int psb_accel_2d_copy(struct drm_psb_private *dev_priv, | ||
173 | uint32_t src_offset, uint32_t src_stride, | ||
174 | uint32_t src_format, uint32_t dst_offset, | ||
175 | uint32_t dst_stride, uint32_t dst_format, | ||
176 | uint16_t src_x, uint16_t src_y, | ||
177 | uint16_t dst_x, uint16_t dst_y, | ||
178 | uint16_t size_x, uint16_t size_y) | ||
179 | { | ||
180 | uint32_t blit_cmd; | ||
181 | uint32_t buffer[10]; | ||
182 | uint32_t *buf; | ||
183 | uint32_t direction; | ||
184 | |||
185 | buf = buffer; | ||
186 | |||
187 | direction = | ||
188 | psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y); | ||
189 | |||
190 | if (direction == PSB_2D_COPYORDER_BR2TL || | ||
191 | direction == PSB_2D_COPYORDER_TR2BL) { | ||
192 | src_x += size_x - 1; | ||
193 | dst_x += size_x - 1; | ||
194 | } | ||
195 | if (direction == PSB_2D_COPYORDER_BR2TL || | ||
196 | direction == PSB_2D_COPYORDER_BL2TR) { | ||
197 | src_y += size_y - 1; | ||
198 | dst_y += size_y - 1; | ||
199 | } | ||
200 | |||
201 | blit_cmd = | ||
202 | PSB_2D_BLIT_BH | | ||
203 | PSB_2D_ROT_NONE | | ||
204 | PSB_2D_DSTCK_DISABLE | | ||
205 | PSB_2D_SRCCK_DISABLE | | ||
206 | PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction; | ||
207 | |||
208 | *buf++ = PSB_2D_FENCE_BH; | ||
209 | *buf++ = | ||
210 | PSB_2D_DST_SURF_BH | dst_format | (dst_stride << | ||
211 | PSB_2D_DST_STRIDE_SHIFT); | ||
212 | *buf++ = dst_offset; | ||
213 | *buf++ = | ||
214 | PSB_2D_SRC_SURF_BH | src_format | (src_stride << | ||
215 | PSB_2D_SRC_STRIDE_SHIFT); | ||
216 | *buf++ = src_offset; | ||
217 | *buf++ = | ||
218 | PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) | | ||
219 | (src_y << PSB_2D_SRCOFF_YSTART_SHIFT); | ||
220 | *buf++ = blit_cmd; | ||
221 | *buf++ = | ||
222 | (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y << | ||
223 | PSB_2D_DST_YSTART_SHIFT); | ||
224 | *buf++ = | ||
225 | (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y << | ||
226 | PSB_2D_DST_YSIZE_SHIFT); | ||
227 | *buf++ = PSB_2D_FLUSH_BH; | ||
228 | |||
229 | return psbfb_2d_submit(dev_priv, buffer, buf - buffer); | ||
230 | } | ||
231 | |||
232 | /** | ||
233 | * psbfb_copyarea_accel - copyarea acceleration for /dev/fb | ||
234 | * @info: our framebuffer | ||
235 | * @a: copyarea parameters from the framebuffer core | ||
236 | * | ||
237 | * Perform a 2D copy via the accelerator | ||
238 | */ | ||
239 | static void psbfb_copyarea_accel(struct fb_info *info, | ||
240 | const struct fb_copyarea *a) | ||
241 | { | ||
242 | struct psb_fbdev *fbdev = info->par; | ||
243 | struct psb_framebuffer *psbfb = &fbdev->pfb; | ||
244 | struct drm_device *dev = psbfb->base.dev; | ||
245 | struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb; | ||
246 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
247 | uint32_t offset; | ||
248 | uint32_t stride; | ||
249 | uint32_t src_format; | ||
250 | uint32_t dst_format; | ||
251 | |||
252 | if (!fb) | ||
253 | return; | ||
254 | |||
255 | offset = psbfb->gtt->offset; | ||
256 | stride = fb->pitches[0]; | ||
257 | |||
258 | switch (fb->depth) { | ||
259 | case 8: | ||
260 | src_format = PSB_2D_SRC_332RGB; | ||
261 | dst_format = PSB_2D_DST_332RGB; | ||
262 | break; | ||
263 | case 15: | ||
264 | src_format = PSB_2D_SRC_555RGB; | ||
265 | dst_format = PSB_2D_DST_555RGB; | ||
266 | break; | ||
267 | case 16: | ||
268 | src_format = PSB_2D_SRC_565RGB; | ||
269 | dst_format = PSB_2D_DST_565RGB; | ||
270 | break; | ||
271 | case 24: | ||
272 | case 32: | ||
273 | /* this is wrong but since we don't do blending its okay */ | ||
274 | src_format = PSB_2D_SRC_8888ARGB; | ||
275 | dst_format = PSB_2D_DST_8888ARGB; | ||
276 | break; | ||
277 | default: | ||
278 | /* software fallback */ | ||
279 | cfb_copyarea(info, a); | ||
280 | return; | ||
281 | } | ||
282 | |||
283 | if (!gma_power_begin(dev, false)) { | ||
284 | cfb_copyarea(info, a); | ||
285 | return; | ||
286 | } | ||
287 | psb_accel_2d_copy(dev_priv, | ||
288 | offset, stride, src_format, | ||
289 | offset, stride, dst_format, | ||
290 | a->sx, a->sy, a->dx, a->dy, a->width, a->height); | ||
291 | gma_power_end(dev); | ||
292 | } | ||
293 | |||
294 | /** | ||
295 | * psbfb_copyarea - 2D copy interface | ||
296 | * @info: our framebuffer | ||
297 | * @region: region to copy | ||
298 | * | ||
299 | * Copy an area of the framebuffer console either by the accelerator | ||
300 | * or directly using the cfb helpers according to the request | ||
301 | */ | ||
302 | void psbfb_copyarea(struct fb_info *info, | ||
303 | const struct fb_copyarea *region) | ||
304 | { | ||
305 | if (unlikely(info->state != FBINFO_STATE_RUNNING)) | ||
306 | return; | ||
307 | |||
308 | /* Avoid the 8 pixel erratum */ | ||
309 | if (region->width == 8 || region->height == 8 || | ||
310 | (info->flags & FBINFO_HWACCEL_DISABLED)) | ||
311 | return cfb_copyarea(info, region); | ||
312 | |||
313 | psbfb_copyarea_accel(info, region); | ||
314 | } | ||
315 | |||
316 | /** | ||
317 | * psbfb_sync - synchronize 2D | ||
318 | * @info: our framebuffer | ||
319 | * | ||
320 | * Wait for the 2D engine to quiesce so that we can do CPU | ||
321 | * access to the framebuffer again | ||
322 | */ | ||
323 | int psbfb_sync(struct fb_info *info) | ||
324 | { | ||
325 | struct psb_fbdev *fbdev = info->par; | ||
326 | struct psb_framebuffer *psbfb = &fbdev->pfb; | ||
327 | struct drm_device *dev = psbfb->base.dev; | ||
328 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
329 | unsigned long _end = jiffies + DRM_HZ; | ||
330 | int busy = 0; | ||
331 | unsigned long flags; | ||
332 | |||
333 | spin_lock_irqsave(&dev_priv->lock_2d, flags); | ||
334 | /* | ||
335 | * First idle the 2D engine. | ||
336 | */ | ||
337 | |||
338 | if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) && | ||
339 | ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0)) | ||
340 | goto out; | ||
341 | |||
342 | do { | ||
343 | busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); | ||
344 | cpu_relax(); | ||
345 | } while (busy && !time_after_eq(jiffies, _end)); | ||
346 | |||
347 | if (busy) | ||
348 | busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY); | ||
349 | if (busy) | ||
350 | goto out; | ||
351 | |||
352 | do { | ||
353 | busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & | ||
354 | _PSB_C2B_STATUS_BUSY) != 0); | ||
355 | cpu_relax(); | ||
356 | } while (busy && !time_after_eq(jiffies, _end)); | ||
357 | if (busy) | ||
358 | busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & | ||
359 | _PSB_C2B_STATUS_BUSY) != 0); | ||
360 | |||
361 | out: | ||
362 | spin_unlock_irqrestore(&dev_priv->lock_2d, flags); | ||
363 | return (busy) ? -EBUSY : 0; | ||
364 | } | ||
365 | |||
366 | int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file) | ||
367 | { | ||
368 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
369 | struct drm_psb_2d_op *op = data; | ||
370 | u32 *op_ptr = &op->cmd[0]; | ||
371 | int i; | ||
372 | struct drm_gem_object *obj; | ||
373 | struct gtt_range *gtt; | ||
374 | int err = -EINVAL; | ||
375 | |||
376 | if (!dev_priv->ops->accel_2d) | ||
377 | return -EOPNOTSUPP; | ||
378 | if (op->size > PSB_2D_OP_BUFLEN) | ||
379 | return -EINVAL; | ||
380 | |||
381 | /* The GEM object being used. We need to support separate src/dst/etc | ||
382 | in the end but for now keep them all the same */ | ||
383 | obj = drm_gem_object_lookup(dev, file, op->src); | ||
384 | if (obj == NULL) | ||
385 | return -ENOENT; | ||
386 | gtt = container_of(obj, struct gtt_range, gem); | ||
387 | |||
388 | if (psb_gtt_pin(gtt) < 0) | ||
389 | goto bad_2; | ||
390 | for (i = 0; i < op->size; i++, op_ptr++) { | ||
391 | u32 r = *op_ptr & 0xF0000000; | ||
392 | /* Fill in the GTT offsets for the command buffer */ | ||
393 | if (r == PSB_2D_SRC_SURF_BH || | ||
394 | r == PSB_2D_DST_SURF_BH || | ||
395 | r == PSB_2D_MASK_SURF_BH || | ||
396 | r == PSB_2D_PAT_SURF_BH) { | ||
397 | i++; | ||
398 | op_ptr++; | ||
399 | if (i == op->size) | ||
400 | goto bad; | ||
401 | if (*op_ptr) | ||
402 | goto bad; | ||
403 | *op_ptr = gtt->offset; | ||
404 | continue; | ||
405 | } | ||
406 | } | ||
407 | psbfb_2d_submit(dev_priv, op->cmd, op->size); | ||
408 | err = 0; | ||
409 | bad: | ||
410 | psb_gtt_unpin(gtt); | ||
411 | bad_2: | ||
412 | drm_gem_object_unreference(obj); | ||
413 | return err; | ||
414 | } | ||
diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c deleted file mode 100644 index 20793951fcac..000000000000 --- a/drivers/staging/gma500/backlight.c +++ /dev/null | |||
@@ -1,49 +0,0 @@ | |||
1 | /* | ||
2 | * GMA500 Backlight Interface | ||
3 | * | ||
4 | * Copyright (c) 2009-2011, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * | ||
19 | * Authors: Eric Knopp | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include "psb_drv.h" | ||
24 | #include "psb_intel_reg.h" | ||
25 | #include "psb_intel_drv.h" | ||
26 | #include "intel_bios.h" | ||
27 | #include "power.h" | ||
28 | |||
29 | int gma_backlight_init(struct drm_device *dev) | ||
30 | { | ||
31 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
32 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
33 | return dev_priv->ops->backlight_init(dev); | ||
34 | #else | ||
35 | return 0; | ||
36 | #endif | ||
37 | } | ||
38 | |||
39 | void gma_backlight_exit(struct drm_device *dev) | ||
40 | { | ||
41 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
42 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
43 | if (dev_priv->backlight_device) { | ||
44 | dev_priv->backlight_device->props.brightness = 0; | ||
45 | backlight_update_status(dev_priv->backlight_device); | ||
46 | backlight_device_unregister(dev_priv->backlight_device); | ||
47 | } | ||
48 | #endif | ||
49 | } | ||
diff --git a/drivers/staging/gma500/cdv_device.c b/drivers/staging/gma500/cdv_device.c deleted file mode 100644 index 8ec10caab13e..000000000000 --- a/drivers/staging/gma500/cdv_device.c +++ /dev/null | |||
@@ -1,350 +0,0 @@ | |||
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 | static void cdv_disable_vga(struct drm_device *dev) | ||
34 | { | ||
35 | u8 sr1; | ||
36 | u32 vga_reg; | ||
37 | |||
38 | vga_reg = VGACNTRL; | ||
39 | |||
40 | outb(1, VGA_SR_INDEX); | ||
41 | sr1 = inb(VGA_SR_DATA); | ||
42 | outb(sr1 | 1<<5, VGA_SR_DATA); | ||
43 | udelay(300); | ||
44 | |||
45 | REG_WRITE(vga_reg, VGA_DISP_DISABLE); | ||
46 | REG_READ(vga_reg); | ||
47 | } | ||
48 | |||
49 | static int cdv_output_init(struct drm_device *dev) | ||
50 | { | ||
51 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
52 | cdv_disable_vga(dev); | ||
53 | |||
54 | cdv_intel_crt_init(dev, &dev_priv->mode_dev); | ||
55 | cdv_intel_lvds_init(dev, &dev_priv->mode_dev); | ||
56 | |||
57 | /* These bits indicate HDMI not SDVO on CDV, but we don't yet support | ||
58 | the HDMI interface */ | ||
59 | if (REG_READ(SDVOB) & SDVO_DETECTED) | ||
60 | cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB); | ||
61 | if (REG_READ(SDVOC) & SDVO_DETECTED) | ||
62 | cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC); | ||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
67 | |||
68 | /* | ||
69 | * Poulsbo Backlight Interfaces | ||
70 | */ | ||
71 | |||
72 | #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ | ||
73 | #define BLC_PWM_FREQ_CALC_CONSTANT 32 | ||
74 | #define MHz 1000000 | ||
75 | |||
76 | #define PSB_BLC_PWM_PRECISION_FACTOR 10 | ||
77 | #define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE | ||
78 | #define PSB_BLC_MIN_PWM_REG_FREQ 0x2 | ||
79 | |||
80 | #define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) | ||
81 | #define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) | ||
82 | |||
83 | static int cdv_brightness; | ||
84 | static struct backlight_device *cdv_backlight_device; | ||
85 | |||
86 | static int cdv_get_brightness(struct backlight_device *bd) | ||
87 | { | ||
88 | /* return locally cached var instead of HW read (due to DPST etc.) */ | ||
89 | /* FIXME: ideally return actual value in case firmware fiddled with | ||
90 | it */ | ||
91 | return cdv_brightness; | ||
92 | } | ||
93 | |||
94 | |||
95 | static int cdv_backlight_setup(struct drm_device *dev) | ||
96 | { | ||
97 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
98 | unsigned long core_clock; | ||
99 | /* u32 bl_max_freq; */ | ||
100 | /* unsigned long value; */ | ||
101 | u16 bl_max_freq; | ||
102 | uint32_t value; | ||
103 | uint32_t blc_pwm_precision_factor; | ||
104 | |||
105 | /* get bl_max_freq and pol from dev_priv*/ | ||
106 | if (!dev_priv->lvds_bl) { | ||
107 | dev_err(dev->dev, "Has no valid LVDS backlight info\n"); | ||
108 | return -ENOENT; | ||
109 | } | ||
110 | bl_max_freq = dev_priv->lvds_bl->freq; | ||
111 | blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; | ||
112 | |||
113 | core_clock = dev_priv->core_freq; | ||
114 | |||
115 | value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; | ||
116 | value *= blc_pwm_precision_factor; | ||
117 | value /= bl_max_freq; | ||
118 | value /= blc_pwm_precision_factor; | ||
119 | |||
120 | if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || | ||
121 | value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) | ||
122 | return -ERANGE; | ||
123 | else { | ||
124 | /* FIXME */ | ||
125 | } | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int cdv_set_brightness(struct backlight_device *bd) | ||
130 | { | ||
131 | int level = bd->props.brightness; | ||
132 | |||
133 | /* Percentage 1-100% being valid */ | ||
134 | if (level < 1) | ||
135 | level = 1; | ||
136 | |||
137 | /*cdv_intel_lvds_set_brightness(dev, level); FIXME */ | ||
138 | cdv_brightness = level; | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | static const struct backlight_ops cdv_ops = { | ||
143 | .get_brightness = cdv_get_brightness, | ||
144 | .update_status = cdv_set_brightness, | ||
145 | }; | ||
146 | |||
147 | static int cdv_backlight_init(struct drm_device *dev) | ||
148 | { | ||
149 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
150 | int ret; | ||
151 | struct backlight_properties props; | ||
152 | |||
153 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
154 | props.max_brightness = 100; | ||
155 | props.type = BACKLIGHT_PLATFORM; | ||
156 | |||
157 | cdv_backlight_device = backlight_device_register("psb-bl", | ||
158 | NULL, (void *)dev, &cdv_ops, &props); | ||
159 | if (IS_ERR(cdv_backlight_device)) | ||
160 | return PTR_ERR(cdv_backlight_device); | ||
161 | |||
162 | ret = cdv_backlight_setup(dev); | ||
163 | if (ret < 0) { | ||
164 | backlight_device_unregister(cdv_backlight_device); | ||
165 | cdv_backlight_device = NULL; | ||
166 | return ret; | ||
167 | } | ||
168 | cdv_backlight_device->props.brightness = 100; | ||
169 | cdv_backlight_device->props.max_brightness = 100; | ||
170 | backlight_update_status(cdv_backlight_device); | ||
171 | dev_priv->backlight_device = cdv_backlight_device; | ||
172 | return 0; | ||
173 | } | ||
174 | |||
175 | #endif | ||
176 | |||
177 | /* | ||
178 | * Provide the Cedarview specific chip logic and low level methods | ||
179 | * for power management | ||
180 | * | ||
181 | * FIXME: we need to implement the apm/ospm base management bits | ||
182 | * for this and the MID devices. | ||
183 | */ | ||
184 | |||
185 | static inline u32 CDV_MSG_READ32(uint port, uint offset) | ||
186 | { | ||
187 | int mcr = (0x10<<24) | (port << 16) | (offset << 8); | ||
188 | uint32_t ret_val = 0; | ||
189 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | ||
190 | pci_write_config_dword(pci_root, 0xD0, mcr); | ||
191 | pci_read_config_dword(pci_root, 0xD4, &ret_val); | ||
192 | pci_dev_put(pci_root); | ||
193 | return ret_val; | ||
194 | } | ||
195 | |||
196 | static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value) | ||
197 | { | ||
198 | int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; | ||
199 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | ||
200 | pci_write_config_dword(pci_root, 0xD4, value); | ||
201 | pci_write_config_dword(pci_root, 0xD0, mcr); | ||
202 | pci_dev_put(pci_root); | ||
203 | } | ||
204 | |||
205 | #define PSB_APM_CMD 0x0 | ||
206 | #define PSB_APM_STS 0x04 | ||
207 | #define PSB_PM_SSC 0x20 | ||
208 | #define PSB_PM_SSS 0x30 | ||
209 | #define PSB_PWRGT_GFX_MASK 0x3 | ||
210 | #define CDV_PWRGT_DISPLAY_CNTR 0x000fc00c | ||
211 | #define CDV_PWRGT_DISPLAY_STS 0x000fc00c | ||
212 | |||
213 | static void cdv_init_pm(struct drm_device *dev) | ||
214 | { | ||
215 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
216 | u32 pwr_cnt; | ||
217 | int i; | ||
218 | |||
219 | dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, | ||
220 | PSB_APMBA) & 0xFFFF; | ||
221 | dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT, | ||
222 | PSB_OSPMBA) & 0xFFFF; | ||
223 | |||
224 | /* Force power on for now */ | ||
225 | pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD); | ||
226 | pwr_cnt &= ~PSB_PWRGT_GFX_MASK; | ||
227 | |||
228 | outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD); | ||
229 | for (i = 0; i < 5; i++) { | ||
230 | u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS); | ||
231 | if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0) | ||
232 | break; | ||
233 | udelay(10); | ||
234 | } | ||
235 | pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC); | ||
236 | pwr_cnt &= ~CDV_PWRGT_DISPLAY_CNTR; | ||
237 | outl(pwr_cnt, dev_priv->ospm_base + PSB_PM_SSC); | ||
238 | for (i = 0; i < 5; i++) { | ||
239 | u32 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); | ||
240 | if ((pwr_sts & CDV_PWRGT_DISPLAY_STS) == 0) | ||
241 | break; | ||
242 | udelay(10); | ||
243 | } | ||
244 | } | ||
245 | |||
246 | /** | ||
247 | * cdv_save_display_registers - save registers lost on suspend | ||
248 | * @dev: our DRM device | ||
249 | * | ||
250 | * Save the state we need in order to be able to restore the interface | ||
251 | * upon resume from suspend | ||
252 | * | ||
253 | * FIXME: review | ||
254 | */ | ||
255 | static int cdv_save_display_registers(struct drm_device *dev) | ||
256 | { | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | /** | ||
261 | * cdv_restore_display_registers - restore lost register state | ||
262 | * @dev: our DRM device | ||
263 | * | ||
264 | * Restore register state that was lost during suspend and resume. | ||
265 | * | ||
266 | * FIXME: review | ||
267 | */ | ||
268 | static int cdv_restore_display_registers(struct drm_device *dev) | ||
269 | { | ||
270 | return 0; | ||
271 | } | ||
272 | |||
273 | static int cdv_power_down(struct drm_device *dev) | ||
274 | { | ||
275 | return 0; | ||
276 | } | ||
277 | |||
278 | static int cdv_power_up(struct drm_device *dev) | ||
279 | { | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | /* FIXME ? - shared with Poulsbo */ | ||
284 | static void cdv_get_core_freq(struct drm_device *dev) | ||
285 | { | ||
286 | uint32_t clock; | ||
287 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | ||
288 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
289 | |||
290 | pci_write_config_dword(pci_root, 0xD0, 0xD0050300); | ||
291 | pci_read_config_dword(pci_root, 0xD4, &clock); | ||
292 | pci_dev_put(pci_root); | ||
293 | |||
294 | switch (clock & 0x07) { | ||
295 | case 0: | ||
296 | dev_priv->core_freq = 100; | ||
297 | break; | ||
298 | case 1: | ||
299 | dev_priv->core_freq = 133; | ||
300 | break; | ||
301 | case 2: | ||
302 | dev_priv->core_freq = 150; | ||
303 | break; | ||
304 | case 3: | ||
305 | dev_priv->core_freq = 178; | ||
306 | break; | ||
307 | case 4: | ||
308 | dev_priv->core_freq = 200; | ||
309 | break; | ||
310 | case 5: | ||
311 | case 6: | ||
312 | case 7: | ||
313 | dev_priv->core_freq = 266; | ||
314 | default: | ||
315 | dev_priv->core_freq = 0; | ||
316 | } | ||
317 | } | ||
318 | |||
319 | static int cdv_chip_setup(struct drm_device *dev) | ||
320 | { | ||
321 | cdv_get_core_freq(dev); | ||
322 | gma_intel_opregion_init(dev); | ||
323 | psb_intel_init_bios(dev); | ||
324 | return 0; | ||
325 | } | ||
326 | |||
327 | /* CDV is much like Poulsbo but has MID like SGX offsets and PM */ | ||
328 | |||
329 | const struct psb_ops cdv_chip_ops = { | ||
330 | .name = "Cedartrail", | ||
331 | .accel_2d = 0, | ||
332 | .pipes = 2, | ||
333 | .sgx_offset = MRST_SGX_OFFSET, | ||
334 | .chip_setup = cdv_chip_setup, | ||
335 | |||
336 | .crtc_helper = &cdv_intel_helper_funcs, | ||
337 | .crtc_funcs = &cdv_intel_crtc_funcs, | ||
338 | |||
339 | .output_init = cdv_output_init, | ||
340 | |||
341 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
342 | .backlight_init = cdv_backlight_init, | ||
343 | #endif | ||
344 | |||
345 | .init_pm = cdv_init_pm, | ||
346 | .save_regs = cdv_save_display_registers, | ||
347 | .restore_regs = cdv_restore_display_registers, | ||
348 | .power_down = cdv_power_down, | ||
349 | .power_up = cdv_power_up, | ||
350 | }; | ||
diff --git a/drivers/staging/gma500/cdv_device.h b/drivers/staging/gma500/cdv_device.h deleted file mode 100644 index 2a88b7beb551..000000000000 --- a/drivers/staging/gma500/cdv_device.h +++ /dev/null | |||
@@ -1,36 +0,0 @@ | |||
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 | |||
18 | extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs; | ||
19 | extern const struct drm_crtc_funcs cdv_intel_crtc_funcs; | ||
20 | extern void cdv_intel_crt_init(struct drm_device *dev, | ||
21 | struct psb_intel_mode_device *mode_dev); | ||
22 | extern void cdv_intel_lvds_init(struct drm_device *dev, | ||
23 | struct psb_intel_mode_device *mode_dev); | ||
24 | extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev, | ||
25 | int reg); | ||
26 | extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev, | ||
27 | struct drm_crtc *crtc); | ||
28 | |||
29 | extern 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/staging/gma500/cdv_intel_crt.c b/drivers/staging/gma500/cdv_intel_crt.c deleted file mode 100644 index efda63b97b45..000000000000 --- a/drivers/staging/gma500/cdv_intel_crt.c +++ /dev/null | |||
@@ -1,326 +0,0 @@ | |||
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 | |||
38 | static 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 | |||
66 | static 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 | |||
88 | static 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 | |||
95 | static 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 | */ | ||
146 | static 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 | |||
196 | static 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 | |||
205 | static 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 | |||
215 | static 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 | |||
222 | static 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 | |||
233 | static 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 | |||
241 | static 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 | |||
249 | static 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 | |||
256 | static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder) | ||
257 | { | ||
258 | drm_encoder_cleanup(encoder); | ||
259 | } | ||
260 | |||
261 | static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = { | ||
262 | .destroy = cdv_intel_crt_enc_destroy, | ||
263 | }; | ||
264 | |||
265 | void 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; | ||
321 | failed_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/staging/gma500/cdv_intel_display.c b/drivers/staging/gma500/cdv_intel_display.c deleted file mode 100644 index c63a32776a9e..000000000000 --- a/drivers/staging/gma500/cdv_intel_display.c +++ /dev/null | |||
@@ -1,1508 +0,0 @@ | |||
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 | |||
34 | struct cdv_intel_range_t { | ||
35 | int min, max; | ||
36 | }; | ||
37 | |||
38 | struct cdv_intel_p2_t { | ||
39 | int dot_limit; | ||
40 | int p2_slow, p2_fast; | ||
41 | }; | ||
42 | |||
43 | struct 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 | |||
57 | struct 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 | |||
67 | static 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 | |||
135 | static 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 | |||
162 | static 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 | */ | ||
204 | static 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 | */ | ||
217 | static int | ||
218 | cdv_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 | */ | ||
347 | bool 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 | |||
364 | static 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 */ | ||
387 | static 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; } | ||
398 | static 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 | |||
419 | static 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 | |||
479 | int 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->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); | ||
511 | |||
512 | REG_WRITE(dspstride, crtc->fb->pitches[0]); | ||
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 | |||
546 | psb_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 | |||
551 | psb_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 | */ | ||
562 | static 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 | |||
671 | static 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 | |||
677 | static 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 | |||
683 | void 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 | |||
691 | void 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 | |||
699 | static 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 | */ | ||
711 | static 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 | |||
723 | static 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 */ | ||
931 | void 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 | */ | ||
986 | static 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 | */ | ||
1049 | static 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 | |||
1153 | static 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 | |||
1242 | static 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 | |||
1273 | static 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 | |||
1289 | static 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 | |||
1311 | static 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. */ | ||
1320 | static 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. */ | ||
1402 | struct 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 | |||
1451 | static 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 | |||
1460 | const 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 | |||
1469 | const 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 | */ | ||
1483 | void 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/staging/gma500/cdv_intel_hdmi.c b/drivers/staging/gma500/cdv_intel_hdmi.c deleted file mode 100644 index cbca2b0c7d58..000000000000 --- a/drivers/staging/gma500/cdv_intel_hdmi.c +++ /dev/null | |||
@@ -1,376 +0,0 @@ | |||
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 | |||
49 | struct 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 | |||
61 | static 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 | |||
91 | static 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 | |||
98 | static 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 | |||
114 | static 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 | |||
123 | static 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 | |||
133 | static 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 | |||
162 | static 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 | */ | ||
221 | static 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 | |||
239 | static 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 | |||
267 | static 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 | |||
279 | static 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 | |||
287 | static 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 | |||
294 | static 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 | |||
304 | void 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 | |||
372 | failed_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/staging/gma500/cdv_intel_lvds.c b/drivers/staging/gma500/cdv_intel_lvds.c deleted file mode 100644 index 988b2d0acf43..000000000000 --- a/drivers/staging/gma500/cdv_intel_lvds.c +++ /dev/null | |||
@@ -1,721 +0,0 @@ | |||
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 | |||
52 | struct 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 | */ | ||
69 | static 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 | */ | ||
91 | static 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 | |||
126 | static 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 | */ | ||
154 | void 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 | */ | ||
174 | static 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 | */ | ||
197 | static 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 | |||
227 | static 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 | |||
238 | static void cdv_intel_lvds_save(struct drm_connector *connector) | ||
239 | { | ||
240 | } | ||
241 | |||
242 | static void cdv_intel_lvds_restore(struct drm_connector *connector) | ||
243 | { | ||
244 | } | ||
245 | |||
246 | int 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 | |||
271 | bool 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 | |||
321 | static 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 | |||
339 | static 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 | |||
352 | static 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 | */ | ||
392 | static 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 | */ | ||
401 | static 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 | */ | ||
440 | void 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 | |||
452 | int 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 | |||
522 | static 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 | |||
531 | static 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 | |||
538 | static 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 | |||
549 | static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder) | ||
550 | { | ||
551 | drm_encoder_cleanup(encoder); | ||
552 | } | ||
553 | |||
554 | const 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 | */ | ||
565 | void 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 | |||
704 | out: | ||
705 | drm_sysfs_connector_add(connector); | ||
706 | return; | ||
707 | |||
708 | failed_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); | ||
712 | failed_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); | ||
716 | failed_blc_i2c: | ||
717 | printk(KERN_ERR "Failed BLC\n"); | ||
718 | drm_encoder_cleanup(encoder); | ||
719 | drm_connector_cleanup(connector); | ||
720 | kfree(connector); | ||
721 | } | ||
diff --git a/drivers/staging/gma500/displays/hdmi.h b/drivers/staging/gma500/displays/hdmi.h deleted file mode 100644 index d58ba9bd010f..000000000000 --- a/drivers/staging/gma500/displays/hdmi.h +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef HDMI_H | ||
29 | #define HDMI_H | ||
30 | |||
31 | extern void hdmi_init(struct drm_device *dev); | ||
32 | |||
33 | #endif | ||
diff --git a/drivers/staging/gma500/displays/pyr_cmd.h b/drivers/staging/gma500/displays/pyr_cmd.h deleted file mode 100644 index 84bae5c8c552..000000000000 --- a/drivers/staging/gma500/displays/pyr_cmd.h +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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, sublicensen | ||
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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef PYR_CMD_H | ||
29 | #define PYR_CMD_H | ||
30 | |||
31 | extern void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs); | ||
32 | |||
33 | #endif | ||
34 | |||
diff --git a/drivers/staging/gma500/displays/pyr_vid.h b/drivers/staging/gma500/displays/pyr_vid.h deleted file mode 100644 index ce98860fa68a..000000000000 --- a/drivers/staging/gma500/displays/pyr_vid.h +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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, sublicensen | ||
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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef PYR_VID_H | ||
29 | #define PYR_VID_H | ||
30 | |||
31 | extern void pyr_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs); | ||
32 | extern struct drm_display_mode *pyr_vid_get_config_mode(struct drm_device* dev); | ||
33 | |||
34 | #endif | ||
diff --git a/drivers/staging/gma500/displays/tmd_cmd.h b/drivers/staging/gma500/displays/tmd_cmd.h deleted file mode 100644 index 641e85eedece..000000000000 --- a/drivers/staging/gma500/displays/tmd_cmd.h +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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, sublicensen | ||
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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef TMD_CMD_H | ||
29 | #define TMD_CMD_H | ||
30 | |||
31 | extern void tmd_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs); | ||
32 | extern struct drm_display_mode *tmd_cmd_get_config_mode(struct drm_device *dev); | ||
33 | |||
34 | #endif | ||
diff --git a/drivers/staging/gma500/displays/tmd_vid.h b/drivers/staging/gma500/displays/tmd_vid.h deleted file mode 100644 index 7a5fa3b935e3..000000000000 --- a/drivers/staging/gma500/displays/tmd_vid.h +++ /dev/null | |||
@@ -1,34 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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, sublicensen | ||
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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef TMD_VID_H | ||
29 | #define TMD_VID_H | ||
30 | |||
31 | extern void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs); | ||
32 | extern struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev); | ||
33 | |||
34 | #endif | ||
diff --git a/drivers/staging/gma500/displays/tpo_cmd.h b/drivers/staging/gma500/displays/tpo_cmd.h deleted file mode 100644 index 610552730d71..000000000000 --- a/drivers/staging/gma500/displays/tpo_cmd.h +++ /dev/null | |||
@@ -1,35 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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, sublicensen | ||
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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef TPO_CMD_H | ||
29 | #define TPO_CMD_H | ||
30 | |||
31 | extern void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs); | ||
32 | /* extern struct drm_display_mode * */ | ||
33 | /* tpo_cmd_get_config_mode(struct drm_device *dev); */ | ||
34 | |||
35 | #endif | ||
diff --git a/drivers/staging/gma500/displays/tpo_vid.h b/drivers/staging/gma500/displays/tpo_vid.h deleted file mode 100644 index c24f05722de1..000000000000 --- a/drivers/staging/gma500/displays/tpo_vid.h +++ /dev/null | |||
@@ -1,33 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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, sublicensen | ||
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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef TPO_VID_H | ||
29 | #define TPO_VID_H | ||
30 | |||
31 | extern void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs); | ||
32 | |||
33 | #endif | ||
diff --git a/drivers/staging/gma500/framebuffer.c b/drivers/staging/gma500/framebuffer.c deleted file mode 100644 index b00761cba144..000000000000 --- a/drivers/staging/gma500/framebuffer.c +++ /dev/null | |||
@@ -1,856 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2007-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/module.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/errno.h> | ||
23 | #include <linux/string.h> | ||
24 | #include <linux/mm.h> | ||
25 | #include <linux/tty.h> | ||
26 | #include <linux/slab.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <linux/fb.h> | ||
29 | #include <linux/init.h> | ||
30 | #include <linux/console.h> | ||
31 | |||
32 | #include <drm/drmP.h> | ||
33 | #include <drm/drm.h> | ||
34 | #include <drm/drm_crtc.h> | ||
35 | #include <drm/drm_fb_helper.h> | ||
36 | |||
37 | #include "psb_drv.h" | ||
38 | #include "psb_intel_reg.h" | ||
39 | #include "psb_intel_drv.h" | ||
40 | #include "framebuffer.h" | ||
41 | #include "gtt.h" | ||
42 | |||
43 | #include "mdfld_output.h" | ||
44 | |||
45 | static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb); | ||
46 | static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, | ||
47 | struct drm_file *file_priv, | ||
48 | unsigned int *handle); | ||
49 | |||
50 | static const struct drm_framebuffer_funcs psb_fb_funcs = { | ||
51 | .destroy = psb_user_framebuffer_destroy, | ||
52 | .create_handle = psb_user_framebuffer_create_handle, | ||
53 | }; | ||
54 | |||
55 | #define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16) | ||
56 | |||
57 | static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green, | ||
58 | unsigned blue, unsigned transp, | ||
59 | struct fb_info *info) | ||
60 | { | ||
61 | struct psb_fbdev *fbdev = info->par; | ||
62 | struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb; | ||
63 | uint32_t v; | ||
64 | |||
65 | if (!fb) | ||
66 | return -ENOMEM; | ||
67 | |||
68 | if (regno > 255) | ||
69 | return 1; | ||
70 | |||
71 | red = CMAP_TOHW(red, info->var.red.length); | ||
72 | blue = CMAP_TOHW(blue, info->var.blue.length); | ||
73 | green = CMAP_TOHW(green, info->var.green.length); | ||
74 | transp = CMAP_TOHW(transp, info->var.transp.length); | ||
75 | |||
76 | v = (red << info->var.red.offset) | | ||
77 | (green << info->var.green.offset) | | ||
78 | (blue << info->var.blue.offset) | | ||
79 | (transp << info->var.transp.offset); | ||
80 | |||
81 | if (regno < 16) { | ||
82 | switch (fb->bits_per_pixel) { | ||
83 | case 16: | ||
84 | ((uint32_t *) info->pseudo_palette)[regno] = v; | ||
85 | break; | ||
86 | case 24: | ||
87 | case 32: | ||
88 | ((uint32_t *) info->pseudo_palette)[regno] = v; | ||
89 | break; | ||
90 | } | ||
91 | } | ||
92 | |||
93 | return 0; | ||
94 | } | ||
95 | |||
96 | static int psbfb_pan(struct fb_var_screeninfo *var, struct fb_info *info) | ||
97 | { | ||
98 | struct psb_fbdev *fbdev = info->par; | ||
99 | struct psb_framebuffer *psbfb = &fbdev->pfb; | ||
100 | struct drm_device *dev = psbfb->base.dev; | ||
101 | |||
102 | /* | ||
103 | * We have to poke our nose in here. The core fb code assumes | ||
104 | * panning is part of the hardware that can be invoked before | ||
105 | * the actual fb is mapped. In our case that isn't quite true. | ||
106 | */ | ||
107 | if (psbfb->gtt->npage) | ||
108 | psb_gtt_roll(dev, psbfb->gtt, var->yoffset); | ||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | void psbfb_suspend(struct drm_device *dev) | ||
113 | { | ||
114 | struct drm_framebuffer *fb = 0; | ||
115 | struct psb_framebuffer *psbfb = to_psb_fb(fb); | ||
116 | |||
117 | console_lock(); | ||
118 | mutex_lock(&dev->mode_config.mutex); | ||
119 | list_for_each_entry(fb, &dev->mode_config.fb_list, head) { | ||
120 | struct fb_info *info = psbfb->fbdev; | ||
121 | fb_set_suspend(info, 1); | ||
122 | drm_fb_helper_blank(FB_BLANK_POWERDOWN, info); | ||
123 | } | ||
124 | mutex_unlock(&dev->mode_config.mutex); | ||
125 | console_unlock(); | ||
126 | } | ||
127 | |||
128 | void psbfb_resume(struct drm_device *dev) | ||
129 | { | ||
130 | struct drm_framebuffer *fb = 0; | ||
131 | struct psb_framebuffer *psbfb = to_psb_fb(fb); | ||
132 | |||
133 | console_lock(); | ||
134 | mutex_lock(&dev->mode_config.mutex); | ||
135 | list_for_each_entry(fb, &dev->mode_config.fb_list, head) { | ||
136 | struct fb_info *info = psbfb->fbdev; | ||
137 | fb_set_suspend(info, 0); | ||
138 | drm_fb_helper_blank(FB_BLANK_UNBLANK, info); | ||
139 | } | ||
140 | mutex_unlock(&dev->mode_config.mutex); | ||
141 | console_unlock(); | ||
142 | drm_helper_disable_unused_functions(dev); | ||
143 | } | ||
144 | |||
145 | static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
146 | { | ||
147 | struct psb_framebuffer *psbfb = vma->vm_private_data; | ||
148 | struct drm_device *dev = psbfb->base.dev; | ||
149 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
150 | int page_num; | ||
151 | int i; | ||
152 | unsigned long address; | ||
153 | int ret; | ||
154 | unsigned long pfn; | ||
155 | /* FIXME: assumes fb at stolen base which may not be true */ | ||
156 | unsigned long phys_addr = (unsigned long)dev_priv->stolen_base; | ||
157 | |||
158 | page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; | ||
159 | address = (unsigned long)vmf->virtual_address; | ||
160 | |||
161 | vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot); | ||
162 | |||
163 | for (i = 0; i < page_num; i++) { | ||
164 | pfn = (phys_addr >> PAGE_SHIFT); | ||
165 | |||
166 | ret = vm_insert_mixed(vma, address, pfn); | ||
167 | if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0))) | ||
168 | break; | ||
169 | else if (unlikely(ret != 0)) { | ||
170 | ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS; | ||
171 | return ret; | ||
172 | } | ||
173 | address += PAGE_SIZE; | ||
174 | phys_addr += PAGE_SIZE; | ||
175 | } | ||
176 | return VM_FAULT_NOPAGE; | ||
177 | } | ||
178 | |||
179 | static void psbfb_vm_open(struct vm_area_struct *vma) | ||
180 | { | ||
181 | } | ||
182 | |||
183 | static void psbfb_vm_close(struct vm_area_struct *vma) | ||
184 | { | ||
185 | } | ||
186 | |||
187 | static struct vm_operations_struct psbfb_vm_ops = { | ||
188 | .fault = psbfb_vm_fault, | ||
189 | .open = psbfb_vm_open, | ||
190 | .close = psbfb_vm_close | ||
191 | }; | ||
192 | |||
193 | static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma) | ||
194 | { | ||
195 | struct psb_fbdev *fbdev = info->par; | ||
196 | struct psb_framebuffer *psbfb = &fbdev->pfb; | ||
197 | |||
198 | if (vma->vm_pgoff != 0) | ||
199 | return -EINVAL; | ||
200 | if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT)) | ||
201 | return -EINVAL; | ||
202 | |||
203 | if (!psbfb->addr_space) | ||
204 | psbfb->addr_space = vma->vm_file->f_mapping; | ||
205 | /* | ||
206 | * If this is a GEM object then info->screen_base is the virtual | ||
207 | * kernel remapping of the object. FIXME: Review if this is | ||
208 | * suitable for our mmap work | ||
209 | */ | ||
210 | vma->vm_ops = &psbfb_vm_ops; | ||
211 | vma->vm_private_data = (void *)psbfb; | ||
212 | vma->vm_flags |= VM_RESERVED | VM_IO | | ||
213 | VM_MIXEDMAP | VM_DONTEXPAND; | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | static int psbfb_ioctl(struct fb_info *info, unsigned int cmd, | ||
218 | unsigned long arg) | ||
219 | { | ||
220 | return -ENOTTY; | ||
221 | } | ||
222 | |||
223 | static struct fb_ops psbfb_ops = { | ||
224 | .owner = THIS_MODULE, | ||
225 | .fb_check_var = drm_fb_helper_check_var, | ||
226 | .fb_set_par = drm_fb_helper_set_par, | ||
227 | .fb_blank = drm_fb_helper_blank, | ||
228 | .fb_setcolreg = psbfb_setcolreg, | ||
229 | .fb_fillrect = cfb_fillrect, | ||
230 | .fb_copyarea = psbfb_copyarea, | ||
231 | .fb_imageblit = cfb_imageblit, | ||
232 | .fb_mmap = psbfb_mmap, | ||
233 | .fb_sync = psbfb_sync, | ||
234 | .fb_ioctl = psbfb_ioctl, | ||
235 | }; | ||
236 | |||
237 | static struct fb_ops psbfb_roll_ops = { | ||
238 | .owner = THIS_MODULE, | ||
239 | .fb_check_var = drm_fb_helper_check_var, | ||
240 | .fb_set_par = drm_fb_helper_set_par, | ||
241 | .fb_blank = drm_fb_helper_blank, | ||
242 | .fb_setcolreg = psbfb_setcolreg, | ||
243 | .fb_fillrect = cfb_fillrect, | ||
244 | .fb_copyarea = cfb_copyarea, | ||
245 | .fb_imageblit = cfb_imageblit, | ||
246 | .fb_pan_display = psbfb_pan, | ||
247 | .fb_mmap = psbfb_mmap, | ||
248 | .fb_sync = psbfb_sync, | ||
249 | .fb_ioctl = psbfb_ioctl, | ||
250 | }; | ||
251 | |||
252 | static struct fb_ops psbfb_unaccel_ops = { | ||
253 | .owner = THIS_MODULE, | ||
254 | .fb_check_var = drm_fb_helper_check_var, | ||
255 | .fb_set_par = drm_fb_helper_set_par, | ||
256 | .fb_blank = drm_fb_helper_blank, | ||
257 | .fb_setcolreg = psbfb_setcolreg, | ||
258 | .fb_fillrect = cfb_fillrect, | ||
259 | .fb_copyarea = cfb_copyarea, | ||
260 | .fb_imageblit = cfb_imageblit, | ||
261 | .fb_mmap = psbfb_mmap, | ||
262 | .fb_ioctl = psbfb_ioctl, | ||
263 | }; | ||
264 | |||
265 | /** | ||
266 | * psb_framebuffer_init - initialize a framebuffer | ||
267 | * @dev: our DRM device | ||
268 | * @fb: framebuffer to set up | ||
269 | * @mode_cmd: mode description | ||
270 | * @gt: backing object | ||
271 | * | ||
272 | * Configure and fill in the boilerplate for our frame buffer. Return | ||
273 | * 0 on success or an error code if we fail. | ||
274 | */ | ||
275 | static int psb_framebuffer_init(struct drm_device *dev, | ||
276 | struct psb_framebuffer *fb, | ||
277 | struct drm_mode_fb_cmd2 *mode_cmd, | ||
278 | struct gtt_range *gt) | ||
279 | { | ||
280 | u32 bpp, depth; | ||
281 | int ret; | ||
282 | |||
283 | drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp); | ||
284 | |||
285 | if (mode_cmd->pitches[0] & 63) | ||
286 | return -EINVAL; | ||
287 | switch (bpp) { | ||
288 | case 8: | ||
289 | case 16: | ||
290 | case 24: | ||
291 | case 32: | ||
292 | break; | ||
293 | default: | ||
294 | return -EINVAL; | ||
295 | } | ||
296 | ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs); | ||
297 | if (ret) { | ||
298 | dev_err(dev->dev, "framebuffer init failed: %d\n", ret); | ||
299 | return ret; | ||
300 | } | ||
301 | drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd); | ||
302 | fb->gtt = gt; | ||
303 | return 0; | ||
304 | } | ||
305 | |||
306 | /** | ||
307 | * psb_framebuffer_create - create a framebuffer backed by gt | ||
308 | * @dev: our DRM device | ||
309 | * @mode_cmd: the description of the requested mode | ||
310 | * @gt: the backing object | ||
311 | * | ||
312 | * Create a framebuffer object backed by the gt, and fill in the | ||
313 | * boilerplate required | ||
314 | * | ||
315 | * TODO: review object references | ||
316 | */ | ||
317 | |||
318 | static struct drm_framebuffer *psb_framebuffer_create | ||
319 | (struct drm_device *dev, | ||
320 | struct drm_mode_fb_cmd2 *mode_cmd, | ||
321 | struct gtt_range *gt) | ||
322 | { | ||
323 | struct psb_framebuffer *fb; | ||
324 | int ret; | ||
325 | |||
326 | fb = kzalloc(sizeof(*fb), GFP_KERNEL); | ||
327 | if (!fb) | ||
328 | return ERR_PTR(-ENOMEM); | ||
329 | |||
330 | ret = psb_framebuffer_init(dev, fb, mode_cmd, gt); | ||
331 | if (ret) { | ||
332 | kfree(fb); | ||
333 | return ERR_PTR(ret); | ||
334 | } | ||
335 | return &fb->base; | ||
336 | } | ||
337 | |||
338 | /** | ||
339 | * psbfb_alloc - allocate frame buffer memory | ||
340 | * @dev: the DRM device | ||
341 | * @aligned_size: space needed | ||
342 | * @force: fall back to GEM buffers if need be | ||
343 | * | ||
344 | * Allocate the frame buffer. In the usual case we get a GTT range that | ||
345 | * is stolen memory backed and life is simple. If there isn't sufficient | ||
346 | * stolen memory or the system has no stolen memory we allocate a range | ||
347 | * and back it with a GEM object. | ||
348 | * | ||
349 | * In this case the GEM object has no handle. | ||
350 | */ | ||
351 | static struct gtt_range *psbfb_alloc(struct drm_device *dev, | ||
352 | int aligned_size, int force) | ||
353 | { | ||
354 | struct gtt_range *backing; | ||
355 | /* Begin by trying to use stolen memory backing */ | ||
356 | backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1); | ||
357 | if (backing) { | ||
358 | if (drm_gem_private_object_init(dev, | ||
359 | &backing->gem, aligned_size) == 0) | ||
360 | return backing; | ||
361 | psb_gtt_free_range(dev, backing); | ||
362 | } | ||
363 | if (!force) | ||
364 | return NULL; | ||
365 | |||
366 | /* Next try using GEM host memory */ | ||
367 | backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0); | ||
368 | if (backing == NULL) | ||
369 | return NULL; | ||
370 | |||
371 | /* Now back it with an object */ | ||
372 | if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) { | ||
373 | psb_gtt_free_range(dev, backing); | ||
374 | return NULL; | ||
375 | } | ||
376 | return backing; | ||
377 | } | ||
378 | |||
379 | /** | ||
380 | * psbfb_create - create a framebuffer | ||
381 | * @fbdev: the framebuffer device | ||
382 | * @sizes: specification of the layout | ||
383 | * | ||
384 | * Create a framebuffer to the specifications provided | ||
385 | */ | ||
386 | static int psbfb_create(struct psb_fbdev *fbdev, | ||
387 | struct drm_fb_helper_surface_size *sizes) | ||
388 | { | ||
389 | struct drm_device *dev = fbdev->psb_fb_helper.dev; | ||
390 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
391 | struct fb_info *info; | ||
392 | struct drm_framebuffer *fb; | ||
393 | struct psb_framebuffer *psbfb = &fbdev->pfb; | ||
394 | struct drm_mode_fb_cmd2 mode_cmd; | ||
395 | struct device *device = &dev->pdev->dev; | ||
396 | int size; | ||
397 | int ret; | ||
398 | struct gtt_range *backing; | ||
399 | int gtt_roll = 1; | ||
400 | u32 bpp, depth; | ||
401 | |||
402 | mode_cmd.width = sizes->surface_width; | ||
403 | mode_cmd.height = sizes->surface_height; | ||
404 | bpp = sizes->surface_bpp; | ||
405 | |||
406 | /* No 24bit packed */ | ||
407 | if (bpp == 24) | ||
408 | bpp = 32; | ||
409 | |||
410 | /* Acceleration via the GTT requires pitch to be 4096 byte aligned | ||
411 | (ie 1024 or 2048 pixels in normal use) */ | ||
412 | mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 4096); | ||
413 | depth = sizes->surface_depth; | ||
414 | |||
415 | size = mode_cmd.pitches[0] * mode_cmd.height; | ||
416 | size = ALIGN(size, PAGE_SIZE); | ||
417 | |||
418 | /* Allocate the framebuffer in the GTT with stolen page backing */ | ||
419 | backing = psbfb_alloc(dev, size, 0); | ||
420 | if (backing == NULL) { | ||
421 | /* | ||
422 | * We couldn't get the space we wanted, fall back to the | ||
423 | * display engine requirement instead. The HW requires | ||
424 | * the pitch to be 64 byte aligned | ||
425 | */ | ||
426 | |||
427 | gtt_roll = 0; /* Don't use GTT accelerated scrolling */ | ||
428 | |||
429 | mode_cmd.pitches[0] = ALIGN(mode_cmd.width * ((bpp + 7) / 8), 64); | ||
430 | depth = sizes->surface_depth; | ||
431 | |||
432 | size = mode_cmd.pitches[0] * mode_cmd.height; | ||
433 | size = ALIGN(size, PAGE_SIZE); | ||
434 | |||
435 | /* Allocate the framebuffer in the GTT with stolen page | ||
436 | backing when there is room */ | ||
437 | backing = psbfb_alloc(dev, size, 1); | ||
438 | if (backing == NULL) | ||
439 | return -ENOMEM; | ||
440 | } | ||
441 | |||
442 | mutex_lock(&dev->struct_mutex); | ||
443 | |||
444 | info = framebuffer_alloc(0, device); | ||
445 | if (!info) { | ||
446 | ret = -ENOMEM; | ||
447 | goto out_err1; | ||
448 | } | ||
449 | info->par = fbdev; | ||
450 | |||
451 | mode_cmd.pixel_format = drm_mode_legacy_fb_format(bpp, depth); | ||
452 | |||
453 | ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing); | ||
454 | if (ret) | ||
455 | goto out_unref; | ||
456 | |||
457 | fb = &psbfb->base; | ||
458 | psbfb->fbdev = info; | ||
459 | |||
460 | fbdev->psb_fb_helper.fb = fb; | ||
461 | fbdev->psb_fb_helper.fbdev = info; | ||
462 | |||
463 | strcpy(info->fix.id, "psbfb"); | ||
464 | |||
465 | info->flags = FBINFO_DEFAULT; | ||
466 | if (gtt_roll) { /* GTT rolling seems best */ | ||
467 | info->fbops = &psbfb_roll_ops; | ||
468 | info->flags |= FBINFO_HWACCEL_YPAN; | ||
469 | } | ||
470 | else if (dev_priv->ops->accel_2d) /* 2D engine */ | ||
471 | info->fbops = &psbfb_ops; | ||
472 | else /* Software */ | ||
473 | info->fbops = &psbfb_unaccel_ops; | ||
474 | |||
475 | ret = fb_alloc_cmap(&info->cmap, 256, 0); | ||
476 | if (ret) { | ||
477 | ret = -ENOMEM; | ||
478 | goto out_unref; | ||
479 | } | ||
480 | |||
481 | info->fix.smem_start = dev->mode_config.fb_base; | ||
482 | info->fix.smem_len = size; | ||
483 | info->fix.ywrapstep = gtt_roll; | ||
484 | info->fix.ypanstep = gtt_roll; | ||
485 | |||
486 | if (backing->stolen) { | ||
487 | /* Accessed stolen memory directly */ | ||
488 | info->screen_base = (char *)dev_priv->vram_addr + | ||
489 | backing->offset; | ||
490 | } else { | ||
491 | /* Pin the pages into the GTT and create a mapping to them */ | ||
492 | psb_gtt_pin(backing); | ||
493 | info->screen_base = vm_map_ram(backing->pages, backing->npage, | ||
494 | -1, PAGE_KERNEL); | ||
495 | if (info->screen_base == NULL) { | ||
496 | psb_gtt_unpin(backing); | ||
497 | ret = -ENOMEM; | ||
498 | goto out_unref; | ||
499 | } | ||
500 | psbfb->vm_map = 1; | ||
501 | } | ||
502 | info->screen_size = size; | ||
503 | |||
504 | if (dev_priv->gtt.stolen_size) { | ||
505 | info->apertures = alloc_apertures(1); | ||
506 | if (!info->apertures) { | ||
507 | ret = -ENOMEM; | ||
508 | goto out_unref; | ||
509 | } | ||
510 | info->apertures->ranges[0].base = dev->mode_config.fb_base; | ||
511 | info->apertures->ranges[0].size = dev_priv->gtt.stolen_size; | ||
512 | } | ||
513 | |||
514 | drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth); | ||
515 | drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper, | ||
516 | sizes->fb_width, sizes->fb_height); | ||
517 | |||
518 | info->fix.mmio_start = pci_resource_start(dev->pdev, 0); | ||
519 | info->fix.mmio_len = pci_resource_len(dev->pdev, 0); | ||
520 | |||
521 | info->pixmap.size = 64 * 1024; | ||
522 | info->pixmap.buf_align = 8; | ||
523 | info->pixmap.access_align = 32; | ||
524 | info->pixmap.flags = FB_PIXMAP_SYSTEM; | ||
525 | info->pixmap.scan_align = 1; | ||
526 | |||
527 | dev_info(dev->dev, "allocated %dx%d fb\n", | ||
528 | psbfb->base.width, psbfb->base.height); | ||
529 | |||
530 | mutex_unlock(&dev->struct_mutex); | ||
531 | return 0; | ||
532 | out_unref: | ||
533 | if (backing->stolen) | ||
534 | psb_gtt_free_range(dev, backing); | ||
535 | else { | ||
536 | if (psbfb->vm_map) | ||
537 | vm_unmap_ram(info->screen_base, backing->npage); | ||
538 | drm_gem_object_unreference(&backing->gem); | ||
539 | } | ||
540 | out_err1: | ||
541 | mutex_unlock(&dev->struct_mutex); | ||
542 | psb_gtt_free_range(dev, backing); | ||
543 | return ret; | ||
544 | } | ||
545 | |||
546 | /** | ||
547 | * psb_user_framebuffer_create - create framebuffer | ||
548 | * @dev: our DRM device | ||
549 | * @filp: client file | ||
550 | * @cmd: mode request | ||
551 | * | ||
552 | * Create a new framebuffer backed by a userspace GEM object | ||
553 | */ | ||
554 | static struct drm_framebuffer *psb_user_framebuffer_create | ||
555 | (struct drm_device *dev, struct drm_file *filp, | ||
556 | struct drm_mode_fb_cmd2 *cmd) | ||
557 | { | ||
558 | struct gtt_range *r; | ||
559 | struct drm_gem_object *obj; | ||
560 | |||
561 | /* | ||
562 | * Find the GEM object and thus the gtt range object that is | ||
563 | * to back this space | ||
564 | */ | ||
565 | obj = drm_gem_object_lookup(dev, filp, cmd->handles[0]); | ||
566 | if (obj == NULL) | ||
567 | return ERR_PTR(-ENOENT); | ||
568 | |||
569 | /* Let the core code do all the work */ | ||
570 | r = container_of(obj, struct gtt_range, gem); | ||
571 | return psb_framebuffer_create(dev, cmd, r); | ||
572 | } | ||
573 | |||
574 | static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, | ||
575 | u16 blue, int regno) | ||
576 | { | ||
577 | } | ||
578 | |||
579 | static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red, | ||
580 | u16 *green, u16 *blue, int regno) | ||
581 | { | ||
582 | } | ||
583 | |||
584 | static int psbfb_probe(struct drm_fb_helper *helper, | ||
585 | struct drm_fb_helper_surface_size *sizes) | ||
586 | { | ||
587 | struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper; | ||
588 | int new_fb = 0; | ||
589 | int ret; | ||
590 | |||
591 | if (!helper->fb) { | ||
592 | ret = psbfb_create(psb_fbdev, sizes); | ||
593 | if (ret) | ||
594 | return ret; | ||
595 | new_fb = 1; | ||
596 | } | ||
597 | return new_fb; | ||
598 | } | ||
599 | |||
600 | struct drm_fb_helper_funcs psb_fb_helper_funcs = { | ||
601 | .gamma_set = psbfb_gamma_set, | ||
602 | .gamma_get = psbfb_gamma_get, | ||
603 | .fb_probe = psbfb_probe, | ||
604 | }; | ||
605 | |||
606 | int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev) | ||
607 | { | ||
608 | struct fb_info *info; | ||
609 | struct psb_framebuffer *psbfb = &fbdev->pfb; | ||
610 | |||
611 | if (fbdev->psb_fb_helper.fbdev) { | ||
612 | info = fbdev->psb_fb_helper.fbdev; | ||
613 | |||
614 | /* If this is our base framebuffer then kill any virtual map | ||
615 | for the framebuffer layer and unpin it */ | ||
616 | if (psbfb->vm_map) { | ||
617 | vm_unmap_ram(info->screen_base, psbfb->gtt->npage); | ||
618 | psb_gtt_unpin(psbfb->gtt); | ||
619 | } | ||
620 | unregister_framebuffer(info); | ||
621 | if (info->cmap.len) | ||
622 | fb_dealloc_cmap(&info->cmap); | ||
623 | framebuffer_release(info); | ||
624 | } | ||
625 | drm_fb_helper_fini(&fbdev->psb_fb_helper); | ||
626 | drm_framebuffer_cleanup(&psbfb->base); | ||
627 | |||
628 | if (psbfb->gtt) | ||
629 | drm_gem_object_unreference(&psbfb->gtt->gem); | ||
630 | return 0; | ||
631 | } | ||
632 | |||
633 | int psb_fbdev_init(struct drm_device *dev) | ||
634 | { | ||
635 | struct psb_fbdev *fbdev; | ||
636 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
637 | |||
638 | fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL); | ||
639 | if (!fbdev) { | ||
640 | dev_err(dev->dev, "no memory\n"); | ||
641 | return -ENOMEM; | ||
642 | } | ||
643 | |||
644 | dev_priv->fbdev = fbdev; | ||
645 | fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs; | ||
646 | |||
647 | drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs, | ||
648 | INTELFB_CONN_LIMIT); | ||
649 | |||
650 | drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper); | ||
651 | drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32); | ||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | void psb_fbdev_fini(struct drm_device *dev) | ||
656 | { | ||
657 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
658 | |||
659 | if (!dev_priv->fbdev) | ||
660 | return; | ||
661 | |||
662 | psb_fbdev_destroy(dev, dev_priv->fbdev); | ||
663 | kfree(dev_priv->fbdev); | ||
664 | dev_priv->fbdev = NULL; | ||
665 | } | ||
666 | |||
667 | static void psbfb_output_poll_changed(struct drm_device *dev) | ||
668 | { | ||
669 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
670 | struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev; | ||
671 | drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper); | ||
672 | } | ||
673 | |||
674 | /** | ||
675 | * psb_user_framebuffer_create_handle - add hamdle to a framebuffer | ||
676 | * @fb: framebuffer | ||
677 | * @file_priv: our DRM file | ||
678 | * @handle: returned handle | ||
679 | * | ||
680 | * Our framebuffer object is a GTT range which also contains a GEM | ||
681 | * object. We need to turn it into a handle for userspace. GEM will do | ||
682 | * the work for us | ||
683 | */ | ||
684 | static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb, | ||
685 | struct drm_file *file_priv, | ||
686 | unsigned int *handle) | ||
687 | { | ||
688 | struct psb_framebuffer *psbfb = to_psb_fb(fb); | ||
689 | struct gtt_range *r = psbfb->gtt; | ||
690 | return drm_gem_handle_create(file_priv, &r->gem, handle); | ||
691 | } | ||
692 | |||
693 | /** | ||
694 | * psb_user_framebuffer_destroy - destruct user created fb | ||
695 | * @fb: framebuffer | ||
696 | * | ||
697 | * User framebuffers are backed by GEM objects so all we have to do is | ||
698 | * clean up a bit and drop the reference, GEM will handle the fallout | ||
699 | */ | ||
700 | static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb) | ||
701 | { | ||
702 | struct psb_framebuffer *psbfb = to_psb_fb(fb); | ||
703 | struct gtt_range *r = psbfb->gtt; | ||
704 | struct drm_device *dev = fb->dev; | ||
705 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
706 | struct psb_fbdev *fbdev = dev_priv->fbdev; | ||
707 | struct drm_crtc *crtc; | ||
708 | int reset = 0; | ||
709 | |||
710 | /* Should never get stolen memory for a user fb */ | ||
711 | WARN_ON(r->stolen); | ||
712 | |||
713 | /* Check if we are erroneously live */ | ||
714 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | ||
715 | if (crtc->fb == fb) | ||
716 | reset = 1; | ||
717 | |||
718 | if (reset) | ||
719 | /* | ||
720 | * Now force a sane response before we permit the DRM CRTC | ||
721 | * layer to do stupid things like blank the display. Instead | ||
722 | * we reset this framebuffer as if the user had forced a reset. | ||
723 | * We must do this before the cleanup so that the DRM layer | ||
724 | * doesn't get a chance to stick its oar in where it isn't | ||
725 | * wanted. | ||
726 | */ | ||
727 | drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper); | ||
728 | |||
729 | /* Let DRM do its clean up */ | ||
730 | drm_framebuffer_cleanup(fb); | ||
731 | /* We are no longer using the resource in GEM */ | ||
732 | drm_gem_object_unreference_unlocked(&r->gem); | ||
733 | kfree(fb); | ||
734 | } | ||
735 | |||
736 | static const struct drm_mode_config_funcs psb_mode_funcs = { | ||
737 | .fb_create = psb_user_framebuffer_create, | ||
738 | .output_poll_changed = psbfb_output_poll_changed, | ||
739 | }; | ||
740 | |||
741 | static int psb_create_backlight_property(struct drm_device *dev) | ||
742 | { | ||
743 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
744 | struct drm_property *backlight; | ||
745 | |||
746 | if (dev_priv->backlight_property) | ||
747 | return 0; | ||
748 | |||
749 | backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE, | ||
750 | "backlight", 2); | ||
751 | backlight->values[0] = 0; | ||
752 | backlight->values[1] = 100; | ||
753 | |||
754 | dev_priv->backlight_property = backlight; | ||
755 | |||
756 | return 0; | ||
757 | } | ||
758 | |||
759 | static void psb_setup_outputs(struct drm_device *dev) | ||
760 | { | ||
761 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
762 | struct drm_connector *connector; | ||
763 | |||
764 | drm_mode_create_scaling_mode_property(dev); | ||
765 | psb_create_backlight_property(dev); | ||
766 | |||
767 | dev_priv->ops->output_init(dev); | ||
768 | |||
769 | list_for_each_entry(connector, &dev->mode_config.connector_list, | ||
770 | head) { | ||
771 | struct psb_intel_output *psb_intel_output = | ||
772 | to_psb_intel_output(connector); | ||
773 | struct drm_encoder *encoder = &psb_intel_output->enc; | ||
774 | int crtc_mask = 0, clone_mask = 0; | ||
775 | |||
776 | /* valid crtcs */ | ||
777 | switch (psb_intel_output->type) { | ||
778 | case INTEL_OUTPUT_ANALOG: | ||
779 | crtc_mask = (1 << 0); | ||
780 | clone_mask = (1 << INTEL_OUTPUT_ANALOG); | ||
781 | break; | ||
782 | case INTEL_OUTPUT_SDVO: | ||
783 | crtc_mask = ((1 << 0) | (1 << 1)); | ||
784 | clone_mask = (1 << INTEL_OUTPUT_SDVO); | ||
785 | break; | ||
786 | case INTEL_OUTPUT_LVDS: | ||
787 | if (IS_MRST(dev)) | ||
788 | crtc_mask = (1 << 0); | ||
789 | else | ||
790 | crtc_mask = (1 << 1); | ||
791 | clone_mask = (1 << INTEL_OUTPUT_LVDS); | ||
792 | break; | ||
793 | case INTEL_OUTPUT_MIPI: | ||
794 | crtc_mask = (1 << 0); | ||
795 | clone_mask = (1 << INTEL_OUTPUT_MIPI); | ||
796 | break; | ||
797 | case INTEL_OUTPUT_MIPI2: | ||
798 | crtc_mask = (1 << 2); | ||
799 | clone_mask = (1 << INTEL_OUTPUT_MIPI2); | ||
800 | break; | ||
801 | case INTEL_OUTPUT_HDMI: | ||
802 | /* HDMI on crtc 1 for SoC devices and crtc 0 for | ||
803 | Cedarview. HDMI on Poulsbo is only via external | ||
804 | logic */ | ||
805 | if (IS_MFLD(dev) || IS_MRST(dev)) | ||
806 | crtc_mask = (1 << 1); | ||
807 | else | ||
808 | crtc_mask = (1 << 0); /* Cedarview */ | ||
809 | clone_mask = (1 << INTEL_OUTPUT_HDMI); | ||
810 | break; | ||
811 | } | ||
812 | encoder->possible_crtcs = crtc_mask; | ||
813 | encoder->possible_clones = | ||
814 | psb_intel_connector_clones(dev, clone_mask); | ||
815 | } | ||
816 | } | ||
817 | |||
818 | void psb_modeset_init(struct drm_device *dev) | ||
819 | { | ||
820 | struct drm_psb_private *dev_priv = | ||
821 | (struct drm_psb_private *) dev->dev_private; | ||
822 | struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev; | ||
823 | int i; | ||
824 | |||
825 | drm_mode_config_init(dev); | ||
826 | |||
827 | dev->mode_config.min_width = 0; | ||
828 | dev->mode_config.min_height = 0; | ||
829 | |||
830 | dev->mode_config.funcs = (void *) &psb_mode_funcs; | ||
831 | |||
832 | /* set memory base */ | ||
833 | /* MRST and PSB should use BAR 2*/ | ||
834 | pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *) | ||
835 | &(dev->mode_config.fb_base)); | ||
836 | |||
837 | /* num pipes is 2 for PSB but 1 for Mrst */ | ||
838 | for (i = 0; i < dev_priv->num_pipe; i++) | ||
839 | psb_intel_crtc_init(dev, i, mode_dev); | ||
840 | |||
841 | dev->mode_config.max_width = 2048; | ||
842 | dev->mode_config.max_height = 2048; | ||
843 | |||
844 | psb_setup_outputs(dev); | ||
845 | } | ||
846 | |||
847 | void psb_modeset_cleanup(struct drm_device *dev) | ||
848 | { | ||
849 | mutex_lock(&dev->struct_mutex); | ||
850 | |||
851 | drm_kms_helper_poll_fini(dev); | ||
852 | psb_fbdev_fini(dev); | ||
853 | drm_mode_config_cleanup(dev); | ||
854 | |||
855 | mutex_unlock(&dev->struct_mutex); | ||
856 | } | ||
diff --git a/drivers/staging/gma500/framebuffer.h b/drivers/staging/gma500/framebuffer.h deleted file mode 100644 index d1b2289447f0..000000000000 --- a/drivers/staging/gma500/framebuffer.h +++ /dev/null | |||
@@ -1,48 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008-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 | |||
22 | #ifndef _FRAMEBUFFER_H_ | ||
23 | #define _FRAMEBUFFER_H_ | ||
24 | |||
25 | #include <drm/drmP.h> | ||
26 | #include <drm/drm_fb_helper.h> | ||
27 | |||
28 | #include "psb_drv.h" | ||
29 | |||
30 | struct psb_framebuffer { | ||
31 | struct drm_framebuffer base; | ||
32 | struct address_space *addr_space; | ||
33 | struct fb_info *fbdev; | ||
34 | struct gtt_range *gtt; | ||
35 | bool vm_map; /* True if we must undo a vm_map_ram */ | ||
36 | }; | ||
37 | |||
38 | struct psb_fbdev { | ||
39 | struct drm_fb_helper psb_fb_helper; | ||
40 | struct psb_framebuffer pfb; | ||
41 | }; | ||
42 | |||
43 | #define to_psb_fb(x) container_of(x, struct psb_framebuffer, base) | ||
44 | |||
45 | extern int psb_intel_connector_clones(struct drm_device *dev, int type_mask); | ||
46 | |||
47 | #endif | ||
48 | |||
diff --git a/drivers/staging/gma500/gem.c b/drivers/staging/gma500/gem.c deleted file mode 100644 index f6433c037d24..000000000000 --- a/drivers/staging/gma500/gem.c +++ /dev/null | |||
@@ -1,292 +0,0 @@ | |||
1 | /* | ||
2 | * psb GEM interface | ||
3 | * | ||
4 | * Copyright (c) 2011, Intel Corporation. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * | ||
19 | * Authors: Alan Cox | ||
20 | * | ||
21 | * TODO: | ||
22 | * - we need to work out if the MMU is relevant (eg for | ||
23 | * accelerated operations on a GEM object) | ||
24 | */ | ||
25 | |||
26 | #include <drm/drmP.h> | ||
27 | #include <drm/drm.h> | ||
28 | #include "psb_drm.h" | ||
29 | #include "psb_drv.h" | ||
30 | |||
31 | int psb_gem_init_object(struct drm_gem_object *obj) | ||
32 | { | ||
33 | return -EINVAL; | ||
34 | } | ||
35 | |||
36 | void psb_gem_free_object(struct drm_gem_object *obj) | ||
37 | { | ||
38 | struct gtt_range *gtt = container_of(obj, struct gtt_range, gem); | ||
39 | drm_gem_object_release_wrap(obj); | ||
40 | /* This must occur last as it frees up the memory of the GEM object */ | ||
41 | psb_gtt_free_range(obj->dev, gtt); | ||
42 | } | ||
43 | |||
44 | int psb_gem_get_aperture(struct drm_device *dev, void *data, | ||
45 | struct drm_file *file) | ||
46 | { | ||
47 | return -EINVAL; | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * psb_gem_dumb_map_gtt - buffer mapping for dumb interface | ||
52 | * @file: our drm client file | ||
53 | * @dev: drm device | ||
54 | * @handle: GEM handle to the object (from dumb_create) | ||
55 | * | ||
56 | * Do the necessary setup to allow the mapping of the frame buffer | ||
57 | * into user memory. We don't have to do much here at the moment. | ||
58 | */ | ||
59 | int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, | ||
60 | uint32_t handle, uint64_t *offset) | ||
61 | { | ||
62 | int ret = 0; | ||
63 | struct drm_gem_object *obj; | ||
64 | |||
65 | if (!(dev->driver->driver_features & DRIVER_GEM)) | ||
66 | return -ENODEV; | ||
67 | |||
68 | mutex_lock(&dev->struct_mutex); | ||
69 | |||
70 | /* GEM does all our handle to object mapping */ | ||
71 | obj = drm_gem_object_lookup(dev, file, handle); | ||
72 | if (obj == NULL) { | ||
73 | ret = -ENOENT; | ||
74 | goto unlock; | ||
75 | } | ||
76 | /* What validation is needed here ? */ | ||
77 | |||
78 | /* Make it mmapable */ | ||
79 | if (!obj->map_list.map) { | ||
80 | ret = gem_create_mmap_offset(obj); | ||
81 | if (ret) | ||
82 | goto out; | ||
83 | } | ||
84 | /* GEM should really work out the hash offsets for us */ | ||
85 | *offset = (u64)obj->map_list.hash.key << PAGE_SHIFT; | ||
86 | out: | ||
87 | drm_gem_object_unreference(obj); | ||
88 | unlock: | ||
89 | mutex_unlock(&dev->struct_mutex); | ||
90 | return ret; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * psb_gem_create - create a mappable object | ||
95 | * @file: the DRM file of the client | ||
96 | * @dev: our device | ||
97 | * @size: the size requested | ||
98 | * @handlep: returned handle (opaque number) | ||
99 | * | ||
100 | * Create a GEM object, fill in the boilerplate and attach a handle to | ||
101 | * it so that userspace can speak about it. This does the core work | ||
102 | * for the various methods that do/will create GEM objects for things | ||
103 | */ | ||
104 | static int psb_gem_create(struct drm_file *file, | ||
105 | struct drm_device *dev, uint64_t size, uint32_t *handlep) | ||
106 | { | ||
107 | struct gtt_range *r; | ||
108 | int ret; | ||
109 | u32 handle; | ||
110 | |||
111 | size = roundup(size, PAGE_SIZE); | ||
112 | |||
113 | /* Allocate our object - for now a direct gtt range which is not | ||
114 | stolen memory backed */ | ||
115 | r = psb_gtt_alloc_range(dev, size, "gem", 0); | ||
116 | if (r == NULL) { | ||
117 | dev_err(dev->dev, "no memory for %lld byte GEM object\n", size); | ||
118 | return -ENOSPC; | ||
119 | } | ||
120 | /* Initialize the extra goodies GEM needs to do all the hard work */ | ||
121 | if (drm_gem_object_init(dev, &r->gem, size) != 0) { | ||
122 | psb_gtt_free_range(dev, r); | ||
123 | /* GEM doesn't give an error code so use -ENOMEM */ | ||
124 | dev_err(dev->dev, "GEM init failed for %lld\n", size); | ||
125 | return -ENOMEM; | ||
126 | } | ||
127 | /* Give the object a handle so we can carry it more easily */ | ||
128 | ret = drm_gem_handle_create(file, &r->gem, &handle); | ||
129 | if (ret) { | ||
130 | dev_err(dev->dev, "GEM handle failed for %p, %lld\n", | ||
131 | &r->gem, size); | ||
132 | drm_gem_object_release(&r->gem); | ||
133 | psb_gtt_free_range(dev, r); | ||
134 | return ret; | ||
135 | } | ||
136 | /* We have the initial and handle reference but need only one now */ | ||
137 | drm_gem_object_unreference(&r->gem); | ||
138 | *handlep = handle; | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | /** | ||
143 | * psb_gem_dumb_create - create a dumb buffer | ||
144 | * @drm_file: our client file | ||
145 | * @dev: our device | ||
146 | * @args: the requested arguments copied from userspace | ||
147 | * | ||
148 | * Allocate a buffer suitable for use for a frame buffer of the | ||
149 | * form described by user space. Give userspace a handle by which | ||
150 | * to reference it. | ||
151 | */ | ||
152 | int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, | ||
153 | struct drm_mode_create_dumb *args) | ||
154 | { | ||
155 | args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64); | ||
156 | args->size = args->pitch * args->height; | ||
157 | return psb_gem_create(file, dev, args->size, &args->handle); | ||
158 | } | ||
159 | |||
160 | /** | ||
161 | * psb_gem_dumb_destroy - destroy a dumb buffer | ||
162 | * @file: client file | ||
163 | * @dev: our DRM device | ||
164 | * @handle: the object handle | ||
165 | * | ||
166 | * Destroy a handle that was created via psb_gem_dumb_create, at least | ||
167 | * we hope it was created that way. i915 seems to assume the caller | ||
168 | * does the checking but that might be worth review ! FIXME | ||
169 | */ | ||
170 | int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, | ||
171 | uint32_t handle) | ||
172 | { | ||
173 | /* No special work needed, drop the reference and see what falls out */ | ||
174 | return drm_gem_handle_delete(file, handle); | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * psb_gem_fault - pagefault handler for GEM objects | ||
179 | * @vma: the VMA of the GEM object | ||
180 | * @vmf: fault detail | ||
181 | * | ||
182 | * Invoked when a fault occurs on an mmap of a GEM managed area. GEM | ||
183 | * does most of the work for us including the actual map/unmap calls | ||
184 | * but we need to do the actual page work. | ||
185 | * | ||
186 | * This code eventually needs to handle faulting objects in and out | ||
187 | * of the GTT and repacking it when we run out of space. We can put | ||
188 | * that off for now and for our simple uses | ||
189 | * | ||
190 | * The VMA was set up by GEM. In doing so it also ensured that the | ||
191 | * vma->vm_private_data points to the GEM object that is backing this | ||
192 | * mapping. | ||
193 | */ | ||
194 | int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf) | ||
195 | { | ||
196 | struct drm_gem_object *obj; | ||
197 | struct gtt_range *r; | ||
198 | int ret; | ||
199 | unsigned long pfn; | ||
200 | pgoff_t page_offset; | ||
201 | struct drm_device *dev; | ||
202 | struct drm_psb_private *dev_priv; | ||
203 | |||
204 | obj = vma->vm_private_data; /* GEM object */ | ||
205 | dev = obj->dev; | ||
206 | dev_priv = dev->dev_private; | ||
207 | |||
208 | r = container_of(obj, struct gtt_range, gem); /* Get the gtt range */ | ||
209 | |||
210 | /* Make sure we don't parallel update on a fault, nor move or remove | ||
211 | something from beneath our feet */ | ||
212 | mutex_lock(&dev->struct_mutex); | ||
213 | |||
214 | /* For now the mmap pins the object and it stays pinned. As things | ||
215 | stand that will do us no harm */ | ||
216 | if (r->mmapping == 0) { | ||
217 | ret = psb_gtt_pin(r); | ||
218 | if (ret < 0) { | ||
219 | dev_err(dev->dev, "gma500: pin failed: %d\n", ret); | ||
220 | goto fail; | ||
221 | } | ||
222 | r->mmapping = 1; | ||
223 | } | ||
224 | |||
225 | /* Page relative to the VMA start - we must calculate this ourselves | ||
226 | because vmf->pgoff is the fake GEM offset */ | ||
227 | page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start) | ||
228 | >> PAGE_SHIFT; | ||
229 | |||
230 | /* CPU view of the page, don't go via the GART for CPU writes */ | ||
231 | if (r->stolen) | ||
232 | pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT; | ||
233 | else | ||
234 | pfn = page_to_pfn(r->pages[page_offset]); | ||
235 | ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn); | ||
236 | |||
237 | fail: | ||
238 | mutex_unlock(&dev->struct_mutex); | ||
239 | switch (ret) { | ||
240 | case 0: | ||
241 | case -ERESTARTSYS: | ||
242 | case -EINTR: | ||
243 | return VM_FAULT_NOPAGE; | ||
244 | case -ENOMEM: | ||
245 | return VM_FAULT_OOM; | ||
246 | default: | ||
247 | return VM_FAULT_SIGBUS; | ||
248 | } | ||
249 | } | ||
250 | |||
251 | static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev, | ||
252 | int size, u32 *handle) | ||
253 | { | ||
254 | struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1); | ||
255 | if (gtt == NULL) | ||
256 | return -ENOMEM; | ||
257 | if (drm_gem_private_object_init(dev, >t->gem, size) != 0) | ||
258 | goto free_gtt; | ||
259 | if (drm_gem_handle_create(file, >t->gem, handle) == 0) | ||
260 | return 0; | ||
261 | free_gtt: | ||
262 | psb_gtt_free_range(dev, gtt); | ||
263 | return -ENOMEM; | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * GEM interfaces for our specific client | ||
268 | */ | ||
269 | int psb_gem_create_ioctl(struct drm_device *dev, void *data, | ||
270 | struct drm_file *file) | ||
271 | { | ||
272 | struct drm_psb_gem_create *args = data; | ||
273 | int ret; | ||
274 | if (args->flags & PSB_GEM_CREATE_STOLEN) { | ||
275 | ret = psb_gem_create_stolen(file, dev, args->size, | ||
276 | &args->handle); | ||
277 | if (ret == 0) | ||
278 | return 0; | ||
279 | /* Fall throguh */ | ||
280 | args->flags &= ~PSB_GEM_CREATE_STOLEN; | ||
281 | } | ||
282 | return psb_gem_create(file, dev, args->size, &args->handle); | ||
283 | } | ||
284 | |||
285 | int psb_gem_mmap_ioctl(struct drm_device *dev, void *data, | ||
286 | struct drm_file *file) | ||
287 | { | ||
288 | struct drm_psb_gem_mmap *args = data; | ||
289 | return dev->driver->dumb_map_offset(file, dev, | ||
290 | args->handle, &args->offset); | ||
291 | } | ||
292 | |||
diff --git a/drivers/staging/gma500/gem_glue.c b/drivers/staging/gma500/gem_glue.c deleted file mode 100644 index daac12120653..000000000000 --- a/drivers/staging/gma500/gem_glue.c +++ /dev/null | |||
@@ -1,89 +0,0 @@ | |||
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 <drm/drmP.h> | ||
21 | #include <drm/drm.h> | ||
22 | |||
23 | void drm_gem_object_release_wrap(struct drm_gem_object *obj) | ||
24 | { | ||
25 | /* Remove the list map if one is present */ | ||
26 | if (obj->map_list.map) { | ||
27 | struct drm_gem_mm *mm = obj->dev->mm_private; | ||
28 | struct drm_map_list *list = &obj->map_list; | ||
29 | drm_ht_remove_item(&mm->offset_hash, &list->hash); | ||
30 | drm_mm_put_block(list->file_offset_node); | ||
31 | kfree(list->map); | ||
32 | list->map = NULL; | ||
33 | } | ||
34 | drm_gem_object_release(obj); | ||
35 | } | ||
36 | |||
37 | /** | ||
38 | * gem_create_mmap_offset - invent an mmap offset | ||
39 | * @obj: our object | ||
40 | * | ||
41 | * Standard implementation of offset generation for mmap as is | ||
42 | * duplicated in several drivers. This belongs in GEM. | ||
43 | */ | ||
44 | int gem_create_mmap_offset(struct drm_gem_object *obj) | ||
45 | { | ||
46 | struct drm_device *dev = obj->dev; | ||
47 | struct drm_gem_mm *mm = dev->mm_private; | ||
48 | struct drm_map_list *list; | ||
49 | struct drm_local_map *map; | ||
50 | int ret; | ||
51 | |||
52 | list = &obj->map_list; | ||
53 | list->map = kzalloc(sizeof(struct drm_map_list), GFP_KERNEL); | ||
54 | if (list->map == NULL) | ||
55 | return -ENOMEM; | ||
56 | map = list->map; | ||
57 | map->type = _DRM_GEM; | ||
58 | map->size = obj->size; | ||
59 | map->handle = obj; | ||
60 | |||
61 | list->file_offset_node = drm_mm_search_free(&mm->offset_manager, | ||
62 | obj->size / PAGE_SIZE, 0, 0); | ||
63 | if (!list->file_offset_node) { | ||
64 | dev_err(dev->dev, "failed to allocate offset for bo %d\n", | ||
65 | obj->name); | ||
66 | ret = -ENOSPC; | ||
67 | goto free_it; | ||
68 | } | ||
69 | list->file_offset_node = drm_mm_get_block(list->file_offset_node, | ||
70 | obj->size / PAGE_SIZE, 0); | ||
71 | if (!list->file_offset_node) { | ||
72 | ret = -ENOMEM; | ||
73 | goto free_it; | ||
74 | } | ||
75 | list->hash.key = list->file_offset_node->start; | ||
76 | ret = drm_ht_insert_item(&mm->offset_hash, &list->hash); | ||
77 | if (ret) { | ||
78 | dev_err(dev->dev, "failed to add to map hash\n"); | ||
79 | goto free_mm; | ||
80 | } | ||
81 | return 0; | ||
82 | |||
83 | free_mm: | ||
84 | drm_mm_put_block(list->file_offset_node); | ||
85 | free_it: | ||
86 | kfree(list->map); | ||
87 | list->map = NULL; | ||
88 | return ret; | ||
89 | } | ||
diff --git a/drivers/staging/gma500/gem_glue.h b/drivers/staging/gma500/gem_glue.h deleted file mode 100644 index ce5ce30f74db..000000000000 --- a/drivers/staging/gma500/gem_glue.h +++ /dev/null | |||
@@ -1,2 +0,0 @@ | |||
1 | extern void drm_gem_object_release_wrap(struct drm_gem_object *obj); | ||
2 | extern int gem_create_mmap_offset(struct drm_gem_object *obj); | ||
diff --git a/drivers/staging/gma500/gtt.c b/drivers/staging/gma500/gtt.c deleted file mode 100644 index e770bd190a5c..000000000000 --- a/drivers/staging/gma500/gtt.c +++ /dev/null | |||
@@ -1,553 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007, 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 | * Authors: Thomas Hellstrom <thomas-at-tungstengraphics.com> | ||
19 | * Alan Cox <alan@linux.intel.com> | ||
20 | */ | ||
21 | |||
22 | #include <drm/drmP.h> | ||
23 | #include "psb_drv.h" | ||
24 | |||
25 | |||
26 | /* | ||
27 | * GTT resource allocator - manage page mappings in GTT space | ||
28 | */ | ||
29 | |||
30 | /** | ||
31 | * psb_gtt_mask_pte - generate GTT pte entry | ||
32 | * @pfn: page number to encode | ||
33 | * @type: type of memory in the GTT | ||
34 | * | ||
35 | * Set the GTT entry for the appropriate memory type. | ||
36 | */ | ||
37 | static inline uint32_t psb_gtt_mask_pte(uint32_t pfn, int type) | ||
38 | { | ||
39 | uint32_t mask = PSB_PTE_VALID; | ||
40 | |||
41 | if (type & PSB_MMU_CACHED_MEMORY) | ||
42 | mask |= PSB_PTE_CACHED; | ||
43 | if (type & PSB_MMU_RO_MEMORY) | ||
44 | mask |= PSB_PTE_RO; | ||
45 | if (type & PSB_MMU_WO_MEMORY) | ||
46 | mask |= PSB_PTE_WO; | ||
47 | |||
48 | return (pfn << PAGE_SHIFT) | mask; | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * psb_gtt_entry - find the GTT entries for a gtt_range | ||
53 | * @dev: our DRM device | ||
54 | * @r: our GTT range | ||
55 | * | ||
56 | * Given a gtt_range object return the GTT offset of the page table | ||
57 | * entries for this gtt_range | ||
58 | */ | ||
59 | u32 *psb_gtt_entry(struct drm_device *dev, struct gtt_range *r) | ||
60 | { | ||
61 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
62 | unsigned long offset; | ||
63 | |||
64 | offset = r->resource.start - dev_priv->gtt_mem->start; | ||
65 | |||
66 | return dev_priv->gtt_map + (offset >> PAGE_SHIFT); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * psb_gtt_insert - put an object into the GTT | ||
71 | * @dev: our DRM device | ||
72 | * @r: our GTT range | ||
73 | * | ||
74 | * Take our preallocated GTT range and insert the GEM object into | ||
75 | * the GTT. This is protected via the gtt mutex which the caller | ||
76 | * must hold. | ||
77 | */ | ||
78 | static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r) | ||
79 | { | ||
80 | u32 *gtt_slot, pte; | ||
81 | struct page **pages; | ||
82 | int i; | ||
83 | |||
84 | if (r->pages == NULL) { | ||
85 | WARN_ON(1); | ||
86 | return -EINVAL; | ||
87 | } | ||
88 | |||
89 | WARN_ON(r->stolen); /* refcount these maybe ? */ | ||
90 | |||
91 | gtt_slot = psb_gtt_entry(dev, r); | ||
92 | pages = r->pages; | ||
93 | |||
94 | /* Make sure changes are visible to the GPU */ | ||
95 | set_pages_array_uc(pages, r->npage); | ||
96 | |||
97 | /* Write our page entries into the GTT itself */ | ||
98 | for (i = r->roll; i < r->npage; i++) { | ||
99 | pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); | ||
100 | iowrite32(pte, gtt_slot++); | ||
101 | } | ||
102 | for (i = 0; i < r->roll; i++) { | ||
103 | pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); | ||
104 | iowrite32(pte, gtt_slot++); | ||
105 | } | ||
106 | /* Make sure all the entries are set before we return */ | ||
107 | ioread32(gtt_slot - 1); | ||
108 | |||
109 | return 0; | ||
110 | } | ||
111 | |||
112 | /** | ||
113 | * psb_gtt_remove - remove an object from the GTT | ||
114 | * @dev: our DRM device | ||
115 | * @r: our GTT range | ||
116 | * | ||
117 | * Remove a preallocated GTT range from the GTT. Overwrite all the | ||
118 | * page table entries with the dummy page. This is protected via the gtt | ||
119 | * mutex which the caller must hold. | ||
120 | */ | ||
121 | static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r) | ||
122 | { | ||
123 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
124 | u32 *gtt_slot, pte; | ||
125 | int i; | ||
126 | |||
127 | WARN_ON(r->stolen); | ||
128 | |||
129 | gtt_slot = psb_gtt_entry(dev, r); | ||
130 | pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0); | ||
131 | |||
132 | for (i = 0; i < r->npage; i++) | ||
133 | iowrite32(pte, gtt_slot++); | ||
134 | ioread32(gtt_slot - 1); | ||
135 | set_pages_array_wb(r->pages, r->npage); | ||
136 | } | ||
137 | |||
138 | /** | ||
139 | * psb_gtt_roll - set scrolling position | ||
140 | * @dev: our DRM device | ||
141 | * @r: the gtt mapping we are using | ||
142 | * @roll: roll offset | ||
143 | * | ||
144 | * Roll an existing pinned mapping by moving the pages through the GTT. | ||
145 | * This allows us to implement hardware scrolling on the consoles without | ||
146 | * a 2D engine | ||
147 | */ | ||
148 | void psb_gtt_roll(struct drm_device *dev, struct gtt_range *r, int roll) | ||
149 | { | ||
150 | u32 *gtt_slot, pte; | ||
151 | int i; | ||
152 | |||
153 | if (roll >= r->npage) { | ||
154 | WARN_ON(1); | ||
155 | return; | ||
156 | } | ||
157 | |||
158 | r->roll = roll; | ||
159 | |||
160 | /* Not currently in the GTT - no worry we will write the mapping at | ||
161 | the right position when it gets pinned */ | ||
162 | if (!r->stolen && !r->in_gart) | ||
163 | return; | ||
164 | |||
165 | gtt_slot = psb_gtt_entry(dev, r); | ||
166 | |||
167 | for (i = r->roll; i < r->npage; i++) { | ||
168 | pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); | ||
169 | iowrite32(pte, gtt_slot++); | ||
170 | } | ||
171 | for (i = 0; i < r->roll; i++) { | ||
172 | pte = psb_gtt_mask_pte(page_to_pfn(r->pages[i]), 0); | ||
173 | iowrite32(pte, gtt_slot++); | ||
174 | } | ||
175 | ioread32(gtt_slot - 1); | ||
176 | } | ||
177 | |||
178 | /** | ||
179 | * psb_gtt_attach_pages - attach and pin GEM pages | ||
180 | * @gt: the gtt range | ||
181 | * | ||
182 | * Pin and build an in kernel list of the pages that back our GEM object. | ||
183 | * While we hold this the pages cannot be swapped out. This is protected | ||
184 | * via the gtt mutex which the caller must hold. | ||
185 | */ | ||
186 | static int psb_gtt_attach_pages(struct gtt_range *gt) | ||
187 | { | ||
188 | struct inode *inode; | ||
189 | struct address_space *mapping; | ||
190 | int i; | ||
191 | struct page *p; | ||
192 | int pages = gt->gem.size / PAGE_SIZE; | ||
193 | |||
194 | WARN_ON(gt->pages); | ||
195 | |||
196 | /* This is the shared memory object that backs the GEM resource */ | ||
197 | inode = gt->gem.filp->f_path.dentry->d_inode; | ||
198 | mapping = inode->i_mapping; | ||
199 | |||
200 | gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL); | ||
201 | if (gt->pages == NULL) | ||
202 | return -ENOMEM; | ||
203 | gt->npage = pages; | ||
204 | |||
205 | for (i = 0; i < pages; i++) { | ||
206 | /* FIXME: needs updating as per mail from Hugh Dickins */ | ||
207 | p = read_cache_page_gfp(mapping, i, | ||
208 | __GFP_COLD | GFP_KERNEL); | ||
209 | if (IS_ERR(p)) | ||
210 | goto err; | ||
211 | gt->pages[i] = p; | ||
212 | } | ||
213 | return 0; | ||
214 | |||
215 | err: | ||
216 | while (i--) | ||
217 | page_cache_release(gt->pages[i]); | ||
218 | kfree(gt->pages); | ||
219 | gt->pages = NULL; | ||
220 | return PTR_ERR(p); | ||
221 | } | ||
222 | |||
223 | /** | ||
224 | * psb_gtt_detach_pages - attach and pin GEM pages | ||
225 | * @gt: the gtt range | ||
226 | * | ||
227 | * Undo the effect of psb_gtt_attach_pages. At this point the pages | ||
228 | * must have been removed from the GTT as they could now be paged out | ||
229 | * and move bus address. This is protected via the gtt mutex which the | ||
230 | * caller must hold. | ||
231 | */ | ||
232 | static void psb_gtt_detach_pages(struct gtt_range *gt) | ||
233 | { | ||
234 | int i; | ||
235 | for (i = 0; i < gt->npage; i++) { | ||
236 | /* FIXME: do we need to force dirty */ | ||
237 | set_page_dirty(gt->pages[i]); | ||
238 | page_cache_release(gt->pages[i]); | ||
239 | } | ||
240 | kfree(gt->pages); | ||
241 | gt->pages = NULL; | ||
242 | } | ||
243 | |||
244 | /** | ||
245 | * psb_gtt_pin - pin pages into the GTT | ||
246 | * @gt: range to pin | ||
247 | * | ||
248 | * Pin a set of pages into the GTT. The pins are refcounted so that | ||
249 | * multiple pins need multiple unpins to undo. | ||
250 | * | ||
251 | * Non GEM backed objects treat this as a no-op as they are always GTT | ||
252 | * backed objects. | ||
253 | */ | ||
254 | int psb_gtt_pin(struct gtt_range *gt) | ||
255 | { | ||
256 | int ret = 0; | ||
257 | struct drm_device *dev = gt->gem.dev; | ||
258 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
259 | |||
260 | mutex_lock(&dev_priv->gtt_mutex); | ||
261 | |||
262 | if (gt->in_gart == 0 && gt->stolen == 0) { | ||
263 | ret = psb_gtt_attach_pages(gt); | ||
264 | if (ret < 0) | ||
265 | goto out; | ||
266 | ret = psb_gtt_insert(dev, gt); | ||
267 | if (ret < 0) { | ||
268 | psb_gtt_detach_pages(gt); | ||
269 | goto out; | ||
270 | } | ||
271 | } | ||
272 | gt->in_gart++; | ||
273 | out: | ||
274 | mutex_unlock(&dev_priv->gtt_mutex); | ||
275 | return ret; | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * psb_gtt_unpin - Drop a GTT pin requirement | ||
280 | * @gt: range to pin | ||
281 | * | ||
282 | * Undoes the effect of psb_gtt_pin. On the last drop the GEM object | ||
283 | * will be removed from the GTT which will also drop the page references | ||
284 | * and allow the VM to clean up or page stuff. | ||
285 | * | ||
286 | * Non GEM backed objects treat this as a no-op as they are always GTT | ||
287 | * backed objects. | ||
288 | */ | ||
289 | void psb_gtt_unpin(struct gtt_range *gt) | ||
290 | { | ||
291 | struct drm_device *dev = gt->gem.dev; | ||
292 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
293 | |||
294 | mutex_lock(&dev_priv->gtt_mutex); | ||
295 | |||
296 | WARN_ON(!gt->in_gart); | ||
297 | |||
298 | gt->in_gart--; | ||
299 | if (gt->in_gart == 0 && gt->stolen == 0) { | ||
300 | psb_gtt_remove(dev, gt); | ||
301 | psb_gtt_detach_pages(gt); | ||
302 | } | ||
303 | mutex_unlock(&dev_priv->gtt_mutex); | ||
304 | } | ||
305 | |||
306 | /* | ||
307 | * GTT resource allocator - allocate and manage GTT address space | ||
308 | */ | ||
309 | |||
310 | /** | ||
311 | * psb_gtt_alloc_range - allocate GTT address space | ||
312 | * @dev: Our DRM device | ||
313 | * @len: length (bytes) of address space required | ||
314 | * @name: resource name | ||
315 | * @backed: resource should be backed by stolen pages | ||
316 | * | ||
317 | * Ask the kernel core to find us a suitable range of addresses | ||
318 | * to use for a GTT mapping. | ||
319 | * | ||
320 | * Returns a gtt_range structure describing the object, or NULL on | ||
321 | * error. On successful return the resource is both allocated and marked | ||
322 | * as in use. | ||
323 | */ | ||
324 | struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, | ||
325 | const char *name, int backed) | ||
326 | { | ||
327 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
328 | struct gtt_range *gt; | ||
329 | struct resource *r = dev_priv->gtt_mem; | ||
330 | int ret; | ||
331 | unsigned long start, end; | ||
332 | |||
333 | if (backed) { | ||
334 | /* The start of the GTT is the stolen pages */ | ||
335 | start = r->start; | ||
336 | end = r->start + dev_priv->gtt.stolen_size - 1; | ||
337 | } else { | ||
338 | /* The rest we will use for GEM backed objects */ | ||
339 | start = r->start + dev_priv->gtt.stolen_size; | ||
340 | end = r->end; | ||
341 | } | ||
342 | |||
343 | gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL); | ||
344 | if (gt == NULL) | ||
345 | return NULL; | ||
346 | gt->resource.name = name; | ||
347 | gt->stolen = backed; | ||
348 | gt->in_gart = backed; | ||
349 | gt->roll = 0; | ||
350 | /* Ensure this is set for non GEM objects */ | ||
351 | gt->gem.dev = dev; | ||
352 | ret = allocate_resource(dev_priv->gtt_mem, >->resource, | ||
353 | len, start, end, PAGE_SIZE, NULL, NULL); | ||
354 | if (ret == 0) { | ||
355 | gt->offset = gt->resource.start - r->start; | ||
356 | return gt; | ||
357 | } | ||
358 | kfree(gt); | ||
359 | return NULL; | ||
360 | } | ||
361 | |||
362 | /** | ||
363 | * psb_gtt_free_range - release GTT address space | ||
364 | * @dev: our DRM device | ||
365 | * @gt: a mapping created with psb_gtt_alloc_range | ||
366 | * | ||
367 | * Release a resource that was allocated with psb_gtt_alloc_range. If the | ||
368 | * object has been pinned by mmap users we clean this up here currently. | ||
369 | */ | ||
370 | void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt) | ||
371 | { | ||
372 | /* Undo the mmap pin if we are destroying the object */ | ||
373 | if (gt->mmapping) { | ||
374 | psb_gtt_unpin(gt); | ||
375 | gt->mmapping = 0; | ||
376 | } | ||
377 | WARN_ON(gt->in_gart && !gt->stolen); | ||
378 | release_resource(>->resource); | ||
379 | kfree(gt); | ||
380 | } | ||
381 | |||
382 | void psb_gtt_alloc(struct drm_device *dev) | ||
383 | { | ||
384 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
385 | init_rwsem(&dev_priv->gtt.sem); | ||
386 | } | ||
387 | |||
388 | void psb_gtt_takedown(struct drm_device *dev) | ||
389 | { | ||
390 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
391 | |||
392 | if (dev_priv->gtt_map) { | ||
393 | iounmap(dev_priv->gtt_map); | ||
394 | dev_priv->gtt_map = NULL; | ||
395 | } | ||
396 | if (dev_priv->gtt_initialized) { | ||
397 | pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, | ||
398 | dev_priv->gmch_ctrl); | ||
399 | PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL); | ||
400 | (void) PSB_RVDC32(PSB_PGETBL_CTL); | ||
401 | } | ||
402 | if (dev_priv->vram_addr) | ||
403 | iounmap(dev_priv->gtt_map); | ||
404 | } | ||
405 | |||
406 | int psb_gtt_init(struct drm_device *dev, int resume) | ||
407 | { | ||
408 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
409 | unsigned gtt_pages; | ||
410 | unsigned long stolen_size, vram_stolen_size; | ||
411 | unsigned i, num_pages; | ||
412 | unsigned pfn_base; | ||
413 | uint32_t vram_pages; | ||
414 | uint32_t dvmt_mode = 0; | ||
415 | struct psb_gtt *pg; | ||
416 | |||
417 | int ret = 0; | ||
418 | uint32_t pte; | ||
419 | |||
420 | mutex_init(&dev_priv->gtt_mutex); | ||
421 | |||
422 | psb_gtt_alloc(dev); | ||
423 | pg = &dev_priv->gtt; | ||
424 | |||
425 | /* Enable the GTT */ | ||
426 | pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl); | ||
427 | pci_write_config_word(dev->pdev, PSB_GMCH_CTRL, | ||
428 | dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); | ||
429 | |||
430 | dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL); | ||
431 | PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); | ||
432 | (void) PSB_RVDC32(PSB_PGETBL_CTL); | ||
433 | |||
434 | /* The root resource we allocate address space from */ | ||
435 | dev_priv->gtt_initialized = 1; | ||
436 | |||
437 | pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK; | ||
438 | |||
439 | /* | ||
440 | * The video mmu has a hw bug when accessing 0x0D0000000. | ||
441 | * Make gatt start at 0x0e000,0000. This doesn't actually | ||
442 | * matter for us but may do if the video acceleration ever | ||
443 | * gets opened up. | ||
444 | */ | ||
445 | pg->mmu_gatt_start = 0xE0000000; | ||
446 | |||
447 | pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE); | ||
448 | gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE) | ||
449 | >> PAGE_SHIFT; | ||
450 | /* Some CDV firmware doesn't report this currently. In which case the | ||
451 | system has 64 gtt pages */ | ||
452 | if (pg->gtt_start == 0 || gtt_pages == 0) { | ||
453 | dev_err(dev->dev, "GTT PCI BAR not initialized.\n"); | ||
454 | gtt_pages = 64; | ||
455 | pg->gtt_start = dev_priv->pge_ctl; | ||
456 | } | ||
457 | |||
458 | pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE); | ||
459 | pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE) | ||
460 | >> PAGE_SHIFT; | ||
461 | dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE]; | ||
462 | |||
463 | if (pg->gatt_pages == 0 || pg->gatt_start == 0) { | ||
464 | static struct resource fudge; /* Preferably peppermint */ | ||
465 | /* This can occur on CDV SDV systems. Fudge it in this case. | ||
466 | We really don't care what imaginary space is being allocated | ||
467 | at this point */ | ||
468 | dev_err(dev->dev, "GATT PCI BAR not initialized.\n"); | ||
469 | pg->gatt_start = 0x40000000; | ||
470 | pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT; | ||
471 | /* This is a little confusing but in fact the GTT is providing | ||
472 | a view from the GPU into memory and not vice versa. As such | ||
473 | this is really allocating space that is not the same as the | ||
474 | CPU address space on CDV */ | ||
475 | fudge.start = 0x40000000; | ||
476 | fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1; | ||
477 | fudge.name = "fudge"; | ||
478 | fudge.flags = IORESOURCE_MEM; | ||
479 | dev_priv->gtt_mem = &fudge; | ||
480 | } | ||
481 | |||
482 | pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base); | ||
483 | vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base | ||
484 | - PAGE_SIZE; | ||
485 | |||
486 | stolen_size = vram_stolen_size; | ||
487 | |||
488 | printk(KERN_INFO "Stolen memory information\n"); | ||
489 | printk(KERN_INFO " base in RAM: 0x%x\n", dev_priv->stolen_base); | ||
490 | printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n", | ||
491 | vram_stolen_size/1024); | ||
492 | dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7; | ||
493 | printk(KERN_INFO " the correct size should be: %dM(dvmt mode=%d)\n", | ||
494 | (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode); | ||
495 | |||
496 | if (resume && (gtt_pages != pg->gtt_pages) && | ||
497 | (stolen_size != pg->stolen_size)) { | ||
498 | dev_err(dev->dev, "GTT resume error.\n"); | ||
499 | ret = -EINVAL; | ||
500 | goto out_err; | ||
501 | } | ||
502 | |||
503 | pg->gtt_pages = gtt_pages; | ||
504 | pg->stolen_size = stolen_size; | ||
505 | dev_priv->vram_stolen_size = vram_stolen_size; | ||
506 | |||
507 | /* | ||
508 | * Map the GTT and the stolen memory area | ||
509 | */ | ||
510 | dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start, | ||
511 | gtt_pages << PAGE_SHIFT); | ||
512 | if (!dev_priv->gtt_map) { | ||
513 | dev_err(dev->dev, "Failure to map gtt.\n"); | ||
514 | ret = -ENOMEM; | ||
515 | goto out_err; | ||
516 | } | ||
517 | |||
518 | dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size); | ||
519 | if (!dev_priv->vram_addr) { | ||
520 | dev_err(dev->dev, "Failure to map stolen base.\n"); | ||
521 | ret = -ENOMEM; | ||
522 | goto out_err; | ||
523 | } | ||
524 | |||
525 | /* | ||
526 | * Insert vram stolen pages into the GTT | ||
527 | */ | ||
528 | |||
529 | pfn_base = dev_priv->stolen_base >> PAGE_SHIFT; | ||
530 | vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT; | ||
531 | printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n", | ||
532 | num_pages, pfn_base << PAGE_SHIFT, 0); | ||
533 | for (i = 0; i < num_pages; ++i) { | ||
534 | pte = psb_gtt_mask_pte(pfn_base + i, 0); | ||
535 | iowrite32(pte, dev_priv->gtt_map + i); | ||
536 | } | ||
537 | |||
538 | /* | ||
539 | * Init rest of GTT to the scratch page to avoid accidents or scribbles | ||
540 | */ | ||
541 | |||
542 | pfn_base = page_to_pfn(dev_priv->scratch_page); | ||
543 | pte = psb_gtt_mask_pte(pfn_base, 0); | ||
544 | for (; i < gtt_pages; ++i) | ||
545 | iowrite32(pte, dev_priv->gtt_map + i); | ||
546 | |||
547 | (void) ioread32(dev_priv->gtt_map + i - 1); | ||
548 | return 0; | ||
549 | |||
550 | out_err: | ||
551 | psb_gtt_takedown(dev); | ||
552 | return ret; | ||
553 | } | ||
diff --git a/drivers/staging/gma500/gtt.h b/drivers/staging/gma500/gtt.h deleted file mode 100644 index aa1742387f5a..000000000000 --- a/drivers/staging/gma500/gtt.h +++ /dev/null | |||
@@ -1,64 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2007-2008, 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 | #ifndef _PSB_GTT_H_ | ||
21 | #define _PSB_GTT_H_ | ||
22 | |||
23 | #include <drm/drmP.h> | ||
24 | |||
25 | /* This wants cleaning up with respect to the psb_dev and un-needed stuff */ | ||
26 | struct psb_gtt { | ||
27 | uint32_t gatt_start; | ||
28 | uint32_t mmu_gatt_start; | ||
29 | uint32_t gtt_start; | ||
30 | uint32_t gtt_phys_start; | ||
31 | unsigned gtt_pages; | ||
32 | unsigned gatt_pages; | ||
33 | unsigned long stolen_size; | ||
34 | unsigned long vram_stolen_size; | ||
35 | struct rw_semaphore sem; | ||
36 | }; | ||
37 | |||
38 | /* Exported functions */ | ||
39 | extern int psb_gtt_init(struct drm_device *dev, int resume); | ||
40 | extern void psb_gtt_takedown(struct drm_device *dev); | ||
41 | |||
42 | /* Each gtt_range describes an allocation in the GTT area */ | ||
43 | struct gtt_range { | ||
44 | struct resource resource; /* Resource for our allocation */ | ||
45 | u32 offset; /* GTT offset of our object */ | ||
46 | struct drm_gem_object gem; /* GEM high level stuff */ | ||
47 | int in_gart; /* Currently in the GART (ref ct) */ | ||
48 | bool stolen; /* Backed from stolen RAM */ | ||
49 | bool mmapping; /* Is mmappable */ | ||
50 | struct page **pages; /* Backing pages if present */ | ||
51 | int npage; /* Number of backing pages */ | ||
52 | int roll; /* Roll applied to the GTT entries */ | ||
53 | }; | ||
54 | |||
55 | extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len, | ||
56 | const char *name, int backed); | ||
57 | extern void psb_gtt_kref_put(struct gtt_range *gt); | ||
58 | extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt); | ||
59 | extern int psb_gtt_pin(struct gtt_range *gt); | ||
60 | extern void psb_gtt_unpin(struct gtt_range *gt); | ||
61 | extern void psb_gtt_roll(struct drm_device *dev, | ||
62 | struct gtt_range *gt, int roll); | ||
63 | |||
64 | #endif | ||
diff --git a/drivers/staging/gma500/intel_bios.c b/drivers/staging/gma500/intel_bios.c deleted file mode 100644 index 096757f9bc89..000000000000 --- a/drivers/staging/gma500/intel_bios.c +++ /dev/null | |||
@@ -1,303 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006 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 <drm/drmP.h> | ||
22 | #include <drm/drm.h> | ||
23 | #include "psb_drm.h" | ||
24 | #include "psb_drv.h" | ||
25 | #include "psb_intel_drv.h" | ||
26 | #include "psb_intel_reg.h" | ||
27 | #include "intel_bios.h" | ||
28 | |||
29 | |||
30 | static void *find_section(struct bdb_header *bdb, int section_id) | ||
31 | { | ||
32 | u8 *base = (u8 *)bdb; | ||
33 | int index = 0; | ||
34 | u16 total, current_size; | ||
35 | u8 current_id; | ||
36 | |||
37 | /* skip to first section */ | ||
38 | index += bdb->header_size; | ||
39 | total = bdb->bdb_size; | ||
40 | |||
41 | /* walk the sections looking for section_id */ | ||
42 | while (index < total) { | ||
43 | current_id = *(base + index); | ||
44 | index++; | ||
45 | current_size = *((u16 *)(base + index)); | ||
46 | index += 2; | ||
47 | if (current_id == section_id) | ||
48 | return base + index; | ||
49 | index += current_size; | ||
50 | } | ||
51 | |||
52 | return NULL; | ||
53 | } | ||
54 | |||
55 | static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, | ||
56 | struct lvds_dvo_timing *dvo_timing) | ||
57 | { | ||
58 | panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | | ||
59 | dvo_timing->hactive_lo; | ||
60 | panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + | ||
61 | ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); | ||
62 | panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + | ||
63 | dvo_timing->hsync_pulse_width; | ||
64 | panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + | ||
65 | ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); | ||
66 | |||
67 | panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | | ||
68 | dvo_timing->vactive_lo; | ||
69 | panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + | ||
70 | dvo_timing->vsync_off; | ||
71 | panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + | ||
72 | dvo_timing->vsync_pulse_width; | ||
73 | panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + | ||
74 | ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); | ||
75 | panel_fixed_mode->clock = dvo_timing->clock * 10; | ||
76 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; | ||
77 | |||
78 | /* Some VBTs have bogus h/vtotal values */ | ||
79 | if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) | ||
80 | panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; | ||
81 | if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) | ||
82 | panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; | ||
83 | |||
84 | drm_mode_set_name(panel_fixed_mode); | ||
85 | } | ||
86 | |||
87 | static void parse_backlight_data(struct drm_psb_private *dev_priv, | ||
88 | struct bdb_header *bdb) | ||
89 | { | ||
90 | struct bdb_lvds_backlight *vbt_lvds_bl = NULL; | ||
91 | struct bdb_lvds_backlight *lvds_bl; | ||
92 | u8 p_type = 0; | ||
93 | void *bl_start = NULL; | ||
94 | struct bdb_lvds_options *lvds_opts | ||
95 | = find_section(bdb, BDB_LVDS_OPTIONS); | ||
96 | |||
97 | dev_priv->lvds_bl = NULL; | ||
98 | |||
99 | if (lvds_opts) | ||
100 | p_type = lvds_opts->panel_type; | ||
101 | else | ||
102 | return; | ||
103 | |||
104 | bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT); | ||
105 | vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type; | ||
106 | |||
107 | lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL); | ||
108 | if (!lvds_bl) { | ||
109 | dev_err(dev_priv->dev->dev, "out of memory for backlight data\n"); | ||
110 | return; | ||
111 | } | ||
112 | memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl)); | ||
113 | dev_priv->lvds_bl = lvds_bl; | ||
114 | } | ||
115 | |||
116 | /* Try to find integrated panel data */ | ||
117 | static void parse_lfp_panel_data(struct drm_psb_private *dev_priv, | ||
118 | struct bdb_header *bdb) | ||
119 | { | ||
120 | struct bdb_lvds_options *lvds_options; | ||
121 | struct bdb_lvds_lfp_data *lvds_lfp_data; | ||
122 | struct bdb_lvds_lfp_data_entry *entry; | ||
123 | struct lvds_dvo_timing *dvo_timing; | ||
124 | struct drm_display_mode *panel_fixed_mode; | ||
125 | |||
126 | /* Defaults if we can't find VBT info */ | ||
127 | dev_priv->lvds_dither = 0; | ||
128 | dev_priv->lvds_vbt = 0; | ||
129 | |||
130 | lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); | ||
131 | if (!lvds_options) | ||
132 | return; | ||
133 | |||
134 | dev_priv->lvds_dither = lvds_options->pixel_dither; | ||
135 | if (lvds_options->panel_type == 0xff) | ||
136 | return; | ||
137 | |||
138 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); | ||
139 | if (!lvds_lfp_data) | ||
140 | return; | ||
141 | |||
142 | |||
143 | entry = &lvds_lfp_data->data[lvds_options->panel_type]; | ||
144 | dvo_timing = &entry->dvo_timing; | ||
145 | |||
146 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), | ||
147 | GFP_KERNEL); | ||
148 | if (panel_fixed_mode == NULL) { | ||
149 | dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n"); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | dev_priv->lvds_vbt = 1; | ||
154 | fill_detail_timing_data(panel_fixed_mode, dvo_timing); | ||
155 | |||
156 | if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) { | ||
157 | dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; | ||
158 | drm_mode_debug_printmodeline(panel_fixed_mode); | ||
159 | } else { | ||
160 | dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n"); | ||
161 | dev_priv->lvds_vbt = 0; | ||
162 | kfree(panel_fixed_mode); | ||
163 | } | ||
164 | return; | ||
165 | } | ||
166 | |||
167 | /* Try to find sdvo panel data */ | ||
168 | static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv, | ||
169 | struct bdb_header *bdb) | ||
170 | { | ||
171 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; | ||
172 | struct lvds_dvo_timing *dvo_timing; | ||
173 | struct drm_display_mode *panel_fixed_mode; | ||
174 | |||
175 | dev_priv->sdvo_lvds_vbt_mode = NULL; | ||
176 | |||
177 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); | ||
178 | if (!sdvo_lvds_options) | ||
179 | return; | ||
180 | |||
181 | dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); | ||
182 | if (!dvo_timing) | ||
183 | return; | ||
184 | |||
185 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); | ||
186 | |||
187 | if (!panel_fixed_mode) | ||
188 | return; | ||
189 | |||
190 | fill_detail_timing_data(panel_fixed_mode, | ||
191 | dvo_timing + sdvo_lvds_options->panel_type); | ||
192 | |||
193 | dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; | ||
194 | |||
195 | return; | ||
196 | } | ||
197 | |||
198 | static void parse_general_features(struct drm_psb_private *dev_priv, | ||
199 | struct bdb_header *bdb) | ||
200 | { | ||
201 | struct bdb_general_features *general; | ||
202 | |||
203 | /* Set sensible defaults in case we can't find the general block */ | ||
204 | dev_priv->int_tv_support = 1; | ||
205 | dev_priv->int_crt_support = 1; | ||
206 | |||
207 | general = find_section(bdb, BDB_GENERAL_FEATURES); | ||
208 | if (general) { | ||
209 | dev_priv->int_tv_support = general->int_tv_support; | ||
210 | dev_priv->int_crt_support = general->int_crt_support; | ||
211 | dev_priv->lvds_use_ssc = general->enable_ssc; | ||
212 | |||
213 | if (dev_priv->lvds_use_ssc) { | ||
214 | dev_priv->lvds_ssc_freq | ||
215 | = general->ssc_freq ? 100 : 96; | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * psb_intel_init_bios - initialize VBIOS settings & find VBT | ||
222 | * @dev: DRM device | ||
223 | * | ||
224 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers | ||
225 | * to appropriate values. | ||
226 | * | ||
227 | * VBT existence is a sanity check that is relied on by other i830_bios.c code. | ||
228 | * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may | ||
229 | * feed an updated VBT back through that, compared to what we'll fetch using | ||
230 | * this method of groping around in the BIOS data. | ||
231 | * | ||
232 | * Returns 0 on success, nonzero on failure. | ||
233 | */ | ||
234 | bool psb_intel_init_bios(struct drm_device *dev) | ||
235 | { | ||
236 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
237 | struct pci_dev *pdev = dev->pdev; | ||
238 | struct vbt_header *vbt = NULL; | ||
239 | struct bdb_header *bdb; | ||
240 | u8 __iomem *bios; | ||
241 | size_t size; | ||
242 | int i; | ||
243 | |||
244 | bios = pci_map_rom(pdev, &size); | ||
245 | if (!bios) | ||
246 | return -1; | ||
247 | |||
248 | /* Scour memory looking for the VBT signature */ | ||
249 | for (i = 0; i + 4 < size; i++) { | ||
250 | if (!memcmp(bios + i, "$VBT", 4)) { | ||
251 | vbt = (struct vbt_header *)(bios + i); | ||
252 | break; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | if (!vbt) { | ||
257 | dev_err(dev->dev, "VBT signature missing\n"); | ||
258 | pci_unmap_rom(pdev, bios); | ||
259 | return -1; | ||
260 | } | ||
261 | |||
262 | bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); | ||
263 | |||
264 | /* Grab useful general definitions */ | ||
265 | parse_general_features(dev_priv, bdb); | ||
266 | parse_lfp_panel_data(dev_priv, bdb); | ||
267 | parse_sdvo_panel_data(dev_priv, bdb); | ||
268 | parse_backlight_data(dev_priv, bdb); | ||
269 | |||
270 | pci_unmap_rom(pdev, bios); | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * Destroy and free VBT data | ||
277 | */ | ||
278 | void psb_intel_destroy_bios(struct drm_device *dev) | ||
279 | { | ||
280 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
281 | struct drm_display_mode *sdvo_lvds_vbt_mode = | ||
282 | dev_priv->sdvo_lvds_vbt_mode; | ||
283 | struct drm_display_mode *lfp_lvds_vbt_mode = | ||
284 | dev_priv->lfp_lvds_vbt_mode; | ||
285 | struct bdb_lvds_backlight *lvds_bl = | ||
286 | dev_priv->lvds_bl; | ||
287 | |||
288 | /*free sdvo panel mode*/ | ||
289 | if (sdvo_lvds_vbt_mode) { | ||
290 | dev_priv->sdvo_lvds_vbt_mode = NULL; | ||
291 | kfree(sdvo_lvds_vbt_mode); | ||
292 | } | ||
293 | |||
294 | if (lfp_lvds_vbt_mode) { | ||
295 | dev_priv->lfp_lvds_vbt_mode = NULL; | ||
296 | kfree(lfp_lvds_vbt_mode); | ||
297 | } | ||
298 | |||
299 | if (lvds_bl) { | ||
300 | dev_priv->lvds_bl = NULL; | ||
301 | kfree(lvds_bl); | ||
302 | } | ||
303 | } | ||
diff --git a/drivers/staging/gma500/intel_bios.h b/drivers/staging/gma500/intel_bios.h deleted file mode 100644 index 70f1bf018183..000000000000 --- a/drivers/staging/gma500/intel_bios.h +++ /dev/null | |||
@@ -1,430 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006 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 | |||
22 | #ifndef _I830_BIOS_H_ | ||
23 | #define _I830_BIOS_H_ | ||
24 | |||
25 | #include <drm/drmP.h> | ||
26 | |||
27 | struct vbt_header { | ||
28 | u8 signature[20]; /**< Always starts with 'VBT$' */ | ||
29 | u16 version; /**< decimal */ | ||
30 | u16 header_size; /**< in bytes */ | ||
31 | u16 vbt_size; /**< in bytes */ | ||
32 | u8 vbt_checksum; | ||
33 | u8 reserved0; | ||
34 | u32 bdb_offset; /**< from beginning of VBT */ | ||
35 | u32 aim_offset[4]; /**< from beginning of VBT */ | ||
36 | } __attribute__((packed)); | ||
37 | |||
38 | |||
39 | struct bdb_header { | ||
40 | u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */ | ||
41 | u16 version; /**< decimal */ | ||
42 | u16 header_size; /**< in bytes */ | ||
43 | u16 bdb_size; /**< in bytes */ | ||
44 | }; | ||
45 | |||
46 | /* strictly speaking, this is a "skip" block, but it has interesting info */ | ||
47 | struct vbios_data { | ||
48 | u8 type; /* 0 == desktop, 1 == mobile */ | ||
49 | u8 relstage; | ||
50 | u8 chipset; | ||
51 | u8 lvds_present:1; | ||
52 | u8 tv_present:1; | ||
53 | u8 rsvd2:6; /* finish byte */ | ||
54 | u8 rsvd3[4]; | ||
55 | u8 signon[155]; | ||
56 | u8 copyright[61]; | ||
57 | u16 code_segment; | ||
58 | u8 dos_boot_mode; | ||
59 | u8 bandwidth_percent; | ||
60 | u8 rsvd4; /* popup memory size */ | ||
61 | u8 resize_pci_bios; | ||
62 | u8 rsvd5; /* is crt already on ddc2 */ | ||
63 | } __attribute__((packed)); | ||
64 | |||
65 | /* | ||
66 | * There are several types of BIOS data blocks (BDBs), each block has | ||
67 | * an ID and size in the first 3 bytes (ID in first, size in next 2). | ||
68 | * Known types are listed below. | ||
69 | */ | ||
70 | #define BDB_GENERAL_FEATURES 1 | ||
71 | #define BDB_GENERAL_DEFINITIONS 2 | ||
72 | #define BDB_OLD_TOGGLE_LIST 3 | ||
73 | #define BDB_MODE_SUPPORT_LIST 4 | ||
74 | #define BDB_GENERIC_MODE_TABLE 5 | ||
75 | #define BDB_EXT_MMIO_REGS 6 | ||
76 | #define BDB_SWF_IO 7 | ||
77 | #define BDB_SWF_MMIO 8 | ||
78 | #define BDB_DOT_CLOCK_TABLE 9 | ||
79 | #define BDB_MODE_REMOVAL_TABLE 10 | ||
80 | #define BDB_CHILD_DEVICE_TABLE 11 | ||
81 | #define BDB_DRIVER_FEATURES 12 | ||
82 | #define BDB_DRIVER_PERSISTENCE 13 | ||
83 | #define BDB_EXT_TABLE_PTRS 14 | ||
84 | #define BDB_DOT_CLOCK_OVERRIDE 15 | ||
85 | #define BDB_DISPLAY_SELECT 16 | ||
86 | /* 17 rsvd */ | ||
87 | #define BDB_DRIVER_ROTATION 18 | ||
88 | #define BDB_DISPLAY_REMOVE 19 | ||
89 | #define BDB_OEM_CUSTOM 20 | ||
90 | #define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */ | ||
91 | #define BDB_SDVO_LVDS_OPTIONS 22 | ||
92 | #define BDB_SDVO_PANEL_DTDS 23 | ||
93 | #define BDB_SDVO_LVDS_PNP_IDS 24 | ||
94 | #define BDB_SDVO_LVDS_POWER_SEQ 25 | ||
95 | #define BDB_TV_OPTIONS 26 | ||
96 | #define BDB_LVDS_OPTIONS 40 | ||
97 | #define BDB_LVDS_LFP_DATA_PTRS 41 | ||
98 | #define BDB_LVDS_LFP_DATA 42 | ||
99 | #define BDB_LVDS_BACKLIGHT 43 | ||
100 | #define BDB_LVDS_POWER 44 | ||
101 | #define BDB_SKIP 254 /* VBIOS private block, ignore */ | ||
102 | |||
103 | struct bdb_general_features { | ||
104 | /* bits 1 */ | ||
105 | u8 panel_fitting:2; | ||
106 | u8 flexaim:1; | ||
107 | u8 msg_enable:1; | ||
108 | u8 clear_screen:3; | ||
109 | u8 color_flip:1; | ||
110 | |||
111 | /* bits 2 */ | ||
112 | u8 download_ext_vbt:1; | ||
113 | u8 enable_ssc:1; | ||
114 | u8 ssc_freq:1; | ||
115 | u8 enable_lfp_on_override:1; | ||
116 | u8 disable_ssc_ddt:1; | ||
117 | u8 rsvd8:3; /* finish byte */ | ||
118 | |||
119 | /* bits 3 */ | ||
120 | u8 disable_smooth_vision:1; | ||
121 | u8 single_dvi:1; | ||
122 | u8 rsvd9:6; /* finish byte */ | ||
123 | |||
124 | /* bits 4 */ | ||
125 | u8 legacy_monitor_detect; | ||
126 | |||
127 | /* bits 5 */ | ||
128 | u8 int_crt_support:1; | ||
129 | u8 int_tv_support:1; | ||
130 | u8 rsvd11:6; /* finish byte */ | ||
131 | } __attribute__((packed)); | ||
132 | |||
133 | struct bdb_general_definitions { | ||
134 | /* DDC GPIO */ | ||
135 | u8 crt_ddc_gmbus_pin; | ||
136 | |||
137 | /* DPMS bits */ | ||
138 | u8 dpms_acpi:1; | ||
139 | u8 skip_boot_crt_detect:1; | ||
140 | u8 dpms_aim:1; | ||
141 | u8 rsvd1:5; /* finish byte */ | ||
142 | |||
143 | /* boot device bits */ | ||
144 | u8 boot_display[2]; | ||
145 | u8 child_dev_size; | ||
146 | |||
147 | /* device info */ | ||
148 | u8 tv_or_lvds_info[33]; | ||
149 | u8 dev1[33]; | ||
150 | u8 dev2[33]; | ||
151 | u8 dev3[33]; | ||
152 | u8 dev4[33]; | ||
153 | /* may be another device block here on some platforms */ | ||
154 | }; | ||
155 | |||
156 | struct bdb_lvds_options { | ||
157 | u8 panel_type; | ||
158 | u8 rsvd1; | ||
159 | /* LVDS capabilities, stored in a dword */ | ||
160 | u8 pfit_mode:2; | ||
161 | u8 pfit_text_mode_enhanced:1; | ||
162 | u8 pfit_gfx_mode_enhanced:1; | ||
163 | u8 pfit_ratio_auto:1; | ||
164 | u8 pixel_dither:1; | ||
165 | u8 lvds_edid:1; | ||
166 | u8 rsvd2:1; | ||
167 | u8 rsvd4; | ||
168 | } __attribute__((packed)); | ||
169 | |||
170 | struct bdb_lvds_backlight { | ||
171 | u8 type:2; | ||
172 | u8 pol:1; | ||
173 | u8 gpio:3; | ||
174 | u8 gmbus:2; | ||
175 | u16 freq; | ||
176 | u8 minbrightness; | ||
177 | u8 i2caddr; | ||
178 | u8 brightnesscmd; | ||
179 | /*FIXME: more...*/ | ||
180 | } __attribute__((packed)); | ||
181 | |||
182 | /* LFP pointer table contains entries to the struct below */ | ||
183 | struct bdb_lvds_lfp_data_ptr { | ||
184 | u16 fp_timing_offset; /* offsets are from start of bdb */ | ||
185 | u8 fp_table_size; | ||
186 | u16 dvo_timing_offset; | ||
187 | u8 dvo_table_size; | ||
188 | u16 panel_pnp_id_offset; | ||
189 | u8 pnp_table_size; | ||
190 | } __attribute__((packed)); | ||
191 | |||
192 | struct bdb_lvds_lfp_data_ptrs { | ||
193 | u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */ | ||
194 | struct bdb_lvds_lfp_data_ptr ptr[16]; | ||
195 | } __attribute__((packed)); | ||
196 | |||
197 | /* LFP data has 3 blocks per entry */ | ||
198 | struct lvds_fp_timing { | ||
199 | u16 x_res; | ||
200 | u16 y_res; | ||
201 | u32 lvds_reg; | ||
202 | u32 lvds_reg_val; | ||
203 | u32 pp_on_reg; | ||
204 | u32 pp_on_reg_val; | ||
205 | u32 pp_off_reg; | ||
206 | u32 pp_off_reg_val; | ||
207 | u32 pp_cycle_reg; | ||
208 | u32 pp_cycle_reg_val; | ||
209 | u32 pfit_reg; | ||
210 | u32 pfit_reg_val; | ||
211 | u16 terminator; | ||
212 | } __attribute__((packed)); | ||
213 | |||
214 | struct lvds_dvo_timing { | ||
215 | u16 clock; /**< In 10khz */ | ||
216 | u8 hactive_lo; | ||
217 | u8 hblank_lo; | ||
218 | u8 hblank_hi:4; | ||
219 | u8 hactive_hi:4; | ||
220 | u8 vactive_lo; | ||
221 | u8 vblank_lo; | ||
222 | u8 vblank_hi:4; | ||
223 | u8 vactive_hi:4; | ||
224 | u8 hsync_off_lo; | ||
225 | u8 hsync_pulse_width; | ||
226 | u8 vsync_pulse_width:4; | ||
227 | u8 vsync_off:4; | ||
228 | u8 rsvd0:6; | ||
229 | u8 hsync_off_hi:2; | ||
230 | u8 h_image; | ||
231 | u8 v_image; | ||
232 | u8 max_hv; | ||
233 | u8 h_border; | ||
234 | u8 v_border; | ||
235 | u8 rsvd1:3; | ||
236 | u8 digital:2; | ||
237 | u8 vsync_positive:1; | ||
238 | u8 hsync_positive:1; | ||
239 | u8 rsvd2:1; | ||
240 | } __attribute__((packed)); | ||
241 | |||
242 | struct lvds_pnp_id { | ||
243 | u16 mfg_name; | ||
244 | u16 product_code; | ||
245 | u32 serial; | ||
246 | u8 mfg_week; | ||
247 | u8 mfg_year; | ||
248 | } __attribute__((packed)); | ||
249 | |||
250 | struct bdb_lvds_lfp_data_entry { | ||
251 | struct lvds_fp_timing fp_timing; | ||
252 | struct lvds_dvo_timing dvo_timing; | ||
253 | struct lvds_pnp_id pnp_id; | ||
254 | } __attribute__((packed)); | ||
255 | |||
256 | struct bdb_lvds_lfp_data { | ||
257 | struct bdb_lvds_lfp_data_entry data[16]; | ||
258 | } __attribute__((packed)); | ||
259 | |||
260 | struct aimdb_header { | ||
261 | char signature[16]; | ||
262 | char oem_device[20]; | ||
263 | u16 aimdb_version; | ||
264 | u16 aimdb_header_size; | ||
265 | u16 aimdb_size; | ||
266 | } __attribute__((packed)); | ||
267 | |||
268 | struct aimdb_block { | ||
269 | u8 aimdb_id; | ||
270 | u16 aimdb_size; | ||
271 | } __attribute__((packed)); | ||
272 | |||
273 | struct vch_panel_data { | ||
274 | u16 fp_timing_offset; | ||
275 | u8 fp_timing_size; | ||
276 | u16 dvo_timing_offset; | ||
277 | u8 dvo_timing_size; | ||
278 | u16 text_fitting_offset; | ||
279 | u8 text_fitting_size; | ||
280 | u16 graphics_fitting_offset; | ||
281 | u8 graphics_fitting_size; | ||
282 | } __attribute__((packed)); | ||
283 | |||
284 | struct vch_bdb_22 { | ||
285 | struct aimdb_block aimdb_block; | ||
286 | struct vch_panel_data panels[16]; | ||
287 | } __attribute__((packed)); | ||
288 | |||
289 | struct bdb_sdvo_lvds_options { | ||
290 | u8 panel_backlight; | ||
291 | u8 h40_set_panel_type; | ||
292 | u8 panel_type; | ||
293 | u8 ssc_clk_freq; | ||
294 | u16 als_low_trip; | ||
295 | u16 als_high_trip; | ||
296 | u8 sclalarcoeff_tab_row_num; | ||
297 | u8 sclalarcoeff_tab_row_size; | ||
298 | u8 coefficient[8]; | ||
299 | u8 panel_misc_bits_1; | ||
300 | u8 panel_misc_bits_2; | ||
301 | u8 panel_misc_bits_3; | ||
302 | u8 panel_misc_bits_4; | ||
303 | } __attribute__((packed)); | ||
304 | |||
305 | |||
306 | extern bool psb_intel_init_bios(struct drm_device *dev); | ||
307 | extern void psb_intel_destroy_bios(struct drm_device *dev); | ||
308 | |||
309 | /* | ||
310 | * Driver<->VBIOS interaction occurs through scratch bits in | ||
311 | * GR18 & SWF*. | ||
312 | */ | ||
313 | |||
314 | /* GR18 bits are set on display switch and hotkey events */ | ||
315 | #define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */ | ||
316 | #define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */ | ||
317 | #define GR18_HK_NONE (0x0<<3) | ||
318 | #define GR18_HK_LFP_STRETCH (0x1<<3) | ||
319 | #define GR18_HK_TOGGLE_DISP (0x2<<3) | ||
320 | #define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */ | ||
321 | #define GR18_HK_POPUP_DISABLED (0x6<<3) | ||
322 | #define GR18_HK_POPUP_ENABLED (0x7<<3) | ||
323 | #define GR18_HK_PFIT (0x8<<3) | ||
324 | #define GR18_HK_APM_CHANGE (0xa<<3) | ||
325 | #define GR18_HK_MULTIPLE (0xc<<3) | ||
326 | #define GR18_USER_INT_EN (1<<2) | ||
327 | #define GR18_A0000_FLUSH_EN (1<<1) | ||
328 | #define GR18_SMM_EN (1<<0) | ||
329 | |||
330 | /* Set by driver, cleared by VBIOS */ | ||
331 | #define SWF00_YRES_SHIFT 16 | ||
332 | #define SWF00_XRES_SHIFT 0 | ||
333 | #define SWF00_RES_MASK 0xffff | ||
334 | |||
335 | /* Set by VBIOS at boot time and driver at runtime */ | ||
336 | #define SWF01_TV2_FORMAT_SHIFT 8 | ||
337 | #define SWF01_TV1_FORMAT_SHIFT 0 | ||
338 | #define SWF01_TV_FORMAT_MASK 0xffff | ||
339 | |||
340 | #define SWF10_VBIOS_BLC_I2C_EN (1<<29) | ||
341 | #define SWF10_GTT_OVERRIDE_EN (1<<28) | ||
342 | #define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */ | ||
343 | #define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24) | ||
344 | #define SWF10_OLD_TOGGLE 0x0 | ||
345 | #define SWF10_TOGGLE_LIST_1 0x1 | ||
346 | #define SWF10_TOGGLE_LIST_2 0x2 | ||
347 | #define SWF10_TOGGLE_LIST_3 0x3 | ||
348 | #define SWF10_TOGGLE_LIST_4 0x4 | ||
349 | #define SWF10_PANNING_EN (1<<23) | ||
350 | #define SWF10_DRIVER_LOADED (1<<22) | ||
351 | #define SWF10_EXTENDED_DESKTOP (1<<21) | ||
352 | #define SWF10_EXCLUSIVE_MODE (1<<20) | ||
353 | #define SWF10_OVERLAY_EN (1<<19) | ||
354 | #define SWF10_PLANEB_HOLDOFF (1<<18) | ||
355 | #define SWF10_PLANEA_HOLDOFF (1<<17) | ||
356 | #define SWF10_VGA_HOLDOFF (1<<16) | ||
357 | #define SWF10_ACTIVE_DISP_MASK 0xffff | ||
358 | #define SWF10_PIPEB_LFP2 (1<<15) | ||
359 | #define SWF10_PIPEB_EFP2 (1<<14) | ||
360 | #define SWF10_PIPEB_TV2 (1<<13) | ||
361 | #define SWF10_PIPEB_CRT2 (1<<12) | ||
362 | #define SWF10_PIPEB_LFP (1<<11) | ||
363 | #define SWF10_PIPEB_EFP (1<<10) | ||
364 | #define SWF10_PIPEB_TV (1<<9) | ||
365 | #define SWF10_PIPEB_CRT (1<<8) | ||
366 | #define SWF10_PIPEA_LFP2 (1<<7) | ||
367 | #define SWF10_PIPEA_EFP2 (1<<6) | ||
368 | #define SWF10_PIPEA_TV2 (1<<5) | ||
369 | #define SWF10_PIPEA_CRT2 (1<<4) | ||
370 | #define SWF10_PIPEA_LFP (1<<3) | ||
371 | #define SWF10_PIPEA_EFP (1<<2) | ||
372 | #define SWF10_PIPEA_TV (1<<1) | ||
373 | #define SWF10_PIPEA_CRT (1<<0) | ||
374 | |||
375 | #define SWF11_MEMORY_SIZE_SHIFT 16 | ||
376 | #define SWF11_SV_TEST_EN (1<<15) | ||
377 | #define SWF11_IS_AGP (1<<14) | ||
378 | #define SWF11_DISPLAY_HOLDOFF (1<<13) | ||
379 | #define SWF11_DPMS_REDUCED (1<<12) | ||
380 | #define SWF11_IS_VBE_MODE (1<<11) | ||
381 | #define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */ | ||
382 | #define SWF11_DPMS_MASK 0x07 | ||
383 | #define SWF11_DPMS_OFF (1<<2) | ||
384 | #define SWF11_DPMS_SUSPEND (1<<1) | ||
385 | #define SWF11_DPMS_STANDBY (1<<0) | ||
386 | #define SWF11_DPMS_ON 0 | ||
387 | |||
388 | #define SWF14_GFX_PFIT_EN (1<<31) | ||
389 | #define SWF14_TEXT_PFIT_EN (1<<30) | ||
390 | #define SWF14_LID_STATUS_CLOSED (1<<29) /* 0 here means open */ | ||
391 | #define SWF14_POPUP_EN (1<<28) | ||
392 | #define SWF14_DISPLAY_HOLDOFF (1<<27) | ||
393 | #define SWF14_DISP_DETECT_EN (1<<26) | ||
394 | #define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */ | ||
395 | #define SWF14_DRIVER_STATUS (1<<24) | ||
396 | #define SWF14_OS_TYPE_WIN9X (1<<23) | ||
397 | #define SWF14_OS_TYPE_WINNT (1<<22) | ||
398 | /* 21:19 rsvd */ | ||
399 | #define SWF14_PM_TYPE_MASK 0x00070000 | ||
400 | #define SWF14_PM_ACPI_VIDEO (0x4 << 16) | ||
401 | #define SWF14_PM_ACPI (0x3 << 16) | ||
402 | #define SWF14_PM_APM_12 (0x2 << 16) | ||
403 | #define SWF14_PM_APM_11 (0x1 << 16) | ||
404 | #define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */ | ||
405 | /* if GR18 indicates a display switch */ | ||
406 | #define SWF14_DS_PIPEB_LFP2_EN (1<<15) | ||
407 | #define SWF14_DS_PIPEB_EFP2_EN (1<<14) | ||
408 | #define SWF14_DS_PIPEB_TV2_EN (1<<13) | ||
409 | #define SWF14_DS_PIPEB_CRT2_EN (1<<12) | ||
410 | #define SWF14_DS_PIPEB_LFP_EN (1<<11) | ||
411 | #define SWF14_DS_PIPEB_EFP_EN (1<<10) | ||
412 | #define SWF14_DS_PIPEB_TV_EN (1<<9) | ||
413 | #define SWF14_DS_PIPEB_CRT_EN (1<<8) | ||
414 | #define SWF14_DS_PIPEA_LFP2_EN (1<<7) | ||
415 | #define SWF14_DS_PIPEA_EFP2_EN (1<<6) | ||
416 | #define SWF14_DS_PIPEA_TV2_EN (1<<5) | ||
417 | #define SWF14_DS_PIPEA_CRT2_EN (1<<4) | ||
418 | #define SWF14_DS_PIPEA_LFP_EN (1<<3) | ||
419 | #define SWF14_DS_PIPEA_EFP_EN (1<<2) | ||
420 | #define SWF14_DS_PIPEA_TV_EN (1<<1) | ||
421 | #define SWF14_DS_PIPEA_CRT_EN (1<<0) | ||
422 | /* if GR18 indicates a panel fitting request */ | ||
423 | #define SWF14_PFIT_EN (1<<0) /* 0 means disable */ | ||
424 | /* if GR18 indicates an APM change request */ | ||
425 | #define SWF14_APM_HIBERNATE 0x4 | ||
426 | #define SWF14_APM_SUSPEND 0x3 | ||
427 | #define SWF14_APM_STANDBY 0x1 | ||
428 | #define SWF14_APM_RESTORE 0x0 | ||
429 | |||
430 | #endif /* _I830_BIOS_H_ */ | ||
diff --git a/drivers/staging/gma500/intel_i2c.c b/drivers/staging/gma500/intel_i2c.c deleted file mode 100644 index 51cbf65268e6..000000000000 --- a/drivers/staging/gma500/intel_i2c.c +++ /dev/null | |||
@@ -1,170 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2006-2007 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/i2c-algo-bit.h> | ||
23 | #include <linux/export.h> | ||
24 | |||
25 | #include "psb_drv.h" | ||
26 | #include "psb_intel_reg.h" | ||
27 | |||
28 | /* | ||
29 | * Intel GPIO access functions | ||
30 | */ | ||
31 | |||
32 | #define I2C_RISEFALL_TIME 20 | ||
33 | |||
34 | static int get_clock(void *data) | ||
35 | { | ||
36 | struct psb_intel_i2c_chan *chan = data; | ||
37 | struct drm_device *dev = chan->drm_dev; | ||
38 | u32 val; | ||
39 | |||
40 | val = REG_READ(chan->reg); | ||
41 | return (val & GPIO_CLOCK_VAL_IN) != 0; | ||
42 | } | ||
43 | |||
44 | static int get_data(void *data) | ||
45 | { | ||
46 | struct psb_intel_i2c_chan *chan = data; | ||
47 | struct drm_device *dev = chan->drm_dev; | ||
48 | u32 val; | ||
49 | |||
50 | val = REG_READ(chan->reg); | ||
51 | return (val & GPIO_DATA_VAL_IN) != 0; | ||
52 | } | ||
53 | |||
54 | static void set_clock(void *data, int state_high) | ||
55 | { | ||
56 | struct psb_intel_i2c_chan *chan = data; | ||
57 | struct drm_device *dev = chan->drm_dev; | ||
58 | u32 reserved = 0, clock_bits; | ||
59 | |||
60 | /* On most chips, these bits must be preserved in software. */ | ||
61 | reserved = | ||
62 | REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | | ||
63 | GPIO_CLOCK_PULLUP_DISABLE); | ||
64 | |||
65 | if (state_high) | ||
66 | clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK; | ||
67 | else | ||
68 | clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK | | ||
69 | GPIO_CLOCK_VAL_MASK; | ||
70 | REG_WRITE(chan->reg, reserved | clock_bits); | ||
71 | udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ | ||
72 | } | ||
73 | |||
74 | static void set_data(void *data, int state_high) | ||
75 | { | ||
76 | struct psb_intel_i2c_chan *chan = data; | ||
77 | struct drm_device *dev = chan->drm_dev; | ||
78 | u32 reserved = 0, data_bits; | ||
79 | |||
80 | /* On most chips, these bits must be preserved in software. */ | ||
81 | reserved = | ||
82 | REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE | | ||
83 | GPIO_CLOCK_PULLUP_DISABLE); | ||
84 | |||
85 | if (state_high) | ||
86 | data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK; | ||
87 | else | ||
88 | data_bits = | ||
89 | GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK | | ||
90 | GPIO_DATA_VAL_MASK; | ||
91 | |||
92 | REG_WRITE(chan->reg, reserved | data_bits); | ||
93 | udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */ | ||
94 | } | ||
95 | |||
96 | /** | ||
97 | * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg | ||
98 | * @dev: DRM device | ||
99 | * @output: driver specific output device | ||
100 | * @reg: GPIO reg to use | ||
101 | * @name: name for this bus | ||
102 | * | ||
103 | * Creates and registers a new i2c bus with the Linux i2c layer, for use | ||
104 | * in output probing and control (e.g. DDC or SDVO control functions). | ||
105 | * | ||
106 | * Possible values for @reg include: | ||
107 | * %GPIOA | ||
108 | * %GPIOB | ||
109 | * %GPIOC | ||
110 | * %GPIOD | ||
111 | * %GPIOE | ||
112 | * %GPIOF | ||
113 | * %GPIOG | ||
114 | * %GPIOH | ||
115 | * see PRM for details on how these different busses are used. | ||
116 | */ | ||
117 | struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, | ||
118 | const u32 reg, const char *name) | ||
119 | { | ||
120 | struct psb_intel_i2c_chan *chan; | ||
121 | |||
122 | chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL); | ||
123 | if (!chan) | ||
124 | goto out_free; | ||
125 | |||
126 | chan->drm_dev = dev; | ||
127 | chan->reg = reg; | ||
128 | snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name); | ||
129 | chan->adapter.owner = THIS_MODULE; | ||
130 | chan->adapter.algo_data = &chan->algo; | ||
131 | chan->adapter.dev.parent = &dev->pdev->dev; | ||
132 | chan->algo.setsda = set_data; | ||
133 | chan->algo.setscl = set_clock; | ||
134 | chan->algo.getsda = get_data; | ||
135 | chan->algo.getscl = get_clock; | ||
136 | chan->algo.udelay = 20; | ||
137 | chan->algo.timeout = usecs_to_jiffies(2200); | ||
138 | chan->algo.data = chan; | ||
139 | |||
140 | i2c_set_adapdata(&chan->adapter, chan); | ||
141 | |||
142 | if (i2c_bit_add_bus(&chan->adapter)) | ||
143 | goto out_free; | ||
144 | |||
145 | /* JJJ: raise SCL and SDA? */ | ||
146 | set_data(chan, 1); | ||
147 | set_clock(chan, 1); | ||
148 | udelay(20); | ||
149 | |||
150 | return chan; | ||
151 | |||
152 | out_free: | ||
153 | kfree(chan); | ||
154 | return NULL; | ||
155 | } | ||
156 | |||
157 | /** | ||
158 | * psb_intel_i2c_destroy - unregister and free i2c bus resources | ||
159 | * @output: channel to free | ||
160 | * | ||
161 | * Unregister the adapter from the i2c layer, then free the structure. | ||
162 | */ | ||
163 | void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan) | ||
164 | { | ||
165 | if (!chan) | ||
166 | return; | ||
167 | |||
168 | i2c_del_adapter(&chan->adapter); | ||
169 | kfree(chan); | ||
170 | } | ||
diff --git a/drivers/staging/gma500/intel_opregion.c b/drivers/staging/gma500/intel_opregion.c deleted file mode 100644 index d946bc1b17bf..000000000000 --- a/drivers/staging/gma500/intel_opregion.c +++ /dev/null | |||
@@ -1,81 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2010 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 | * FIXME: resolve with the i915 version | ||
24 | */ | ||
25 | |||
26 | #include "psb_drv.h" | ||
27 | |||
28 | struct opregion_header { | ||
29 | u8 signature[16]; | ||
30 | u32 size; | ||
31 | u32 opregion_ver; | ||
32 | u8 bios_ver[32]; | ||
33 | u8 vbios_ver[16]; | ||
34 | u8 driver_ver[16]; | ||
35 | u32 mboxes; | ||
36 | u8 reserved[164]; | ||
37 | } __packed; | ||
38 | |||
39 | struct opregion_apci { | ||
40 | /*FIXME: add it later*/ | ||
41 | } __packed; | ||
42 | |||
43 | struct opregion_swsci { | ||
44 | /*FIXME: add it later*/ | ||
45 | } __packed; | ||
46 | |||
47 | struct opregion_acpi { | ||
48 | /*FIXME: add it later*/ | ||
49 | } __packed; | ||
50 | |||
51 | int gma_intel_opregion_init(struct drm_device *dev) | ||
52 | { | ||
53 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
54 | u32 opregion_phy; | ||
55 | void *base; | ||
56 | u32 *lid_state; | ||
57 | |||
58 | dev_priv->lid_state = NULL; | ||
59 | |||
60 | pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy); | ||
61 | if (opregion_phy == 0) | ||
62 | return -ENOTSUPP; | ||
63 | |||
64 | base = ioremap(opregion_phy, 8*1024); | ||
65 | if (!base) | ||
66 | return -ENOMEM; | ||
67 | |||
68 | lid_state = base + 0x01ac; | ||
69 | |||
70 | dev_priv->lid_state = lid_state; | ||
71 | dev_priv->lid_last_state = readl(lid_state); | ||
72 | return 0; | ||
73 | } | ||
74 | |||
75 | int gma_intel_opregion_exit(struct drm_device *dev) | ||
76 | { | ||
77 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
78 | if (dev_priv->lid_state) | ||
79 | iounmap(dev_priv->lid_state); | ||
80 | return 0; | ||
81 | } | ||
diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c deleted file mode 100644 index f47aeb7a2039..000000000000 --- a/drivers/staging/gma500/mdfld_device.c +++ /dev/null | |||
@@ -1,714 +0,0 @@ | |||
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_reg.h" | ||
24 | #include "psb_intel_reg.h" | ||
25 | #include "psb_drm.h" | ||
26 | #include "psb_drv.h" | ||
27 | #include "mdfld_output.h" | ||
28 | #include "mdfld_dsi_output.h" | ||
29 | #include "mid_bios.h" | ||
30 | |||
31 | /* | ||
32 | * Provide the Medfield specific backlight management | ||
33 | */ | ||
34 | |||
35 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
36 | |||
37 | static int mdfld_brightness; | ||
38 | struct backlight_device *mdfld_backlight_device; | ||
39 | |||
40 | static int mfld_set_brightness(struct backlight_device *bd) | ||
41 | { | ||
42 | struct drm_device *dev = bl_get_data(mdfld_backlight_device); | ||
43 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
44 | int level = bd->props.brightness; | ||
45 | |||
46 | /* Percentage 1-100% being valid */ | ||
47 | if (level < 1) | ||
48 | level = 1; | ||
49 | |||
50 | if (gma_power_begin(dev, 0)) { | ||
51 | /* Calculate and set the brightness value */ | ||
52 | u32 adjusted_level; | ||
53 | |||
54 | /* Adjust the backlight level with the percent in | ||
55 | * dev_priv->blc_adj2; | ||
56 | */ | ||
57 | adjusted_level = level * dev_priv->blc_adj2; | ||
58 | adjusted_level = adjusted_level / 100; | ||
59 | #if 0 | ||
60 | #ifndef CONFIG_MDFLD_DSI_DPU | ||
61 | if(!(dev_priv->dsr_fb_update & MDFLD_DSR_MIPI_CONTROL) && | ||
62 | (dev_priv->dbi_panel_on || dev_priv->dbi_panel_on2)){ | ||
63 | mdfld_dsi_dbi_exit_dsr(dev,MDFLD_DSR_MIPI_CONTROL, 0, 0); | ||
64 | dev_dbg(dev->dev, "Out of DSR before set brightness to %d.\n",adjusted_level); | ||
65 | } | ||
66 | #endif | ||
67 | mdfld_dsi_brightness_control(dev, 0, adjusted_level); | ||
68 | |||
69 | if ((dev_priv->dbi_panel_on2) || (dev_priv->dpi_panel_on2)) | ||
70 | mdfld_dsi_brightness_control(dev, 2, adjusted_level); | ||
71 | #endif | ||
72 | gma_power_end(dev); | ||
73 | } | ||
74 | mdfld_brightness = level; | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | int psb_get_brightness(struct backlight_device *bd) | ||
79 | { | ||
80 | /* return locally cached var instead of HW read (due to DPST etc.) */ | ||
81 | /* FIXME: ideally return actual value in case firmware fiddled with | ||
82 | it */ | ||
83 | return mdfld_brightness; | ||
84 | } | ||
85 | |||
86 | static const struct backlight_ops mfld_ops = { | ||
87 | .get_brightness = psb_get_brightness, | ||
88 | .update_status = mfld_set_brightness, | ||
89 | }; | ||
90 | |||
91 | static int mdfld_backlight_init(struct drm_device *dev) | ||
92 | { | ||
93 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
94 | struct backlight_properties props; | ||
95 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
96 | props.max_brightness = 100; | ||
97 | props.type = BACKLIGHT_PLATFORM; | ||
98 | |||
99 | mdfld_backlight_device = backlight_device_register("mfld-bl", | ||
100 | NULL, (void *)dev, &mfld_ops, &props); | ||
101 | |||
102 | if (IS_ERR(mdfld_backlight_device)) | ||
103 | return PTR_ERR(mdfld_backlight_device); | ||
104 | |||
105 | dev_priv->blc_adj1 = 100; | ||
106 | dev_priv->blc_adj2 = 100; | ||
107 | mdfld_backlight_device->props.brightness = 100; | ||
108 | mdfld_backlight_device->props.max_brightness = 100; | ||
109 | backlight_update_status(mdfld_backlight_device); | ||
110 | dev_priv->backlight_device = mdfld_backlight_device; | ||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | #endif | ||
115 | |||
116 | /* | ||
117 | * Provide the Medfield specific chip logic and low level methods for | ||
118 | * power management. | ||
119 | */ | ||
120 | |||
121 | static void mdfld_init_pm(struct drm_device *dev) | ||
122 | { | ||
123 | /* No work needed here yet */ | ||
124 | } | ||
125 | |||
126 | /** | ||
127 | * mdfld_save_display_registers - save registers for pipe | ||
128 | * @dev: our device | ||
129 | * @pipe: pipe to save | ||
130 | * | ||
131 | * Save the pipe state of the device before we power it off. Keep everything | ||
132 | * we need to put it back again | ||
133 | */ | ||
134 | static int mdfld_save_display_registers(struct drm_device *dev, int pipe) | ||
135 | { | ||
136 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
137 | int i; | ||
138 | |||
139 | /* register */ | ||
140 | u32 dpll_reg = MRST_DPLL_A; | ||
141 | u32 fp_reg = MRST_FPA0; | ||
142 | u32 pipeconf_reg = PIPEACONF; | ||
143 | u32 htot_reg = HTOTAL_A; | ||
144 | u32 hblank_reg = HBLANK_A; | ||
145 | u32 hsync_reg = HSYNC_A; | ||
146 | u32 vtot_reg = VTOTAL_A; | ||
147 | u32 vblank_reg = VBLANK_A; | ||
148 | u32 vsync_reg = VSYNC_A; | ||
149 | u32 pipesrc_reg = PIPEASRC; | ||
150 | u32 dspstride_reg = DSPASTRIDE; | ||
151 | u32 dsplinoff_reg = DSPALINOFF; | ||
152 | u32 dsptileoff_reg = DSPATILEOFF; | ||
153 | u32 dspsize_reg = DSPASIZE; | ||
154 | u32 dsppos_reg = DSPAPOS; | ||
155 | u32 dspsurf_reg = DSPASURF; | ||
156 | u32 mipi_reg = MIPI; | ||
157 | u32 dspcntr_reg = DSPACNTR; | ||
158 | u32 dspstatus_reg = PIPEASTAT; | ||
159 | u32 palette_reg = PALETTE_A; | ||
160 | |||
161 | /* pointer to values */ | ||
162 | u32 *dpll_val = &dev_priv->saveDPLL_A; | ||
163 | u32 *fp_val = &dev_priv->saveFPA0; | ||
164 | u32 *pipeconf_val = &dev_priv->savePIPEACONF; | ||
165 | u32 *htot_val = &dev_priv->saveHTOTAL_A; | ||
166 | u32 *hblank_val = &dev_priv->saveHBLANK_A; | ||
167 | u32 *hsync_val = &dev_priv->saveHSYNC_A; | ||
168 | u32 *vtot_val = &dev_priv->saveVTOTAL_A; | ||
169 | u32 *vblank_val = &dev_priv->saveVBLANK_A; | ||
170 | u32 *vsync_val = &dev_priv->saveVSYNC_A; | ||
171 | u32 *pipesrc_val = &dev_priv->savePIPEASRC; | ||
172 | u32 *dspstride_val = &dev_priv->saveDSPASTRIDE; | ||
173 | u32 *dsplinoff_val = &dev_priv->saveDSPALINOFF; | ||
174 | u32 *dsptileoff_val = &dev_priv->saveDSPATILEOFF; | ||
175 | u32 *dspsize_val = &dev_priv->saveDSPASIZE; | ||
176 | u32 *dsppos_val = &dev_priv->saveDSPAPOS; | ||
177 | u32 *dspsurf_val = &dev_priv->saveDSPASURF; | ||
178 | u32 *mipi_val = &dev_priv->saveMIPI; | ||
179 | u32 *dspcntr_val = &dev_priv->saveDSPACNTR; | ||
180 | u32 *dspstatus_val = &dev_priv->saveDSPASTATUS; | ||
181 | u32 *palette_val = dev_priv->save_palette_a; | ||
182 | |||
183 | switch (pipe) { | ||
184 | case 0: | ||
185 | break; | ||
186 | case 1: | ||
187 | /* register */ | ||
188 | dpll_reg = MDFLD_DPLL_B; | ||
189 | fp_reg = MDFLD_DPLL_DIV0; | ||
190 | pipeconf_reg = PIPEBCONF; | ||
191 | htot_reg = HTOTAL_B; | ||
192 | hblank_reg = HBLANK_B; | ||
193 | hsync_reg = HSYNC_B; | ||
194 | vtot_reg = VTOTAL_B; | ||
195 | vblank_reg = VBLANK_B; | ||
196 | vsync_reg = VSYNC_B; | ||
197 | pipesrc_reg = PIPEBSRC; | ||
198 | dspstride_reg = DSPBSTRIDE; | ||
199 | dsplinoff_reg = DSPBLINOFF; | ||
200 | dsptileoff_reg = DSPBTILEOFF; | ||
201 | dspsize_reg = DSPBSIZE; | ||
202 | dsppos_reg = DSPBPOS; | ||
203 | dspsurf_reg = DSPBSURF; | ||
204 | dspcntr_reg = DSPBCNTR; | ||
205 | dspstatus_reg = PIPEBSTAT; | ||
206 | palette_reg = PALETTE_B; | ||
207 | |||
208 | /* values */ | ||
209 | dpll_val = &dev_priv->saveDPLL_B; | ||
210 | fp_val = &dev_priv->saveFPB0; | ||
211 | pipeconf_val = &dev_priv->savePIPEBCONF; | ||
212 | htot_val = &dev_priv->saveHTOTAL_B; | ||
213 | hblank_val = &dev_priv->saveHBLANK_B; | ||
214 | hsync_val = &dev_priv->saveHSYNC_B; | ||
215 | vtot_val = &dev_priv->saveVTOTAL_B; | ||
216 | vblank_val = &dev_priv->saveVBLANK_B; | ||
217 | vsync_val = &dev_priv->saveVSYNC_B; | ||
218 | pipesrc_val = &dev_priv->savePIPEBSRC; | ||
219 | dspstride_val = &dev_priv->saveDSPBSTRIDE; | ||
220 | dsplinoff_val = &dev_priv->saveDSPBLINOFF; | ||
221 | dsptileoff_val = &dev_priv->saveDSPBTILEOFF; | ||
222 | dspsize_val = &dev_priv->saveDSPBSIZE; | ||
223 | dsppos_val = &dev_priv->saveDSPBPOS; | ||
224 | dspsurf_val = &dev_priv->saveDSPBSURF; | ||
225 | dspcntr_val = &dev_priv->saveDSPBCNTR; | ||
226 | dspstatus_val = &dev_priv->saveDSPBSTATUS; | ||
227 | palette_val = dev_priv->save_palette_b; | ||
228 | break; | ||
229 | case 2: | ||
230 | /* register */ | ||
231 | pipeconf_reg = PIPECCONF; | ||
232 | htot_reg = HTOTAL_C; | ||
233 | hblank_reg = HBLANK_C; | ||
234 | hsync_reg = HSYNC_C; | ||
235 | vtot_reg = VTOTAL_C; | ||
236 | vblank_reg = VBLANK_C; | ||
237 | vsync_reg = VSYNC_C; | ||
238 | pipesrc_reg = PIPECSRC; | ||
239 | dspstride_reg = DSPCSTRIDE; | ||
240 | dsplinoff_reg = DSPCLINOFF; | ||
241 | dsptileoff_reg = DSPCTILEOFF; | ||
242 | dspsize_reg = DSPCSIZE; | ||
243 | dsppos_reg = DSPCPOS; | ||
244 | dspsurf_reg = DSPCSURF; | ||
245 | mipi_reg = MIPI_C; | ||
246 | dspcntr_reg = DSPCCNTR; | ||
247 | dspstatus_reg = PIPECSTAT; | ||
248 | palette_reg = PALETTE_C; | ||
249 | |||
250 | /* pointer to values */ | ||
251 | pipeconf_val = &dev_priv->savePIPECCONF; | ||
252 | htot_val = &dev_priv->saveHTOTAL_C; | ||
253 | hblank_val = &dev_priv->saveHBLANK_C; | ||
254 | hsync_val = &dev_priv->saveHSYNC_C; | ||
255 | vtot_val = &dev_priv->saveVTOTAL_C; | ||
256 | vblank_val = &dev_priv->saveVBLANK_C; | ||
257 | vsync_val = &dev_priv->saveVSYNC_C; | ||
258 | pipesrc_val = &dev_priv->savePIPECSRC; | ||
259 | dspstride_val = &dev_priv->saveDSPCSTRIDE; | ||
260 | dsplinoff_val = &dev_priv->saveDSPCLINOFF; | ||
261 | dsptileoff_val = &dev_priv->saveDSPCTILEOFF; | ||
262 | dspsize_val = &dev_priv->saveDSPCSIZE; | ||
263 | dsppos_val = &dev_priv->saveDSPCPOS; | ||
264 | dspsurf_val = &dev_priv->saveDSPCSURF; | ||
265 | mipi_val = &dev_priv->saveMIPI_C; | ||
266 | dspcntr_val = &dev_priv->saveDSPCCNTR; | ||
267 | dspstatus_val = &dev_priv->saveDSPCSTATUS; | ||
268 | palette_val = dev_priv->save_palette_c; | ||
269 | break; | ||
270 | default: | ||
271 | DRM_ERROR("%s, invalid pipe number.\n", __func__); | ||
272 | return -EINVAL; | ||
273 | } | ||
274 | |||
275 | /* Pipe & plane A info */ | ||
276 | *dpll_val = PSB_RVDC32(dpll_reg); | ||
277 | *fp_val = PSB_RVDC32(fp_reg); | ||
278 | *pipeconf_val = PSB_RVDC32(pipeconf_reg); | ||
279 | *htot_val = PSB_RVDC32(htot_reg); | ||
280 | *hblank_val = PSB_RVDC32(hblank_reg); | ||
281 | *hsync_val = PSB_RVDC32(hsync_reg); | ||
282 | *vtot_val = PSB_RVDC32(vtot_reg); | ||
283 | *vblank_val = PSB_RVDC32(vblank_reg); | ||
284 | *vsync_val = PSB_RVDC32(vsync_reg); | ||
285 | *pipesrc_val = PSB_RVDC32(pipesrc_reg); | ||
286 | *dspstride_val = PSB_RVDC32(dspstride_reg); | ||
287 | *dsplinoff_val = PSB_RVDC32(dsplinoff_reg); | ||
288 | *dsptileoff_val = PSB_RVDC32(dsptileoff_reg); | ||
289 | *dspsize_val = PSB_RVDC32(dspsize_reg); | ||
290 | *dsppos_val = PSB_RVDC32(dsppos_reg); | ||
291 | *dspsurf_val = PSB_RVDC32(dspsurf_reg); | ||
292 | *dspcntr_val = PSB_RVDC32(dspcntr_reg); | ||
293 | *dspstatus_val = PSB_RVDC32(dspstatus_reg); | ||
294 | |||
295 | /*save palette (gamma) */ | ||
296 | for (i = 0; i < 256; i++) | ||
297 | palette_val[i] = PSB_RVDC32(palette_reg + (i<<2)); | ||
298 | |||
299 | if (pipe == 1) { | ||
300 | dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); | ||
301 | dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); | ||
302 | dev_priv->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL); | ||
303 | dev_priv->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL); | ||
304 | return 0; | ||
305 | } | ||
306 | *mipi_val = PSB_RVDC32(mipi_reg); | ||
307 | return 0; | ||
308 | } | ||
309 | |||
310 | /** | ||
311 | * mdfld_save_cursor_overlay_registers - save cursor overlay info | ||
312 | * @dev: our device | ||
313 | * | ||
314 | * Save the cursor and overlay register state | ||
315 | */ | ||
316 | static int mdfld_save_cursor_overlay_registers(struct drm_device *dev) | ||
317 | { | ||
318 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
319 | |||
320 | /* Save cursor regs */ | ||
321 | dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR); | ||
322 | dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE); | ||
323 | dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS); | ||
324 | |||
325 | dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR); | ||
326 | dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE); | ||
327 | dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS); | ||
328 | |||
329 | dev_priv->saveDSPCCURSOR_CTRL = PSB_RVDC32(CURCCNTR); | ||
330 | dev_priv->saveDSPCCURSOR_BASE = PSB_RVDC32(CURCBASE); | ||
331 | dev_priv->saveDSPCCURSOR_POS = PSB_RVDC32(CURCPOS); | ||
332 | |||
333 | /* HW overlay */ | ||
334 | dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD); | ||
335 | dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0); | ||
336 | dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1); | ||
337 | dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2); | ||
338 | dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3); | ||
339 | dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4); | ||
340 | dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5); | ||
341 | |||
342 | dev_priv->saveOV_OVADD_C = PSB_RVDC32(OV_OVADD + OV_C_OFFSET); | ||
343 | dev_priv->saveOV_OGAMC0_C = PSB_RVDC32(OV_OGAMC0 + OV_C_OFFSET); | ||
344 | dev_priv->saveOV_OGAMC1_C = PSB_RVDC32(OV_OGAMC1 + OV_C_OFFSET); | ||
345 | dev_priv->saveOV_OGAMC2_C = PSB_RVDC32(OV_OGAMC2 + OV_C_OFFSET); | ||
346 | dev_priv->saveOV_OGAMC3_C = PSB_RVDC32(OV_OGAMC3 + OV_C_OFFSET); | ||
347 | dev_priv->saveOV_OGAMC4_C = PSB_RVDC32(OV_OGAMC4 + OV_C_OFFSET); | ||
348 | dev_priv->saveOV_OGAMC5_C = PSB_RVDC32(OV_OGAMC5 + OV_C_OFFSET); | ||
349 | |||
350 | return 0; | ||
351 | } | ||
352 | /* | ||
353 | * mdfld_restore_display_registers - restore the state of a pipe | ||
354 | * @dev: our device | ||
355 | * @pipe: the pipe to restore | ||
356 | * | ||
357 | * Restore the state of a pipe to that which was saved by the register save | ||
358 | * functions. | ||
359 | */ | ||
360 | static int mdfld_restore_display_registers(struct drm_device *dev, int pipe) | ||
361 | { | ||
362 | /* To get panel out of ULPS mode */ | ||
363 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
364 | struct mdfld_dsi_config *dsi_config = NULL; | ||
365 | u32 i = 0; | ||
366 | u32 dpll = 0; | ||
367 | u32 timeout = 0; | ||
368 | u32 reg_offset = 0; | ||
369 | |||
370 | /* register */ | ||
371 | u32 dpll_reg = MRST_DPLL_A; | ||
372 | u32 fp_reg = MRST_FPA0; | ||
373 | u32 pipeconf_reg = PIPEACONF; | ||
374 | u32 htot_reg = HTOTAL_A; | ||
375 | u32 hblank_reg = HBLANK_A; | ||
376 | u32 hsync_reg = HSYNC_A; | ||
377 | u32 vtot_reg = VTOTAL_A; | ||
378 | u32 vblank_reg = VBLANK_A; | ||
379 | u32 vsync_reg = VSYNC_A; | ||
380 | u32 pipesrc_reg = PIPEASRC; | ||
381 | u32 dspstride_reg = DSPASTRIDE; | ||
382 | u32 dsplinoff_reg = DSPALINOFF; | ||
383 | u32 dsptileoff_reg = DSPATILEOFF; | ||
384 | u32 dspsize_reg = DSPASIZE; | ||
385 | u32 dsppos_reg = DSPAPOS; | ||
386 | u32 dspsurf_reg = DSPASURF; | ||
387 | u32 dspstatus_reg = PIPEASTAT; | ||
388 | u32 mipi_reg = MIPI; | ||
389 | u32 dspcntr_reg = DSPACNTR; | ||
390 | u32 palette_reg = PALETTE_A; | ||
391 | |||
392 | /* values */ | ||
393 | u32 dpll_val = dev_priv->saveDPLL_A & ~DPLL_VCO_ENABLE; | ||
394 | u32 fp_val = dev_priv->saveFPA0; | ||
395 | u32 pipeconf_val = dev_priv->savePIPEACONF; | ||
396 | u32 htot_val = dev_priv->saveHTOTAL_A; | ||
397 | u32 hblank_val = dev_priv->saveHBLANK_A; | ||
398 | u32 hsync_val = dev_priv->saveHSYNC_A; | ||
399 | u32 vtot_val = dev_priv->saveVTOTAL_A; | ||
400 | u32 vblank_val = dev_priv->saveVBLANK_A; | ||
401 | u32 vsync_val = dev_priv->saveVSYNC_A; | ||
402 | u32 pipesrc_val = dev_priv->savePIPEASRC; | ||
403 | u32 dspstride_val = dev_priv->saveDSPASTRIDE; | ||
404 | u32 dsplinoff_val = dev_priv->saveDSPALINOFF; | ||
405 | u32 dsptileoff_val = dev_priv->saveDSPATILEOFF; | ||
406 | u32 dspsize_val = dev_priv->saveDSPASIZE; | ||
407 | u32 dsppos_val = dev_priv->saveDSPAPOS; | ||
408 | u32 dspsurf_val = dev_priv->saveDSPASURF; | ||
409 | u32 dspstatus_val = dev_priv->saveDSPASTATUS; | ||
410 | u32 mipi_val = dev_priv->saveMIPI; | ||
411 | u32 dspcntr_val = dev_priv->saveDSPACNTR; | ||
412 | u32 *palette_val = dev_priv->save_palette_a; | ||
413 | |||
414 | switch (pipe) { | ||
415 | case 0: | ||
416 | dsi_config = dev_priv->dsi_configs[0]; | ||
417 | break; | ||
418 | case 1: | ||
419 | /* register */ | ||
420 | dpll_reg = MDFLD_DPLL_B; | ||
421 | fp_reg = MDFLD_DPLL_DIV0; | ||
422 | pipeconf_reg = PIPEBCONF; | ||
423 | htot_reg = HTOTAL_B; | ||
424 | hblank_reg = HBLANK_B; | ||
425 | hsync_reg = HSYNC_B; | ||
426 | vtot_reg = VTOTAL_B; | ||
427 | vblank_reg = VBLANK_B; | ||
428 | vsync_reg = VSYNC_B; | ||
429 | pipesrc_reg = PIPEBSRC; | ||
430 | dspstride_reg = DSPBSTRIDE; | ||
431 | dsplinoff_reg = DSPBLINOFF; | ||
432 | dsptileoff_reg = DSPBTILEOFF; | ||
433 | dspsize_reg = DSPBSIZE; | ||
434 | dsppos_reg = DSPBPOS; | ||
435 | dspsurf_reg = DSPBSURF; | ||
436 | dspcntr_reg = DSPBCNTR; | ||
437 | palette_reg = PALETTE_B; | ||
438 | dspstatus_reg = PIPEBSTAT; | ||
439 | |||
440 | /* values */ | ||
441 | dpll_val = dev_priv->saveDPLL_B & ~DPLL_VCO_ENABLE; | ||
442 | fp_val = dev_priv->saveFPB0; | ||
443 | pipeconf_val = dev_priv->savePIPEBCONF; | ||
444 | htot_val = dev_priv->saveHTOTAL_B; | ||
445 | hblank_val = dev_priv->saveHBLANK_B; | ||
446 | hsync_val = dev_priv->saveHSYNC_B; | ||
447 | vtot_val = dev_priv->saveVTOTAL_B; | ||
448 | vblank_val = dev_priv->saveVBLANK_B; | ||
449 | vsync_val = dev_priv->saveVSYNC_B; | ||
450 | pipesrc_val = dev_priv->savePIPEBSRC; | ||
451 | dspstride_val = dev_priv->saveDSPBSTRIDE; | ||
452 | dsplinoff_val = dev_priv->saveDSPBLINOFF; | ||
453 | dsptileoff_val = dev_priv->saveDSPBTILEOFF; | ||
454 | dspsize_val = dev_priv->saveDSPBSIZE; | ||
455 | dsppos_val = dev_priv->saveDSPBPOS; | ||
456 | dspsurf_val = dev_priv->saveDSPBSURF; | ||
457 | dspcntr_val = dev_priv->saveDSPBCNTR; | ||
458 | dspstatus_val = dev_priv->saveDSPBSTATUS; | ||
459 | palette_val = dev_priv->save_palette_b; | ||
460 | break; | ||
461 | case 2: | ||
462 | reg_offset = MIPIC_REG_OFFSET; | ||
463 | |||
464 | /* register */ | ||
465 | pipeconf_reg = PIPECCONF; | ||
466 | htot_reg = HTOTAL_C; | ||
467 | hblank_reg = HBLANK_C; | ||
468 | hsync_reg = HSYNC_C; | ||
469 | vtot_reg = VTOTAL_C; | ||
470 | vblank_reg = VBLANK_C; | ||
471 | vsync_reg = VSYNC_C; | ||
472 | pipesrc_reg = PIPECSRC; | ||
473 | dspstride_reg = DSPCSTRIDE; | ||
474 | dsplinoff_reg = DSPCLINOFF; | ||
475 | dsptileoff_reg = DSPCTILEOFF; | ||
476 | dspsize_reg = DSPCSIZE; | ||
477 | dsppos_reg = DSPCPOS; | ||
478 | dspsurf_reg = DSPCSURF; | ||
479 | mipi_reg = MIPI_C; | ||
480 | dspcntr_reg = DSPCCNTR; | ||
481 | palette_reg = PALETTE_C; | ||
482 | dspstatus_reg = PIPECSTAT; | ||
483 | |||
484 | /* values */ | ||
485 | pipeconf_val = dev_priv->savePIPECCONF; | ||
486 | htot_val = dev_priv->saveHTOTAL_C; | ||
487 | hblank_val = dev_priv->saveHBLANK_C; | ||
488 | hsync_val = dev_priv->saveHSYNC_C; | ||
489 | vtot_val = dev_priv->saveVTOTAL_C; | ||
490 | vblank_val = dev_priv->saveVBLANK_C; | ||
491 | vsync_val = dev_priv->saveVSYNC_C; | ||
492 | pipesrc_val = dev_priv->savePIPECSRC; | ||
493 | dspstride_val = dev_priv->saveDSPCSTRIDE; | ||
494 | dsplinoff_val = dev_priv->saveDSPCLINOFF; | ||
495 | dsptileoff_val = dev_priv->saveDSPCTILEOFF; | ||
496 | dspsize_val = dev_priv->saveDSPCSIZE; | ||
497 | dsppos_val = dev_priv->saveDSPCPOS; | ||
498 | dspsurf_val = dev_priv->saveDSPCSURF; | ||
499 | dspstatus_val = dev_priv->saveDSPCSTATUS; | ||
500 | mipi_val = dev_priv->saveMIPI_C; | ||
501 | dspcntr_val = dev_priv->saveDSPCCNTR; | ||
502 | palette_val = dev_priv->save_palette_c; | ||
503 | |||
504 | dsi_config = dev_priv->dsi_configs[1]; | ||
505 | break; | ||
506 | default: | ||
507 | DRM_ERROR("%s, invalid pipe number.\n", __func__); | ||
508 | return -EINVAL; | ||
509 | } | ||
510 | |||
511 | /* Make sure VGA plane is off. it initializes to on after reset!*/ | ||
512 | PSB_WVDC32(0x80000000, VGACNTRL); | ||
513 | if (pipe == 1) { | ||
514 | PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg); | ||
515 | PSB_RVDC32(dpll_reg); | ||
516 | |||
517 | PSB_WVDC32(fp_val, fp_reg); | ||
518 | } else { | ||
519 | dpll = PSB_RVDC32(dpll_reg); | ||
520 | |||
521 | if (!(dpll & DPLL_VCO_ENABLE)) { | ||
522 | |||
523 | /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */ | ||
524 | if (dpll & MDFLD_PWR_GATE_EN) { | ||
525 | dpll &= ~MDFLD_PWR_GATE_EN; | ||
526 | PSB_WVDC32(dpll, dpll_reg); | ||
527 | udelay(500); /* FIXME: 1 ? */ | ||
528 | } | ||
529 | |||
530 | PSB_WVDC32(fp_val, fp_reg); | ||
531 | PSB_WVDC32(dpll_val, dpll_reg); | ||
532 | /* FIXME_MDFLD PO - change 500 to 1 after PO */ | ||
533 | udelay(500); | ||
534 | |||
535 | dpll_val |= DPLL_VCO_ENABLE; | ||
536 | PSB_WVDC32(dpll_val, dpll_reg); | ||
537 | PSB_RVDC32(dpll_reg); | ||
538 | |||
539 | /* wait for DSI PLL to lock */ | ||
540 | while ((timeout < 20000) && !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { | ||
541 | udelay(150); | ||
542 | timeout++; | ||
543 | } | ||
544 | |||
545 | if (timeout == 20000) { | ||
546 | DRM_ERROR("%s, can't lock DSIPLL.\n", | ||
547 | __func__); | ||
548 | return -EINVAL; | ||
549 | } | ||
550 | } | ||
551 | } | ||
552 | /* Restore mode */ | ||
553 | PSB_WVDC32(htot_val, htot_reg); | ||
554 | PSB_WVDC32(hblank_val, hblank_reg); | ||
555 | PSB_WVDC32(hsync_val, hsync_reg); | ||
556 | PSB_WVDC32(vtot_val, vtot_reg); | ||
557 | PSB_WVDC32(vblank_val, vblank_reg); | ||
558 | PSB_WVDC32(vsync_val, vsync_reg); | ||
559 | PSB_WVDC32(pipesrc_val, pipesrc_reg); | ||
560 | PSB_WVDC32(dspstatus_val, dspstatus_reg); | ||
561 | |||
562 | /* Set up the plane */ | ||
563 | PSB_WVDC32(dspstride_val, dspstride_reg); | ||
564 | PSB_WVDC32(dsplinoff_val, dsplinoff_reg); | ||
565 | PSB_WVDC32(dsptileoff_val, dsptileoff_reg); | ||
566 | PSB_WVDC32(dspsize_val, dspsize_reg); | ||
567 | PSB_WVDC32(dsppos_val, dsppos_reg); | ||
568 | PSB_WVDC32(dspsurf_val, dspsurf_reg); | ||
569 | |||
570 | if (pipe == 1) { | ||
571 | PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL); | ||
572 | PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); | ||
573 | PSB_WVDC32(dev_priv->saveHDMIPHYMISCCTL, HDMIPHYMISCCTL); | ||
574 | PSB_WVDC32(dev_priv->saveHDMIB_CONTROL, HDMIB_CONTROL); | ||
575 | |||
576 | } else { | ||
577 | /* Set up pipe related registers */ | ||
578 | PSB_WVDC32(mipi_val, mipi_reg); | ||
579 | /* Setup MIPI adapter + MIPI IP registers */ | ||
580 | mdfld_dsi_controller_init(dsi_config, pipe); | ||
581 | msleep(20); | ||
582 | } | ||
583 | /* Enable the plane */ | ||
584 | PSB_WVDC32(dspcntr_val, dspcntr_reg); | ||
585 | msleep(20); | ||
586 | /* Enable the pipe */ | ||
587 | PSB_WVDC32(pipeconf_val, pipeconf_reg); | ||
588 | |||
589 | for (i = 0; i < 256; i++) | ||
590 | PSB_WVDC32(palette_val[i], palette_reg + (i<<2)); | ||
591 | if (pipe == 1) | ||
592 | return 0; | ||
593 | if (!mdfld_panel_dpi(dev)) | ||
594 | mdfld_enable_te(dev, pipe); | ||
595 | return 0; | ||
596 | } | ||
597 | |||
598 | /** | ||
599 | * mdfld_restore_cursor_overlay_registers - restore cursor | ||
600 | * @dev: our device | ||
601 | * | ||
602 | * Restore the cursor and overlay state that was saved earlier | ||
603 | */ | ||
604 | static int mdfld_restore_cursor_overlay_registers(struct drm_device *dev) | ||
605 | { | ||
606 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
607 | |||
608 | /* Enable Cursor A */ | ||
609 | PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR); | ||
610 | PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS); | ||
611 | PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE); | ||
612 | |||
613 | PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR); | ||
614 | PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS); | ||
615 | PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE); | ||
616 | |||
617 | PSB_WVDC32(dev_priv->saveDSPCCURSOR_CTRL, CURCCNTR); | ||
618 | PSB_WVDC32(dev_priv->saveDSPCCURSOR_POS, CURCPOS); | ||
619 | PSB_WVDC32(dev_priv->saveDSPCCURSOR_BASE, CURCBASE); | ||
620 | |||
621 | /* Restore HW overlay */ | ||
622 | PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD); | ||
623 | PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0); | ||
624 | PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1); | ||
625 | PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2); | ||
626 | PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3); | ||
627 | PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4); | ||
628 | PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5); | ||
629 | |||
630 | PSB_WVDC32(dev_priv->saveOV_OVADD_C, OV_OVADD + OV_C_OFFSET); | ||
631 | PSB_WVDC32(dev_priv->saveOV_OGAMC0_C, OV_OGAMC0 + OV_C_OFFSET); | ||
632 | PSB_WVDC32(dev_priv->saveOV_OGAMC1_C, OV_OGAMC1 + OV_C_OFFSET); | ||
633 | PSB_WVDC32(dev_priv->saveOV_OGAMC2_C, OV_OGAMC2 + OV_C_OFFSET); | ||
634 | PSB_WVDC32(dev_priv->saveOV_OGAMC3_C, OV_OGAMC3 + OV_C_OFFSET); | ||
635 | PSB_WVDC32(dev_priv->saveOV_OGAMC4_C, OV_OGAMC4 + OV_C_OFFSET); | ||
636 | PSB_WVDC32(dev_priv->saveOV_OGAMC5_C, OV_OGAMC5 + OV_C_OFFSET); | ||
637 | |||
638 | return 0; | ||
639 | } | ||
640 | |||
641 | /** | ||
642 | * mdfld_save_display_registers - save registers lost on suspend | ||
643 | * @dev: our DRM device | ||
644 | * | ||
645 | * Save the state we need in order to be able to restore the interface | ||
646 | * upon resume from suspend | ||
647 | */ | ||
648 | static int mdfld_save_registers(struct drm_device *dev) | ||
649 | { | ||
650 | /* FIXME: We need to shut down panels here if using them | ||
651 | and once the right bits are merged */ | ||
652 | mdfld_save_cursor_overlay_registers(dev); | ||
653 | mdfld_save_display_registers(dev, 0); | ||
654 | mdfld_save_display_registers(dev, 0); | ||
655 | mdfld_save_display_registers(dev, 2); | ||
656 | mdfld_save_display_registers(dev, 1); | ||
657 | mdfld_disable_crtc(dev, 0); | ||
658 | mdfld_disable_crtc(dev, 2); | ||
659 | mdfld_disable_crtc(dev, 1); | ||
660 | return 0; | ||
661 | } | ||
662 | |||
663 | /** | ||
664 | * mdfld_restore_display_registers - restore lost register state | ||
665 | * @dev: our DRM device | ||
666 | * | ||
667 | * Restore register state that was lost during suspend and resume. | ||
668 | */ | ||
669 | static int mdfld_restore_registers(struct drm_device *dev) | ||
670 | { | ||
671 | mdfld_restore_display_registers(dev, 1); | ||
672 | mdfld_restore_display_registers(dev, 0); | ||
673 | mdfld_restore_display_registers(dev, 2); | ||
674 | mdfld_restore_cursor_overlay_registers(dev); | ||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | static int mdfld_power_down(struct drm_device *dev) | ||
679 | { | ||
680 | /* FIXME */ | ||
681 | return 0; | ||
682 | } | ||
683 | |||
684 | static int mdfld_power_up(struct drm_device *dev) | ||
685 | { | ||
686 | /* FIXME */ | ||
687 | return 0; | ||
688 | } | ||
689 | |||
690 | const struct psb_ops mdfld_chip_ops = { | ||
691 | .name = "Medfield", | ||
692 | .accel_2d = 0, | ||
693 | .pipes = 3, | ||
694 | .crtcs = 2, | ||
695 | .sgx_offset = MRST_SGX_OFFSET, | ||
696 | |||
697 | .chip_setup = mid_chip_setup, | ||
698 | |||
699 | .crtc_helper = &mdfld_helper_funcs, | ||
700 | .crtc_funcs = &mdfld_intel_crtc_funcs, | ||
701 | |||
702 | .output_init = mdfld_output_init, | ||
703 | |||
704 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
705 | .backlight_init = mdfld_backlight_init, | ||
706 | #endif | ||
707 | |||
708 | .init_pm = mdfld_init_pm, | ||
709 | .save_regs = mdfld_save_registers, | ||
710 | .restore_regs = mdfld_restore_registers, | ||
711 | .power_down = mdfld_power_down, | ||
712 | .power_up = mdfld_power_up, | ||
713 | }; | ||
714 | |||
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.c b/drivers/staging/gma500/mdfld_dsi_dbi.c deleted file mode 100644 index fd211f3467c4..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_dbi.c +++ /dev/null | |||
@@ -1,761 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
26 | */ | ||
27 | |||
28 | #include "mdfld_dsi_dbi.h" | ||
29 | #include "mdfld_dsi_dbi_dpu.h" | ||
30 | #include "mdfld_dsi_pkg_sender.h" | ||
31 | |||
32 | #include "power.h" | ||
33 | #include <linux/pm_runtime.h> | ||
34 | |||
35 | int enable_gfx_rtpm; | ||
36 | |||
37 | extern struct drm_device *gpDrmDevice; | ||
38 | extern int gfxrtdelay; | ||
39 | int enter_dsr; | ||
40 | struct mdfld_dsi_dbi_output *gdbi_output; | ||
41 | extern bool gbgfxsuspended; | ||
42 | extern int enable_gfx_rtpm; | ||
43 | extern int gfxrtdelay; | ||
44 | |||
45 | #define MDFLD_DSR_MAX_IDLE_COUNT 2 | ||
46 | |||
47 | /* | ||
48 | * set refreshing area | ||
49 | */ | ||
50 | int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output, | ||
51 | u16 x1, u16 y1, u16 x2, u16 y2) | ||
52 | { | ||
53 | struct mdfld_dsi_pkg_sender *sender = | ||
54 | mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); | ||
55 | u8 param[4]; | ||
56 | u8 cmd; | ||
57 | int err; | ||
58 | |||
59 | if (!sender) { | ||
60 | WARN_ON(1); | ||
61 | return -EINVAL; | ||
62 | } | ||
63 | |||
64 | /* Set column */ | ||
65 | cmd = DCS_SET_COLUMN_ADDRESS; | ||
66 | param[0] = x1 >> 8; | ||
67 | param[1] = x1; | ||
68 | param[2] = x2 >> 8; | ||
69 | param[3] = x2; | ||
70 | |||
71 | err = mdfld_dsi_send_dcs(sender, | ||
72 | cmd, | ||
73 | param, | ||
74 | 4, | ||
75 | CMD_DATA_SRC_SYSTEM_MEM, | ||
76 | MDFLD_DSI_QUEUE_PACKAGE); | ||
77 | if (err) { | ||
78 | dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); | ||
79 | goto err_out; | ||
80 | } | ||
81 | |||
82 | /* Set page */ | ||
83 | cmd = DCS_SET_PAGE_ADDRESS; | ||
84 | param[0] = y1 >> 8; | ||
85 | param[1] = y1; | ||
86 | param[2] = y2 >> 8; | ||
87 | param[3] = y2; | ||
88 | |||
89 | err = mdfld_dsi_send_dcs(sender, | ||
90 | cmd, | ||
91 | param, | ||
92 | 4, | ||
93 | CMD_DATA_SRC_SYSTEM_MEM, | ||
94 | MDFLD_DSI_QUEUE_PACKAGE); | ||
95 | if (err) { | ||
96 | dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); | ||
97 | goto err_out; | ||
98 | } | ||
99 | |||
100 | /*update screen*/ | ||
101 | err = mdfld_dsi_send_dcs(sender, | ||
102 | write_mem_start, | ||
103 | NULL, | ||
104 | 0, | ||
105 | CMD_DATA_SRC_PIPE, | ||
106 | MDFLD_DSI_QUEUE_PACKAGE); | ||
107 | if (err) { | ||
108 | dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd); | ||
109 | goto err_out; | ||
110 | } | ||
111 | mdfld_dsi_cmds_kick_out(sender); | ||
112 | err_out: | ||
113 | return err; | ||
114 | } | ||
115 | |||
116 | /* | ||
117 | * set panel's power state | ||
118 | */ | ||
119 | int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output, | ||
120 | int mode) | ||
121 | { | ||
122 | struct drm_device *dev = dbi_output->dev; | ||
123 | struct mdfld_dsi_pkg_sender *sender = | ||
124 | mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); | ||
125 | u8 param = 0; | ||
126 | u32 err = 0; | ||
127 | |||
128 | if (!sender) { | ||
129 | WARN_ON(1); | ||
130 | return -EINVAL; | ||
131 | } | ||
132 | |||
133 | if (mode == DRM_MODE_DPMS_ON) { | ||
134 | /* Exit sleep mode */ | ||
135 | err = mdfld_dsi_send_dcs(sender, | ||
136 | DCS_EXIT_SLEEP_MODE, | ||
137 | NULL, | ||
138 | 0, | ||
139 | CMD_DATA_SRC_SYSTEM_MEM, | ||
140 | MDFLD_DSI_QUEUE_PACKAGE); | ||
141 | if (err) { | ||
142 | dev_err(dev->dev, "DCS 0x%x sent failed\n", | ||
143 | DCS_EXIT_SLEEP_MODE); | ||
144 | goto power_err; | ||
145 | } | ||
146 | |||
147 | /* Set display on */ | ||
148 | err = mdfld_dsi_send_dcs(sender, | ||
149 | DCS_SET_DISPLAY_ON, | ||
150 | NULL, | ||
151 | 0, | ||
152 | CMD_DATA_SRC_SYSTEM_MEM, | ||
153 | MDFLD_DSI_QUEUE_PACKAGE); | ||
154 | if (err) { | ||
155 | dev_err(dev->dev, "DCS 0x%x sent failed\n", | ||
156 | DCS_SET_DISPLAY_ON); | ||
157 | goto power_err; | ||
158 | } | ||
159 | |||
160 | /* set tear effect on */ | ||
161 | err = mdfld_dsi_send_dcs(sender, | ||
162 | DCS_SET_TEAR_ON, | ||
163 | ¶m, | ||
164 | 1, | ||
165 | CMD_DATA_SRC_SYSTEM_MEM, | ||
166 | MDFLD_DSI_QUEUE_PACKAGE); | ||
167 | if (err) { | ||
168 | dev_err(dev->dev, "DCS 0x%x sent failed\n", | ||
169 | set_tear_on); | ||
170 | goto power_err; | ||
171 | } | ||
172 | |||
173 | /** | ||
174 | * FIXME: remove this later | ||
175 | */ | ||
176 | err = mdfld_dsi_send_dcs(sender, | ||
177 | DCS_WRITE_MEM_START, | ||
178 | NULL, | ||
179 | 0, | ||
180 | CMD_DATA_SRC_PIPE, | ||
181 | MDFLD_DSI_QUEUE_PACKAGE); | ||
182 | if (err) { | ||
183 | dev_err(dev->dev, "DCS 0x%x sent failed\n", | ||
184 | DCS_WRITE_MEM_START); | ||
185 | goto power_err; | ||
186 | } | ||
187 | } else { | ||
188 | /* Set tear effect off */ | ||
189 | err = mdfld_dsi_send_dcs(sender, | ||
190 | DCS_SET_TEAR_OFF, | ||
191 | NULL, | ||
192 | 0, | ||
193 | CMD_DATA_SRC_SYSTEM_MEM, | ||
194 | MDFLD_DSI_QUEUE_PACKAGE); | ||
195 | if (err) { | ||
196 | dev_err(dev->dev, "DCS 0x%x sent failed\n", | ||
197 | DCS_SET_TEAR_OFF); | ||
198 | goto power_err; | ||
199 | } | ||
200 | |||
201 | /* Turn display off */ | ||
202 | err = mdfld_dsi_send_dcs(sender, | ||
203 | DCS_SET_DISPLAY_OFF, | ||
204 | NULL, | ||
205 | 0, | ||
206 | CMD_DATA_SRC_SYSTEM_MEM, | ||
207 | MDFLD_DSI_QUEUE_PACKAGE); | ||
208 | if (err) { | ||
209 | dev_err(dev->dev, "DCS 0x%x sent failed\n", | ||
210 | DCS_SET_DISPLAY_OFF); | ||
211 | goto power_err; | ||
212 | } | ||
213 | |||
214 | /* Now enter sleep mode */ | ||
215 | err = mdfld_dsi_send_dcs(sender, | ||
216 | DCS_ENTER_SLEEP_MODE, | ||
217 | NULL, | ||
218 | 0, | ||
219 | CMD_DATA_SRC_SYSTEM_MEM, | ||
220 | MDFLD_DSI_QUEUE_PACKAGE); | ||
221 | if (err) { | ||
222 | dev_err(dev->dev, "DCS 0x%x sent failed\n", | ||
223 | DCS_ENTER_SLEEP_MODE); | ||
224 | goto power_err; | ||
225 | } | ||
226 | } | ||
227 | mdfld_dsi_cmds_kick_out(sender); | ||
228 | power_err: | ||
229 | return err; | ||
230 | } | ||
231 | |||
232 | /* | ||
233 | * send a generic DCS command with a parameter list | ||
234 | */ | ||
235 | int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output, | ||
236 | u8 dcs, u8 *param, u32 num, u8 data_src) | ||
237 | { | ||
238 | struct mdfld_dsi_pkg_sender *sender = | ||
239 | mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); | ||
240 | int ret; | ||
241 | |||
242 | if (!sender) { | ||
243 | WARN_ON(1); | ||
244 | return -EINVAL; | ||
245 | } | ||
246 | |||
247 | ret = mdfld_dsi_send_dcs(sender, | ||
248 | dcs, | ||
249 | param, | ||
250 | num, | ||
251 | data_src, | ||
252 | MDFLD_DSI_SEND_PACKAGE); | ||
253 | |||
254 | return ret; | ||
255 | } | ||
256 | |||
257 | /* | ||
258 | * Enter DSR | ||
259 | */ | ||
260 | void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe) | ||
261 | { | ||
262 | u32 reg_val; | ||
263 | struct drm_device *dev = dbi_output->dev; | ||
264 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
265 | struct drm_crtc *crtc = dbi_output->base.base.crtc; | ||
266 | struct psb_intel_crtc *psb_crtc = (crtc) ? | ||
267 | to_psb_intel_crtc(crtc) : NULL; | ||
268 | u32 dpll_reg = MRST_DPLL_A; | ||
269 | u32 pipeconf_reg = PIPEACONF; | ||
270 | u32 dspcntr_reg = DSPACNTR; | ||
271 | |||
272 | if (!dbi_output) | ||
273 | return; | ||
274 | |||
275 | /* FIXME check if can go */ | ||
276 | dev_priv->is_in_idle = true; | ||
277 | |||
278 | gdbi_output = dbi_output; | ||
279 | if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || | ||
280 | (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) | ||
281 | return; | ||
282 | |||
283 | if (pipe == 2) { | ||
284 | dpll_reg = MRST_DPLL_A; | ||
285 | pipeconf_reg = PIPECCONF; | ||
286 | dspcntr_reg = DSPCCNTR; | ||
287 | } | ||
288 | |||
289 | if (!gma_power_begin(dev, true)) { | ||
290 | dev_err(dev->dev, "hw begin failed\n"); | ||
291 | return; | ||
292 | } | ||
293 | /* Disable te interrupts */ | ||
294 | mdfld_disable_te(dev, pipe); | ||
295 | |||
296 | /* Disable plane */ | ||
297 | reg_val = REG_READ(dspcntr_reg); | ||
298 | if (!(reg_val & DISPLAY_PLANE_ENABLE)) { | ||
299 | REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE); | ||
300 | REG_READ(dspcntr_reg); | ||
301 | } | ||
302 | |||
303 | /* Disable pipe */ | ||
304 | reg_val = REG_READ(pipeconf_reg); | ||
305 | if (!(reg_val & DISPLAY_PLANE_ENABLE)) { | ||
306 | reg_val &= ~DISPLAY_PLANE_ENABLE; | ||
307 | reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF); | ||
308 | REG_WRITE(pipeconf_reg, reg_val); | ||
309 | REG_READ(pipeconf_reg); | ||
310 | mdfldWaitForPipeDisable(dev, pipe); | ||
311 | } | ||
312 | |||
313 | /* Disable DPLL */ | ||
314 | reg_val = REG_READ(dpll_reg); | ||
315 | if (!(reg_val & DPLL_VCO_ENABLE)) { | ||
316 | reg_val &= ~DPLL_VCO_ENABLE; | ||
317 | REG_WRITE(dpll_reg, reg_val); | ||
318 | REG_READ(dpll_reg); | ||
319 | udelay(500); | ||
320 | } | ||
321 | |||
322 | gma_power_end(dev); | ||
323 | dbi_output->mode_flags |= MODE_SETTING_IN_DSR; | ||
324 | if (pipe == 2) { | ||
325 | enter_dsr = 1; | ||
326 | /* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */ | ||
327 | } | ||
328 | } | ||
329 | |||
330 | static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output, | ||
331 | int pipe) | ||
332 | { | ||
333 | struct drm_device *dev = dbi_output->dev; | ||
334 | struct drm_crtc *crtc = dbi_output->base.base.crtc; | ||
335 | struct psb_intel_crtc *psb_crtc = (crtc) ? | ||
336 | to_psb_intel_crtc(crtc) : NULL; | ||
337 | u32 reg_val; | ||
338 | u32 dpll_reg = MRST_DPLL_A; | ||
339 | u32 pipeconf_reg = PIPEACONF; | ||
340 | u32 dspcntr_reg = DSPACNTR; | ||
341 | u32 reg_offset = 0; | ||
342 | |||
343 | /*if mode setting on-going, back off*/ | ||
344 | if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || | ||
345 | (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) | ||
346 | return; | ||
347 | |||
348 | if (pipe == 2) { | ||
349 | dpll_reg = MRST_DPLL_A; | ||
350 | pipeconf_reg = PIPECCONF; | ||
351 | dspcntr_reg = DSPCCNTR; | ||
352 | reg_offset = MIPIC_REG_OFFSET; | ||
353 | } | ||
354 | |||
355 | if (!gma_power_begin(dev, true)) { | ||
356 | dev_err(dev->dev, "hw begin failed\n"); | ||
357 | return; | ||
358 | } | ||
359 | |||
360 | /* Enable DPLL */ | ||
361 | reg_val = REG_READ(dpll_reg); | ||
362 | if (!(reg_val & DPLL_VCO_ENABLE)) { | ||
363 | if (reg_val & MDFLD_PWR_GATE_EN) { | ||
364 | reg_val &= ~MDFLD_PWR_GATE_EN; | ||
365 | REG_WRITE(dpll_reg, reg_val); | ||
366 | REG_READ(dpll_reg); | ||
367 | udelay(500); | ||
368 | } | ||
369 | |||
370 | reg_val |= DPLL_VCO_ENABLE; | ||
371 | REG_WRITE(dpll_reg, reg_val); | ||
372 | REG_READ(dpll_reg); | ||
373 | udelay(500); | ||
374 | |||
375 | /* Add timeout */ | ||
376 | while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) | ||
377 | cpu_relax(); | ||
378 | } | ||
379 | |||
380 | /* Enable pipe */ | ||
381 | reg_val = REG_READ(pipeconf_reg); | ||
382 | if (!(reg_val & PIPEACONF_ENABLE)) { | ||
383 | reg_val |= PIPEACONF_ENABLE; | ||
384 | REG_WRITE(pipeconf_reg, reg_val); | ||
385 | REG_READ(pipeconf_reg); | ||
386 | udelay(500); | ||
387 | mdfldWaitForPipeEnable(dev, pipe); | ||
388 | } | ||
389 | |||
390 | /* Enable plane */ | ||
391 | reg_val = REG_READ(dspcntr_reg); | ||
392 | if (!(reg_val & DISPLAY_PLANE_ENABLE)) { | ||
393 | reg_val |= DISPLAY_PLANE_ENABLE; | ||
394 | REG_WRITE(dspcntr_reg, reg_val); | ||
395 | REG_READ(dspcntr_reg); | ||
396 | udelay(500); | ||
397 | } | ||
398 | |||
399 | /* Enable TE interrupt on this pipe */ | ||
400 | mdfld_enable_te(dev, pipe); | ||
401 | gma_power_end(dev); | ||
402 | |||
403 | /*clean IN_DSR flag*/ | ||
404 | dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; | ||
405 | } | ||
406 | |||
407 | /* | ||
408 | * Exit from DSR | ||
409 | */ | ||
410 | void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src) | ||
411 | { | ||
412 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
413 | struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; | ||
414 | struct mdfld_dsi_dbi_output **dbi_output; | ||
415 | int i; | ||
416 | int pipe; | ||
417 | |||
418 | /* FIXME can go ? */ | ||
419 | dev_priv->is_in_idle = false; | ||
420 | dbi_output = dsr_info->dbi_outputs; | ||
421 | |||
422 | #ifdef CONFIG_PM_RUNTIME | ||
423 | if (!enable_gfx_rtpm) { | ||
424 | /* pm_runtime_allow(&gpDrmDevice->pdev->dev); */ | ||
425 | /* schedule_delayed_work(&rtpm_work, 30 * 1000);*/ /* FIXME: HZ ? */ | ||
426 | } | ||
427 | #endif | ||
428 | |||
429 | /* For each output, exit dsr */ | ||
430 | for (i = 0; i < dsr_info->dbi_output_num; i++) { | ||
431 | /* If panel has been turned off, skip */ | ||
432 | if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on) | ||
433 | continue; | ||
434 | pipe = dbi_output[i]->channel_num ? 2 : 0; | ||
435 | enter_dsr = 0; | ||
436 | mdfld_dbi_output_exit_dsr(dbi_output[i], pipe); | ||
437 | } | ||
438 | dev_priv->dsr_fb_update |= update_src; | ||
439 | } | ||
440 | |||
441 | static bool mdfld_dbi_is_in_dsr(struct drm_device *dev) | ||
442 | { | ||
443 | if (REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE) | ||
444 | return false; | ||
445 | if ((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) || | ||
446 | (REG_READ(PIPECCONF) & PIPEACONF_ENABLE)) | ||
447 | return false; | ||
448 | if ((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) || | ||
449 | (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE)) | ||
450 | return false; | ||
451 | |||
452 | return true; | ||
453 | } | ||
454 | |||
455 | /* Periodically update dbi panel */ | ||
456 | void mdfld_dbi_update_panel(struct drm_device *dev, int pipe) | ||
457 | { | ||
458 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
459 | struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; | ||
460 | struct mdfld_dsi_dbi_output **dbi_outputs; | ||
461 | struct mdfld_dsi_dbi_output *dbi_output; | ||
462 | int i; | ||
463 | int can_enter_dsr = 0; | ||
464 | u32 damage_mask; | ||
465 | |||
466 | dbi_outputs = dsr_info->dbi_outputs; | ||
467 | dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0]; | ||
468 | |||
469 | if (!dbi_output) | ||
470 | return; | ||
471 | |||
472 | if (pipe == 0) | ||
473 | damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0; | ||
474 | else if (pipe == 2) | ||
475 | damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2; | ||
476 | else | ||
477 | return; | ||
478 | |||
479 | /* If FB is damaged and panel is on update on-panel FB */ | ||
480 | if (damage_mask && dbi_output->dbi_panel_on) { | ||
481 | dbi_output->dsr_fb_update_done = false; | ||
482 | |||
483 | if (dbi_output->p_funcs->update_fb) | ||
484 | dbi_output->p_funcs->update_fb(dbi_output, pipe); | ||
485 | |||
486 | if (dev_priv->dsr_enable && dbi_output->dsr_fb_update_done) | ||
487 | dev_priv->dsr_fb_update &= ~damage_mask; | ||
488 | |||
489 | /*clean IN_DSR flag*/ | ||
490 | dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; | ||
491 | |||
492 | dbi_output->dsr_idle_count = 0; | ||
493 | } else { | ||
494 | dbi_output->dsr_idle_count++; | ||
495 | } | ||
496 | |||
497 | switch (dsr_info->dbi_output_num) { | ||
498 | case 1: | ||
499 | if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT) | ||
500 | can_enter_dsr = 1; | ||
501 | break; | ||
502 | case 2: | ||
503 | if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT | ||
504 | && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT) | ||
505 | can_enter_dsr = 1; | ||
506 | break; | ||
507 | default: | ||
508 | DRM_ERROR("Wrong DBI output number\n"); | ||
509 | } | ||
510 | |||
511 | /* Try to enter DSR */ | ||
512 | if (can_enter_dsr) { | ||
513 | for (i = 0; i < dsr_info->dbi_output_num; i++) { | ||
514 | if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] && | ||
515 | !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) { | ||
516 | mdfld_dsi_dbi_enter_dsr(dbi_outputs[i], | ||
517 | dbi_outputs[i]->channel_num ? 2 : 0); | ||
518 | #if 0 | ||
519 | enter_dsr = 1; | ||
520 | pr_err("%s: enter_dsr = 1\n", __func__); | ||
521 | #endif | ||
522 | } | ||
523 | } | ||
524 | /*schedule rpm suspend after gfxrtdelay*/ | ||
525 | #ifdef CONFIG_GFX_RTPM | ||
526 | if (!dev_priv->rpm_enabled | ||
527 | || !enter_dsr | ||
528 | /* || (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN) */ | ||
529 | || pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay)) | ||
530 | dev_warn(dev->dev, | ||
531 | "Runtime PM schedule suspend failed, rpm %d\n", | ||
532 | dev_priv->rpm_enabled); | ||
533 | #endif | ||
534 | } | ||
535 | } | ||
536 | |||
537 | int mdfld_dbi_dsr_init(struct drm_device *dev) | ||
538 | { | ||
539 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
540 | struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; | ||
541 | |||
542 | if (!dsr_info || IS_ERR(dsr_info)) { | ||
543 | dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info), | ||
544 | GFP_KERNEL); | ||
545 | if (!dsr_info) { | ||
546 | dev_err(dev->dev, "No memory\n"); | ||
547 | return -ENOMEM; | ||
548 | } | ||
549 | dev_priv->dbi_dsr_info = dsr_info; | ||
550 | } | ||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | void mdfld_dbi_dsr_exit(struct drm_device *dev) | ||
555 | { | ||
556 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
557 | struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info; | ||
558 | |||
559 | if (dsr_info) { | ||
560 | kfree(dsr_info); | ||
561 | dev_priv->dbi_dsr_info = NULL; | ||
562 | } | ||
563 | } | ||
564 | |||
565 | void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config, | ||
566 | int pipe) | ||
567 | { | ||
568 | struct drm_device *dev = dsi_config->dev; | ||
569 | u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; | ||
570 | int lane_count = dsi_config->lane_count; | ||
571 | u32 val = 0; | ||
572 | |||
573 | dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe); | ||
574 | |||
575 | /* Un-ready device */ | ||
576 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); | ||
577 | |||
578 | /* Init dsi adapter before kicking off */ | ||
579 | REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); | ||
580 | |||
581 | /* TODO: figure out how to setup these registers */ | ||
582 | REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); | ||
583 | REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), | ||
584 | 0x000a0014); | ||
585 | REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400); | ||
586 | REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001); | ||
587 | REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000); | ||
588 | |||
589 | /* Enable all interrupts */ | ||
590 | REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); | ||
591 | /* Max value: 20 clock cycles of txclkesc */ | ||
592 | REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f); | ||
593 | /* Min 21 txclkesc, max: ffffh */ | ||
594 | REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff); | ||
595 | /* Min: 7d0 max: 4e20 */ | ||
596 | REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0); | ||
597 | |||
598 | /* Set up func_prg */ | ||
599 | val |= lane_count; | ||
600 | val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET); | ||
601 | val |= DSI_DBI_COLOR_FORMAT_OPTION2; | ||
602 | REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); | ||
603 | |||
604 | REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff); | ||
605 | REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff); | ||
606 | |||
607 | /* De-assert dbi_stall when half of DBI FIFO is empty */ | ||
608 | /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */ | ||
609 | |||
610 | REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); | ||
611 | REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); | ||
612 | REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); | ||
613 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); | ||
614 | } | ||
615 | |||
616 | #if 0 | ||
617 | /*DBI encoder helper funcs*/ | ||
618 | static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = { | ||
619 | .dpms = mdfld_dsi_dbi_dpms, | ||
620 | .mode_fixup = mdfld_dsi_dbi_mode_fixup, | ||
621 | .prepare = mdfld_dsi_dbi_prepare, | ||
622 | .mode_set = mdfld_dsi_dbi_mode_set, | ||
623 | .commit = mdfld_dsi_dbi_commit, | ||
624 | }; | ||
625 | |||
626 | /*DBI encoder funcs*/ | ||
627 | static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = { | ||
628 | .destroy = drm_encoder_cleanup, | ||
629 | }; | ||
630 | |||
631 | #endif | ||
632 | |||
633 | /* | ||
634 | * Init DSI DBI encoder. | ||
635 | * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector | ||
636 | * return pointer of newly allocated DBI encoder, NULL on error | ||
637 | */ | ||
638 | struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev, | ||
639 | struct mdfld_dsi_connector *dsi_connector, | ||
640 | struct panel_funcs *p_funcs) | ||
641 | { | ||
642 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
643 | struct mdfld_dsi_dbi_output *dbi_output = NULL; | ||
644 | struct mdfld_dsi_config *dsi_config; | ||
645 | struct drm_connector *connector = NULL; | ||
646 | struct drm_encoder *encoder = NULL; | ||
647 | struct drm_display_mode *fixed_mode = NULL; | ||
648 | struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL; | ||
649 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL; | ||
650 | struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL; | ||
651 | u32 data = 0; | ||
652 | int pipe; | ||
653 | int ret; | ||
654 | |||
655 | if (!pg || !dsi_connector || !p_funcs) { | ||
656 | WARN_ON(1); | ||
657 | return NULL; | ||
658 | } | ||
659 | |||
660 | dsi_config = mdfld_dsi_get_config(dsi_connector); | ||
661 | pipe = dsi_connector->pipe; | ||
662 | |||
663 | /*panel hard-reset*/ | ||
664 | if (p_funcs->reset) { | ||
665 | ret = p_funcs->reset(pipe); | ||
666 | if (ret) { | ||
667 | DRM_ERROR("Panel %d hard-reset failed\n", pipe); | ||
668 | return NULL; | ||
669 | } | ||
670 | } | ||
671 | /* Panel drvIC init */ | ||
672 | if (p_funcs->drv_ic_init) | ||
673 | p_funcs->drv_ic_init(dsi_config, pipe); | ||
674 | |||
675 | /* Panel power mode detect */ | ||
676 | ret = mdfld_dsi_get_power_mode(dsi_config, | ||
677 | &data, | ||
678 | MDFLD_DSI_HS_TRANSMISSION); | ||
679 | if (ret) { | ||
680 | DRM_ERROR("Panel %d get power mode failed\n", pipe); | ||
681 | dsi_connector->status = connector_status_disconnected; | ||
682 | } else { | ||
683 | DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); | ||
684 | dsi_connector->status = connector_status_connected; | ||
685 | } | ||
686 | |||
687 | /*TODO: get panel info from DDB*/ | ||
688 | |||
689 | dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL); | ||
690 | if (!dbi_output) { | ||
691 | dev_err(dev->dev, "No memory\n"); | ||
692 | return NULL; | ||
693 | } | ||
694 | |||
695 | if (dsi_connector->pipe == 0) { | ||
696 | dbi_output->channel_num = 0; | ||
697 | dev_priv->dbi_output = dbi_output; | ||
698 | } else if (dsi_connector->pipe == 2) { | ||
699 | dbi_output->channel_num = 1; | ||
700 | dev_priv->dbi_output2 = dbi_output; | ||
701 | } else { | ||
702 | dev_err(dev->dev, "only support 2 DSI outputs\n"); | ||
703 | goto out_err1; | ||
704 | } | ||
705 | |||
706 | dbi_output->dev = dev; | ||
707 | dbi_output->p_funcs = p_funcs; | ||
708 | fixed_mode = dsi_config->fixed_mode; | ||
709 | dbi_output->panel_fixed_mode = fixed_mode; | ||
710 | |||
711 | /* Create drm encoder object */ | ||
712 | connector = &dsi_connector->base.base; | ||
713 | encoder = &dbi_output->base.base; | ||
714 | /* Review this if we ever get MIPI-HDMI bridges or similar */ | ||
715 | drm_encoder_init(dev, | ||
716 | encoder, | ||
717 | p_funcs->encoder_funcs, | ||
718 | DRM_MODE_ENCODER_LVDS); | ||
719 | drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs); | ||
720 | |||
721 | /* Attach to given connector */ | ||
722 | drm_mode_connector_attach_encoder(connector, encoder); | ||
723 | |||
724 | /* Set possible CRTCs and clones */ | ||
725 | if (dsi_connector->pipe) { | ||
726 | encoder->possible_crtcs = (1 << 2); | ||
727 | encoder->possible_clones = (1 << 1); | ||
728 | } else { | ||
729 | encoder->possible_crtcs = (1 << 0); | ||
730 | encoder->possible_clones = (1 << 0); | ||
731 | } | ||
732 | |||
733 | dev_priv->dsr_fb_update = 0; | ||
734 | dev_priv->dsr_enable = false; | ||
735 | dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr; | ||
736 | |||
737 | dbi_output->first_boot = true; | ||
738 | dbi_output->mode_flags = MODE_SETTING_IN_ENCODER; | ||
739 | |||
740 | /* Add this output to dpu_info if in DPU mode */ | ||
741 | if (dpu_info && dsi_connector->status == connector_status_connected) { | ||
742 | if (dsi_connector->pipe == 0) | ||
743 | dpu_info->dbi_outputs[0] = dbi_output; | ||
744 | else | ||
745 | dpu_info->dbi_outputs[1] = dbi_output; | ||
746 | |||
747 | dpu_info->dbi_output_num++; | ||
748 | } else if (dsi_connector->status == connector_status_connected) { | ||
749 | /* Add this output to dsr_info if not */ | ||
750 | if (dsi_connector->pipe == 0) | ||
751 | dsr_info->dbi_outputs[0] = dbi_output; | ||
752 | else | ||
753 | dsr_info->dbi_outputs[1] = dbi_output; | ||
754 | |||
755 | dsr_info->dbi_output_num++; | ||
756 | } | ||
757 | return &dbi_output->base; | ||
758 | out_err1: | ||
759 | kfree(dbi_output); | ||
760 | return NULL; | ||
761 | } | ||
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi.h b/drivers/staging/gma500/mdfld_dsi_dbi.h deleted file mode 100644 index f0fa986fd934..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_dbi.h +++ /dev/null | |||
@@ -1,173 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef __MDFLD_DSI_DBI_H__ | ||
29 | #define __MDFLD_DSI_DBI_H__ | ||
30 | |||
31 | #include <linux/backlight.h> | ||
32 | #include <drm/drmP.h> | ||
33 | #include <drm/drm.h> | ||
34 | #include <drm/drm_crtc.h> | ||
35 | #include <drm/drm_edid.h> | ||
36 | |||
37 | #include "psb_drv.h" | ||
38 | #include "psb_intel_drv.h" | ||
39 | #include "psb_intel_reg.h" | ||
40 | #include "power.h" | ||
41 | |||
42 | #include "mdfld_dsi_output.h" | ||
43 | #include "mdfld_output.h" | ||
44 | |||
45 | /* | ||
46 | * DBI encoder which inherits from mdfld_dsi_encoder | ||
47 | */ | ||
48 | struct mdfld_dsi_dbi_output { | ||
49 | struct mdfld_dsi_encoder base; | ||
50 | struct drm_display_mode *panel_fixed_mode; | ||
51 | u8 last_cmd; | ||
52 | u8 lane_count; | ||
53 | u8 channel_num; | ||
54 | struct drm_device *dev; | ||
55 | |||
56 | /* Backlight operations */ | ||
57 | |||
58 | /* DSR timer */ | ||
59 | u32 dsr_idle_count; | ||
60 | bool dsr_fb_update_done; | ||
61 | |||
62 | /* Mode setting flags */ | ||
63 | u32 mode_flags; | ||
64 | |||
65 | /* Panel status */ | ||
66 | bool dbi_panel_on; | ||
67 | bool first_boot; | ||
68 | struct panel_funcs *p_funcs; | ||
69 | |||
70 | /* DPU */ | ||
71 | u32 *dbi_cb_addr; | ||
72 | u32 dbi_cb_phy; | ||
73 | spinlock_t cb_lock; | ||
74 | u32 cb_write; | ||
75 | }; | ||
76 | |||
77 | #define MDFLD_DSI_DBI_OUTPUT(dsi_encoder) \ | ||
78 | container_of(dsi_encoder, struct mdfld_dsi_dbi_output, base) | ||
79 | |||
80 | struct mdfld_dbi_dsr_info { | ||
81 | int dbi_output_num; | ||
82 | struct mdfld_dsi_dbi_output *dbi_outputs[2]; | ||
83 | |||
84 | u32 dsr_idle_count; | ||
85 | }; | ||
86 | |||
87 | #define DBI_CB_TIMEOUT_COUNT 0xffff | ||
88 | |||
89 | /* Offsets */ | ||
90 | #define CMD_MEM_ADDR_OFFSET 0 | ||
91 | |||
92 | #define CMD_DATA_SRC_SYSTEM_MEM 0 | ||
93 | #define CMD_DATA_SRC_PIPE 1 | ||
94 | |||
95 | static inline int mdfld_dsi_dbi_fifo_ready(struct mdfld_dsi_dbi_output *dbi_output) | ||
96 | { | ||
97 | struct drm_device *dev = dbi_output->dev; | ||
98 | u32 retry = DBI_CB_TIMEOUT_COUNT; | ||
99 | int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0; | ||
100 | int ret = 0; | ||
101 | |||
102 | /* Query the dbi fifo status*/ | ||
103 | while (retry--) { | ||
104 | if (REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset) & (1 << 27)) | ||
105 | break; | ||
106 | } | ||
107 | |||
108 | if (!retry) { | ||
109 | DRM_ERROR("Timeout waiting for DBI FIFO empty\n"); | ||
110 | ret = -EAGAIN; | ||
111 | } | ||
112 | return ret; | ||
113 | } | ||
114 | |||
115 | static inline int mdfld_dsi_dbi_cmd_sent(struct mdfld_dsi_dbi_output *dbi_output) | ||
116 | { | ||
117 | struct drm_device *dev = dbi_output->dev; | ||
118 | u32 retry = DBI_CB_TIMEOUT_COUNT; | ||
119 | int reg_offset = (dbi_output->channel_num == 1) ? MIPIC_REG_OFFSET : 0; | ||
120 | int ret = 0; | ||
121 | |||
122 | /* Query the command execution status */ | ||
123 | while (retry--) | ||
124 | if (!(REG_READ(MIPIA_CMD_ADD_REG + reg_offset) & (1 << 0))) | ||
125 | break; | ||
126 | |||
127 | if (!retry) { | ||
128 | DRM_ERROR("Timeout waiting for DBI command status\n"); | ||
129 | ret = -EAGAIN; | ||
130 | } | ||
131 | |||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | static inline int mdfld_dsi_dbi_cb_ready(struct mdfld_dsi_dbi_output *dbi_output) | ||
136 | { | ||
137 | int ret = 0; | ||
138 | |||
139 | /* Query the command execution status*/ | ||
140 | ret = mdfld_dsi_dbi_cmd_sent(dbi_output); | ||
141 | if (ret) { | ||
142 | DRM_ERROR("Peripheral is busy\n"); | ||
143 | ret = -EAGAIN; | ||
144 | } | ||
145 | /* Query the dbi fifo status*/ | ||
146 | ret = mdfld_dsi_dbi_fifo_ready(dbi_output); | ||
147 | if (ret) { | ||
148 | DRM_ERROR("DBI FIFO is not empty\n"); | ||
149 | ret = -EAGAIN; | ||
150 | } | ||
151 | return ret; | ||
152 | } | ||
153 | |||
154 | extern void mdfld_dsi_dbi_output_init(struct drm_device *dev, | ||
155 | struct psb_intel_mode_device *mode_dev, int pipe); | ||
156 | extern void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src); | ||
157 | extern void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, | ||
158 | int pipe); | ||
159 | extern int mdfld_dbi_dsr_init(struct drm_device *dev); | ||
160 | extern void mdfld_dbi_dsr_exit(struct drm_device *dev); | ||
161 | extern struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev, | ||
162 | struct mdfld_dsi_connector *dsi_connector, | ||
163 | struct panel_funcs *p_funcs); | ||
164 | extern int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output, | ||
165 | u8 dcs, u8 *param, u32 num, u8 data_src); | ||
166 | extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output, | ||
167 | u16 x1, u16 y1, u16 x2, u16 y2); | ||
168 | extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output, | ||
169 | int mode); | ||
170 | extern void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config, | ||
171 | int pipe); | ||
172 | |||
173 | #endif /*__MDFLD_DSI_DBI_H__*/ | ||
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c deleted file mode 100644 index a4e2ff442b1f..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c +++ /dev/null | |||
@@ -1,778 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010-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 | * Jackie Li<yaodong.li@intel.com> | ||
26 | */ | ||
27 | |||
28 | #include "mdfld_dsi_dbi_dpu.h" | ||
29 | #include "mdfld_dsi_dbi.h" | ||
30 | |||
31 | /* | ||
32 | * NOTE: all mdlfd_x_damage funcs should be called by holding dpu_update_lock | ||
33 | */ | ||
34 | |||
35 | static int mdfld_cursor_damage(struct mdfld_dbi_dpu_info *dpu_info, | ||
36 | mdfld_plane_t plane, | ||
37 | struct psb_drm_dpu_rect *damaged_rect) | ||
38 | { | ||
39 | int x, y; | ||
40 | int new_x, new_y; | ||
41 | struct psb_drm_dpu_rect *rect; | ||
42 | struct psb_drm_dpu_rect *pipe_rect; | ||
43 | int cursor_size; | ||
44 | struct mdfld_cursor_info *cursor; | ||
45 | mdfld_plane_t fb_plane; | ||
46 | |||
47 | if (plane == MDFLD_CURSORA) { | ||
48 | cursor = &dpu_info->cursors[0]; | ||
49 | x = dpu_info->cursors[0].x; | ||
50 | y = dpu_info->cursors[0].y; | ||
51 | cursor_size = dpu_info->cursors[0].size; | ||
52 | pipe_rect = &dpu_info->damage_pipea; | ||
53 | fb_plane = MDFLD_PLANEA; | ||
54 | } else { | ||
55 | cursor = &dpu_info->cursors[1]; | ||
56 | x = dpu_info->cursors[1].x; | ||
57 | y = dpu_info->cursors[1].y; | ||
58 | cursor_size = dpu_info->cursors[1].size; | ||
59 | pipe_rect = &dpu_info->damage_pipec; | ||
60 | fb_plane = MDFLD_PLANEC; | ||
61 | } | ||
62 | new_x = damaged_rect->x; | ||
63 | new_y = damaged_rect->y; | ||
64 | |||
65 | if (x == new_x && y == new_y) | ||
66 | return 0; | ||
67 | |||
68 | rect = &dpu_info->damaged_rects[plane]; | ||
69 | /* Move to right */ | ||
70 | if (new_x >= x) { | ||
71 | if (new_y > y) { | ||
72 | rect->x = x; | ||
73 | rect->y = y; | ||
74 | rect->width = (new_x + cursor_size) - x; | ||
75 | rect->height = (new_y + cursor_size) - y; | ||
76 | goto cursor_out; | ||
77 | } else { | ||
78 | rect->x = x; | ||
79 | rect->y = new_y; | ||
80 | rect->width = (new_x + cursor_size) - x; | ||
81 | rect->height = (y - new_y); | ||
82 | goto cursor_out; | ||
83 | } | ||
84 | } else { | ||
85 | if (new_y > y) { | ||
86 | rect->x = new_x; | ||
87 | rect->y = y; | ||
88 | rect->width = (x + cursor_size) - new_x; | ||
89 | rect->height = new_y - y; | ||
90 | goto cursor_out; | ||
91 | } else { | ||
92 | rect->x = new_x; | ||
93 | rect->y = new_y; | ||
94 | rect->width = (x + cursor_size) - new_x; | ||
95 | rect->height = (y + cursor_size) - new_y; | ||
96 | } | ||
97 | } | ||
98 | cursor_out: | ||
99 | if (new_x < 0) | ||
100 | cursor->x = 0; | ||
101 | else if (new_x > 864) | ||
102 | cursor->x = 864; | ||
103 | else | ||
104 | cursor->x = new_x; | ||
105 | |||
106 | if (new_y < 0) | ||
107 | cursor->y = 0; | ||
108 | else if (new_y > 480) | ||
109 | cursor->y = 480; | ||
110 | else | ||
111 | cursor->y = new_y; | ||
112 | |||
113 | /* | ||
114 | * FIXME: this is a workaround for cursor plane update, | ||
115 | * remove it later! | ||
116 | */ | ||
117 | rect->x = 0; | ||
118 | rect->y = 0; | ||
119 | rect->width = 864; | ||
120 | rect->height = 480; | ||
121 | |||
122 | mdfld_check_boundary(dpu_info, rect); | ||
123 | mdfld_dpu_region_extent(pipe_rect, rect); | ||
124 | |||
125 | /* Update pending status of dpu_info */ | ||
126 | dpu_info->pending |= (1 << plane); | ||
127 | /* Update fb panel as well */ | ||
128 | dpu_info->pending |= (1 << fb_plane); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | static int mdfld_fb_damage(struct mdfld_dbi_dpu_info *dpu_info, | ||
133 | mdfld_plane_t plane, | ||
134 | struct psb_drm_dpu_rect *damaged_rect) | ||
135 | { | ||
136 | struct psb_drm_dpu_rect *rect; | ||
137 | |||
138 | if (plane == MDFLD_PLANEA) | ||
139 | rect = &dpu_info->damage_pipea; | ||
140 | else | ||
141 | rect = &dpu_info->damage_pipec; | ||
142 | |||
143 | mdfld_check_boundary(dpu_info, damaged_rect); | ||
144 | |||
145 | /* Add fb damage area to this pipe */ | ||
146 | mdfld_dpu_region_extent(rect, damaged_rect); | ||
147 | |||
148 | /* Update pending status of dpu_info */ | ||
149 | dpu_info->pending |= (1 << plane); | ||
150 | return 0; | ||
151 | } | ||
152 | |||
153 | /* Do nothing here, right now */ | ||
154 | static int mdfld_overlay_damage(struct mdfld_dbi_dpu_info *dpu_info, | ||
155 | mdfld_plane_t plane, | ||
156 | struct psb_drm_dpu_rect *damaged_rect) | ||
157 | { | ||
158 | return 0; | ||
159 | } | ||
160 | |||
161 | int mdfld_dbi_dpu_report_damage(struct drm_device *dev, | ||
162 | mdfld_plane_t plane, | ||
163 | struct psb_drm_dpu_rect *rect) | ||
164 | { | ||
165 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
166 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; | ||
167 | int ret = 0; | ||
168 | |||
169 | /* DPU not in use, no damage reporting needed */ | ||
170 | if (dpu_info == NULL) | ||
171 | return 0; | ||
172 | |||
173 | spin_lock(&dpu_info->dpu_update_lock); | ||
174 | |||
175 | switch (plane) { | ||
176 | case MDFLD_PLANEA: | ||
177 | case MDFLD_PLANEC: | ||
178 | mdfld_fb_damage(dpu_info, plane, rect); | ||
179 | break; | ||
180 | case MDFLD_CURSORA: | ||
181 | case MDFLD_CURSORC: | ||
182 | mdfld_cursor_damage(dpu_info, plane, rect); | ||
183 | break; | ||
184 | case MDFLD_OVERLAYA: | ||
185 | case MDFLD_OVERLAYC: | ||
186 | mdfld_overlay_damage(dpu_info, plane, rect); | ||
187 | break; | ||
188 | default: | ||
189 | DRM_ERROR("Invalid plane type %d\n", plane); | ||
190 | ret = -EINVAL; | ||
191 | } | ||
192 | spin_unlock(&dpu_info->dpu_update_lock); | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev) | ||
197 | { | ||
198 | struct drm_psb_private *dev_priv; | ||
199 | struct mdfld_dbi_dpu_info *dpu_info; | ||
200 | struct mdfld_dsi_config *dsi_config; | ||
201 | struct psb_drm_dpu_rect rect; | ||
202 | int i; | ||
203 | |||
204 | if (!dev) { | ||
205 | DRM_ERROR("Invalid parameter\n"); | ||
206 | return -EINVAL; | ||
207 | } | ||
208 | |||
209 | dev_priv = dev->dev_private; | ||
210 | dpu_info = dev_priv->dbi_dpu_info; | ||
211 | |||
212 | /* This is fine - we may be in non DPU mode */ | ||
213 | if (!dpu_info) | ||
214 | return -EINVAL; | ||
215 | |||
216 | for (i = 0; i < dpu_info->dbi_output_num; i++) { | ||
217 | dsi_config = dev_priv->dsi_configs[i]; | ||
218 | if (dsi_config) { | ||
219 | rect.x = rect.y = 0; | ||
220 | rect.width = dsi_config->fixed_mode->hdisplay; | ||
221 | rect.height = dsi_config->fixed_mode->vdisplay; | ||
222 | mdfld_dbi_dpu_report_damage(dev, | ||
223 | i ? (MDFLD_PLANEC) : (MDFLD_PLANEA), | ||
224 | &rect); | ||
225 | } | ||
226 | } | ||
227 | /* Exit DSR state */ | ||
228 | mdfld_dpu_exit_dsr(dev); | ||
229 | return 0; | ||
230 | } | ||
231 | |||
232 | int mdfld_dsi_dbi_dsr_off(struct drm_device *dev, | ||
233 | struct psb_drm_dpu_rect *rect) | ||
234 | { | ||
235 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
236 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; | ||
237 | |||
238 | mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, rect); | ||
239 | |||
240 | /* If dual display mode */ | ||
241 | if (dpu_info->dbi_output_num == 2) | ||
242 | mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, rect); | ||
243 | |||
244 | /* Force dsi to exit DSR mode */ | ||
245 | mdfld_dpu_exit_dsr(dev); | ||
246 | return 0; | ||
247 | } | ||
248 | |||
249 | static void mdfld_dpu_cursor_plane_flush(struct mdfld_dbi_dpu_info *dpu_info, | ||
250 | mdfld_plane_t plane) | ||
251 | { | ||
252 | struct drm_device *dev = dpu_info->dev; | ||
253 | u32 curpos_reg = CURAPOS; | ||
254 | u32 curbase_reg = CURABASE; | ||
255 | u32 curcntr_reg = CURACNTR; | ||
256 | struct mdfld_cursor_info *cursor = &dpu_info->cursors[0]; | ||
257 | |||
258 | if (plane == MDFLD_CURSORC) { | ||
259 | curpos_reg = CURCPOS; | ||
260 | curbase_reg = CURCBASE; | ||
261 | curcntr_reg = CURCCNTR; | ||
262 | cursor = &dpu_info->cursors[1]; | ||
263 | } | ||
264 | |||
265 | REG_WRITE(curcntr_reg, REG_READ(curcntr_reg)); | ||
266 | REG_WRITE(curpos_reg, | ||
267 | (((cursor->x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) | | ||
268 | ((cursor->y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT))); | ||
269 | REG_WRITE(curbase_reg, REG_READ(curbase_reg)); | ||
270 | } | ||
271 | |||
272 | static void mdfld_dpu_fb_plane_flush(struct mdfld_dbi_dpu_info *dpu_info, | ||
273 | mdfld_plane_t plane) | ||
274 | { | ||
275 | u32 pipesrc_reg = PIPEASRC; | ||
276 | u32 dspsize_reg = DSPASIZE; | ||
277 | u32 dspoff_reg = DSPALINOFF; | ||
278 | u32 dspsurf_reg = DSPASURF; | ||
279 | u32 dspstride_reg = DSPASTRIDE; | ||
280 | u32 stride; | ||
281 | struct psb_drm_dpu_rect *rect = &dpu_info->damage_pipea; | ||
282 | struct drm_device *dev = dpu_info->dev; | ||
283 | |||
284 | if (plane == MDFLD_PLANEC) { | ||
285 | pipesrc_reg = PIPECSRC; | ||
286 | dspsize_reg = DSPCSIZE; | ||
287 | dspoff_reg = DSPCLINOFF; | ||
288 | dspsurf_reg = DSPCSURF; | ||
289 | dspstride_reg = DSPCSTRIDE; | ||
290 | rect = &dpu_info->damage_pipec; | ||
291 | } | ||
292 | |||
293 | stride = REG_READ(dspstride_reg); | ||
294 | /* FIXME: should I do the pipe src update here? */ | ||
295 | REG_WRITE(pipesrc_reg, ((rect->width - 1) << 16) | (rect->height - 1)); | ||
296 | /* Flush plane */ | ||
297 | REG_WRITE(dspsize_reg, ((rect->height - 1) << 16) | (rect->width - 1)); | ||
298 | REG_WRITE(dspoff_reg, ((rect->x * 4) + (rect->y * stride))); | ||
299 | REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); | ||
300 | |||
301 | /* | ||
302 | * TODO: wait for flip finished and restore the pipesrc reg, | ||
303 | * or cursor will be show at a wrong position | ||
304 | */ | ||
305 | } | ||
306 | |||
307 | static void mdfld_dpu_overlay_plane_flush(struct mdfld_dbi_dpu_info *dpu_info, | ||
308 | mdfld_plane_t plane) | ||
309 | { | ||
310 | } | ||
311 | |||
312 | /* | ||
313 | * TODO: we are still in dbi normal mode now, we will try to use partial | ||
314 | * mode later. | ||
315 | */ | ||
316 | static int mdfld_dbi_prepare_cb(struct mdfld_dsi_dbi_output *dbi_output, | ||
317 | struct mdfld_dbi_dpu_info *dpu_info, int pipe) | ||
318 | { | ||
319 | u8 *cb_addr = (u8 *)dbi_output->dbi_cb_addr; | ||
320 | u32 *index; | ||
321 | struct psb_drm_dpu_rect *rect = pipe ? | ||
322 | (&dpu_info->damage_pipec) : (&dpu_info->damage_pipea); | ||
323 | |||
324 | /* FIXME: lock command buffer, this may lead to a deadlock, | ||
325 | as we already hold the dpu_update_lock */ | ||
326 | if (!spin_trylock(&dbi_output->cb_lock)) { | ||
327 | DRM_ERROR("lock command buffer failed, try again\n"); | ||
328 | return -EAGAIN; | ||
329 | } | ||
330 | |||
331 | index = &dbi_output->cb_write; | ||
332 | |||
333 | if (*index) { | ||
334 | DRM_ERROR("DBI command buffer unclean\n"); | ||
335 | return -EAGAIN; | ||
336 | } | ||
337 | |||
338 | /* Column address */ | ||
339 | *(cb_addr + ((*index)++)) = set_column_address; | ||
340 | *(cb_addr + ((*index)++)) = rect->x >> 8; | ||
341 | *(cb_addr + ((*index)++)) = rect->x; | ||
342 | *(cb_addr + ((*index)++)) = (rect->x + rect->width - 1) >> 8; | ||
343 | *(cb_addr + ((*index)++)) = (rect->x + rect->width - 1); | ||
344 | |||
345 | *index = 8; | ||
346 | |||
347 | /* Page address */ | ||
348 | *(cb_addr + ((*index)++)) = set_page_addr; | ||
349 | *(cb_addr + ((*index)++)) = rect->y >> 8; | ||
350 | *(cb_addr + ((*index)++)) = rect->y; | ||
351 | *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1) >> 8; | ||
352 | *(cb_addr + ((*index)++)) = (rect->y + rect->height - 1); | ||
353 | |||
354 | *index = 16; | ||
355 | |||
356 | /*write memory*/ | ||
357 | *(cb_addr + ((*index)++)) = write_mem_start; | ||
358 | |||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static int mdfld_dbi_flush_cb(struct mdfld_dsi_dbi_output *dbi_output, int pipe) | ||
363 | { | ||
364 | u32 cmd_phy = dbi_output->dbi_cb_phy; | ||
365 | u32 *index = &dbi_output->cb_write; | ||
366 | int reg_offset = pipe ? MIPIC_REG_OFFSET : 0; | ||
367 | struct drm_device *dev = dbi_output->dev; | ||
368 | |||
369 | if (*index == 0 || !dbi_output) | ||
370 | return 0; | ||
371 | |||
372 | REG_WRITE((MIPIA_CMD_LEN_REG + reg_offset), 0x010505); | ||
373 | REG_WRITE((MIPIA_CMD_ADD_REG + reg_offset), cmd_phy | 3); | ||
374 | |||
375 | *index = 0; | ||
376 | |||
377 | /* FIXME: unlock command buffer */ | ||
378 | spin_unlock(&dbi_output->cb_lock); | ||
379 | return 0; | ||
380 | } | ||
381 | |||
382 | static int mdfld_dpu_update_pipe(struct mdfld_dsi_dbi_output *dbi_output, | ||
383 | struct mdfld_dbi_dpu_info *dpu_info, int pipe) | ||
384 | { | ||
385 | struct drm_device *dev = dbi_output->dev; | ||
386 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
387 | mdfld_plane_t cursor_plane = MDFLD_CURSORA; | ||
388 | mdfld_plane_t fb_plane = MDFLD_PLANEA; | ||
389 | mdfld_plane_t overlay_plane = MDFLD_OVERLAYA; | ||
390 | int ret = 0; | ||
391 | u32 plane_mask = MDFLD_PIPEA_PLANE_MASK; | ||
392 | |||
393 | /* Damaged rects on this pipe */ | ||
394 | if (pipe) { | ||
395 | cursor_plane = MDFLD_CURSORC; | ||
396 | fb_plane = MDFLD_PLANEC; | ||
397 | overlay_plane = MDFLD_OVERLAYC; | ||
398 | plane_mask = MDFLD_PIPEC_PLANE_MASK; | ||
399 | } | ||
400 | |||
401 | /*update cursor which assigned to @pipe*/ | ||
402 | if (dpu_info->pending & (1 << cursor_plane)) | ||
403 | mdfld_dpu_cursor_plane_flush(dpu_info, cursor_plane); | ||
404 | |||
405 | /*update fb which assigned to @pipe*/ | ||
406 | if (dpu_info->pending & (1 << fb_plane)) | ||
407 | mdfld_dpu_fb_plane_flush(dpu_info, fb_plane); | ||
408 | |||
409 | /* TODO: update overlay */ | ||
410 | if (dpu_info->pending & (1 << overlay_plane)) | ||
411 | mdfld_dpu_overlay_plane_flush(dpu_info, overlay_plane); | ||
412 | |||
413 | /* Flush damage area to panel fb */ | ||
414 | if (dpu_info->pending & plane_mask) { | ||
415 | ret = mdfld_dbi_prepare_cb(dbi_output, dpu_info, pipe); | ||
416 | /* | ||
417 | * TODO: remove b_dsr_enable later, | ||
418 | * added it so that text console could boot smoothly | ||
419 | */ | ||
420 | /* Clean pending flags on this pipe */ | ||
421 | if (!ret && dev_priv->dsr_enable) { | ||
422 | dpu_info->pending &= ~plane_mask; | ||
423 | /* Reset overlay pipe damage rect */ | ||
424 | mdfld_dpu_init_damage(dpu_info, pipe); | ||
425 | } | ||
426 | } | ||
427 | return ret; | ||
428 | } | ||
429 | |||
430 | static int mdfld_dpu_update_fb(struct drm_device *dev) | ||
431 | { | ||
432 | struct drm_crtc *crtc; | ||
433 | struct psb_intel_crtc *psb_crtc; | ||
434 | struct mdfld_dsi_dbi_output **dbi_output; | ||
435 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
436 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; | ||
437 | bool pipe_updated[2]; | ||
438 | unsigned long irq_flags; | ||
439 | u32 dpll_reg = MRST_DPLL_A; | ||
440 | u32 dspcntr_reg = DSPACNTR; | ||
441 | u32 pipeconf_reg = PIPEACONF; | ||
442 | u32 dsplinoff_reg = DSPALINOFF; | ||
443 | u32 dspsurf_reg = DSPASURF; | ||
444 | u32 mipi_state_reg = MIPIA_INTR_STAT_REG; | ||
445 | u32 reg_offset = 0; | ||
446 | int pipe; | ||
447 | int i; | ||
448 | int ret; | ||
449 | |||
450 | dbi_output = dpu_info->dbi_outputs; | ||
451 | pipe_updated[0] = pipe_updated[1] = false; | ||
452 | |||
453 | if (!gma_power_begin(dev, true)) | ||
454 | return -EAGAIN; | ||
455 | |||
456 | /* Try to prevent any new damage reports */ | ||
457 | if (!spin_trylock_irqsave(&dpu_info->dpu_update_lock, irq_flags)) | ||
458 | return -EAGAIN; | ||
459 | |||
460 | for (i = 0; i < dpu_info->dbi_output_num; i++) { | ||
461 | crtc = dbi_output[i]->base.base.crtc; | ||
462 | psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) : NULL; | ||
463 | |||
464 | pipe = dbi_output[i]->channel_num ? 2 : 0; | ||
465 | |||
466 | if (pipe == 2) { | ||
467 | dspcntr_reg = DSPCCNTR; | ||
468 | pipeconf_reg = PIPECCONF; | ||
469 | dsplinoff_reg = DSPCLINOFF; | ||
470 | dspsurf_reg = DSPCSURF; | ||
471 | reg_offset = MIPIC_REG_OFFSET; | ||
472 | } | ||
473 | |||
474 | if (!(REG_READ((MIPIA_GEN_FIFO_STAT_REG + reg_offset)) | ||
475 | & (1 << 27)) || | ||
476 | !(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) || | ||
477 | !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || | ||
478 | !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) { | ||
479 | dev_err(dev->dev, | ||
480 | "DBI FIFO is busy, DSI %d state %x\n", | ||
481 | pipe, | ||
482 | REG_READ(mipi_state_reg + reg_offset)); | ||
483 | continue; | ||
484 | } | ||
485 | |||
486 | /* | ||
487 | * If DBI output is in a exclusive state then the pipe | ||
488 | * change won't be updated | ||
489 | */ | ||
490 | if (dbi_output[i]->dbi_panel_on && | ||
491 | !(dbi_output[i]->mode_flags & MODE_SETTING_ON_GOING) && | ||
492 | !(psb_crtc && | ||
493 | psb_crtc->mode_flags & MODE_SETTING_ON_GOING) && | ||
494 | !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) { | ||
495 | ret = mdfld_dpu_update_pipe(dbi_output[i], | ||
496 | dpu_info, dbi_output[i]->channel_num ? 2 : 0); | ||
497 | if (!ret) | ||
498 | pipe_updated[i] = true; | ||
499 | } | ||
500 | } | ||
501 | |||
502 | for (i = 0; i < dpu_info->dbi_output_num; i++) | ||
503 | if (pipe_updated[i]) | ||
504 | mdfld_dbi_flush_cb(dbi_output[i], | ||
505 | dbi_output[i]->channel_num ? 2 : 0); | ||
506 | |||
507 | spin_unlock_irqrestore(&dpu_info->dpu_update_lock, irq_flags); | ||
508 | gma_power_end(dev); | ||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static int __mdfld_dbi_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output, | ||
513 | int pipe) | ||
514 | { | ||
515 | struct drm_device *dev = dbi_output->dev; | ||
516 | struct drm_crtc *crtc = dbi_output->base.base.crtc; | ||
517 | struct psb_intel_crtc *psb_crtc = (crtc) ? to_psb_intel_crtc(crtc) | ||
518 | : NULL; | ||
519 | u32 reg_val; | ||
520 | u32 dpll_reg = MRST_DPLL_A; | ||
521 | u32 pipeconf_reg = PIPEACONF; | ||
522 | u32 dspcntr_reg = DSPACNTR; | ||
523 | u32 dspbase_reg = DSPABASE; | ||
524 | u32 dspsurf_reg = DSPASURF; | ||
525 | u32 reg_offset = 0; | ||
526 | |||
527 | if (!dbi_output) | ||
528 | return 0; | ||
529 | |||
530 | /* If mode setting on-going, back off */ | ||
531 | if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || | ||
532 | (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING)) | ||
533 | return -EAGAIN; | ||
534 | |||
535 | if (pipe == 2) { | ||
536 | dpll_reg = MRST_DPLL_A; | ||
537 | pipeconf_reg = PIPECCONF; | ||
538 | dspcntr_reg = DSPCCNTR; | ||
539 | dspbase_reg = MDFLD_DSPCBASE; | ||
540 | dspsurf_reg = DSPCSURF; | ||
541 | |||
542 | reg_offset = MIPIC_REG_OFFSET; | ||
543 | } | ||
544 | |||
545 | if (!gma_power_begin(dev, true)) | ||
546 | return -EAGAIN; | ||
547 | |||
548 | /* Enable DPLL */ | ||
549 | reg_val = REG_READ(dpll_reg); | ||
550 | if (!(reg_val & DPLL_VCO_ENABLE)) { | ||
551 | |||
552 | if (reg_val & MDFLD_PWR_GATE_EN) { | ||
553 | reg_val &= ~MDFLD_PWR_GATE_EN; | ||
554 | REG_WRITE(dpll_reg, reg_val); | ||
555 | REG_READ(dpll_reg); | ||
556 | udelay(500); | ||
557 | } | ||
558 | |||
559 | reg_val |= DPLL_VCO_ENABLE; | ||
560 | REG_WRITE(dpll_reg, reg_val); | ||
561 | REG_READ(dpll_reg); | ||
562 | udelay(500); | ||
563 | |||
564 | /* FIXME: add timeout */ | ||
565 | while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) | ||
566 | cpu_relax(); | ||
567 | } | ||
568 | |||
569 | /* Enable pipe */ | ||
570 | reg_val = REG_READ(pipeconf_reg); | ||
571 | if (!(reg_val & PIPEACONF_ENABLE)) { | ||
572 | reg_val |= PIPEACONF_ENABLE; | ||
573 | REG_WRITE(pipeconf_reg, reg_val); | ||
574 | REG_READ(pipeconf_reg); | ||
575 | udelay(500); | ||
576 | mdfldWaitForPipeEnable(dev, pipe); | ||
577 | } | ||
578 | |||
579 | /* Enable plane */ | ||
580 | reg_val = REG_READ(dspcntr_reg); | ||
581 | if (!(reg_val & DISPLAY_PLANE_ENABLE)) { | ||
582 | reg_val |= DISPLAY_PLANE_ENABLE; | ||
583 | REG_WRITE(dspcntr_reg, reg_val); | ||
584 | REG_READ(dspcntr_reg); | ||
585 | udelay(500); | ||
586 | } | ||
587 | |||
588 | gma_power_end(dev); | ||
589 | |||
590 | /* Clean IN_DSR flag */ | ||
591 | dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR; | ||
592 | |||
593 | return 0; | ||
594 | } | ||
595 | |||
596 | int mdfld_dpu_exit_dsr(struct drm_device *dev) | ||
597 | { | ||
598 | struct mdfld_dsi_dbi_output **dbi_output; | ||
599 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
600 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; | ||
601 | int i; | ||
602 | int pipe; | ||
603 | |||
604 | dbi_output = dpu_info->dbi_outputs; | ||
605 | |||
606 | for (i = 0; i < dpu_info->dbi_output_num; i++) { | ||
607 | /* If this output is not in DSR mode, don't call exit dsr */ | ||
608 | if (dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR) | ||
609 | __mdfld_dbi_exit_dsr(dbi_output[i], | ||
610 | dbi_output[i]->channel_num ? 2 : 0); | ||
611 | } | ||
612 | |||
613 | /* Enable TE interrupt */ | ||
614 | for (i = 0; i < dpu_info->dbi_output_num; i++) { | ||
615 | /* If this output is not in DSR mode, don't call exit dsr */ | ||
616 | pipe = dbi_output[i]->channel_num ? 2 : 0; | ||
617 | if (dbi_output[i]->dbi_panel_on && pipe) { | ||
618 | mdfld_disable_te(dev, 0); | ||
619 | mdfld_enable_te(dev, 2); | ||
620 | } else if (dbi_output[i]->dbi_panel_on && !pipe) { | ||
621 | mdfld_disable_te(dev, 2); | ||
622 | mdfld_enable_te(dev, 0); | ||
623 | } | ||
624 | } | ||
625 | return 0; | ||
626 | } | ||
627 | |||
628 | static int mdfld_dpu_enter_dsr(struct drm_device *dev) | ||
629 | { | ||
630 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
631 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; | ||
632 | struct mdfld_dsi_dbi_output **dbi_output; | ||
633 | int i; | ||
634 | |||
635 | dbi_output = dpu_info->dbi_outputs; | ||
636 | |||
637 | for (i = 0; i < dpu_info->dbi_output_num; i++) { | ||
638 | /* If output is off or already in DSR state, don't re-enter */ | ||
639 | if (dbi_output[i]->dbi_panel_on && | ||
640 | !(dbi_output[i]->mode_flags & MODE_SETTING_IN_DSR)) { | ||
641 | mdfld_dsi_dbi_enter_dsr(dbi_output[i], | ||
642 | dbi_output[i]->channel_num ? 2 : 0); | ||
643 | } | ||
644 | } | ||
645 | |||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | static void mdfld_dbi_dpu_timer_func(unsigned long data) | ||
650 | { | ||
651 | struct drm_device *dev = (struct drm_device *)data; | ||
652 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
653 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; | ||
654 | struct timer_list *dpu_timer = &dpu_info->dpu_timer; | ||
655 | unsigned long flags; | ||
656 | |||
657 | if (dpu_info->pending) { | ||
658 | dpu_info->idle_count = 0; | ||
659 | /* Update panel fb with damaged area */ | ||
660 | mdfld_dpu_update_fb(dev); | ||
661 | } else { | ||
662 | dpu_info->idle_count++; | ||
663 | } | ||
664 | |||
665 | if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) { | ||
666 | mdfld_dpu_enter_dsr(dev); | ||
667 | /* Stop timer by return */ | ||
668 | return; | ||
669 | } | ||
670 | |||
671 | spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags); | ||
672 | if (!timer_pending(dpu_timer)) { | ||
673 | dpu_timer->expires = jiffies + MDFLD_DSR_DELAY; | ||
674 | add_timer(dpu_timer); | ||
675 | } | ||
676 | spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags); | ||
677 | } | ||
678 | |||
679 | void mdfld_dpu_update_panel(struct drm_device *dev) | ||
680 | { | ||
681 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
682 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; | ||
683 | |||
684 | if (dpu_info->pending) { | ||
685 | dpu_info->idle_count = 0; | ||
686 | |||
687 | /*update panel fb with damaged area*/ | ||
688 | mdfld_dpu_update_fb(dev); | ||
689 | } else { | ||
690 | dpu_info->idle_count++; | ||
691 | } | ||
692 | |||
693 | if (dpu_info->idle_count >= MDFLD_MAX_IDLE_COUNT) { | ||
694 | /*enter dsr*/ | ||
695 | mdfld_dpu_enter_dsr(dev); | ||
696 | } | ||
697 | } | ||
698 | |||
699 | static int mdfld_dbi_dpu_timer_init(struct drm_device *dev, | ||
700 | struct mdfld_dbi_dpu_info *dpu_info) | ||
701 | { | ||
702 | struct timer_list *dpu_timer = &dpu_info->dpu_timer; | ||
703 | unsigned long flags; | ||
704 | |||
705 | spin_lock_init(&dpu_info->dpu_timer_lock); | ||
706 | spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags); | ||
707 | |||
708 | init_timer(dpu_timer); | ||
709 | |||
710 | dpu_timer->data = (unsigned long)dev; | ||
711 | dpu_timer->function = mdfld_dbi_dpu_timer_func; | ||
712 | dpu_timer->expires = jiffies + MDFLD_DSR_DELAY; | ||
713 | |||
714 | spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags); | ||
715 | |||
716 | return 0; | ||
717 | } | ||
718 | |||
719 | void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info) | ||
720 | { | ||
721 | struct timer_list *dpu_timer = &dpu_info->dpu_timer; | ||
722 | unsigned long flags; | ||
723 | |||
724 | spin_lock_irqsave(&dpu_info->dpu_timer_lock, flags); | ||
725 | if (!timer_pending(dpu_timer)) { | ||
726 | dpu_timer->expires = jiffies + MDFLD_DSR_DELAY; | ||
727 | add_timer(dpu_timer); | ||
728 | } | ||
729 | spin_unlock_irqrestore(&dpu_info->dpu_timer_lock, flags); | ||
730 | } | ||
731 | |||
732 | int mdfld_dbi_dpu_init(struct drm_device *dev) | ||
733 | { | ||
734 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
735 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; | ||
736 | |||
737 | if (!dpu_info || IS_ERR(dpu_info)) { | ||
738 | dpu_info = kzalloc(sizeof(struct mdfld_dbi_dpu_info), | ||
739 | GFP_KERNEL); | ||
740 | if (!dpu_info) { | ||
741 | DRM_ERROR("No memory\n"); | ||
742 | return -ENOMEM; | ||
743 | } | ||
744 | dev_priv->dbi_dpu_info = dpu_info; | ||
745 | } | ||
746 | |||
747 | dpu_info->dev = dev; | ||
748 | |||
749 | dpu_info->cursors[0].size = MDFLD_CURSOR_SIZE; | ||
750 | dpu_info->cursors[1].size = MDFLD_CURSOR_SIZE; | ||
751 | |||
752 | /*init dpu_update_lock*/ | ||
753 | spin_lock_init(&dpu_info->dpu_update_lock); | ||
754 | |||
755 | /*init dpu refresh timer*/ | ||
756 | mdfld_dbi_dpu_timer_init(dev, dpu_info); | ||
757 | |||
758 | /*init pipe damage area*/ | ||
759 | mdfld_dpu_init_damage(dpu_info, 0); | ||
760 | mdfld_dpu_init_damage(dpu_info, 2); | ||
761 | |||
762 | return 0; | ||
763 | } | ||
764 | |||
765 | void mdfld_dbi_dpu_exit(struct drm_device *dev) | ||
766 | { | ||
767 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
768 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; | ||
769 | |||
770 | if (!dpu_info) | ||
771 | return; | ||
772 | |||
773 | del_timer_sync(&dpu_info->dpu_timer); | ||
774 | kfree(dpu_info); | ||
775 | dev_priv->dbi_dpu_info = NULL; | ||
776 | } | ||
777 | |||
778 | |||
diff --git a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h deleted file mode 100644 index 42367ed48c08..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h +++ /dev/null | |||
@@ -1,154 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef __MDFLD_DSI_DBI_DPU_H__ | ||
29 | #define __MDFLD_DSI_DBI_DPU_H__ | ||
30 | |||
31 | #include "mdfld_dsi_dbi.h" | ||
32 | |||
33 | typedef enum { | ||
34 | MDFLD_PLANEA, | ||
35 | MDFLD_PLANEC, | ||
36 | MDFLD_CURSORA, | ||
37 | MDFLD_CURSORC, | ||
38 | MDFLD_OVERLAYA, | ||
39 | MDFLD_OVERLAYC, | ||
40 | MDFLD_PLANE_NUM, | ||
41 | } mdfld_plane_t; | ||
42 | |||
43 | #define MDFLD_PIPEA_PLANE_MASK 0x15 | ||
44 | #define MDFLD_PIPEC_PLANE_MASK 0x2A | ||
45 | |||
46 | struct mdfld_cursor_info { | ||
47 | int x, y; | ||
48 | int size; | ||
49 | }; | ||
50 | |||
51 | #define MDFLD_CURSOR_SIZE 64 | ||
52 | |||
53 | /* | ||
54 | * enter DSR mode if screen has no update for 2 frames. | ||
55 | */ | ||
56 | #define MDFLD_MAX_IDLE_COUNT 2 | ||
57 | |||
58 | struct mdfld_dbi_dpu_info { | ||
59 | struct drm_device *dev; | ||
60 | /* Lock */ | ||
61 | spinlock_t dpu_update_lock; | ||
62 | |||
63 | /* Cursor postion */ | ||
64 | struct mdfld_cursor_info cursors[2]; | ||
65 | |||
66 | /* Damaged area for each plane */ | ||
67 | struct psb_drm_dpu_rect damaged_rects[MDFLD_PLANE_NUM]; | ||
68 | |||
69 | /* Final damaged area */ | ||
70 | struct psb_drm_dpu_rect damage_pipea; | ||
71 | struct psb_drm_dpu_rect damage_pipec; | ||
72 | |||
73 | /* Pending */ | ||
74 | u32 pending; | ||
75 | |||
76 | /* DPU timer */ | ||
77 | struct timer_list dpu_timer; | ||
78 | spinlock_t dpu_timer_lock; | ||
79 | |||
80 | /* DPU idle count */ | ||
81 | u32 idle_count; | ||
82 | |||
83 | /* DSI outputs */ | ||
84 | struct mdfld_dsi_dbi_output *dbi_outputs[2]; | ||
85 | int dbi_output_num; | ||
86 | }; | ||
87 | |||
88 | static inline int mdfld_dpu_region_extent(struct psb_drm_dpu_rect *origin, | ||
89 | struct psb_drm_dpu_rect *rect) | ||
90 | { | ||
91 | int x1, y1, x2, y2; | ||
92 | |||
93 | x1 = origin->x + origin->width; | ||
94 | y1 = origin->y + origin->height; | ||
95 | |||
96 | x2 = rect->x + rect->width; | ||
97 | y2 = rect->y + rect->height; | ||
98 | |||
99 | origin->x = min(origin->x, rect->x); | ||
100 | origin->y = min(origin->y, rect->y); | ||
101 | origin->width = max(x1, x2) - origin->x; | ||
102 | origin->height = max(y1, y2) - origin->y; | ||
103 | |||
104 | return 0; | ||
105 | } | ||
106 | |||
107 | static inline void mdfld_check_boundary(struct mdfld_dbi_dpu_info *dpu_info, | ||
108 | struct psb_drm_dpu_rect *rect) | ||
109 | { | ||
110 | if (rect->x < 0) | ||
111 | rect->x = 0; | ||
112 | if (rect->y < 0) | ||
113 | rect->y = 0; | ||
114 | |||
115 | if (rect->x + rect->width > 864) | ||
116 | rect->width = 864 - rect->x; | ||
117 | if (rect->y + rect->height > 480) | ||
118 | rect->height = 480 - rect->height; | ||
119 | |||
120 | if (!rect->width) | ||
121 | rect->width = 1; | ||
122 | if (!rect->height) | ||
123 | rect->height = 1; | ||
124 | } | ||
125 | |||
126 | static inline void mdfld_dpu_init_damage(struct mdfld_dbi_dpu_info *dpu_info, | ||
127 | int pipe) | ||
128 | { | ||
129 | struct psb_drm_dpu_rect *rect; | ||
130 | |||
131 | if (pipe == 0) | ||
132 | rect = &dpu_info->damage_pipea; | ||
133 | else | ||
134 | rect = &dpu_info->damage_pipec; | ||
135 | |||
136 | rect->x = 864; | ||
137 | rect->y = 480; | ||
138 | rect->width = -864; | ||
139 | rect->height = -480; | ||
140 | } | ||
141 | |||
142 | extern int mdfld_dsi_dbi_dsr_off(struct drm_device *dev, | ||
143 | struct psb_drm_dpu_rect *rect); | ||
144 | extern int mdfld_dbi_dpu_report_damage(struct drm_device *dev, | ||
145 | mdfld_plane_t plane, | ||
146 | struct psb_drm_dpu_rect *rect); | ||
147 | extern int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev); | ||
148 | extern int mdfld_dpu_exit_dsr(struct drm_device *dev); | ||
149 | extern void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info); | ||
150 | extern int mdfld_dbi_dpu_init(struct drm_device *dev); | ||
151 | extern void mdfld_dbi_dpu_exit(struct drm_device *dev); | ||
152 | extern void mdfld_dpu_update_panel(struct drm_device *dev); | ||
153 | |||
154 | #endif /*__MDFLD_DSI_DBI_DPU_H__*/ | ||
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.c b/drivers/staging/gma500/mdfld_dsi_dpi.c deleted file mode 100644 index e685f1217baa..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_dpi.c +++ /dev/null | |||
@@ -1,805 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
26 | */ | ||
27 | |||
28 | #include "mdfld_dsi_dpi.h" | ||
29 | #include "mdfld_output.h" | ||
30 | #include "mdfld_dsi_pkg_sender.h" | ||
31 | |||
32 | |||
33 | static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe) | ||
34 | { | ||
35 | u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; | ||
36 | int timeout = 0; | ||
37 | |||
38 | if (pipe == 2) | ||
39 | gen_fifo_stat_reg += MIPIC_REG_OFFSET; | ||
40 | |||
41 | udelay(500); | ||
42 | |||
43 | /* This will time out after approximately 2+ seconds */ | ||
44 | while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) { | ||
45 | udelay(100); | ||
46 | timeout++; | ||
47 | } | ||
48 | |||
49 | if (timeout == 20000) | ||
50 | dev_warn(dev->dev, "MIPI: HS Data FIFO was never cleared!\n"); | ||
51 | } | ||
52 | |||
53 | static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe) | ||
54 | { | ||
55 | u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; | ||
56 | int timeout = 0; | ||
57 | |||
58 | if (pipe == 2) | ||
59 | gen_fifo_stat_reg += MIPIC_REG_OFFSET; | ||
60 | |||
61 | udelay(500); | ||
62 | |||
63 | /* This will time out after approximately 2+ seconds */ | ||
64 | while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_CTRL_FULL)) { | ||
65 | udelay(100); | ||
66 | timeout++; | ||
67 | } | ||
68 | if (timeout == 20000) | ||
69 | dev_warn(dev->dev, "MIPI: HS CMD FIFO was never cleared!\n"); | ||
70 | } | ||
71 | |||
72 | static void mdfld_wait_for_DPI_CTRL_FIFO(struct drm_device *dev, u32 pipe) | ||
73 | { | ||
74 | u32 gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; | ||
75 | int timeout = 0; | ||
76 | |||
77 | if (pipe == 2) | ||
78 | gen_fifo_stat_reg += MIPIC_REG_OFFSET; | ||
79 | |||
80 | udelay(500); | ||
81 | |||
82 | /* This will time out after approximately 2+ seconds */ | ||
83 | while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) & DPI_FIFO_EMPTY) | ||
84 | != DPI_FIFO_EMPTY)) { | ||
85 | udelay(100); | ||
86 | timeout++; | ||
87 | } | ||
88 | |||
89 | if (timeout == 20000) | ||
90 | dev_warn(dev->dev, "MIPI: DPI FIFO was never cleared!\n"); | ||
91 | } | ||
92 | |||
93 | static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe) | ||
94 | { | ||
95 | u32 intr_stat_reg = MIPIA_INTR_STAT_REG; | ||
96 | int timeout = 0; | ||
97 | |||
98 | if (pipe == 2) | ||
99 | intr_stat_reg += MIPIC_REG_OFFSET; | ||
100 | |||
101 | udelay(500); | ||
102 | |||
103 | /* This will time out after approximately 2+ seconds */ | ||
104 | while ((timeout < 20000) && (!(REG_READ(intr_stat_reg) & DSI_INTR_STATE_SPL_PKG_SENT))) { | ||
105 | udelay(100); | ||
106 | timeout++; | ||
107 | } | ||
108 | |||
109 | if (timeout == 20000) | ||
110 | dev_warn(dev->dev, "MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n"); | ||
111 | } | ||
112 | |||
113 | |||
114 | /* ************************************************************************* *\ | ||
115 | * FUNCTION: mdfld_dsi_tpo_ic_init | ||
116 | * | ||
117 | * DESCRIPTION: This function is called only by mrst_dsi_mode_set and | ||
118 | * restore_display_registers. since this function does not | ||
119 | * acquire the mutex, it is important that the calling function | ||
120 | * does! | ||
121 | \* ************************************************************************* */ | ||
122 | void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe) | ||
123 | { | ||
124 | struct drm_device *dev = dsi_config->dev; | ||
125 | u32 dcsChannelNumber = dsi_config->channel_num; | ||
126 | u32 gen_data_reg = MIPIA_HS_GEN_DATA_REG; | ||
127 | u32 gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG; | ||
128 | u32 gen_ctrl_val = GEN_LONG_WRITE; | ||
129 | |||
130 | if (pipe == 2) { | ||
131 | gen_data_reg = HS_GEN_DATA_REG + MIPIC_REG_OFFSET; | ||
132 | gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET; | ||
133 | } | ||
134 | |||
135 | gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS; | ||
136 | |||
137 | /* Flip page order */ | ||
138 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
139 | REG_WRITE(gen_data_reg, 0x00008036); | ||
140 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
141 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); | ||
142 | |||
143 | /* 0xF0 */ | ||
144 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
145 | REG_WRITE(gen_data_reg, 0x005a5af0); | ||
146 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
147 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); | ||
148 | |||
149 | /* Write protection key */ | ||
150 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
151 | REG_WRITE(gen_data_reg, 0x005a5af1); | ||
152 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
153 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); | ||
154 | |||
155 | /* 0xFC */ | ||
156 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
157 | REG_WRITE(gen_data_reg, 0x005a5afc); | ||
158 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
159 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); | ||
160 | |||
161 | /* 0xB7 */ | ||
162 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
163 | REG_WRITE(gen_data_reg, 0x770000b7); | ||
164 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
165 | REG_WRITE(gen_data_reg, 0x00000044); | ||
166 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
167 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS)); | ||
168 | |||
169 | /* 0xB6 */ | ||
170 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
171 | REG_WRITE(gen_data_reg, 0x000a0ab6); | ||
172 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
173 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); | ||
174 | |||
175 | /* 0xF2 */ | ||
176 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
177 | REG_WRITE(gen_data_reg, 0x081010f2); | ||
178 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
179 | REG_WRITE(gen_data_reg, 0x4a070708); | ||
180 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
181 | REG_WRITE(gen_data_reg, 0x000000c5); | ||
182 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
183 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); | ||
184 | |||
185 | /* 0xF8 */ | ||
186 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
187 | REG_WRITE(gen_data_reg, 0x024003f8); | ||
188 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
189 | REG_WRITE(gen_data_reg, 0x01030a04); | ||
190 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
191 | REG_WRITE(gen_data_reg, 0x0e020220); | ||
192 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
193 | REG_WRITE(gen_data_reg, 0x00000004); | ||
194 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
195 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS)); | ||
196 | |||
197 | /* 0xE2 */ | ||
198 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
199 | REG_WRITE(gen_data_reg, 0x398fc3e2); | ||
200 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
201 | REG_WRITE(gen_data_reg, 0x0000916f); | ||
202 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
203 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS)); | ||
204 | |||
205 | /* 0xB0 */ | ||
206 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
207 | REG_WRITE(gen_data_reg, 0x000000b0); | ||
208 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
209 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS)); | ||
210 | |||
211 | /* 0xF4 */ | ||
212 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
213 | REG_WRITE(gen_data_reg, 0x240242f4); | ||
214 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
215 | REG_WRITE(gen_data_reg, 0x78ee2002); | ||
216 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
217 | REG_WRITE(gen_data_reg, 0x2a071050); | ||
218 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
219 | REG_WRITE(gen_data_reg, 0x507fee10); | ||
220 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
221 | REG_WRITE(gen_data_reg, 0x10300710); | ||
222 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
223 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS)); | ||
224 | |||
225 | /* 0xBA */ | ||
226 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
227 | REG_WRITE(gen_data_reg, 0x19fe07ba); | ||
228 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
229 | REG_WRITE(gen_data_reg, 0x101c0a31); | ||
230 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
231 | REG_WRITE(gen_data_reg, 0x00000010); | ||
232 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
233 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); | ||
234 | |||
235 | /* 0xBB */ | ||
236 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
237 | REG_WRITE(gen_data_reg, 0x28ff07bb); | ||
238 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
239 | REG_WRITE(gen_data_reg, 0x24280a31); | ||
240 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
241 | REG_WRITE(gen_data_reg, 0x00000034); | ||
242 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
243 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS)); | ||
244 | |||
245 | /* 0xFB */ | ||
246 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
247 | REG_WRITE(gen_data_reg, 0x535d05fb); | ||
248 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
249 | REG_WRITE(gen_data_reg, 0x1b1a2130); | ||
250 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
251 | REG_WRITE(gen_data_reg, 0x221e180e); | ||
252 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
253 | REG_WRITE(gen_data_reg, 0x131d2120); | ||
254 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
255 | REG_WRITE(gen_data_reg, 0x535d0508); | ||
256 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
257 | REG_WRITE(gen_data_reg, 0x1c1a2131); | ||
258 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
259 | REG_WRITE(gen_data_reg, 0x231f160d); | ||
260 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
261 | REG_WRITE(gen_data_reg, 0x111b2220); | ||
262 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
263 | REG_WRITE(gen_data_reg, 0x535c2008); | ||
264 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
265 | REG_WRITE(gen_data_reg, 0x1f1d2433); | ||
266 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
267 | REG_WRITE(gen_data_reg, 0x2c251a10); | ||
268 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
269 | REG_WRITE(gen_data_reg, 0x2c34372d); | ||
270 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
271 | REG_WRITE(gen_data_reg, 0x00000023); | ||
272 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
273 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); | ||
274 | |||
275 | /* 0xFA */ | ||
276 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
277 | REG_WRITE(gen_data_reg, 0x525c0bfa); | ||
278 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
279 | REG_WRITE(gen_data_reg, 0x1c1c232f); | ||
280 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
281 | REG_WRITE(gen_data_reg, 0x2623190e); | ||
282 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
283 | REG_WRITE(gen_data_reg, 0x18212625); | ||
284 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
285 | REG_WRITE(gen_data_reg, 0x545d0d0e); | ||
286 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
287 | REG_WRITE(gen_data_reg, 0x1e1d2333); | ||
288 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
289 | REG_WRITE(gen_data_reg, 0x26231a10); | ||
290 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
291 | REG_WRITE(gen_data_reg, 0x1a222725); | ||
292 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
293 | REG_WRITE(gen_data_reg, 0x545d280f); | ||
294 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
295 | REG_WRITE(gen_data_reg, 0x21202635); | ||
296 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
297 | REG_WRITE(gen_data_reg, 0x31292013); | ||
298 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
299 | REG_WRITE(gen_data_reg, 0x31393d33); | ||
300 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
301 | REG_WRITE(gen_data_reg, 0x00000029); | ||
302 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
303 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS)); | ||
304 | |||
305 | /* Set DM */ | ||
306 | mdfld_wait_for_HS_DATA_FIFO(dev, pipe); | ||
307 | REG_WRITE(gen_data_reg, 0x000100f7); | ||
308 | mdfld_wait_for_HS_CTRL_FIFO(dev, pipe); | ||
309 | REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS)); | ||
310 | } | ||
311 | |||
312 | static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count, | ||
313 | int num_lane, int bpp) | ||
314 | { | ||
315 | return (u16)((pixel_clock_count * bpp) / (num_lane * 8)); | ||
316 | } | ||
317 | |||
318 | /* | ||
319 | * Calculate the dpi time basing on a given drm mode @mode | ||
320 | * return 0 on success. | ||
321 | * FIXME: I was using proposed mode value for calculation, may need to | ||
322 | * use crtc mode values later | ||
323 | */ | ||
324 | int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, | ||
325 | struct mdfld_dsi_dpi_timing *dpi_timing, | ||
326 | int num_lane, int bpp) | ||
327 | { | ||
328 | int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive; | ||
329 | int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive; | ||
330 | |||
331 | if(!mode || !dpi_timing) { | ||
332 | DRM_ERROR("Invalid parameter\n"); | ||
333 | return -EINVAL; | ||
334 | } | ||
335 | |||
336 | pclk_hactive = mode->hdisplay; | ||
337 | pclk_hfp = mode->hsync_start - mode->hdisplay; | ||
338 | pclk_hsync = mode->hsync_end - mode->hsync_start; | ||
339 | pclk_hbp = mode->htotal - mode->hsync_end; | ||
340 | |||
341 | pclk_vactive = mode->vdisplay; | ||
342 | pclk_vfp = mode->vsync_start - mode->vdisplay; | ||
343 | pclk_vsync = mode->vsync_end - mode->vsync_start; | ||
344 | pclk_vbp = mode->vtotal - mode->vsync_end; | ||
345 | |||
346 | /* | ||
347 | * byte clock counts were calculated by following formula | ||
348 | * bclock_count = pclk_count * bpp / num_lane / 8 | ||
349 | */ | ||
350 | dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hsync, num_lane, bpp); | ||
351 | dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hbp, num_lane, bpp); | ||
352 | dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hfp, num_lane, bpp); | ||
353 | dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_hactive, num_lane, bpp); | ||
354 | dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vsync, num_lane, bpp); | ||
355 | dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vbp, num_lane, bpp); | ||
356 | dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(pclk_vfp, num_lane, bpp); | ||
357 | |||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe) | ||
362 | { | ||
363 | struct drm_device *dev = dsi_config->dev; | ||
364 | u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; | ||
365 | int lane_count = dsi_config->lane_count; | ||
366 | struct mdfld_dsi_dpi_timing dpi_timing; | ||
367 | struct drm_display_mode *mode = dsi_config->mode; | ||
368 | u32 val = 0; | ||
369 | |||
370 | /*un-ready device*/ | ||
371 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); | ||
372 | |||
373 | /*init dsi adapter before kicking off*/ | ||
374 | REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); | ||
375 | |||
376 | /*enable all interrupts*/ | ||
377 | REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); | ||
378 | |||
379 | |||
380 | /*set up func_prg*/ | ||
381 | val |= lane_count; | ||
382 | val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; | ||
383 | |||
384 | switch(dsi_config->bpp) { | ||
385 | case 16: | ||
386 | val |= DSI_DPI_COLOR_FORMAT_RGB565; | ||
387 | break; | ||
388 | case 18: | ||
389 | val |= DSI_DPI_COLOR_FORMAT_RGB666; | ||
390 | break; | ||
391 | case 24: | ||
392 | val |= DSI_DPI_COLOR_FORMAT_RGB888; | ||
393 | break; | ||
394 | default: | ||
395 | DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp); | ||
396 | } | ||
397 | REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); | ||
398 | |||
399 | REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), | ||
400 | (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); | ||
401 | REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK); | ||
402 | |||
403 | /*max value: 20 clock cycles of txclkesc*/ | ||
404 | REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); | ||
405 | |||
406 | /*min 21 txclkesc, max: ffffh*/ | ||
407 | REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK); | ||
408 | |||
409 | REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay); | ||
410 | |||
411 | /*set DPI timing registers*/ | ||
412 | mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp); | ||
413 | |||
414 | REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); | ||
415 | REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); | ||
416 | REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); | ||
417 | REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); | ||
418 | REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); | ||
419 | REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); | ||
420 | REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); | ||
421 | |||
422 | REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); | ||
423 | |||
424 | /*min: 7d0 max: 4e20*/ | ||
425 | REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0); | ||
426 | |||
427 | /*set up video mode*/ | ||
428 | val = 0; | ||
429 | val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; | ||
430 | REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val); | ||
431 | |||
432 | REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); | ||
433 | |||
434 | REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); | ||
435 | |||
436 | /*TODO: figure out how to setup these registers*/ | ||
437 | REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); | ||
438 | |||
439 | REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14); | ||
440 | /*set device ready*/ | ||
441 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); | ||
442 | } | ||
443 | |||
444 | void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe) | ||
445 | { | ||
446 | struct drm_device *dev = output->dev; | ||
447 | u32 reg_offset = 0; | ||
448 | |||
449 | if(output->panel_on) | ||
450 | return; | ||
451 | |||
452 | if(pipe) | ||
453 | reg_offset = MIPIC_REG_OFFSET; | ||
454 | |||
455 | /* clear special packet sent bit */ | ||
456 | if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { | ||
457 | REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); | ||
458 | } | ||
459 | |||
460 | /*send turn on package*/ | ||
461 | REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON); | ||
462 | |||
463 | /*wait for SPL_PKG_SENT interrupt*/ | ||
464 | mdfld_wait_for_SPL_PKG_SENT(dev, pipe); | ||
465 | |||
466 | if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { | ||
467 | REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); | ||
468 | } | ||
469 | |||
470 | output->panel_on = 1; | ||
471 | |||
472 | /* FIXME the following is disabled to WA the X slow start issue for TMD panel */ | ||
473 | /* if(pipe == 2) */ | ||
474 | /* dev_priv->dpi_panel_on2 = true; */ | ||
475 | /* else if (pipe == 0) */ | ||
476 | /* dev_priv->dpi_panel_on = true; */ | ||
477 | } | ||
478 | |||
479 | static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output, int pipe) | ||
480 | { | ||
481 | struct drm_device *dev = output->dev; | ||
482 | u32 reg_offset = 0; | ||
483 | |||
484 | /*if output is on, or mode setting didn't happen, ignore this*/ | ||
485 | if((!output->panel_on) || output->first_boot) { | ||
486 | output->first_boot = 0; | ||
487 | return; | ||
488 | } | ||
489 | |||
490 | if(pipe) | ||
491 | reg_offset = MIPIC_REG_OFFSET; | ||
492 | |||
493 | /* Wait for dpi fifo to empty */ | ||
494 | mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe); | ||
495 | |||
496 | /* Clear the special packet interrupt bit if set */ | ||
497 | if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { | ||
498 | REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); | ||
499 | } | ||
500 | |||
501 | if(REG_READ(MIPIA_DPI_CONTROL_REG + reg_offset) == DSI_DPI_CTRL_HS_SHUTDOWN) { | ||
502 | dev_warn(dev->dev, "try to send the same package again, abort!"); | ||
503 | goto shutdown_out; | ||
504 | } | ||
505 | |||
506 | REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN); | ||
507 | |||
508 | shutdown_out: | ||
509 | output->panel_on = 0; | ||
510 | output->first_boot = 0; | ||
511 | |||
512 | /* FIXME the following is disabled to WA the X slow start issue for TMD panel */ | ||
513 | /* if(pipe == 2) */ | ||
514 | /* dev_priv->dpi_panel_on2 = false; */ | ||
515 | /* else if (pipe == 0) */ | ||
516 | /* dev_priv->dpi_panel_on = false; */ | ||
517 | /* #ifdef CONFIG_PM_RUNTIME*/ | ||
518 | /* if (drm_psb_ospm && !enable_gfx_rtpm) { */ | ||
519 | /* pm_runtime_allow(&gpDrmDevice->pdev->dev); */ | ||
520 | /* schedule_delayed_work(&dev_priv->rtpm_work, 30 * 1000); */ | ||
521 | /* } */ | ||
522 | /*if (enable_gfx_rtpm) */ | ||
523 | /* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */ | ||
524 | /* #endif */ | ||
525 | } | ||
526 | |||
527 | void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on) | ||
528 | { | ||
529 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
530 | struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); | ||
531 | struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); | ||
532 | int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); | ||
533 | struct drm_device *dev = dsi_config->dev; | ||
534 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
535 | u32 mipi_reg = MIPI; | ||
536 | u32 pipeconf_reg = PIPEACONF; | ||
537 | |||
538 | if(pipe) { | ||
539 | mipi_reg = MIPI_C; | ||
540 | pipeconf_reg = PIPECCONF; | ||
541 | } | ||
542 | |||
543 | /* Start up display island if it was shutdown */ | ||
544 | if (!gma_power_begin(dev, true)) | ||
545 | return; | ||
546 | |||
547 | if(on) { | ||
548 | if (mdfld_get_panel_type(dev, pipe) == TMD_VID){ | ||
549 | mdfld_dsi_dpi_turn_on(dpi_output, pipe); | ||
550 | } else { | ||
551 | /* Enable mipi port */ | ||
552 | REG_WRITE(mipi_reg, (REG_READ(mipi_reg) | (1 << 31))); | ||
553 | REG_READ(mipi_reg); | ||
554 | |||
555 | mdfld_dsi_dpi_turn_on(dpi_output, pipe); | ||
556 | mdfld_dsi_tpo_ic_init(dsi_config, pipe); | ||
557 | } | ||
558 | |||
559 | if(pipe == 2) { | ||
560 | dev_priv->dpi_panel_on2 = true; | ||
561 | } | ||
562 | else { | ||
563 | dev_priv->dpi_panel_on = true; | ||
564 | } | ||
565 | |||
566 | } else { | ||
567 | if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { | ||
568 | mdfld_dsi_dpi_shut_down(dpi_output, pipe); | ||
569 | } else { | ||
570 | mdfld_dsi_dpi_shut_down(dpi_output, pipe); | ||
571 | /* Disable mipi port */ | ||
572 | REG_WRITE(mipi_reg, (REG_READ(mipi_reg) & ~(1<<31))); | ||
573 | REG_READ(mipi_reg); | ||
574 | } | ||
575 | |||
576 | if(pipe == 2) | ||
577 | dev_priv->dpi_panel_on2 = false; | ||
578 | else | ||
579 | dev_priv->dpi_panel_on = false; | ||
580 | } | ||
581 | gma_power_end(dev); | ||
582 | } | ||
583 | |||
584 | void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode) | ||
585 | { | ||
586 | dev_dbg(encoder->dev->dev, "DPMS %s\n", | ||
587 | (mode == DRM_MODE_DPMS_ON ? "on":"off")); | ||
588 | |||
589 | if (mode == DRM_MODE_DPMS_ON) | ||
590 | mdfld_dsi_dpi_set_power(encoder, true); | ||
591 | else { | ||
592 | mdfld_dsi_dpi_set_power(encoder, false); | ||
593 | #if 0 /* FIXME */ | ||
594 | #ifdef CONFIG_PM_RUNTIME | ||
595 | if (enable_gfx_rtpm) | ||
596 | pm_schedule_suspend(&gpDrmDevice->pdev->dev, gfxrtdelay); | ||
597 | #endif | ||
598 | #endif | ||
599 | } | ||
600 | } | ||
601 | |||
602 | bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, | ||
603 | struct drm_display_mode *mode, | ||
604 | struct drm_display_mode *adjusted_mode) | ||
605 | { | ||
606 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
607 | struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); | ||
608 | struct drm_display_mode *fixed_mode = dsi_config->fixed_mode; | ||
609 | |||
610 | if(fixed_mode) { | ||
611 | adjusted_mode->hdisplay = fixed_mode->hdisplay; | ||
612 | adjusted_mode->hsync_start = fixed_mode->hsync_start; | ||
613 | adjusted_mode->hsync_end = fixed_mode->hsync_end; | ||
614 | adjusted_mode->htotal = fixed_mode->htotal; | ||
615 | adjusted_mode->vdisplay = fixed_mode->vdisplay; | ||
616 | adjusted_mode->vsync_start = fixed_mode->vsync_start; | ||
617 | adjusted_mode->vsync_end = fixed_mode->vsync_end; | ||
618 | adjusted_mode->vtotal = fixed_mode->vtotal; | ||
619 | adjusted_mode->clock = fixed_mode->clock; | ||
620 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | ||
621 | } | ||
622 | |||
623 | return true; | ||
624 | } | ||
625 | |||
626 | void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder) | ||
627 | { | ||
628 | mdfld_dsi_dpi_set_power(encoder, false); | ||
629 | } | ||
630 | |||
631 | void mdfld_dsi_dpi_commit(struct drm_encoder *encoder) | ||
632 | { | ||
633 | mdfld_dsi_dpi_set_power(encoder, true); | ||
634 | } | ||
635 | |||
636 | void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, | ||
637 | struct drm_display_mode *mode, | ||
638 | struct drm_display_mode *adjusted_mode) | ||
639 | { | ||
640 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
641 | struct mdfld_dsi_dpi_output *dpi_output = MDFLD_DSI_DPI_OUTPUT(dsi_encoder); | ||
642 | struct mdfld_dsi_config *dsi_config = mdfld_dsi_encoder_get_config(dsi_encoder); | ||
643 | struct drm_device *dev = dsi_config->dev; | ||
644 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
645 | int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder); | ||
646 | |||
647 | u32 pipeconf_reg = PIPEACONF; | ||
648 | u32 dspcntr_reg = DSPACNTR; | ||
649 | u32 mipi_reg = MIPI; | ||
650 | u32 reg_offset = 0; | ||
651 | |||
652 | u32 pipeconf = dev_priv->pipeconf; | ||
653 | u32 dspcntr = dev_priv->dspcntr; | ||
654 | u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; | ||
655 | |||
656 | dev_dbg(dev->dev, "set mode %dx%d on pipe %d\n", | ||
657 | mode->hdisplay, mode->vdisplay, pipe); | ||
658 | |||
659 | if(pipe) { | ||
660 | pipeconf_reg = PIPECCONF; | ||
661 | dspcntr_reg = DSPCCNTR; | ||
662 | mipi_reg = MIPI_C; | ||
663 | reg_offset = MIPIC_REG_OFFSET; | ||
664 | } else { | ||
665 | mipi |= 2; | ||
666 | } | ||
667 | |||
668 | if (!gma_power_begin(dev, true)) | ||
669 | return; | ||
670 | |||
671 | /* Set up mipi port FIXME: do at init time */ | ||
672 | REG_WRITE(mipi_reg, mipi); | ||
673 | REG_READ(mipi_reg); | ||
674 | |||
675 | /* Set up DSI controller DPI interface */ | ||
676 | mdfld_dsi_dpi_controller_init(dsi_config, pipe); | ||
677 | |||
678 | if (mdfld_get_panel_type(dev, pipe) != TMD_VID) { | ||
679 | /* Turn on DPI interface */ | ||
680 | mdfld_dsi_dpi_turn_on(dpi_output, pipe); | ||
681 | } | ||
682 | |||
683 | /* Set up pipe */ | ||
684 | REG_WRITE(pipeconf_reg, pipeconf); | ||
685 | REG_READ(pipeconf_reg); | ||
686 | |||
687 | /* Set up display plane */ | ||
688 | REG_WRITE(dspcntr_reg, dspcntr); | ||
689 | REG_READ(dspcntr_reg); | ||
690 | |||
691 | msleep(20); /* FIXME: this should wait for vblank */ | ||
692 | |||
693 | dev_dbg(dev->dev, "State %x, power %d\n", | ||
694 | REG_READ(MIPIA_INTR_STAT_REG + reg_offset), | ||
695 | dpi_output->panel_on); | ||
696 | |||
697 | if (mdfld_get_panel_type(dev, pipe) != TMD_VID) { | ||
698 | /* Init driver ic */ | ||
699 | mdfld_dsi_tpo_ic_init(dsi_config, pipe); | ||
700 | /* Init backlight */ | ||
701 | mdfld_dsi_brightness_init(dsi_config, pipe); | ||
702 | } | ||
703 | gma_power_end(dev); | ||
704 | } | ||
705 | |||
706 | |||
707 | /* | ||
708 | * Init DSI DPI encoder. | ||
709 | * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector | ||
710 | * return pointer of newly allocated DPI encoder, NULL on error | ||
711 | */ | ||
712 | struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, | ||
713 | struct mdfld_dsi_connector *dsi_connector, | ||
714 | struct panel_funcs *p_funcs) | ||
715 | { | ||
716 | struct mdfld_dsi_dpi_output *dpi_output = NULL; | ||
717 | struct mdfld_dsi_config *dsi_config; | ||
718 | struct drm_connector *connector = NULL; | ||
719 | struct drm_encoder *encoder = NULL; | ||
720 | struct drm_display_mode *fixed_mode = NULL; | ||
721 | int pipe; | ||
722 | u32 data; | ||
723 | int ret; | ||
724 | |||
725 | if (!dsi_connector || !p_funcs) { | ||
726 | WARN_ON(1); | ||
727 | return NULL; | ||
728 | } | ||
729 | |||
730 | dsi_config = mdfld_dsi_get_config(dsi_connector); | ||
731 | pipe = dsi_connector->pipe; | ||
732 | |||
733 | /* Panel hard-reset */ | ||
734 | if (p_funcs->reset) { | ||
735 | ret = p_funcs->reset(pipe); | ||
736 | if (ret) { | ||
737 | DRM_ERROR("Panel %d hard-reset failed\n", pipe); | ||
738 | return NULL; | ||
739 | } | ||
740 | } | ||
741 | |||
742 | /* Panel drvIC init */ | ||
743 | if (p_funcs->drv_ic_init) | ||
744 | p_funcs->drv_ic_init(dsi_config, pipe); | ||
745 | |||
746 | /* Panel power mode detect */ | ||
747 | ret = mdfld_dsi_get_power_mode(dsi_config, | ||
748 | &data, | ||
749 | MDFLD_DSI_LP_TRANSMISSION); | ||
750 | if (ret) { | ||
751 | DRM_ERROR("Panel %d get power mode failed\n", pipe); | ||
752 | dsi_connector->status = connector_status_disconnected; | ||
753 | } else { | ||
754 | DRM_INFO("pipe %d power mode 0x%x\n", pipe, data); | ||
755 | dsi_connector->status = connector_status_connected; | ||
756 | } | ||
757 | |||
758 | dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL); | ||
759 | if(!dpi_output) { | ||
760 | dev_err(dev->dev, "No memory for dsi_dpi_output\n"); | ||
761 | return NULL; | ||
762 | } | ||
763 | |||
764 | if(dsi_connector->pipe) | ||
765 | dpi_output->panel_on = 0; | ||
766 | else | ||
767 | dpi_output->panel_on = 0; | ||
768 | |||
769 | dpi_output->dev = dev; | ||
770 | dpi_output->p_funcs = p_funcs; | ||
771 | dpi_output->first_boot = 1; | ||
772 | |||
773 | /* Get fixed mode */ | ||
774 | dsi_config = mdfld_dsi_get_config(dsi_connector); | ||
775 | fixed_mode = dsi_config->fixed_mode; | ||
776 | |||
777 | /* Create drm encoder object */ | ||
778 | connector = &dsi_connector->base.base; | ||
779 | encoder = &dpi_output->base.base; | ||
780 | /* | ||
781 | * On existing hardware this will be a panel of some form, | ||
782 | * if future devices also have HDMI bridges this will need | ||
783 | * revisiting | ||
784 | */ | ||
785 | drm_encoder_init(dev, | ||
786 | encoder, | ||
787 | p_funcs->encoder_funcs, | ||
788 | DRM_MODE_ENCODER_LVDS); | ||
789 | drm_encoder_helper_add(encoder, | ||
790 | p_funcs->encoder_helper_funcs); | ||
791 | |||
792 | /* Attach to given connector */ | ||
793 | drm_mode_connector_attach_encoder(connector, encoder); | ||
794 | |||
795 | /* Set possible crtcs and clones */ | ||
796 | if(dsi_connector->pipe) { | ||
797 | encoder->possible_crtcs = (1 << 2); | ||
798 | encoder->possible_clones = (1 << 1); | ||
799 | } else { | ||
800 | encoder->possible_crtcs = (1 << 0); | ||
801 | encoder->possible_clones = (1 << 0); | ||
802 | } | ||
803 | return &dpi_output->base; | ||
804 | } | ||
805 | |||
diff --git a/drivers/staging/gma500/mdfld_dsi_dpi.h b/drivers/staging/gma500/mdfld_dsi_dpi.h deleted file mode 100644 index ed92d45ee74a..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_dpi.h +++ /dev/null | |||
@@ -1,78 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef __MDFLD_DSI_DPI_H__ | ||
29 | #define __MDFLD_DSI_DPI_H__ | ||
30 | |||
31 | #include "mdfld_dsi_output.h" | ||
32 | #include "mdfld_output.h" | ||
33 | |||
34 | struct mdfld_dsi_dpi_timing { | ||
35 | u16 hsync_count; | ||
36 | u16 hbp_count; | ||
37 | u16 hfp_count; | ||
38 | u16 hactive_count; | ||
39 | u16 vsync_count; | ||
40 | u16 vbp_count; | ||
41 | u16 vfp_count; | ||
42 | }; | ||
43 | |||
44 | struct mdfld_dsi_dpi_output { | ||
45 | struct mdfld_dsi_encoder base; | ||
46 | struct drm_device *dev; | ||
47 | |||
48 | int panel_on; | ||
49 | int first_boot; | ||
50 | |||
51 | struct panel_funcs *p_funcs; | ||
52 | }; | ||
53 | |||
54 | #define MDFLD_DSI_DPI_OUTPUT(dsi_encoder) \ | ||
55 | container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base) | ||
56 | |||
57 | extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode, | ||
58 | struct mdfld_dsi_dpi_timing *dpi_timing, | ||
59 | int num_lane, int bpp); | ||
60 | extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev, | ||
61 | struct mdfld_dsi_connector *dsi_connector, | ||
62 | struct panel_funcs *p_funcs); | ||
63 | |||
64 | /* Medfield DPI helper functions */ | ||
65 | extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode); | ||
66 | extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder, | ||
67 | struct drm_display_mode *mode, | ||
68 | struct drm_display_mode *adjusted_mode); | ||
69 | extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder); | ||
70 | extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder); | ||
71 | extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder, | ||
72 | struct drm_display_mode *mode, | ||
73 | struct drm_display_mode *adjusted_mode); | ||
74 | extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, | ||
75 | int pipe); | ||
76 | extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *si_config, | ||
77 | int pipe); | ||
78 | #endif /*__MDFLD_DSI_DPI_H__*/ | ||
diff --git a/drivers/staging/gma500/mdfld_dsi_output.c b/drivers/staging/gma500/mdfld_dsi_output.c deleted file mode 100644 index 3f979db2c3a5..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_output.c +++ /dev/null | |||
@@ -1,1014 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
26 | */ | ||
27 | |||
28 | #include "mdfld_dsi_output.h" | ||
29 | #include "mdfld_dsi_dbi.h" | ||
30 | #include "mdfld_dsi_dpi.h" | ||
31 | #include "mdfld_output.h" | ||
32 | #include <asm/intel_scu_ipc.h> | ||
33 | #include "mdfld_dsi_pkg_sender.h" | ||
34 | #include <linux/pm_runtime.h> | ||
35 | #include <linux/moduleparam.h> | ||
36 | |||
37 | #define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100 | ||
38 | |||
39 | static int CABC_control = 1; | ||
40 | static int LABC_control = 1; | ||
41 | |||
42 | module_param (CABC_control, int, 0644); | ||
43 | module_param (LABC_control, int, 0644); | ||
44 | |||
45 | /** | ||
46 | * make these MCS command global | ||
47 | * we don't need 'movl' everytime we send them. | ||
48 | * FIXME: these datas were provided by OEM, we should get them from GCT. | ||
49 | **/ | ||
50 | static u32 mdfld_dbi_mcs_hysteresis[] = { | ||
51 | 0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff, | ||
52 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
53 | 0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff, | ||
54 | 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, | ||
55 | 0x000000ff, | ||
56 | }; | ||
57 | |||
58 | static u32 mdfld_dbi_mcs_display_profile[] = { | ||
59 | 0x50281450, 0x0000c882, 0x00000000, 0x00000000, | ||
60 | 0x00000000, | ||
61 | }; | ||
62 | |||
63 | static u32 mdfld_dbi_mcs_kbbc_profile[] = { | ||
64 | 0x00ffcc60, 0x00000000, 0x00000000, 0x00000000, | ||
65 | }; | ||
66 | |||
67 | static u32 mdfld_dbi_mcs_gamma_profile[] = { | ||
68 | 0x81111158, 0x88888888, 0x88888888, | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * write hysteresis values. | ||
73 | */ | ||
74 | static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config *dsi_config, | ||
75 | int pipe) | ||
76 | { | ||
77 | struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); | ||
78 | |||
79 | if(!sender) { | ||
80 | WARN_ON(1); | ||
81 | return; | ||
82 | } | ||
83 | mdfld_dsi_send_mcs_long_hs(sender, | ||
84 | mdfld_dbi_mcs_hysteresis, | ||
85 | 17, | ||
86 | MDFLD_DSI_SEND_PACKAGE); | ||
87 | } | ||
88 | |||
89 | /* | ||
90 | * write display profile values. | ||
91 | */ | ||
92 | static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config *dsi_config, int pipe) | ||
93 | { | ||
94 | struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); | ||
95 | |||
96 | if(!sender) { | ||
97 | WARN_ON(1); | ||
98 | return; | ||
99 | } | ||
100 | mdfld_dsi_send_mcs_long_hs(sender, | ||
101 | mdfld_dbi_mcs_display_profile, | ||
102 | 5, | ||
103 | MDFLD_DSI_SEND_PACKAGE); | ||
104 | } | ||
105 | |||
106 | /* | ||
107 | * write KBBC profile values. | ||
108 | */ | ||
109 | static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe) | ||
110 | { | ||
111 | struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); | ||
112 | |||
113 | if(!sender) { | ||
114 | WARN_ON(1); | ||
115 | return; | ||
116 | } | ||
117 | mdfld_dsi_send_mcs_long_hs(sender, | ||
118 | mdfld_dbi_mcs_kbbc_profile, | ||
119 | 4, | ||
120 | MDFLD_DSI_SEND_PACKAGE); | ||
121 | } | ||
122 | |||
123 | /* | ||
124 | * write gamma setting. | ||
125 | */ | ||
126 | static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config *dsi_config, int pipe) | ||
127 | { | ||
128 | struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); | ||
129 | |||
130 | if(!sender) { | ||
131 | WARN_ON(1); | ||
132 | return; | ||
133 | } | ||
134 | mdfld_dsi_send_mcs_long_hs(sender, | ||
135 | mdfld_dbi_mcs_gamma_profile, | ||
136 | 3, | ||
137 | MDFLD_DSI_SEND_PACKAGE); | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * Check and see if the generic control or data buffer is empty and ready. | ||
142 | */ | ||
143 | void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat) | ||
144 | { | ||
145 | u32 GEN_BF_time_out_count = 0; | ||
146 | |||
147 | /* Check MIPI Adatper command registers */ | ||
148 | for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++) | ||
149 | { | ||
150 | if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat) | ||
151 | break; | ||
152 | udelay (100); | ||
153 | } | ||
154 | |||
155 | if (GEN_BF_time_out_count == GEN_FB_TIME_OUT) | ||
156 | dev_err(dev->dev, | ||
157 | "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n", | ||
158 | gen_fifo_stat_reg); | ||
159 | } | ||
160 | |||
161 | /* | ||
162 | * Manage the DSI MIPI keyboard and display brightness. | ||
163 | * FIXME: this is exported to OSPM code. should work out an specific | ||
164 | * display interface to OSPM. | ||
165 | */ | ||
166 | void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe) | ||
167 | { | ||
168 | struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config); | ||
169 | struct drm_device *dev = sender->dev; | ||
170 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
171 | u32 gen_ctrl_val; | ||
172 | |||
173 | if(!sender) { | ||
174 | WARN_ON(1); | ||
175 | return; | ||
176 | } | ||
177 | /* Set default display backlight value to 85% (0xd8)*/ | ||
178 | mdfld_dsi_send_mcs_short_hs(sender, | ||
179 | write_display_brightness, | ||
180 | 0xd8, | ||
181 | 1, | ||
182 | MDFLD_DSI_SEND_PACKAGE); | ||
183 | |||
184 | /* Set minimum brightness setting of CABC function to 20% (0x33)*/ | ||
185 | mdfld_dsi_send_mcs_short_hs(sender, | ||
186 | write_cabc_min_bright, | ||
187 | 0x33, | ||
188 | 1, | ||
189 | MDFLD_DSI_SEND_PACKAGE); | ||
190 | |||
191 | mdfld_dsi_write_hysteresis(dsi_config, pipe); | ||
192 | mdfld_dsi_write_display_profile (dsi_config, pipe); | ||
193 | mdfld_dsi_write_kbbc_profile (dsi_config, pipe); | ||
194 | mdfld_dsi_write_gamma_setting (dsi_config, pipe); | ||
195 | |||
196 | /* Enable backlight or/and LABC */ | ||
197 | gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON; | ||
198 | if (LABC_control == 1 || CABC_control == 1) | ||
199 | gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO; | ||
200 | |||
201 | if (LABC_control == 1) | ||
202 | gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON; | ||
203 | |||
204 | dev_priv->mipi_ctrl_display = gen_ctrl_val; | ||
205 | |||
206 | mdfld_dsi_send_mcs_short_hs(sender, | ||
207 | write_ctrl_display, | ||
208 | (u8)gen_ctrl_val, | ||
209 | 1, | ||
210 | MDFLD_DSI_SEND_PACKAGE); | ||
211 | |||
212 | if (CABC_control == 0) | ||
213 | return; | ||
214 | mdfld_dsi_send_mcs_short_hs(sender, | ||
215 | write_ctrl_cabc, | ||
216 | UI_IMAGE, | ||
217 | 1, | ||
218 | MDFLD_DSI_SEND_PACKAGE); | ||
219 | } | ||
220 | |||
221 | /* | ||
222 | * Manage the mipi display brightness. | ||
223 | * TODO: refine this interface later | ||
224 | */ | ||
225 | void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level) | ||
226 | { | ||
227 | struct mdfld_dsi_pkg_sender *sender; | ||
228 | struct drm_psb_private *dev_priv; | ||
229 | struct mdfld_dsi_config *dsi_config; | ||
230 | u32 gen_ctrl_val; | ||
231 | int p_type; | ||
232 | |||
233 | if (!dev || (pipe != 0 && pipe != 2)) { | ||
234 | dev_err(dev->dev, "Invalid parameter\n"); | ||
235 | return; | ||
236 | } | ||
237 | |||
238 | p_type = mdfld_get_panel_type(dev, 0); | ||
239 | |||
240 | dev_priv = dev->dev_private; | ||
241 | |||
242 | if(pipe) | ||
243 | dsi_config = dev_priv->dsi_configs[1]; | ||
244 | else | ||
245 | dsi_config = dev_priv->dsi_configs[0]; | ||
246 | |||
247 | sender = mdfld_dsi_get_pkg_sender(dsi_config); | ||
248 | |||
249 | if(!sender) { | ||
250 | WARN_ON(1); | ||
251 | return; | ||
252 | } | ||
253 | |||
254 | gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff; | ||
255 | |||
256 | dev_dbg(dev->dev, | ||
257 | "pipe = %d, gen_ctrl_val = %d. \n", pipe, gen_ctrl_val); | ||
258 | |||
259 | if(p_type == TMD_VID || p_type == TMD_CMD){ | ||
260 | /* Set display backlight value */ | ||
261 | mdfld_dsi_send_mcs_short_hs(sender, | ||
262 | tmd_write_display_brightness, | ||
263 | (u8)gen_ctrl_val, | ||
264 | 1, | ||
265 | MDFLD_DSI_SEND_PACKAGE); | ||
266 | } else { | ||
267 | /* Set display backlight value */ | ||
268 | mdfld_dsi_send_mcs_short_hs(sender, | ||
269 | write_display_brightness, | ||
270 | (u8)gen_ctrl_val, | ||
271 | 1, | ||
272 | MDFLD_DSI_SEND_PACKAGE); | ||
273 | |||
274 | |||
275 | /* Enable backlight control */ | ||
276 | if (level == 0) | ||
277 | gen_ctrl_val = 0; | ||
278 | else | ||
279 | gen_ctrl_val = dev_priv->mipi_ctrl_display; | ||
280 | |||
281 | mdfld_dsi_send_mcs_short_hs(sender, | ||
282 | write_ctrl_display, | ||
283 | (u8)gen_ctrl_val, | ||
284 | 1, | ||
285 | MDFLD_DSI_SEND_PACKAGE); | ||
286 | } | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * shut down DSI controller | ||
291 | */ | ||
292 | void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe) | ||
293 | { | ||
294 | struct drm_device * dev; | ||
295 | u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; | ||
296 | int retry = 100; | ||
297 | |||
298 | if (!dsi_config) { | ||
299 | WARN_ON(1); | ||
300 | return; | ||
301 | } | ||
302 | |||
303 | dev = dsi_config->dev; | ||
304 | |||
305 | if (!gma_power_begin(dev, true)) { | ||
306 | dev_err(dev->dev, "hw begin failed\n"); | ||
307 | return; | ||
308 | } | ||
309 | |||
310 | if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY)) | ||
311 | goto shutdown_out; | ||
312 | |||
313 | /* Send shut down package, clean packet send bit first */ | ||
314 | if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { | ||
315 | REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), | ||
316 | (REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT)); | ||
317 | } | ||
318 | |||
319 | /*send shut down package in HS*/ | ||
320 | REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN); | ||
321 | |||
322 | |||
323 | /* | ||
324 | * make sure shut down is sent. | ||
325 | * FIXME: add max retry counter | ||
326 | */ | ||
327 | while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) { | ||
328 | retry--; | ||
329 | |||
330 | if(!retry) { | ||
331 | dev_err(dev->dev, "timeout\n"); | ||
332 | break; | ||
333 | } | ||
334 | } | ||
335 | |||
336 | /*sleep 1 ms to ensure shutdown finished*/ | ||
337 | msleep(100); | ||
338 | |||
339 | /*un-ready device*/ | ||
340 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), | ||
341 | (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & ~DSI_DEVICE_READY)); | ||
342 | |||
343 | shutdown_out: | ||
344 | gma_power_end(dev); | ||
345 | } | ||
346 | |||
347 | void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe) | ||
348 | { | ||
349 | struct drm_device * dev; | ||
350 | u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; | ||
351 | int retry = 100; | ||
352 | |||
353 | |||
354 | if (!dsi_config) { | ||
355 | WARN_ON(1); | ||
356 | return; | ||
357 | } | ||
358 | |||
359 | dev = dsi_config->dev; | ||
360 | dev_dbg(dev->dev, "starting up DSI controller on pipe %d...\n", pipe); | ||
361 | |||
362 | if (!gma_power_begin(dev, true)) { | ||
363 | dev_err(dev->dev, "hw begin failed\n"); | ||
364 | return; | ||
365 | } | ||
366 | |||
367 | if((REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY)) | ||
368 | goto startup_out; | ||
369 | |||
370 | /*if config DPI, turn on DPI interface*/ | ||
371 | if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { | ||
372 | if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) { | ||
373 | REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT); | ||
374 | } | ||
375 | |||
376 | REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON); | ||
377 | |||
378 | /* | ||
379 | * make sure shut down is sent. | ||
380 | * FIXME: add max retry counter | ||
381 | */ | ||
382 | while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) { | ||
383 | retry--; | ||
384 | if(!retry) { | ||
385 | dev_err(dev->dev, "timeout\n"); | ||
386 | break; | ||
387 | } | ||
388 | } | ||
389 | |||
390 | msleep(100); | ||
391 | } | ||
392 | |||
393 | /*set device ready*/ | ||
394 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), | ||
395 | (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) | DSI_DEVICE_READY)); | ||
396 | |||
397 | startup_out: | ||
398 | gma_power_end(dev); | ||
399 | } | ||
400 | |||
401 | |||
402 | static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config, | ||
403 | u8 dcs, | ||
404 | u32 *data, | ||
405 | u8 transmission) | ||
406 | { | ||
407 | struct mdfld_dsi_pkg_sender *sender | ||
408 | = mdfld_dsi_get_pkg_sender(dsi_config); | ||
409 | |||
410 | if (!sender || !data) { | ||
411 | DRM_ERROR("Invalid parameter\n"); | ||
412 | return -EINVAL; | ||
413 | } | ||
414 | |||
415 | if (transmission == MDFLD_DSI_HS_TRANSMISSION) | ||
416 | return mdfld_dsi_read_mcs_hs(sender, dcs, data, 1); | ||
417 | else if (transmission == MDFLD_DSI_LP_TRANSMISSION) | ||
418 | return mdfld_dsi_read_mcs_lp(sender, dcs, data, 1); | ||
419 | else | ||
420 | return -EINVAL; | ||
421 | } | ||
422 | |||
423 | int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, | ||
424 | u32 *mode, | ||
425 | u8 transmission) | ||
426 | { | ||
427 | if (!dsi_config || !mode) { | ||
428 | DRM_ERROR("Invalid parameter\n"); | ||
429 | return -EINVAL; | ||
430 | } | ||
431 | |||
432 | return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, transmission); | ||
433 | } | ||
434 | |||
435 | int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config, | ||
436 | u32 *result, | ||
437 | u8 transmission) | ||
438 | { | ||
439 | if (!dsi_config || !result) { | ||
440 | DRM_ERROR("Invalid parameter\n"); | ||
441 | return -EINVAL; | ||
442 | } | ||
443 | |||
444 | return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result, | ||
445 | transmission); | ||
446 | } | ||
447 | |||
448 | /* | ||
449 | * NOTE: this function was used by OSPM. | ||
450 | * TODO: will be removed later, should work out display interfaces for OSPM | ||
451 | */ | ||
452 | void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe) | ||
453 | { | ||
454 | if(!dsi_config || ((pipe != 0) && (pipe != 2))) { | ||
455 | WARN_ON(1); | ||
456 | return; | ||
457 | } | ||
458 | |||
459 | if(dsi_config->type) | ||
460 | mdfld_dsi_dpi_controller_init(dsi_config, pipe); | ||
461 | else | ||
462 | mdfld_dsi_controller_dbi_init(dsi_config, pipe); | ||
463 | } | ||
464 | |||
465 | static void mdfld_dsi_connector_save(struct drm_connector * connector) | ||
466 | { | ||
467 | } | ||
468 | |||
469 | static void mdfld_dsi_connector_restore(struct drm_connector * connector) | ||
470 | { | ||
471 | } | ||
472 | |||
473 | static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force) | ||
474 | { | ||
475 | struct psb_intel_output *psb_output | ||
476 | = to_psb_intel_output(connector); | ||
477 | struct mdfld_dsi_connector *dsi_connector | ||
478 | = MDFLD_DSI_CONNECTOR(psb_output); | ||
479 | return dsi_connector->status; | ||
480 | } | ||
481 | |||
482 | static int mdfld_dsi_connector_set_property(struct drm_connector *connector, | ||
483 | struct drm_property *property, | ||
484 | uint64_t value) | ||
485 | { | ||
486 | struct drm_encoder *encoder = connector->encoder; | ||
487 | |||
488 | if (!strcmp(property->name, "scaling mode") && encoder) { | ||
489 | struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc); | ||
490 | bool bTransitionFromToCentered; | ||
491 | uint64_t curValue; | ||
492 | |||
493 | if (!psb_crtc) | ||
494 | goto set_prop_error; | ||
495 | |||
496 | switch (value) { | ||
497 | case DRM_MODE_SCALE_FULLSCREEN: | ||
498 | break; | ||
499 | case DRM_MODE_SCALE_NO_SCALE: | ||
500 | break; | ||
501 | case DRM_MODE_SCALE_ASPECT: | ||
502 | break; | ||
503 | default: | ||
504 | goto set_prop_error; | ||
505 | } | ||
506 | |||
507 | if (drm_connector_property_get_value(connector, property, &curValue)) | ||
508 | goto set_prop_error; | ||
509 | |||
510 | if (curValue == value) | ||
511 | goto set_prop_done; | ||
512 | |||
513 | if (drm_connector_property_set_value(connector, property, value)) | ||
514 | goto set_prop_error; | ||
515 | |||
516 | bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) || | ||
517 | (value == DRM_MODE_SCALE_NO_SCALE); | ||
518 | |||
519 | if (psb_crtc->saved_mode.hdisplay != 0 && | ||
520 | psb_crtc->saved_mode.vdisplay != 0) { | ||
521 | if (bTransitionFromToCentered) { | ||
522 | if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode, | ||
523 | encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb)) | ||
524 | goto set_prop_error; | ||
525 | } else { | ||
526 | struct drm_encoder_helper_funcs *pEncHFuncs = encoder->helper_private; | ||
527 | pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode, | ||
528 | &psb_crtc->saved_adjusted_mode); | ||
529 | } | ||
530 | } | ||
531 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
532 | } else if (!strcmp(property->name, "backlight") && encoder) { | ||
533 | struct drm_psb_private *dev_priv = encoder->dev->dev_private; | ||
534 | struct backlight_device *psb_bd = dev_priv->backlight_device; | ||
535 | dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value); | ||
536 | if (drm_connector_property_set_value(connector, property, value)) | ||
537 | goto set_prop_error; | ||
538 | else { | ||
539 | dev_dbg(encoder->dev->dev, | ||
540 | "set brightness to %d", (int)value); | ||
541 | if (psb_bd) { | ||
542 | psb_bd->props.brightness = value; | ||
543 | backlight_update_status(psb_bd); | ||
544 | } | ||
545 | } | ||
546 | #endif | ||
547 | } | ||
548 | set_prop_done: | ||
549 | return 0; | ||
550 | set_prop_error: | ||
551 | return -1; | ||
552 | } | ||
553 | |||
554 | static void mdfld_dsi_connector_destroy(struct drm_connector *connector) | ||
555 | { | ||
556 | struct psb_intel_output * psb_output = to_psb_intel_output(connector); | ||
557 | struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); | ||
558 | struct mdfld_dsi_pkg_sender * sender; | ||
559 | |||
560 | if(!dsi_connector) | ||
561 | return; | ||
562 | |||
563 | drm_sysfs_connector_remove(connector); | ||
564 | drm_connector_cleanup(connector); | ||
565 | |||
566 | sender = dsi_connector->pkg_sender; | ||
567 | |||
568 | mdfld_dsi_pkg_sender_destroy(sender); | ||
569 | |||
570 | kfree(dsi_connector); | ||
571 | } | ||
572 | |||
573 | static int mdfld_dsi_connector_get_modes(struct drm_connector * connector) | ||
574 | { | ||
575 | struct psb_intel_output * psb_output = to_psb_intel_output(connector); | ||
576 | struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); | ||
577 | struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector); | ||
578 | struct drm_display_mode * fixed_mode = dsi_config->fixed_mode; | ||
579 | struct drm_display_mode * dup_mode = NULL; | ||
580 | struct drm_device * dev = connector->dev; | ||
581 | |||
582 | connector->display_info.min_vfreq = 0; | ||
583 | connector->display_info.max_vfreq = 200; | ||
584 | connector->display_info.min_hfreq = 0; | ||
585 | connector->display_info.max_hfreq = 200; | ||
586 | |||
587 | if(fixed_mode) { | ||
588 | dev_dbg(dev->dev, "fixed_mode %dx%d\n", | ||
589 | fixed_mode->hdisplay, fixed_mode->vdisplay); | ||
590 | |||
591 | dup_mode = drm_mode_duplicate(dev, fixed_mode); | ||
592 | drm_mode_probed_add(connector, dup_mode); | ||
593 | return 1; | ||
594 | } | ||
595 | dev_err(dev->dev, "Didn't get any modes!\n"); | ||
596 | return 0; | ||
597 | } | ||
598 | |||
599 | static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode) | ||
600 | { | ||
601 | struct psb_intel_output * psb_output = to_psb_intel_output(connector); | ||
602 | struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); | ||
603 | struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector); | ||
604 | struct drm_display_mode * fixed_mode = dsi_config->fixed_mode; | ||
605 | |||
606 | dev_dbg(connector->dev->dev, "mode %p, fixed mode %p\n", | ||
607 | mode, fixed_mode); | ||
608 | |||
609 | if(mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
610 | return MODE_NO_DBLESCAN; | ||
611 | |||
612 | if(mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
613 | return MODE_NO_INTERLACE; | ||
614 | |||
615 | /** | ||
616 | * FIXME: current DC has no fitting unit, reject any mode setting request | ||
617 | * will figure out a way to do up-scaling(pannel fitting) later. | ||
618 | **/ | ||
619 | if(fixed_mode) { | ||
620 | if(mode->hdisplay != fixed_mode->hdisplay) | ||
621 | return MODE_PANEL; | ||
622 | |||
623 | if(mode->vdisplay != fixed_mode->vdisplay) | ||
624 | return MODE_PANEL; | ||
625 | } | ||
626 | dev_dbg(connector->dev->dev, "mode ok\n"); | ||
627 | |||
628 | return MODE_OK; | ||
629 | } | ||
630 | |||
631 | static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode) | ||
632 | { | ||
633 | #ifdef CONFIG_PM_RUNTIME | ||
634 | struct drm_device * dev = connector->dev; | ||
635 | struct drm_psb_private * dev_priv = dev->dev_private; | ||
636 | bool panel_on, panel_on2; | ||
637 | #endif | ||
638 | /* First, execute DPMS */ | ||
639 | drm_helper_connector_dpms(connector, mode); | ||
640 | |||
641 | #ifdef CONFIG_PM_RUNTIME | ||
642 | if(mdfld_panel_dpi(dev)) { | ||
643 | /* DPI panel */ | ||
644 | panel_on = dev_priv->dpi_panel_on; | ||
645 | panel_on2 = dev_priv->dpi_panel_on2; | ||
646 | } else { | ||
647 | /* DBI panel */ | ||
648 | panel_on = dev_priv->dbi_panel_on; | ||
649 | panel_on2 = dev_priv->dbi_panel_on2; | ||
650 | } | ||
651 | |||
652 | /* Then check all display panels + monitors status */ | ||
653 | /* Make sure that the Display (B) sub-system status isn't i3 when | ||
654 | * R/W the DC register, otherwise "Fabric error" issue would occur | ||
655 | * during S0i3 state. */ | ||
656 | if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL) | ||
657 | & HDMIB_PORT_EN)) { | ||
658 | /* Request rpm idle */ | ||
659 | if(dev_priv->rpm_enabled) | ||
660 | pm_request_idle(&dev->pdev->dev); | ||
661 | } | ||
662 | /* | ||
663 | * if rpm wasn't enabled yet, try to allow it | ||
664 | * FIXME: won't enable rpm for DPI since DPI | ||
665 | * CRTC setting is a little messy now. | ||
666 | * Enable it later! | ||
667 | */ | ||
668 | #if 0 | ||
669 | if(!dev_priv->rpm_enabled && !mdfld_panel_dpi(dev)) | ||
670 | ospm_runtime_pm_allow(dev); | ||
671 | #endif | ||
672 | #endif | ||
673 | } | ||
674 | |||
675 | static struct drm_encoder *mdfld_dsi_connector_best_encoder( | ||
676 | struct drm_connector *connector) | ||
677 | { | ||
678 | struct psb_intel_output * psb_output = to_psb_intel_output(connector); | ||
679 | struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output); | ||
680 | struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector); | ||
681 | struct mdfld_dsi_encoder * encoder = NULL; | ||
682 | |||
683 | if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) | ||
684 | encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI]; | ||
685 | else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) | ||
686 | encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI]; | ||
687 | |||
688 | dev_dbg(connector->dev->dev, "get encoder %p\n", encoder); | ||
689 | |||
690 | if(!encoder) { | ||
691 | dev_err(connector->dev->dev, | ||
692 | "Invalid encoder for type %d\n", dsi_config->type); | ||
693 | return NULL; | ||
694 | } | ||
695 | dsi_config->encoder = encoder; | ||
696 | return &encoder->base; | ||
697 | } | ||
698 | |||
699 | /* DSI connector funcs */ | ||
700 | static const struct drm_connector_funcs mdfld_dsi_connector_funcs = { | ||
701 | .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms, | ||
702 | .save = mdfld_dsi_connector_save, | ||
703 | .restore = mdfld_dsi_connector_restore, | ||
704 | .detect = mdfld_dsi_connector_detect, | ||
705 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
706 | .set_property = mdfld_dsi_connector_set_property, | ||
707 | .destroy = mdfld_dsi_connector_destroy, | ||
708 | }; | ||
709 | |||
710 | /* DSI connector helper funcs */ | ||
711 | static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = { | ||
712 | .get_modes = mdfld_dsi_connector_get_modes, | ||
713 | .mode_valid = mdfld_dsi_connector_mode_valid, | ||
714 | .best_encoder = mdfld_dsi_connector_best_encoder, | ||
715 | }; | ||
716 | |||
717 | static int mdfld_dsi_get_default_config(struct drm_device * dev, | ||
718 | struct mdfld_dsi_config * config, int pipe) | ||
719 | { | ||
720 | if(!dev || !config) { | ||
721 | WARN_ON(1); | ||
722 | return -EINVAL; | ||
723 | } | ||
724 | |||
725 | config->bpp = 24; | ||
726 | config->type = mdfld_panel_dpi(dev); | ||
727 | config->lane_count = 2; | ||
728 | config->channel_num = 0; | ||
729 | /*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/ | ||
730 | if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { | ||
731 | config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE; | ||
732 | } else { | ||
733 | config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE; | ||
734 | } | ||
735 | |||
736 | return 0; | ||
737 | } | ||
738 | |||
739 | /* | ||
740 | * Returns the panel fixed mode from configuration. | ||
741 | */ | ||
742 | struct drm_display_mode * | ||
743 | mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe) | ||
744 | { | ||
745 | struct drm_device *dev = dsi_config->dev; | ||
746 | struct drm_display_mode *mode; | ||
747 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
748 | struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; | ||
749 | bool use_gct = false; | ||
750 | |||
751 | mode = kzalloc(sizeof(*mode), GFP_KERNEL); | ||
752 | if (!mode) { | ||
753 | dev_err(dev->dev, "Out of memory for mode\n"); | ||
754 | return NULL; | ||
755 | } | ||
756 | if (use_gct) { | ||
757 | dev_dbg(dev->dev, "gct find MIPI panel.\n"); | ||
758 | |||
759 | mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; | ||
760 | mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; | ||
761 | mode->hsync_start = mode->hdisplay + \ | ||
762 | ((ti->hsync_offset_hi << 8) | \ | ||
763 | ti->hsync_offset_lo); | ||
764 | mode->hsync_end = mode->hsync_start + \ | ||
765 | ((ti->hsync_pulse_width_hi << 8) | \ | ||
766 | ti->hsync_pulse_width_lo); | ||
767 | mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ | ||
768 | ti->hblank_lo); | ||
769 | mode->vsync_start = \ | ||
770 | mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ | ||
771 | ti->vsync_offset_lo); | ||
772 | mode->vsync_end = \ | ||
773 | mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ | ||
774 | ti->vsync_pulse_width_lo); | ||
775 | mode->vtotal = mode->vdisplay + \ | ||
776 | ((ti->vblank_hi << 8) | ti->vblank_lo); | ||
777 | mode->clock = ti->pixel_clock * 10; | ||
778 | } else { | ||
779 | if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { | ||
780 | if (mdfld_get_panel_type(dev, pipe) == TMD_VID) { | ||
781 | mode->hdisplay = 480; | ||
782 | mode->vdisplay = 854; | ||
783 | mode->hsync_start = 487; | ||
784 | mode->hsync_end = 490; | ||
785 | mode->htotal = 499; | ||
786 | mode->vsync_start = 861; | ||
787 | mode->vsync_end = 865; | ||
788 | mode->vtotal = 873; | ||
789 | mode->clock = 33264; | ||
790 | } else { | ||
791 | mode->hdisplay = 864; | ||
792 | mode->vdisplay = 480; | ||
793 | mode->hsync_start = 873; | ||
794 | mode->hsync_end = 876; | ||
795 | mode->htotal = 887; | ||
796 | mode->vsync_start = 487; | ||
797 | mode->vsync_end = 490; | ||
798 | mode->vtotal = 499; | ||
799 | mode->clock = 33264; | ||
800 | } | ||
801 | } else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) { | ||
802 | mode->hdisplay = 864; | ||
803 | mode->vdisplay = 480; | ||
804 | mode->hsync_start = 872; | ||
805 | mode->hsync_end = 876; | ||
806 | mode->htotal = 884; | ||
807 | mode->vsync_start = 482; | ||
808 | mode->vsync_end = 494; | ||
809 | mode->vtotal = 486; | ||
810 | mode->clock = 25777; | ||
811 | |||
812 | } | ||
813 | } | ||
814 | |||
815 | drm_mode_set_name(mode); | ||
816 | drm_mode_set_crtcinfo(mode, 0); | ||
817 | |||
818 | mode->type |= DRM_MODE_TYPE_PREFERRED; | ||
819 | |||
820 | return mode; | ||
821 | } | ||
822 | |||
823 | int mdfld_dsi_panel_reset(int pipe) | ||
824 | { | ||
825 | unsigned gpio; | ||
826 | int ret = 0; | ||
827 | |||
828 | switch (pipe) { | ||
829 | case 0: | ||
830 | gpio = 128; | ||
831 | break; | ||
832 | case 2: | ||
833 | gpio = 34; | ||
834 | break; | ||
835 | default: | ||
836 | DRM_ERROR("Invalid output\n"); | ||
837 | return -EINVAL; | ||
838 | } | ||
839 | |||
840 | ret = gpio_request(gpio, "gfx"); | ||
841 | if (ret) { | ||
842 | DRM_ERROR("gpio_rqueset failed\n"); | ||
843 | return ret; | ||
844 | } | ||
845 | |||
846 | ret = gpio_direction_output(gpio, 1); | ||
847 | if (ret) { | ||
848 | DRM_ERROR("gpio_direction_output failed\n"); | ||
849 | goto gpio_error; | ||
850 | } | ||
851 | |||
852 | gpio_get_value(128); | ||
853 | |||
854 | gpio_error: | ||
855 | if (gpio_is_valid(gpio)) | ||
856 | gpio_free(gpio); | ||
857 | |||
858 | return ret; | ||
859 | } | ||
860 | |||
861 | /* | ||
862 | * MIPI output init | ||
863 | * @dev drm device | ||
864 | * @pipe pipe number. 0 or 2 | ||
865 | * @config | ||
866 | * | ||
867 | * Do the initialization of a MIPI output, including create DRM mode objects | ||
868 | * initialization of DSI output on @pipe | ||
869 | */ | ||
870 | void mdfld_dsi_output_init(struct drm_device *dev, | ||
871 | int pipe, | ||
872 | struct mdfld_dsi_config *config, | ||
873 | struct panel_funcs* p_cmd_funcs, | ||
874 | struct panel_funcs* p_vid_funcs) | ||
875 | { | ||
876 | struct mdfld_dsi_config * dsi_config; | ||
877 | struct mdfld_dsi_connector * dsi_connector; | ||
878 | struct psb_intel_output * psb_output; | ||
879 | struct drm_connector * connector; | ||
880 | struct mdfld_dsi_encoder * encoder; | ||
881 | struct drm_psb_private * dev_priv = dev->dev_private; | ||
882 | struct panel_info dsi_panel_info; | ||
883 | u32 width_mm, height_mm; | ||
884 | |||
885 | dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe); | ||
886 | |||
887 | if(!dev || ((pipe != 0) && (pipe != 2))) { | ||
888 | WARN_ON(1); | ||
889 | return; | ||
890 | } | ||
891 | |||
892 | /*create a new connetor*/ | ||
893 | dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL); | ||
894 | if(!dsi_connector) { | ||
895 | DRM_ERROR("No memory"); | ||
896 | return; | ||
897 | } | ||
898 | |||
899 | dsi_connector->pipe = pipe; | ||
900 | |||
901 | /*set DSI config*/ | ||
902 | if(config) { | ||
903 | dsi_config = config; | ||
904 | } else { | ||
905 | dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL); | ||
906 | if(!dsi_config) { | ||
907 | dev_err(dev->dev, | ||
908 | "cannot allocate memory for DSI config\n"); | ||
909 | goto dsi_init_err0; | ||
910 | } | ||
911 | |||
912 | mdfld_dsi_get_default_config(dev, dsi_config, pipe); | ||
913 | } | ||
914 | |||
915 | dsi_connector->private = dsi_config; | ||
916 | |||
917 | dsi_config->changed = 1; | ||
918 | dsi_config->dev = dev; | ||
919 | |||
920 | /* Init fixed mode basing on DSI config type */ | ||
921 | if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) { | ||
922 | dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev); | ||
923 | if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info)) | ||
924 | goto dsi_init_err0; | ||
925 | } else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { | ||
926 | dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev); | ||
927 | if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info)) | ||
928 | goto dsi_init_err0; | ||
929 | } | ||
930 | |||
931 | width_mm = dsi_panel_info.width_mm; | ||
932 | height_mm = dsi_panel_info.height_mm; | ||
933 | |||
934 | dsi_config->mode = dsi_config->fixed_mode; | ||
935 | dsi_config->connector = dsi_connector; | ||
936 | |||
937 | if(!dsi_config->fixed_mode) { | ||
938 | dev_err(dev->dev, "No pannel fixed mode was found\n"); | ||
939 | goto dsi_init_err0; | ||
940 | } | ||
941 | |||
942 | if(pipe && dev_priv->dsi_configs[0]) { | ||
943 | dsi_config->dvr_ic_inited = 0; | ||
944 | dev_priv->dsi_configs[1] = dsi_config; | ||
945 | } else if(pipe == 0) { | ||
946 | dsi_config->dvr_ic_inited = 1; | ||
947 | dev_priv->dsi_configs[0] = dsi_config; | ||
948 | } else { | ||
949 | dev_err(dev->dev, "Trying to init MIPI1 before MIPI0\n"); | ||
950 | goto dsi_init_err0; | ||
951 | } | ||
952 | |||
953 | /*init drm connector object*/ | ||
954 | psb_output = &dsi_connector->base; | ||
955 | |||
956 | psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2; | ||
957 | |||
958 | connector = &psb_output->base; | ||
959 | /* Revisit type if MIPI/HDMI bridges ever appear on Medfield */ | ||
960 | drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs, | ||
961 | DRM_MODE_CONNECTOR_LVDS); | ||
962 | drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs); | ||
963 | |||
964 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | ||
965 | connector->display_info.width_mm = width_mm; | ||
966 | connector->display_info.height_mm = height_mm; | ||
967 | connector->interlace_allowed = false; | ||
968 | connector->doublescan_allowed = false; | ||
969 | |||
970 | /* Attach properties */ | ||
971 | drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN); | ||
972 | drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL); | ||
973 | |||
974 | /* Init DSI package sender on this output */ | ||
975 | if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) { | ||
976 | DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe); | ||
977 | goto dsi_init_err0; | ||
978 | } | ||
979 | |||
980 | /* Init DBI & DPI encoders */ | ||
981 | if (p_cmd_funcs) { | ||
982 | encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs); | ||
983 | if(!encoder) { | ||
984 | dev_err(dev->dev, "Create DBI encoder failed\n"); | ||
985 | goto dsi_init_err1; | ||
986 | } | ||
987 | encoder->private = dsi_config; | ||
988 | dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder; | ||
989 | } | ||
990 | |||
991 | if(p_vid_funcs) { | ||
992 | encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs); | ||
993 | if(!encoder) { | ||
994 | dev_err(dev->dev, "Create DPI encoder failed\n"); | ||
995 | goto dsi_init_err1; | ||
996 | } | ||
997 | encoder->private = dsi_config; | ||
998 | dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder; | ||
999 | } | ||
1000 | |||
1001 | drm_sysfs_connector_add(connector); | ||
1002 | return; | ||
1003 | |||
1004 | /*TODO: add code to destroy outputs on error*/ | ||
1005 | dsi_init_err1: | ||
1006 | /*destroy sender*/ | ||
1007 | mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender); | ||
1008 | |||
1009 | drm_connector_cleanup(connector); | ||
1010 | kfree(dsi_config->fixed_mode); | ||
1011 | kfree(dsi_config); | ||
1012 | dsi_init_err0: | ||
1013 | kfree(dsi_connector); | ||
1014 | } | ||
diff --git a/drivers/staging/gma500/mdfld_dsi_output.h b/drivers/staging/gma500/mdfld_dsi_output.h deleted file mode 100644 index 4699267efd60..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_output.h +++ /dev/null | |||
@@ -1,138 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef __MDFLD_DSI_OUTPUT_H__ | ||
29 | #define __MDFLD_DSI_OUTPUT_H__ | ||
30 | |||
31 | #include <linux/backlight.h> | ||
32 | #include <drm/drmP.h> | ||
33 | #include <drm/drm.h> | ||
34 | #include <drm/drm_crtc.h> | ||
35 | #include <drm/drm_edid.h> | ||
36 | |||
37 | #include "psb_drv.h" | ||
38 | #include "psb_intel_drv.h" | ||
39 | #include "psb_intel_reg.h" | ||
40 | #include "power.h" | ||
41 | #include "mdfld_output.h" | ||
42 | |||
43 | #include <asm/mrst.h> | ||
44 | |||
45 | |||
46 | static inline struct mdfld_dsi_config * | ||
47 | mdfld_dsi_get_config(struct mdfld_dsi_connector *connector) | ||
48 | { | ||
49 | if (!connector) | ||
50 | return NULL; | ||
51 | return (struct mdfld_dsi_config *)connector->private; | ||
52 | } | ||
53 | |||
54 | static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config) | ||
55 | { | ||
56 | struct mdfld_dsi_connector *dsi_connector; | ||
57 | |||
58 | if (!config) | ||
59 | return NULL; | ||
60 | |||
61 | dsi_connector = config->connector; | ||
62 | |||
63 | if (!dsi_connector) | ||
64 | return NULL; | ||
65 | |||
66 | return dsi_connector->pkg_sender; | ||
67 | } | ||
68 | |||
69 | static inline struct mdfld_dsi_config * | ||
70 | mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder) | ||
71 | { | ||
72 | if (!encoder) | ||
73 | return NULL; | ||
74 | return (struct mdfld_dsi_config *)encoder->private; | ||
75 | } | ||
76 | |||
77 | static inline struct mdfld_dsi_connector * | ||
78 | mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder) | ||
79 | { | ||
80 | struct mdfld_dsi_config *config; | ||
81 | |||
82 | if (!encoder) | ||
83 | return NULL; | ||
84 | |||
85 | config = mdfld_dsi_encoder_get_config(encoder); | ||
86 | if (!config) | ||
87 | return NULL; | ||
88 | |||
89 | return config->connector; | ||
90 | } | ||
91 | |||
92 | static inline void *mdfld_dsi_encoder_get_pkg_sender( | ||
93 | struct mdfld_dsi_encoder *encoder) | ||
94 | { | ||
95 | struct mdfld_dsi_config *dsi_config; | ||
96 | |||
97 | dsi_config = mdfld_dsi_encoder_get_config(encoder); | ||
98 | if (!dsi_config) | ||
99 | return NULL; | ||
100 | |||
101 | return mdfld_dsi_get_pkg_sender(dsi_config); | ||
102 | } | ||
103 | |||
104 | static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder) | ||
105 | { | ||
106 | struct mdfld_dsi_connector *connector; | ||
107 | |||
108 | if (!encoder) | ||
109 | return -1; | ||
110 | |||
111 | connector = mdfld_dsi_encoder_get_connector(encoder); | ||
112 | if (!connector) | ||
113 | return -1; | ||
114 | |||
115 | return connector->pipe; | ||
116 | } | ||
117 | |||
118 | extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev, | ||
119 | u32 gen_fifo_stat_reg, u32 fifo_stat); | ||
120 | extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, | ||
121 | int pipe); | ||
122 | extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, | ||
123 | int level); | ||
124 | extern void mdfld_dsi_output_init(struct drm_device *dev, int pipe, | ||
125 | struct mdfld_dsi_config *config, | ||
126 | struct panel_funcs *p_cmd_funcs, | ||
127 | struct panel_funcs *p_vid_funcs); | ||
128 | extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, | ||
129 | int pipe); | ||
130 | extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, | ||
131 | u32 *mode, | ||
132 | u8 transmission); | ||
133 | extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config, | ||
134 | u32 *result, | ||
135 | u8 transmission); | ||
136 | extern int mdfld_dsi_panel_reset(int pipe); | ||
137 | |||
138 | #endif /*__MDFLD_DSI_OUTPUT_H__*/ | ||
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c deleted file mode 100644 index 9b96a5c9abcd..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_pkg_sender.c +++ /dev/null | |||
@@ -1,1484 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
25 | */ | ||
26 | |||
27 | #include <linux/freezer.h> | ||
28 | |||
29 | #include "mdfld_dsi_output.h" | ||
30 | #include "mdfld_dsi_pkg_sender.h" | ||
31 | #include "mdfld_dsi_dbi.h" | ||
32 | #include "mdfld_dsi_dpi.h" | ||
33 | |||
34 | #define MDFLD_DSI_DBI_FIFO_TIMEOUT 100 | ||
35 | #define MDFLD_DSI_MAX_RETURN_PACKET_SIZE 512 | ||
36 | #define MDFLD_DSI_READ_MAX_COUNT 5000 | ||
37 | |||
38 | static const char * const dsi_errors[] = { | ||
39 | "RX SOT Error", | ||
40 | "RX SOT Sync Error", | ||
41 | "RX EOT Sync Error", | ||
42 | "RX Escape Mode Entry Error", | ||
43 | "RX LP TX Sync Error", | ||
44 | "RX HS Receive Timeout Error", | ||
45 | "RX False Control Error", | ||
46 | "RX ECC Single Bit Error", | ||
47 | "RX ECC Multibit Error", | ||
48 | "RX Checksum Error", | ||
49 | "RX DSI Data Type Not Recognised", | ||
50 | "RX DSI VC ID Invalid", | ||
51 | "TX False Control Error", | ||
52 | "TX ECC Single Bit Error", | ||
53 | "TX ECC Multibit Error", | ||
54 | "TX Checksum Error", | ||
55 | "TX DSI Data Type Not Recognised", | ||
56 | "TX DSI VC ID invalid", | ||
57 | "High Contention", | ||
58 | "Low contention", | ||
59 | "DPI FIFO Under run", | ||
60 | "HS TX Timeout", | ||
61 | "LP RX Timeout", | ||
62 | "Turn Around ACK Timeout", | ||
63 | "ACK With No Error", | ||
64 | "RX Invalid TX Length", | ||
65 | "RX Prot Violation", | ||
66 | "HS Generic Write FIFO Full", | ||
67 | "LP Generic Write FIFO Full", | ||
68 | "Generic Read Data Avail", | ||
69 | "Special Packet Sent", | ||
70 | "Tearing Effect", | ||
71 | }; | ||
72 | |||
73 | static int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender, | ||
74 | u32 mask) | ||
75 | { | ||
76 | struct drm_device *dev = sender->dev; | ||
77 | u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg; | ||
78 | int retry = 0xffff; | ||
79 | |||
80 | while (retry--) { | ||
81 | if ((mask & REG_READ(gen_fifo_stat_reg)) == mask) | ||
82 | return 0; | ||
83 | udelay(100); | ||
84 | } | ||
85 | dev_err(dev->dev, "fifo is NOT empty 0x%08x\n", | ||
86 | REG_READ(gen_fifo_stat_reg)); | ||
87 | return -EIO; | ||
88 | } | ||
89 | |||
90 | static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender) | ||
91 | { | ||
92 | return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 10) | (1 << 18) | ||
93 | | (1 << 26) | (1 << 27) | (1 << 28)); | ||
94 | } | ||
95 | |||
96 | static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender) | ||
97 | { | ||
98 | return wait_for_gen_fifo_empty(sender, (1 << 10) | (1 << 26)); | ||
99 | } | ||
100 | |||
101 | static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender) | ||
102 | { | ||
103 | return wait_for_gen_fifo_empty(sender, (1 << 2) | (1 << 18)); | ||
104 | } | ||
105 | |||
106 | static int wait_for_dbi_fifo_empty(struct mdfld_dsi_pkg_sender *sender) | ||
107 | { | ||
108 | return wait_for_gen_fifo_empty(sender, (1 << 27)); | ||
109 | } | ||
110 | |||
111 | static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask) | ||
112 | { | ||
113 | u32 intr_stat_reg = sender->mipi_intr_stat_reg; | ||
114 | struct drm_device *dev = sender->dev; | ||
115 | |||
116 | switch (mask) { | ||
117 | case (1 << 0): | ||
118 | case (1 << 1): | ||
119 | case (1 << 2): | ||
120 | case (1 << 3): | ||
121 | case (1 << 4): | ||
122 | case (1 << 5): | ||
123 | case (1 << 6): | ||
124 | case (1 << 7): | ||
125 | case (1 << 8): | ||
126 | case (1 << 9): | ||
127 | case (1 << 10): | ||
128 | case (1 << 11): | ||
129 | case (1 << 12): | ||
130 | case (1 << 13): | ||
131 | break; | ||
132 | case (1 << 14): | ||
133 | /*wait for all fifo empty*/ | ||
134 | /*wait_for_all_fifos_empty(sender)*/; | ||
135 | break; | ||
136 | case (1 << 15): | ||
137 | break; | ||
138 | case (1 << 16): | ||
139 | break; | ||
140 | case (1 << 17): | ||
141 | break; | ||
142 | case (1 << 18): | ||
143 | case (1 << 19): | ||
144 | /*wait for contention recovery time*/ | ||
145 | /*mdelay(10);*/ | ||
146 | /*wait for all fifo empty*/ | ||
147 | if (0) | ||
148 | wait_for_all_fifos_empty(sender); | ||
149 | break; | ||
150 | case (1 << 20): | ||
151 | break; | ||
152 | case (1 << 21): | ||
153 | /*wait for all fifo empty*/ | ||
154 | /*wait_for_all_fifos_empty(sender);*/ | ||
155 | break; | ||
156 | case (1 << 22): | ||
157 | break; | ||
158 | case (1 << 23): | ||
159 | case (1 << 24): | ||
160 | case (1 << 25): | ||
161 | case (1 << 26): | ||
162 | case (1 << 27): | ||
163 | /* HS Gen fifo full */ | ||
164 | REG_WRITE(intr_stat_reg, mask); | ||
165 | wait_for_hs_fifos_empty(sender); | ||
166 | break; | ||
167 | case (1 << 28): | ||
168 | /* LP Gen fifo full\n */ | ||
169 | REG_WRITE(intr_stat_reg, mask); | ||
170 | wait_for_lp_fifos_empty(sender); | ||
171 | break; | ||
172 | case (1 << 29): | ||
173 | case (1 << 30): | ||
174 | case (1 << 31): | ||
175 | break; | ||
176 | } | ||
177 | |||
178 | if (mask & REG_READ(intr_stat_reg)) | ||
179 | dev_warn(dev->dev, "Cannot clean interrupt 0x%08x\n", mask); | ||
180 | |||
181 | return 0; | ||
182 | } | ||
183 | |||
184 | static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender) | ||
185 | { | ||
186 | struct drm_device *dev = sender->dev; | ||
187 | u32 intr_stat_reg = sender->mipi_intr_stat_reg; | ||
188 | u32 mask; | ||
189 | u32 intr_stat; | ||
190 | int i; | ||
191 | int err = 0; | ||
192 | |||
193 | intr_stat = REG_READ(intr_stat_reg); | ||
194 | |||
195 | for (i = 0; i < 32; i++) { | ||
196 | mask = (0x00000001UL) << i; | ||
197 | if (intr_stat & mask) { | ||
198 | dev_dbg(dev->dev, "[DSI]: %s\n", dsi_errors[i]); | ||
199 | err = handle_dsi_error(sender, mask); | ||
200 | if (err) | ||
201 | dev_err(dev->dev, "Cannot handle error\n"); | ||
202 | } | ||
203 | } | ||
204 | return err; | ||
205 | } | ||
206 | |||
207 | static inline int dbi_cmd_sent(struct mdfld_dsi_pkg_sender *sender) | ||
208 | { | ||
209 | struct drm_device *dev = sender->dev; | ||
210 | u32 retry = 0xffff; | ||
211 | u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg; | ||
212 | |||
213 | /* Query the command execution status */ | ||
214 | while (retry--) { | ||
215 | if (!(REG_READ(dbi_cmd_addr_reg) & (1 << 0))) | ||
216 | break; | ||
217 | } | ||
218 | |||
219 | if (!retry) { | ||
220 | dev_err(dev->dev, "Timeout waiting for DBI Command status\n"); | ||
221 | return -EAGAIN; | ||
222 | } | ||
223 | return 0; | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * NOTE: this interface is abandoned expect for write_mem_start DCS | ||
228 | * other DCS are sent via generic pkg interfaces | ||
229 | */ | ||
230 | static int send_dcs_pkg(struct mdfld_dsi_pkg_sender *sender, | ||
231 | struct mdfld_dsi_pkg *pkg) | ||
232 | { | ||
233 | struct drm_device *dev = sender->dev; | ||
234 | struct mdfld_dsi_dcs_pkg *dcs_pkg = &pkg->pkg.dcs_pkg; | ||
235 | u32 dbi_cmd_len_reg = sender->mipi_cmd_len_reg; | ||
236 | u32 dbi_cmd_addr_reg = sender->mipi_cmd_addr_reg; | ||
237 | u32 cb_phy = sender->dbi_cb_phy; | ||
238 | u32 index = 0; | ||
239 | u8 *cb = (u8 *)sender->dbi_cb_addr; | ||
240 | int i; | ||
241 | int ret; | ||
242 | |||
243 | if (!sender->dbi_pkg_support) { | ||
244 | dev_err(dev->dev, "Trying to send DCS on a non DBI output, abort!\n"); | ||
245 | return -ENOTSUPP; | ||
246 | } | ||
247 | |||
248 | /*wait for DBI fifo empty*/ | ||
249 | wait_for_dbi_fifo_empty(sender); | ||
250 | |||
251 | *(cb + (index++)) = dcs_pkg->cmd; | ||
252 | if (dcs_pkg->param_num) { | ||
253 | for (i = 0; i < dcs_pkg->param_num; i++) | ||
254 | *(cb + (index++)) = *(dcs_pkg->param + i); | ||
255 | } | ||
256 | |||
257 | REG_WRITE(dbi_cmd_len_reg, (1 + dcs_pkg->param_num)); | ||
258 | REG_WRITE(dbi_cmd_addr_reg, | ||
259 | (cb_phy << CMD_MEM_ADDR_OFFSET) | ||
260 | | (1 << 0) | ||
261 | | ((dcs_pkg->data_src == CMD_DATA_SRC_PIPE) ? (1 << 1) : 0)); | ||
262 | |||
263 | ret = dbi_cmd_sent(sender); | ||
264 | if (ret) { | ||
265 | dev_err(dev->dev, "command 0x%x not complete\n", dcs_pkg->cmd); | ||
266 | return -EAGAIN; | ||
267 | } | ||
268 | return 0; | ||
269 | } | ||
270 | |||
271 | static int __send_short_pkg(struct mdfld_dsi_pkg_sender *sender, | ||
272 | struct mdfld_dsi_pkg *pkg) | ||
273 | { | ||
274 | struct drm_device *dev = sender->dev; | ||
275 | u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg; | ||
276 | u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg; | ||
277 | u32 gen_ctrl_val = 0; | ||
278 | struct mdfld_dsi_gen_short_pkg *short_pkg = &pkg->pkg.short_pkg; | ||
279 | |||
280 | gen_ctrl_val |= short_pkg->cmd << MCS_COMMANDS_POS; | ||
281 | gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS; | ||
282 | gen_ctrl_val |= pkg->pkg_type; | ||
283 | gen_ctrl_val |= short_pkg->param << MCS_PARAMETER_POS; | ||
284 | |||
285 | if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) { | ||
286 | /* wait for hs fifo empty */ | ||
287 | /* wait_for_hs_fifos_empty(sender); */ | ||
288 | /* Send pkg */ | ||
289 | REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val); | ||
290 | } else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) { | ||
291 | /* wait_for_lp_fifos_empty(sender); */ | ||
292 | /* Send pkg*/ | ||
293 | REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val); | ||
294 | } else { | ||
295 | dev_err(dev->dev, "Unknown transmission type %d\n", | ||
296 | pkg->transmission_type); | ||
297 | return -EINVAL; | ||
298 | } | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int __send_long_pkg(struct mdfld_dsi_pkg_sender *sender, | ||
304 | struct mdfld_dsi_pkg *pkg) | ||
305 | { | ||
306 | struct drm_device *dev = sender->dev; | ||
307 | u32 hs_gen_ctrl_reg = sender->mipi_hs_gen_ctrl_reg; | ||
308 | u32 hs_gen_data_reg = sender->mipi_hs_gen_data_reg; | ||
309 | u32 lp_gen_ctrl_reg = sender->mipi_lp_gen_ctrl_reg; | ||
310 | u32 lp_gen_data_reg = sender->mipi_lp_gen_data_reg; | ||
311 | u32 gen_ctrl_val = 0; | ||
312 | u32 *dp; | ||
313 | int i; | ||
314 | struct mdfld_dsi_gen_long_pkg *long_pkg = &pkg->pkg.long_pkg; | ||
315 | |||
316 | dp = long_pkg->data; | ||
317 | |||
318 | /* | ||
319 | * Set up word count for long pkg | ||
320 | * FIXME: double check word count field. | ||
321 | * currently, using the byte counts of the payload as the word count. | ||
322 | * ------------------------------------------------------------ | ||
323 | * | DI | WC | ECC| PAYLOAD |CHECKSUM| | ||
324 | * ------------------------------------------------------------ | ||
325 | */ | ||
326 | gen_ctrl_val |= (long_pkg->len << 2) << WORD_COUNTS_POS; | ||
327 | gen_ctrl_val |= 0 << DCS_CHANNEL_NUMBER_POS; | ||
328 | gen_ctrl_val |= pkg->pkg_type; | ||
329 | |||
330 | if (pkg->transmission_type == MDFLD_DSI_HS_TRANSMISSION) { | ||
331 | /* Wait for hs ctrl and data fifos to be empty */ | ||
332 | /* wait_for_hs_fifos_empty(sender); */ | ||
333 | for (i = 0; i < long_pkg->len; i++) | ||
334 | REG_WRITE(hs_gen_data_reg, *(dp + i)); | ||
335 | REG_WRITE(hs_gen_ctrl_reg, gen_ctrl_val); | ||
336 | } else if (pkg->transmission_type == MDFLD_DSI_LP_TRANSMISSION) { | ||
337 | /* wait_for_lp_fifos_empty(sender); */ | ||
338 | for (i = 0; i < long_pkg->len; i++) | ||
339 | REG_WRITE(lp_gen_data_reg, *(dp + i)); | ||
340 | REG_WRITE(lp_gen_ctrl_reg, gen_ctrl_val); | ||
341 | } else { | ||
342 | dev_err(dev->dev, "Unknown transmission type %d\n", | ||
343 | pkg->transmission_type); | ||
344 | return -EINVAL; | ||
345 | } | ||
346 | |||
347 | return 0; | ||
348 | |||
349 | } | ||
350 | |||
351 | static int send_mcs_short_pkg(struct mdfld_dsi_pkg_sender *sender, | ||
352 | struct mdfld_dsi_pkg *pkg) | ||
353 | { | ||
354 | return __send_short_pkg(sender, pkg); | ||
355 | } | ||
356 | |||
357 | static int send_mcs_long_pkg(struct mdfld_dsi_pkg_sender *sender, | ||
358 | struct mdfld_dsi_pkg *pkg) | ||
359 | { | ||
360 | return __send_long_pkg(sender, pkg); | ||
361 | } | ||
362 | |||
363 | static int send_gen_short_pkg(struct mdfld_dsi_pkg_sender *sender, | ||
364 | struct mdfld_dsi_pkg *pkg) | ||
365 | { | ||
366 | return __send_short_pkg(sender, pkg); | ||
367 | } | ||
368 | |||
369 | static int send_gen_long_pkg(struct mdfld_dsi_pkg_sender *sender, | ||
370 | struct mdfld_dsi_pkg *pkg) | ||
371 | { | ||
372 | return __send_long_pkg(sender, pkg); | ||
373 | } | ||
374 | |||
375 | static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, | ||
376 | struct mdfld_dsi_pkg *pkg) | ||
377 | { | ||
378 | u8 cmd; | ||
379 | u8 *data; | ||
380 | |||
381 | switch (pkg->pkg_type) { | ||
382 | case MDFLD_DSI_PKG_DCS: | ||
383 | cmd = pkg->pkg.dcs_pkg.cmd; | ||
384 | break; | ||
385 | case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0: | ||
386 | case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1: | ||
387 | cmd = pkg->pkg.short_pkg.cmd; | ||
388 | break; | ||
389 | case MDFLD_DSI_PKG_MCS_LONG_WRITE: | ||
390 | data = (u8 *)pkg->pkg.long_pkg.data; | ||
391 | cmd = *data; | ||
392 | break; | ||
393 | default: | ||
394 | return 0; | ||
395 | } | ||
396 | |||
397 | /* This prevents other package sending while doing msleep */ | ||
398 | sender->status = MDFLD_DSI_PKG_SENDER_BUSY; | ||
399 | |||
400 | /* Check panel mode v.s. sending command */ | ||
401 | if ((sender->panel_mode & MDFLD_DSI_PANEL_MODE_SLEEP) && | ||
402 | cmd != exit_sleep_mode) { | ||
403 | dev_err(sender->dev->dev, | ||
404 | "sending 0x%x when panel sleep in\n", cmd); | ||
405 | sender->status = MDFLD_DSI_PKG_SENDER_FREE; | ||
406 | return -EINVAL; | ||
407 | } | ||
408 | |||
409 | /* Wait for 120 milliseconds in case exit_sleep_mode just be sent */ | ||
410 | if (cmd == DCS_ENTER_SLEEP_MODE) { | ||
411 | /*TODO: replace it with msleep later*/ | ||
412 | mdelay(120); | ||
413 | } | ||
414 | return 0; | ||
415 | } | ||
416 | |||
417 | static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, | ||
418 | struct mdfld_dsi_pkg *pkg) | ||
419 | { | ||
420 | u8 cmd; | ||
421 | u8 *data; | ||
422 | |||
423 | switch (pkg->pkg_type) { | ||
424 | case MDFLD_DSI_PKG_DCS: | ||
425 | cmd = pkg->pkg.dcs_pkg.cmd; | ||
426 | break; | ||
427 | case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0: | ||
428 | case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1: | ||
429 | cmd = pkg->pkg.short_pkg.cmd; | ||
430 | break; | ||
431 | case MDFLD_DSI_PKG_MCS_LONG_WRITE: | ||
432 | data = (u8 *)pkg->pkg.long_pkg.data; | ||
433 | cmd = *data; | ||
434 | break; | ||
435 | default: | ||
436 | return 0; | ||
437 | } | ||
438 | |||
439 | /* Update panel status */ | ||
440 | if (cmd == DCS_ENTER_SLEEP_MODE) { | ||
441 | sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP; | ||
442 | /*TODO: replace it with msleep later*/ | ||
443 | mdelay(120); | ||
444 | } else if (cmd == DCS_EXIT_SLEEP_MODE) { | ||
445 | sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP; | ||
446 | /*TODO: replace it with msleep later*/ | ||
447 | mdelay(120); | ||
448 | } else if (unlikely(cmd == DCS_SOFT_RESET)) { | ||
449 | /*TODO: replace it with msleep later*/ | ||
450 | mdelay(5); | ||
451 | } | ||
452 | sender->status = MDFLD_DSI_PKG_SENDER_FREE; | ||
453 | return 0; | ||
454 | |||
455 | } | ||
456 | |||
457 | static int do_send_pkg(struct mdfld_dsi_pkg_sender *sender, | ||
458 | struct mdfld_dsi_pkg *pkg) | ||
459 | { | ||
460 | int ret; | ||
461 | |||
462 | if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) { | ||
463 | dev_err(sender->dev->dev, "sender is busy\n"); | ||
464 | return -EAGAIN; | ||
465 | } | ||
466 | |||
467 | ret = send_pkg_prepare(sender, pkg); | ||
468 | if (ret) { | ||
469 | dev_err(sender->dev->dev, "send_pkg_prepare error\n"); | ||
470 | return ret; | ||
471 | } | ||
472 | |||
473 | switch (pkg->pkg_type) { | ||
474 | case MDFLD_DSI_PKG_DCS: | ||
475 | ret = send_dcs_pkg(sender, pkg); | ||
476 | break; | ||
477 | case MDFLD_DSI_PKG_GEN_SHORT_WRITE_0: | ||
478 | case MDFLD_DSI_PKG_GEN_SHORT_WRITE_1: | ||
479 | case MDFLD_DSI_PKG_GEN_SHORT_WRITE_2: | ||
480 | case MDFLD_DSI_PKG_GEN_READ_0: | ||
481 | case MDFLD_DSI_PKG_GEN_READ_1: | ||
482 | case MDFLD_DSI_PKG_GEN_READ_2: | ||
483 | ret = send_gen_short_pkg(sender, pkg); | ||
484 | break; | ||
485 | case MDFLD_DSI_PKG_GEN_LONG_WRITE: | ||
486 | ret = send_gen_long_pkg(sender, pkg); | ||
487 | break; | ||
488 | case MDFLD_DSI_PKG_MCS_SHORT_WRITE_0: | ||
489 | case MDFLD_DSI_PKG_MCS_SHORT_WRITE_1: | ||
490 | case MDFLD_DSI_PKG_MCS_READ: | ||
491 | ret = send_mcs_short_pkg(sender, pkg); | ||
492 | break; | ||
493 | case MDFLD_DSI_PKG_MCS_LONG_WRITE: | ||
494 | ret = send_mcs_long_pkg(sender, pkg); | ||
495 | break; | ||
496 | default: | ||
497 | dev_err(sender->dev->dev, "Invalid pkg type 0x%x\n", | ||
498 | pkg->pkg_type); | ||
499 | ret = -EINVAL; | ||
500 | } | ||
501 | send_pkg_done(sender, pkg); | ||
502 | return ret; | ||
503 | } | ||
504 | |||
505 | static int send_pkg(struct mdfld_dsi_pkg_sender *sender, | ||
506 | struct mdfld_dsi_pkg *pkg) | ||
507 | { | ||
508 | int err ; | ||
509 | |||
510 | /* Handle DSI error */ | ||
511 | err = dsi_error_handler(sender); | ||
512 | if (err) { | ||
513 | dev_err(sender->dev->dev, "Error handling failed\n"); | ||
514 | err = -EAGAIN; | ||
515 | goto send_pkg_err; | ||
516 | } | ||
517 | |||
518 | /* Send pkg */ | ||
519 | err = do_send_pkg(sender, pkg); | ||
520 | if (err) { | ||
521 | dev_err(sender->dev->dev, "sent pkg failed\n"); | ||
522 | err = -EAGAIN; | ||
523 | goto send_pkg_err; | ||
524 | } | ||
525 | |||
526 | /* FIXME: should I query complete and fifo empty here? */ | ||
527 | send_pkg_err: | ||
528 | return err; | ||
529 | } | ||
530 | |||
531 | static struct mdfld_dsi_pkg *pkg_sender_get_pkg_locked( | ||
532 | struct mdfld_dsi_pkg_sender *sender) | ||
533 | { | ||
534 | struct mdfld_dsi_pkg *pkg; | ||
535 | |||
536 | if (list_empty(&sender->free_list)) { | ||
537 | dev_err(sender->dev->dev, "No free pkg left\n"); | ||
538 | return NULL; | ||
539 | } | ||
540 | pkg = list_first_entry(&sender->free_list, struct mdfld_dsi_pkg, entry); | ||
541 | /* Detach from free list */ | ||
542 | list_del_init(&pkg->entry); | ||
543 | return pkg; | ||
544 | } | ||
545 | |||
546 | static void pkg_sender_put_pkg_locked(struct mdfld_dsi_pkg_sender *sender, | ||
547 | struct mdfld_dsi_pkg *pkg) | ||
548 | { | ||
549 | memset(pkg, 0, sizeof(struct mdfld_dsi_pkg)); | ||
550 | INIT_LIST_HEAD(&pkg->entry); | ||
551 | list_add_tail(&pkg->entry, &sender->free_list); | ||
552 | } | ||
553 | |||
554 | static int mdfld_dbi_cb_init(struct mdfld_dsi_pkg_sender *sender, | ||
555 | struct psb_gtt *pg, int pipe) | ||
556 | { | ||
557 | unsigned long phys; | ||
558 | void *virt_addr = NULL; | ||
559 | |||
560 | switch (pipe) { | ||
561 | case 0: | ||
562 | /* FIXME: Doesn't this collide with stolen space ? */ | ||
563 | phys = pg->gtt_phys_start - 0x1000; | ||
564 | break; | ||
565 | case 2: | ||
566 | phys = pg->gtt_phys_start - 0x800; | ||
567 | break; | ||
568 | default: | ||
569 | dev_err(sender->dev->dev, "Unsupported channel %d\n", pipe); | ||
570 | return -EINVAL; | ||
571 | } | ||
572 | |||
573 | virt_addr = ioremap_nocache(phys, 0x800); | ||
574 | if (!virt_addr) { | ||
575 | dev_err(sender->dev->dev, "Map DBI command buffer error\n"); | ||
576 | return -ENOMEM; | ||
577 | } | ||
578 | sender->dbi_cb_phy = phys; | ||
579 | sender->dbi_cb_addr = virt_addr; | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | static void mdfld_dbi_cb_destroy(struct mdfld_dsi_pkg_sender *sender) | ||
584 | { | ||
585 | if (sender && sender->dbi_cb_addr) | ||
586 | iounmap(sender->dbi_cb_addr); | ||
587 | } | ||
588 | |||
589 | static void pkg_sender_queue_pkg(struct mdfld_dsi_pkg_sender *sender, | ||
590 | struct mdfld_dsi_pkg *pkg, | ||
591 | int delay) | ||
592 | { | ||
593 | unsigned long flags; | ||
594 | |||
595 | spin_lock_irqsave(&sender->lock, flags); | ||
596 | |||
597 | if (!delay) { | ||
598 | send_pkg(sender, pkg); | ||
599 | pkg_sender_put_pkg_locked(sender, pkg); | ||
600 | } else { | ||
601 | /* Queue it */ | ||
602 | list_add_tail(&pkg->entry, &sender->pkg_list); | ||
603 | } | ||
604 | spin_unlock_irqrestore(&sender->lock, flags); | ||
605 | } | ||
606 | |||
607 | static void process_pkg_list(struct mdfld_dsi_pkg_sender *sender) | ||
608 | { | ||
609 | struct mdfld_dsi_pkg *pkg; | ||
610 | unsigned long flags; | ||
611 | |||
612 | spin_lock_irqsave(&sender->lock, flags); | ||
613 | |||
614 | while (!list_empty(&sender->pkg_list)) { | ||
615 | pkg = list_first_entry(&sender->pkg_list, | ||
616 | struct mdfld_dsi_pkg, entry); | ||
617 | send_pkg(sender, pkg); | ||
618 | list_del_init(&pkg->entry); | ||
619 | pkg_sender_put_pkg_locked(sender, pkg); | ||
620 | } | ||
621 | |||
622 | spin_unlock_irqrestore(&sender->lock, flags); | ||
623 | } | ||
624 | |||
625 | static int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, | ||
626 | u32 *data, u32 len, u8 transmission, int delay) | ||
627 | { | ||
628 | struct mdfld_dsi_pkg *pkg; | ||
629 | unsigned long flags; | ||
630 | |||
631 | spin_lock_irqsave(&sender->lock, flags); | ||
632 | pkg = pkg_sender_get_pkg_locked(sender); | ||
633 | spin_unlock_irqrestore(&sender->lock, flags); | ||
634 | |||
635 | if (!pkg) { | ||
636 | dev_err(sender->dev->dev, "No memory\n"); | ||
637 | return -ENOMEM; | ||
638 | } | ||
639 | pkg->pkg_type = MDFLD_DSI_PKG_MCS_LONG_WRITE; | ||
640 | pkg->transmission_type = transmission; | ||
641 | pkg->pkg.long_pkg.data = data; | ||
642 | pkg->pkg.long_pkg.len = len; | ||
643 | INIT_LIST_HEAD(&pkg->entry); | ||
644 | |||
645 | pkg_sender_queue_pkg(sender, pkg, delay); | ||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | static int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, | ||
650 | u8 cmd, u8 param, u8 param_num, | ||
651 | u8 transmission, | ||
652 | int delay) | ||
653 | { | ||
654 | struct mdfld_dsi_pkg *pkg; | ||
655 | unsigned long flags; | ||
656 | |||
657 | spin_lock_irqsave(&sender->lock, flags); | ||
658 | pkg = pkg_sender_get_pkg_locked(sender); | ||
659 | spin_unlock_irqrestore(&sender->lock, flags); | ||
660 | |||
661 | if (!pkg) { | ||
662 | dev_err(sender->dev->dev, "No memory\n"); | ||
663 | return -ENOMEM; | ||
664 | } | ||
665 | |||
666 | if (param_num) { | ||
667 | pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_1; | ||
668 | pkg->pkg.short_pkg.param = param; | ||
669 | } else { | ||
670 | pkg->pkg_type = MDFLD_DSI_PKG_MCS_SHORT_WRITE_0; | ||
671 | pkg->pkg.short_pkg.param = 0; | ||
672 | } | ||
673 | pkg->transmission_type = transmission; | ||
674 | pkg->pkg.short_pkg.cmd = cmd; | ||
675 | INIT_LIST_HEAD(&pkg->entry); | ||
676 | |||
677 | pkg_sender_queue_pkg(sender, pkg, delay); | ||
678 | return 0; | ||
679 | } | ||
680 | |||
681 | static int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, | ||
682 | u8 param0, u8 param1, u8 param_num, | ||
683 | u8 transmission, | ||
684 | int delay) | ||
685 | { | ||
686 | struct mdfld_dsi_pkg *pkg; | ||
687 | unsigned long flags; | ||
688 | |||
689 | spin_lock_irqsave(&sender->lock, flags); | ||
690 | pkg = pkg_sender_get_pkg_locked(sender); | ||
691 | spin_unlock_irqrestore(&sender->lock, flags); | ||
692 | |||
693 | if (!pkg) { | ||
694 | dev_err(sender->dev->dev, "No pkg memory\n"); | ||
695 | return -ENOMEM; | ||
696 | } | ||
697 | |||
698 | switch (param_num) { | ||
699 | case 0: | ||
700 | pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_0; | ||
701 | pkg->pkg.short_pkg.cmd = 0; | ||
702 | pkg->pkg.short_pkg.param = 0; | ||
703 | break; | ||
704 | case 1: | ||
705 | pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_1; | ||
706 | pkg->pkg.short_pkg.cmd = param0; | ||
707 | pkg->pkg.short_pkg.param = 0; | ||
708 | break; | ||
709 | case 2: | ||
710 | pkg->pkg_type = MDFLD_DSI_PKG_GEN_SHORT_WRITE_2; | ||
711 | pkg->pkg.short_pkg.cmd = param0; | ||
712 | pkg->pkg.short_pkg.param = param1; | ||
713 | break; | ||
714 | } | ||
715 | |||
716 | pkg->transmission_type = transmission; | ||
717 | INIT_LIST_HEAD(&pkg->entry); | ||
718 | |||
719 | pkg_sender_queue_pkg(sender, pkg, delay); | ||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, | ||
724 | u32 *data, u32 len, u8 transmission, int delay) | ||
725 | { | ||
726 | struct mdfld_dsi_pkg *pkg; | ||
727 | unsigned long flags; | ||
728 | |||
729 | spin_lock_irqsave(&sender->lock, flags); | ||
730 | pkg = pkg_sender_get_pkg_locked(sender); | ||
731 | spin_unlock_irqrestore(&sender->lock, flags); | ||
732 | |||
733 | if (!pkg) { | ||
734 | dev_err(sender->dev->dev, "No pkg memory\n"); | ||
735 | return -ENOMEM; | ||
736 | } | ||
737 | |||
738 | pkg->pkg_type = MDFLD_DSI_PKG_GEN_LONG_WRITE; | ||
739 | pkg->transmission_type = transmission; | ||
740 | pkg->pkg.long_pkg.data = data; | ||
741 | pkg->pkg.long_pkg.len = len; | ||
742 | |||
743 | INIT_LIST_HEAD(&pkg->entry); | ||
744 | |||
745 | pkg_sender_queue_pkg(sender, pkg, delay); | ||
746 | |||
747 | return 0; | ||
748 | } | ||
749 | |||
750 | static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, | ||
751 | struct mdfld_dsi_pkg *pkg, | ||
752 | u32 *data, | ||
753 | u16 len) | ||
754 | { | ||
755 | unsigned long flags; | ||
756 | struct drm_device *dev = sender->dev; | ||
757 | int i; | ||
758 | u32 gen_data_reg; | ||
759 | int retry = MDFLD_DSI_READ_MAX_COUNT; | ||
760 | u8 transmission = pkg->transmission_type; | ||
761 | |||
762 | /* | ||
763 | * do reading. | ||
764 | * 0) send out generic read request | ||
765 | * 1) polling read data avail interrupt | ||
766 | * 2) read data | ||
767 | */ | ||
768 | spin_lock_irqsave(&sender->lock, flags); | ||
769 | |||
770 | REG_WRITE(sender->mipi_intr_stat_reg, 1 << 29); | ||
771 | |||
772 | if ((REG_READ(sender->mipi_intr_stat_reg) & (1 << 29))) | ||
773 | DRM_ERROR("Can NOT clean read data valid interrupt\n"); | ||
774 | |||
775 | /*send out read request*/ | ||
776 | send_pkg(sender, pkg); | ||
777 | |||
778 | pkg_sender_put_pkg_locked(sender, pkg); | ||
779 | |||
780 | /*polling read data avail interrupt*/ | ||
781 | while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & (1 << 29))) { | ||
782 | udelay(100); | ||
783 | retry--; | ||
784 | } | ||
785 | |||
786 | if (!retry) { | ||
787 | spin_unlock_irqrestore(&sender->lock, flags); | ||
788 | return -ETIMEDOUT; | ||
789 | } | ||
790 | |||
791 | REG_WRITE(sender->mipi_intr_stat_reg, (1 << 29)); | ||
792 | |||
793 | /*read data*/ | ||
794 | if (transmission == MDFLD_DSI_HS_TRANSMISSION) | ||
795 | gen_data_reg = sender->mipi_hs_gen_data_reg; | ||
796 | else if (transmission == MDFLD_DSI_LP_TRANSMISSION) | ||
797 | gen_data_reg = sender->mipi_lp_gen_data_reg; | ||
798 | else { | ||
799 | DRM_ERROR("Unknown transmission"); | ||
800 | spin_unlock_irqrestore(&sender->lock, flags); | ||
801 | return -EINVAL; | ||
802 | } | ||
803 | |||
804 | for (i=0; i<len; i++) | ||
805 | *(data + i) = REG_READ(gen_data_reg); | ||
806 | |||
807 | spin_unlock_irqrestore(&sender->lock, flags); | ||
808 | |||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | static int mdfld_dsi_read_gen(struct mdfld_dsi_pkg_sender *sender, | ||
813 | u8 param0, | ||
814 | u8 param1, | ||
815 | u8 param_num, | ||
816 | u32 *data, | ||
817 | u16 len, | ||
818 | u8 transmission) | ||
819 | { | ||
820 | struct mdfld_dsi_pkg *pkg; | ||
821 | unsigned long flags; | ||
822 | |||
823 | spin_lock_irqsave(&sender->lock, flags); | ||
824 | |||
825 | pkg = pkg_sender_get_pkg_locked(sender); | ||
826 | |||
827 | spin_unlock_irqrestore(&sender->lock,flags); | ||
828 | |||
829 | if (!pkg) { | ||
830 | dev_err(sender->dev->dev, "No pkg memory\n"); | ||
831 | return -ENOMEM; | ||
832 | } | ||
833 | |||
834 | switch (param_num) { | ||
835 | case 0: | ||
836 | pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_0; | ||
837 | pkg->pkg.short_pkg.cmd = 0; | ||
838 | pkg->pkg.short_pkg.param = 0; | ||
839 | break; | ||
840 | case 1: | ||
841 | pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_1; | ||
842 | pkg->pkg.short_pkg.cmd = param0; | ||
843 | pkg->pkg.short_pkg.param = 0; | ||
844 | break; | ||
845 | case 2: | ||
846 | pkg->pkg_type = MDFLD_DSI_PKG_GEN_READ_2; | ||
847 | pkg->pkg.short_pkg.cmd = param0; | ||
848 | pkg->pkg.short_pkg.param = param1; | ||
849 | break; | ||
850 | } | ||
851 | |||
852 | pkg->transmission_type = transmission; | ||
853 | |||
854 | INIT_LIST_HEAD(&pkg->entry); | ||
855 | |||
856 | return __read_panel_data(sender, pkg, data, len); | ||
857 | } | ||
858 | |||
859 | static int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, | ||
860 | u8 cmd, | ||
861 | u32 *data, | ||
862 | u16 len, | ||
863 | u8 transmission) | ||
864 | { | ||
865 | struct mdfld_dsi_pkg *pkg; | ||
866 | unsigned long flags; | ||
867 | |||
868 | spin_lock_irqsave(&sender->lock, flags); | ||
869 | |||
870 | pkg = pkg_sender_get_pkg_locked(sender); | ||
871 | |||
872 | spin_unlock_irqrestore(&sender->lock, flags); | ||
873 | |||
874 | if (!pkg) { | ||
875 | dev_err(sender->dev->dev, "No pkg memory\n"); | ||
876 | return -ENOMEM; | ||
877 | } | ||
878 | |||
879 | pkg->pkg_type = MDFLD_DSI_PKG_MCS_READ; | ||
880 | pkg->pkg.short_pkg.cmd = cmd; | ||
881 | pkg->pkg.short_pkg.param = 0; | ||
882 | |||
883 | pkg->transmission_type = transmission; | ||
884 | |||
885 | INIT_LIST_HEAD(&pkg->entry); | ||
886 | |||
887 | return __read_panel_data(sender, pkg, data, len); | ||
888 | } | ||
889 | |||
890 | void dsi_controller_dbi_init(struct mdfld_dsi_config * dsi_config, int pipe) | ||
891 | { | ||
892 | struct drm_device * dev = dsi_config->dev; | ||
893 | u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; | ||
894 | int lane_count = dsi_config->lane_count; | ||
895 | u32 val = 0; | ||
896 | |||
897 | /*un-ready device*/ | ||
898 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); | ||
899 | |||
900 | /*init dsi adapter before kicking off*/ | ||
901 | REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); | ||
902 | |||
903 | /*TODO: figure out how to setup these registers*/ | ||
904 | REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); | ||
905 | REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), 0x000a0014); | ||
906 | REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400); | ||
907 | REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001); | ||
908 | REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000); | ||
909 | |||
910 | /*enable all interrupts*/ | ||
911 | REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); | ||
912 | /*max value: 20 clock cycles of txclkesc*/ | ||
913 | REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f); | ||
914 | /*min 21 txclkesc, max: ffffh*/ | ||
915 | REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff); | ||
916 | /*min: 7d0 max: 4e20*/ | ||
917 | REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0); | ||
918 | |||
919 | /*set up max return packet size*/ | ||
920 | REG_WRITE((MIPIA_MAX_RETURN_PACK_SIZE_REG + reg_offset), | ||
921 | MDFLD_DSI_MAX_RETURN_PACKET_SIZE); | ||
922 | |||
923 | /*set up func_prg*/ | ||
924 | val |= lane_count; | ||
925 | val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET); | ||
926 | val |= DSI_DBI_COLOR_FORMAT_OPTION2; | ||
927 | REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); | ||
928 | |||
929 | REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff); | ||
930 | REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff); | ||
931 | |||
932 | REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); | ||
933 | REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); | ||
934 | REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); | ||
935 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); | ||
936 | } | ||
937 | |||
938 | void dsi_controller_dpi_init(struct mdfld_dsi_config * dsi_config, int pipe) | ||
939 | { | ||
940 | struct drm_device * dev = dsi_config->dev; | ||
941 | u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; | ||
942 | int lane_count = dsi_config->lane_count; | ||
943 | struct mdfld_dsi_dpi_timing dpi_timing; | ||
944 | struct drm_display_mode * mode = dsi_config->mode; | ||
945 | u32 val = 0; | ||
946 | |||
947 | /*un-ready device*/ | ||
948 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); | ||
949 | |||
950 | /*init dsi adapter before kicking off*/ | ||
951 | REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); | ||
952 | |||
953 | /*enable all interrupts*/ | ||
954 | REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); | ||
955 | |||
956 | /*set up func_prg*/ | ||
957 | val |= lane_count; | ||
958 | val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET; | ||
959 | |||
960 | switch(dsi_config->bpp) { | ||
961 | case 16: | ||
962 | val |= DSI_DPI_COLOR_FORMAT_RGB565; | ||
963 | break; | ||
964 | case 18: | ||
965 | val |= DSI_DPI_COLOR_FORMAT_RGB666; | ||
966 | break; | ||
967 | case 24: | ||
968 | val |= DSI_DPI_COLOR_FORMAT_RGB888; | ||
969 | break; | ||
970 | default: | ||
971 | DRM_ERROR("unsupported color format, bpp = %d\n", dsi_config->bpp); | ||
972 | } | ||
973 | |||
974 | REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); | ||
975 | |||
976 | REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), | ||
977 | (mode->vtotal * mode->htotal * dsi_config->bpp / (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK); | ||
978 | REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff & DSI_LP_RX_TIMEOUT_MASK); | ||
979 | |||
980 | /*max value: 20 clock cycles of txclkesc*/ | ||
981 | REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK); | ||
982 | |||
983 | /*min 21 txclkesc, max: ffffh*/ | ||
984 | REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0xffff & DSI_RESET_TIMER_MASK); | ||
985 | |||
986 | REG_WRITE((MIPIA_DPI_RESOLUTION_REG + reg_offset), mode->vdisplay << 16 | mode->hdisplay); | ||
987 | |||
988 | /*set DPI timing registers*/ | ||
989 | mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing, dsi_config->lane_count, dsi_config->bpp); | ||
990 | |||
991 | REG_WRITE((MIPIA_HSYNC_COUNT_REG + reg_offset), dpi_timing.hsync_count & DSI_DPI_TIMING_MASK); | ||
992 | REG_WRITE((MIPIA_HBP_COUNT_REG + reg_offset), dpi_timing.hbp_count & DSI_DPI_TIMING_MASK); | ||
993 | REG_WRITE((MIPIA_HFP_COUNT_REG + reg_offset), dpi_timing.hfp_count & DSI_DPI_TIMING_MASK); | ||
994 | REG_WRITE((MIPIA_HACTIVE_COUNT_REG + reg_offset), dpi_timing.hactive_count & DSI_DPI_TIMING_MASK); | ||
995 | REG_WRITE((MIPIA_VSYNC_COUNT_REG + reg_offset), dpi_timing.vsync_count & DSI_DPI_TIMING_MASK); | ||
996 | REG_WRITE((MIPIA_VBP_COUNT_REG + reg_offset), dpi_timing.vbp_count & DSI_DPI_TIMING_MASK); | ||
997 | REG_WRITE((MIPIA_VFP_COUNT_REG + reg_offset), dpi_timing.vfp_count & DSI_DPI_TIMING_MASK); | ||
998 | |||
999 | REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); | ||
1000 | |||
1001 | /*min: 7d0 max: 4e20*/ | ||
1002 | REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x000007d0); | ||
1003 | |||
1004 | /*set up video mode*/ | ||
1005 | val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE; | ||
1006 | REG_WRITE((MIPIA_VIDEO_MODE_FORMAT_REG + reg_offset), val); | ||
1007 | |||
1008 | REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000); | ||
1009 | |||
1010 | REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); | ||
1011 | |||
1012 | /*TODO: figure out how to setup these registers*/ | ||
1013 | REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408); | ||
1014 | |||
1015 | REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), (0xa << 16) | 0x14); | ||
1016 | |||
1017 | /*set device ready*/ | ||
1018 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); | ||
1019 | } | ||
1020 | |||
1021 | static void dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe) | ||
1022 | { | ||
1023 | if (!dsi_config || ((pipe != 0) && (pipe != 2))) { | ||
1024 | DRM_ERROR("Invalid parameters\n"); | ||
1025 | return; | ||
1026 | } | ||
1027 | |||
1028 | if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) | ||
1029 | dsi_controller_dpi_init(dsi_config, pipe); | ||
1030 | else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) | ||
1031 | dsi_controller_dbi_init(dsi_config, pipe); | ||
1032 | else | ||
1033 | DRM_ERROR("Bad DSI encoder type\n"); | ||
1034 | } | ||
1035 | |||
1036 | void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender) | ||
1037 | { | ||
1038 | process_pkg_list(sender); | ||
1039 | } | ||
1040 | |||
1041 | int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, | ||
1042 | u8 dcs, u8 *param, u32 param_num, u8 data_src, | ||
1043 | int delay) | ||
1044 | { | ||
1045 | struct mdfld_dsi_pkg *pkg; | ||
1046 | u32 cb_phy = sender->dbi_cb_phy; | ||
1047 | struct drm_device *dev = sender->dev; | ||
1048 | u32 index = 0; | ||
1049 | u8 *cb = (u8 *)sender->dbi_cb_addr; | ||
1050 | unsigned long flags; | ||
1051 | int retry; | ||
1052 | u8 *dst = NULL; | ||
1053 | u32 len; | ||
1054 | |||
1055 | if (!sender) { | ||
1056 | WARN_ON(1); | ||
1057 | return -EINVAL; | ||
1058 | } | ||
1059 | |||
1060 | if (!sender->dbi_pkg_support) { | ||
1061 | dev_err(dev->dev, "No DBI pkg sending on this sender\n"); | ||
1062 | return -ENOTSUPP; | ||
1063 | } | ||
1064 | |||
1065 | if (param_num > MDFLD_MAX_DCS_PARAM) { | ||
1066 | dev_err(dev->dev, "Sender only supports up to %d DCS params\n", | ||
1067 | MDFLD_MAX_DCS_PARAM); | ||
1068 | return -EINVAL; | ||
1069 | } | ||
1070 | |||
1071 | /* | ||
1072 | * If dcs is write_mem_start, send it directly using DSI adapter | ||
1073 | * interface | ||
1074 | */ | ||
1075 | if (dcs == DCS_WRITE_MEM_START) { | ||
1076 | if (!spin_trylock(&sender->lock)) | ||
1077 | return -EAGAIN; | ||
1078 | |||
1079 | /* | ||
1080 | * query whether DBI FIFO is empty, | ||
1081 | * if not wait it becoming empty | ||
1082 | */ | ||
1083 | retry = MDFLD_DSI_DBI_FIFO_TIMEOUT; | ||
1084 | while (retry && | ||
1085 | !(REG_READ(sender->mipi_gen_fifo_stat_reg) & (1 << 27))) { | ||
1086 | udelay(500); | ||
1087 | retry--; | ||
1088 | } | ||
1089 | |||
1090 | /* If DBI FIFO timeout, drop this frame */ | ||
1091 | if (!retry) { | ||
1092 | spin_unlock(&sender->lock); | ||
1093 | return 0; | ||
1094 | } | ||
1095 | |||
1096 | *(cb + (index++)) = write_mem_start; | ||
1097 | |||
1098 | REG_WRITE(sender->mipi_cmd_len_reg, 1); | ||
1099 | REG_WRITE(sender->mipi_cmd_addr_reg, | ||
1100 | cb_phy | (1 << 0) | (1 << 1)); | ||
1101 | |||
1102 | retry = MDFLD_DSI_DBI_FIFO_TIMEOUT; | ||
1103 | while (retry && | ||
1104 | (REG_READ(sender->mipi_cmd_addr_reg) & (1 << 0))) { | ||
1105 | udelay(1); | ||
1106 | retry--; | ||
1107 | } | ||
1108 | |||
1109 | spin_unlock(&sender->lock); | ||
1110 | return 0; | ||
1111 | } | ||
1112 | |||
1113 | /* Get a free pkg */ | ||
1114 | spin_lock_irqsave(&sender->lock, flags); | ||
1115 | pkg = pkg_sender_get_pkg_locked(sender); | ||
1116 | spin_unlock_irqrestore(&sender->lock, flags); | ||
1117 | |||
1118 | if (!pkg) { | ||
1119 | dev_err(dev->dev, "No packages memory\n"); | ||
1120 | return -ENOMEM; | ||
1121 | } | ||
1122 | |||
1123 | dst = pkg->pkg.dcs_pkg.param; | ||
1124 | memcpy(dst, param, param_num); | ||
1125 | |||
1126 | pkg->pkg_type = MDFLD_DSI_PKG_DCS; | ||
1127 | pkg->transmission_type = MDFLD_DSI_DCS; | ||
1128 | pkg->pkg.dcs_pkg.cmd = dcs; | ||
1129 | pkg->pkg.dcs_pkg.param_num = param_num; | ||
1130 | pkg->pkg.dcs_pkg.data_src = data_src; | ||
1131 | |||
1132 | INIT_LIST_HEAD(&pkg->entry); | ||
1133 | |||
1134 | if (param_num == 0) | ||
1135 | return mdfld_dsi_send_mcs_short_hs(sender, dcs, 0, 0, delay); | ||
1136 | else if (param_num == 1) | ||
1137 | return mdfld_dsi_send_mcs_short_hs(sender, dcs, | ||
1138 | param[0], 1, delay); | ||
1139 | else if (param_num > 1) { | ||
1140 | len = (param_num + 1) / 4; | ||
1141 | if ((param_num + 1) % 4) | ||
1142 | len++; | ||
1143 | return mdfld_dsi_send_mcs_long_hs(sender, | ||
1144 | (u32 *)&pkg->pkg.dcs_pkg, len, delay); | ||
1145 | } | ||
1146 | return 0; | ||
1147 | } | ||
1148 | |||
1149 | int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender, | ||
1150 | u8 cmd, u8 param, u8 param_num, int delay) | ||
1151 | { | ||
1152 | if (!sender) { | ||
1153 | WARN_ON(1); | ||
1154 | return -EINVAL; | ||
1155 | } | ||
1156 | return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num, | ||
1157 | MDFLD_DSI_HS_TRANSMISSION, delay); | ||
1158 | } | ||
1159 | |||
1160 | int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender, | ||
1161 | u8 cmd, u8 param, u8 param_num, int delay) | ||
1162 | { | ||
1163 | if (!sender) { | ||
1164 | WARN_ON(1); | ||
1165 | return -EINVAL; | ||
1166 | } | ||
1167 | return mdfld_dsi_send_mcs_short(sender, cmd, param, param_num, | ||
1168 | MDFLD_DSI_LP_TRANSMISSION, delay); | ||
1169 | } | ||
1170 | |||
1171 | int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender, | ||
1172 | u32 *data, | ||
1173 | u32 len, | ||
1174 | int delay) | ||
1175 | { | ||
1176 | if (!sender || !data || !len) { | ||
1177 | DRM_ERROR("Invalid parameters\n"); | ||
1178 | return -EINVAL; | ||
1179 | } | ||
1180 | return mdfld_dsi_send_mcs_long(sender, data, len, | ||
1181 | MDFLD_DSI_HS_TRANSMISSION, delay); | ||
1182 | } | ||
1183 | |||
1184 | int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender, | ||
1185 | u32 *data, | ||
1186 | u32 len, | ||
1187 | int delay) | ||
1188 | { | ||
1189 | if (!sender || !data || !len) { | ||
1190 | WARN_ON(1); | ||
1191 | return -EINVAL; | ||
1192 | } | ||
1193 | return mdfld_dsi_send_mcs_long(sender, data, len, | ||
1194 | MDFLD_DSI_LP_TRANSMISSION, delay); | ||
1195 | } | ||
1196 | |||
1197 | int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender, | ||
1198 | u8 param0, u8 param1, u8 param_num, int delay) | ||
1199 | { | ||
1200 | if (!sender) { | ||
1201 | WARN_ON(1); | ||
1202 | return -EINVAL; | ||
1203 | } | ||
1204 | return mdfld_dsi_send_gen_short(sender, param0, param1, param_num, | ||
1205 | MDFLD_DSI_HS_TRANSMISSION, delay); | ||
1206 | } | ||
1207 | |||
1208 | int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender, | ||
1209 | u8 param0, u8 param1, u8 param_num, int delay) | ||
1210 | { | ||
1211 | if (!sender || param_num < 0 || param_num > 2) { | ||
1212 | WARN_ON(1); | ||
1213 | return -EINVAL; | ||
1214 | } | ||
1215 | return mdfld_dsi_send_gen_short(sender, param0, param1, param_num, | ||
1216 | MDFLD_DSI_LP_TRANSMISSION, delay); | ||
1217 | } | ||
1218 | |||
1219 | int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender, | ||
1220 | u32 *data, | ||
1221 | u32 len, | ||
1222 | int delay) | ||
1223 | { | ||
1224 | if (!sender || !data || !len) { | ||
1225 | WARN_ON(1); | ||
1226 | return -EINVAL; | ||
1227 | } | ||
1228 | return mdfld_dsi_send_gen_long(sender, data, len, | ||
1229 | MDFLD_DSI_HS_TRANSMISSION, delay); | ||
1230 | } | ||
1231 | |||
1232 | int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender, | ||
1233 | u32 *data, | ||
1234 | u32 len, | ||
1235 | int delay) | ||
1236 | { | ||
1237 | if (!sender || !data || !len) { | ||
1238 | WARN_ON(1); | ||
1239 | return -EINVAL; | ||
1240 | } | ||
1241 | return mdfld_dsi_send_gen_long(sender, data, len, | ||
1242 | MDFLD_DSI_LP_TRANSMISSION, delay); | ||
1243 | } | ||
1244 | |||
1245 | int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender, | ||
1246 | u8 param0, | ||
1247 | u8 param1, | ||
1248 | u8 param_num, | ||
1249 | u32 *data, | ||
1250 | u16 len) | ||
1251 | { | ||
1252 | if (!sender || !data || param_num < 0 || param_num > 2 | ||
1253 | || !data || !len) { | ||
1254 | DRM_ERROR("Invalid parameters\n"); | ||
1255 | return -EINVAL; | ||
1256 | } | ||
1257 | |||
1258 | return mdfld_dsi_read_gen(sender, param0, param1, param_num, | ||
1259 | data, len, MDFLD_DSI_HS_TRANSMISSION); | ||
1260 | |||
1261 | } | ||
1262 | |||
1263 | int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender, | ||
1264 | u8 param0, | ||
1265 | u8 param1, | ||
1266 | u8 param_num, | ||
1267 | u32 *data, | ||
1268 | u16 len) | ||
1269 | { | ||
1270 | if (!sender || !data || param_num < 0 || param_num > 2 | ||
1271 | || !data || !len) { | ||
1272 | DRM_ERROR("Invalid parameters\n"); | ||
1273 | return -EINVAL; | ||
1274 | } | ||
1275 | |||
1276 | return mdfld_dsi_read_gen(sender, param0, param1, param_num, | ||
1277 | data, len, MDFLD_DSI_LP_TRANSMISSION); | ||
1278 | } | ||
1279 | |||
1280 | int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender, | ||
1281 | u8 cmd, | ||
1282 | u32 *data, | ||
1283 | u16 len) | ||
1284 | { | ||
1285 | if (!sender || !data || !len) { | ||
1286 | DRM_ERROR("Invalid parameters\n"); | ||
1287 | return -EINVAL; | ||
1288 | } | ||
1289 | |||
1290 | return mdfld_dsi_read_mcs(sender, cmd, data, len, | ||
1291 | MDFLD_DSI_HS_TRANSMISSION); | ||
1292 | } | ||
1293 | |||
1294 | int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender, | ||
1295 | u8 cmd, | ||
1296 | u32 *data, | ||
1297 | u16 len) | ||
1298 | { | ||
1299 | if (!sender || !data || !len) { | ||
1300 | WARN_ON(1); | ||
1301 | return -EINVAL; | ||
1302 | } | ||
1303 | |||
1304 | return mdfld_dsi_read_mcs(sender, cmd, data, len, | ||
1305 | MDFLD_DSI_LP_TRANSMISSION); | ||
1306 | } | ||
1307 | |||
1308 | int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, | ||
1309 | int pipe) | ||
1310 | { | ||
1311 | int ret; | ||
1312 | struct mdfld_dsi_pkg_sender *pkg_sender; | ||
1313 | struct mdfld_dsi_config *dsi_config = | ||
1314 | mdfld_dsi_get_config(dsi_connector); | ||
1315 | struct drm_device *dev = dsi_config->dev; | ||
1316 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
1317 | struct psb_gtt *pg = &dev_priv->gtt; | ||
1318 | int i; | ||
1319 | struct mdfld_dsi_pkg *pkg, *tmp; | ||
1320 | u32 mipi_val = 0; | ||
1321 | |||
1322 | if (!dsi_connector) { | ||
1323 | WARN_ON(1); | ||
1324 | return -EINVAL; | ||
1325 | } | ||
1326 | |||
1327 | pkg_sender = dsi_connector->pkg_sender; | ||
1328 | |||
1329 | if (!pkg_sender || IS_ERR(pkg_sender)) { | ||
1330 | pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender), | ||
1331 | GFP_KERNEL); | ||
1332 | if (!pkg_sender) { | ||
1333 | dev_err(dev->dev, "Create DSI pkg sender failed\n"); | ||
1334 | return -ENOMEM; | ||
1335 | } | ||
1336 | |||
1337 | dsi_connector->pkg_sender = (void *)pkg_sender; | ||
1338 | } | ||
1339 | |||
1340 | pkg_sender->dev = dev; | ||
1341 | pkg_sender->dsi_connector = dsi_connector; | ||
1342 | pkg_sender->pipe = pipe; | ||
1343 | pkg_sender->pkg_num = 0; | ||
1344 | pkg_sender->panel_mode = 0; | ||
1345 | pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE; | ||
1346 | |||
1347 | /* Init dbi command buffer*/ | ||
1348 | |||
1349 | if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) { | ||
1350 | pkg_sender->dbi_pkg_support = 1; | ||
1351 | ret = mdfld_dbi_cb_init(pkg_sender, pg, pipe); | ||
1352 | if (ret) { | ||
1353 | dev_err(dev->dev, "DBI command buffer map failed\n"); | ||
1354 | goto mapping_err; | ||
1355 | } | ||
1356 | } | ||
1357 | |||
1358 | /* Init regs */ | ||
1359 | if (pipe == 0) { | ||
1360 | pkg_sender->dpll_reg = MRST_DPLL_A; | ||
1361 | pkg_sender->dspcntr_reg = DSPACNTR; | ||
1362 | pkg_sender->pipeconf_reg = PIPEACONF; | ||
1363 | pkg_sender->dsplinoff_reg = DSPALINOFF; | ||
1364 | pkg_sender->dspsurf_reg = DSPASURF; | ||
1365 | pkg_sender->pipestat_reg = PIPEASTAT; | ||
1366 | |||
1367 | pkg_sender->mipi_intr_stat_reg = MIPIA_INTR_STAT_REG; | ||
1368 | pkg_sender->mipi_lp_gen_data_reg = MIPIA_LP_GEN_DATA_REG; | ||
1369 | pkg_sender->mipi_hs_gen_data_reg = MIPIA_HS_GEN_DATA_REG; | ||
1370 | pkg_sender->mipi_lp_gen_ctrl_reg = MIPIA_LP_GEN_CTRL_REG; | ||
1371 | pkg_sender->mipi_hs_gen_ctrl_reg = MIPIA_HS_GEN_CTRL_REG; | ||
1372 | pkg_sender->mipi_gen_fifo_stat_reg = MIPIA_GEN_FIFO_STAT_REG; | ||
1373 | pkg_sender->mipi_data_addr_reg = MIPIA_DATA_ADD_REG; | ||
1374 | pkg_sender->mipi_data_len_reg = MIPIA_DATA_LEN_REG; | ||
1375 | pkg_sender->mipi_cmd_addr_reg = MIPIA_CMD_ADD_REG; | ||
1376 | pkg_sender->mipi_cmd_len_reg = MIPIA_CMD_LEN_REG; | ||
1377 | } else if (pipe == 2) { | ||
1378 | pkg_sender->dpll_reg = MRST_DPLL_A; | ||
1379 | pkg_sender->dspcntr_reg = DSPCCNTR; | ||
1380 | pkg_sender->pipeconf_reg = PIPECCONF; | ||
1381 | pkg_sender->dsplinoff_reg = DSPCLINOFF; | ||
1382 | pkg_sender->dspsurf_reg = DSPCSURF; | ||
1383 | pkg_sender->pipestat_reg = PIPECSTAT; | ||
1384 | |||
1385 | pkg_sender->mipi_intr_stat_reg = | ||
1386 | MIPIA_INTR_STAT_REG + MIPIC_REG_OFFSET; | ||
1387 | pkg_sender->mipi_lp_gen_data_reg = | ||
1388 | MIPIA_LP_GEN_DATA_REG + MIPIC_REG_OFFSET; | ||
1389 | pkg_sender->mipi_hs_gen_data_reg = | ||
1390 | MIPIA_HS_GEN_DATA_REG + MIPIC_REG_OFFSET; | ||
1391 | pkg_sender->mipi_lp_gen_ctrl_reg = | ||
1392 | MIPIA_LP_GEN_CTRL_REG + MIPIC_REG_OFFSET; | ||
1393 | pkg_sender->mipi_hs_gen_ctrl_reg = | ||
1394 | MIPIA_HS_GEN_CTRL_REG + MIPIC_REG_OFFSET; | ||
1395 | pkg_sender->mipi_gen_fifo_stat_reg = | ||
1396 | MIPIA_GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET; | ||
1397 | pkg_sender->mipi_data_addr_reg = | ||
1398 | MIPIA_DATA_ADD_REG + MIPIC_REG_OFFSET; | ||
1399 | pkg_sender->mipi_data_len_reg = | ||
1400 | MIPIA_DATA_LEN_REG + MIPIC_REG_OFFSET; | ||
1401 | pkg_sender->mipi_cmd_addr_reg = | ||
1402 | MIPIA_CMD_ADD_REG + MIPIC_REG_OFFSET; | ||
1403 | pkg_sender->mipi_cmd_len_reg = | ||
1404 | MIPIA_CMD_LEN_REG + MIPIC_REG_OFFSET; | ||
1405 | } | ||
1406 | |||
1407 | /* Init pkg list */ | ||
1408 | INIT_LIST_HEAD(&pkg_sender->pkg_list); | ||
1409 | INIT_LIST_HEAD(&pkg_sender->free_list); | ||
1410 | |||
1411 | spin_lock_init(&pkg_sender->lock); | ||
1412 | |||
1413 | /* Allocate free pkg pool */ | ||
1414 | for (i = 0; i < MDFLD_MAX_PKG_NUM; i++) { | ||
1415 | pkg = kzalloc(sizeof(struct mdfld_dsi_pkg), GFP_KERNEL); | ||
1416 | if (!pkg) { | ||
1417 | dev_err(dev->dev, "Out of memory allocating pkg pool"); | ||
1418 | ret = -ENOMEM; | ||
1419 | goto pkg_alloc_err; | ||
1420 | } | ||
1421 | INIT_LIST_HEAD(&pkg->entry); | ||
1422 | list_add_tail(&pkg->entry, &pkg_sender->free_list); | ||
1423 | } | ||
1424 | |||
1425 | /* | ||
1426 | * For video mode, don't enable DPI timing output here, | ||
1427 | * will init the DPI timing output during mode setting. | ||
1428 | */ | ||
1429 | if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) | ||
1430 | mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX; | ||
1431 | else if (dsi_config->type == MDFLD_DSI_ENCODER_DBI) | ||
1432 | mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX | ||
1433 | | TE_TRIGGER_GPIO_PIN; | ||
1434 | else | ||
1435 | DRM_ERROR("Bad DSI encoder type\n"); | ||
1436 | |||
1437 | if (pipe == 0) { | ||
1438 | mipi_val |= 0x2; | ||
1439 | REG_WRITE(MIPI, mipi_val); | ||
1440 | REG_READ(MIPI); | ||
1441 | } else if (pipe == 2) { | ||
1442 | REG_WRITE(MIPI_C, mipi_val); | ||
1443 | REG_READ(MIPI_C); | ||
1444 | } | ||
1445 | |||
1446 | /*do dsi controller init*/ | ||
1447 | dsi_controller_init(dsi_config, pipe); | ||
1448 | |||
1449 | return 0; | ||
1450 | |||
1451 | pkg_alloc_err: | ||
1452 | list_for_each_entry_safe(pkg, tmp, &pkg_sender->free_list, entry) { | ||
1453 | list_del(&pkg->entry); | ||
1454 | kfree(pkg); | ||
1455 | } | ||
1456 | |||
1457 | /* Free mapped command buffer */ | ||
1458 | mdfld_dbi_cb_destroy(pkg_sender); | ||
1459 | mapping_err: | ||
1460 | kfree(pkg_sender); | ||
1461 | dsi_connector->pkg_sender = NULL; | ||
1462 | return ret; | ||
1463 | } | ||
1464 | |||
1465 | void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender) | ||
1466 | { | ||
1467 | struct mdfld_dsi_pkg *pkg, *tmp; | ||
1468 | |||
1469 | if (!sender || IS_ERR(sender)) | ||
1470 | return; | ||
1471 | |||
1472 | /* Free pkg pool */ | ||
1473 | list_for_each_entry_safe(pkg, tmp, &sender->free_list, entry) { | ||
1474 | list_del(&pkg->entry); | ||
1475 | kfree(pkg); | ||
1476 | } | ||
1477 | /* Free pkg list */ | ||
1478 | list_for_each_entry_safe(pkg, tmp, &sender->pkg_list, entry) { | ||
1479 | list_del(&pkg->entry); | ||
1480 | kfree(pkg); | ||
1481 | } | ||
1482 | mdfld_dbi_cb_destroy(sender); /* free mapped command buffer */ | ||
1483 | kfree(sender); | ||
1484 | } | ||
diff --git a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h deleted file mode 100644 index f24abc700684..000000000000 --- a/drivers/staging/gma500/mdfld_dsi_pkg_sender.h +++ /dev/null | |||
@@ -1,184 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
25 | */ | ||
26 | #ifndef __MDFLD_DSI_PKG_SENDER_H__ | ||
27 | #define __MDFLD_DSI_PKG_SENDER_H__ | ||
28 | |||
29 | #include <linux/kthread.h> | ||
30 | |||
31 | #define MDFLD_MAX_DCS_PARAM 8 | ||
32 | #define MDFLD_MAX_PKG_NUM 2048 | ||
33 | |||
34 | enum { | ||
35 | MDFLD_DSI_PKG_DCS, | ||
36 | MDFLD_DSI_PKG_GEN_SHORT_WRITE_0 = 0x03, | ||
37 | MDFLD_DSI_PKG_GEN_SHORT_WRITE_1 = 0x13, | ||
38 | MDFLD_DSI_PKG_GEN_SHORT_WRITE_2 = 0x23, | ||
39 | MDFLD_DSI_PKG_GEN_READ_0 = 0x04, | ||
40 | MDFLD_DSI_PKG_GEN_READ_1 = 0x14, | ||
41 | MDFLD_DSI_PKG_GEN_READ_2 = 0x24, | ||
42 | MDFLD_DSI_PKG_GEN_LONG_WRITE = 0x29, | ||
43 | MDFLD_DSI_PKG_MCS_SHORT_WRITE_0 = 0x05, | ||
44 | MDFLD_DSI_PKG_MCS_SHORT_WRITE_1 = 0x15, | ||
45 | MDFLD_DSI_PKG_MCS_READ = 0x06, | ||
46 | MDFLD_DSI_PKG_MCS_LONG_WRITE = 0x39, | ||
47 | }; | ||
48 | |||
49 | enum { | ||
50 | MDFLD_DSI_LP_TRANSMISSION, | ||
51 | MDFLD_DSI_HS_TRANSMISSION, | ||
52 | MDFLD_DSI_DCS, | ||
53 | }; | ||
54 | |||
55 | enum { | ||
56 | MDFLD_DSI_PANEL_MODE_SLEEP = 0x1, | ||
57 | }; | ||
58 | |||
59 | enum { | ||
60 | MDFLD_DSI_PKG_SENDER_FREE = 0x0, | ||
61 | MDFLD_DSI_PKG_SENDER_BUSY = 0x1, | ||
62 | }; | ||
63 | |||
64 | enum { | ||
65 | MDFLD_DSI_SEND_PACKAGE, | ||
66 | MDFLD_DSI_QUEUE_PACKAGE, | ||
67 | }; | ||
68 | |||
69 | struct mdfld_dsi_gen_short_pkg { | ||
70 | u8 cmd; | ||
71 | u8 param; | ||
72 | }; | ||
73 | |||
74 | struct mdfld_dsi_gen_long_pkg { | ||
75 | u32 *data; | ||
76 | u32 len; | ||
77 | }; | ||
78 | |||
79 | struct mdfld_dsi_dcs_pkg { | ||
80 | u8 cmd; | ||
81 | u8 param[MDFLD_MAX_DCS_PARAM]; | ||
82 | u32 param_num; | ||
83 | u8 data_src; | ||
84 | }; | ||
85 | |||
86 | struct mdfld_dsi_pkg { | ||
87 | u8 pkg_type; | ||
88 | u8 transmission_type; | ||
89 | |||
90 | union { | ||
91 | struct mdfld_dsi_gen_short_pkg short_pkg; | ||
92 | struct mdfld_dsi_gen_long_pkg long_pkg; | ||
93 | struct mdfld_dsi_dcs_pkg dcs_pkg; | ||
94 | } pkg; | ||
95 | |||
96 | struct list_head entry; | ||
97 | }; | ||
98 | |||
99 | struct mdfld_dsi_pkg_sender { | ||
100 | struct drm_device *dev; | ||
101 | struct mdfld_dsi_connector *dsi_connector; | ||
102 | u32 status; | ||
103 | |||
104 | u32 panel_mode; | ||
105 | |||
106 | int pipe; | ||
107 | |||
108 | spinlock_t lock; | ||
109 | struct list_head pkg_list; | ||
110 | struct list_head free_list; | ||
111 | |||
112 | u32 pkg_num; | ||
113 | |||
114 | int dbi_pkg_support; | ||
115 | |||
116 | u32 dbi_cb_phy; | ||
117 | void *dbi_cb_addr; | ||
118 | |||
119 | /* Registers */ | ||
120 | u32 dpll_reg; | ||
121 | u32 dspcntr_reg; | ||
122 | u32 pipeconf_reg; | ||
123 | u32 pipestat_reg; | ||
124 | u32 dsplinoff_reg; | ||
125 | u32 dspsurf_reg; | ||
126 | |||
127 | u32 mipi_intr_stat_reg; | ||
128 | u32 mipi_lp_gen_data_reg; | ||
129 | u32 mipi_hs_gen_data_reg; | ||
130 | u32 mipi_lp_gen_ctrl_reg; | ||
131 | u32 mipi_hs_gen_ctrl_reg; | ||
132 | u32 mipi_gen_fifo_stat_reg; | ||
133 | u32 mipi_data_addr_reg; | ||
134 | u32 mipi_data_len_reg; | ||
135 | u32 mipi_cmd_addr_reg; | ||
136 | u32 mipi_cmd_len_reg; | ||
137 | }; | ||
138 | |||
139 | /* DCS definitions */ | ||
140 | #define DCS_SOFT_RESET 0x01 | ||
141 | #define DCS_ENTER_SLEEP_MODE 0x10 | ||
142 | #define DCS_EXIT_SLEEP_MODE 0x11 | ||
143 | #define DCS_SET_DISPLAY_OFF 0x28 | ||
144 | #define DCS_SET_DISPLAY_ON 0x29 | ||
145 | #define DCS_SET_COLUMN_ADDRESS 0x2a | ||
146 | #define DCS_SET_PAGE_ADDRESS 0x2b | ||
147 | #define DCS_WRITE_MEM_START 0x2c | ||
148 | #define DCS_SET_TEAR_OFF 0x34 | ||
149 | #define DCS_SET_TEAR_ON 0x35 | ||
150 | |||
151 | extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector, | ||
152 | int pipe); | ||
153 | extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender); | ||
154 | extern int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, u8 dcs, | ||
155 | u8 *param, u32 param_num, u8 data_src, int delay); | ||
156 | extern int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender, | ||
157 | u8 cmd, u8 param, u8 param_num, int delay); | ||
158 | extern int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender, | ||
159 | u8 cmd, u8 param, u8 param_num, int delay); | ||
160 | extern int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender, | ||
161 | u32 *data, u32 len, int delay); | ||
162 | extern int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender, | ||
163 | u32 *data, u32 len, int delay); | ||
164 | extern int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender, | ||
165 | u8 param0, u8 param1, u8 param_num, int delay); | ||
166 | extern int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender, | ||
167 | u8 param0, u8 param1, u8 param_num, int delay); | ||
168 | extern int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender, | ||
169 | u32 *data, u32 len, int delay); | ||
170 | extern int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender, | ||
171 | u32 *data, u32 len, int delay); | ||
172 | |||
173 | extern int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender, | ||
174 | u8 param0, u8 param1, u8 param_num, u32 *data, u16 len); | ||
175 | extern int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender, | ||
176 | u8 param0, u8 param1, u8 param_num, u32 *data, u16 len); | ||
177 | extern int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender, | ||
178 | u8 cmd, u32 *data, u16 len); | ||
179 | extern int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender, | ||
180 | u8 cmd, u32 *data, u16 len); | ||
181 | |||
182 | extern void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender); | ||
183 | |||
184 | #endif /* __MDFLD_DSI_PKG_SENDER_H__ */ | ||
diff --git a/drivers/staging/gma500/mdfld_intel_display.c b/drivers/staging/gma500/mdfld_intel_display.c deleted file mode 100644 index 0b37b7b6b02a..000000000000 --- a/drivers/staging/gma500/mdfld_intel_display.c +++ /dev/null | |||
@@ -1,1404 +0,0 @@ | |||
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 | * Eric Anholt <eric@anholt.net> | ||
25 | */ | ||
26 | |||
27 | #include "framebuffer.h" | ||
28 | #include "psb_intel_display.h" | ||
29 | #include "mdfld_dsi_dbi.h" | ||
30 | #include "mdfld_dsi_dpi.h" | ||
31 | #include "mdfld_dsi_dbi_dpu.h" | ||
32 | |||
33 | #include <linux/pm_runtime.h> | ||
34 | |||
35 | #ifdef MIN | ||
36 | #undef MIN | ||
37 | #endif | ||
38 | |||
39 | #define MIN(x, y) (((x) < (y)) ? (x) : (y)) | ||
40 | |||
41 | /* Hardcoded currently */ | ||
42 | static int ksel = KSEL_CRYSTAL_19; | ||
43 | |||
44 | extern void mdfld_save_display(struct drm_device *dev); | ||
45 | extern bool gbgfxsuspended; | ||
46 | |||
47 | struct psb_intel_range_t { | ||
48 | int min, max; | ||
49 | }; | ||
50 | |||
51 | struct mdfld_limit_t { | ||
52 | struct psb_intel_range_t dot, m, p1; | ||
53 | }; | ||
54 | |||
55 | struct mdfld_intel_clock_t { | ||
56 | /* given values */ | ||
57 | int n; | ||
58 | int m1, m2; | ||
59 | int p1, p2; | ||
60 | /* derived values */ | ||
61 | int dot; | ||
62 | int vco; | ||
63 | int m; | ||
64 | int p; | ||
65 | }; | ||
66 | |||
67 | |||
68 | |||
69 | #define COUNT_MAX 0x10000000 | ||
70 | |||
71 | void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe) | ||
72 | { | ||
73 | int count, temp; | ||
74 | u32 pipeconf_reg = PIPEACONF; | ||
75 | |||
76 | switch (pipe) { | ||
77 | case 0: | ||
78 | break; | ||
79 | case 1: | ||
80 | pipeconf_reg = PIPEBCONF; | ||
81 | break; | ||
82 | case 2: | ||
83 | pipeconf_reg = PIPECCONF; | ||
84 | break; | ||
85 | default: | ||
86 | DRM_ERROR("Illegal Pipe Number. \n"); | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | /* FIXME JLIU7_PO */ | ||
91 | psb_intel_wait_for_vblank(dev); | ||
92 | return; | ||
93 | |||
94 | /* Wait for for the pipe disable to take effect. */ | ||
95 | for (count = 0; count < COUNT_MAX; count++) { | ||
96 | temp = REG_READ(pipeconf_reg); | ||
97 | if ((temp & PIPEACONF_PIPE_STATE) == 0) | ||
98 | break; | ||
99 | } | ||
100 | } | ||
101 | |||
102 | void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe) | ||
103 | { | ||
104 | int count, temp; | ||
105 | u32 pipeconf_reg = PIPEACONF; | ||
106 | |||
107 | switch (pipe) { | ||
108 | case 0: | ||
109 | break; | ||
110 | case 1: | ||
111 | pipeconf_reg = PIPEBCONF; | ||
112 | break; | ||
113 | case 2: | ||
114 | pipeconf_reg = PIPECCONF; | ||
115 | break; | ||
116 | default: | ||
117 | dev_err(dev->dev, "Illegal Pipe Number.\n"); | ||
118 | return; | ||
119 | } | ||
120 | |||
121 | /* FIXME JLIU7_PO */ | ||
122 | psb_intel_wait_for_vblank(dev); | ||
123 | return; | ||
124 | |||
125 | /* Wait for for the pipe enable to take effect. */ | ||
126 | for (count = 0; count < COUNT_MAX; count++) { | ||
127 | temp = REG_READ(pipeconf_reg); | ||
128 | if ((temp & PIPEACONF_PIPE_STATE) == 1) | ||
129 | break; | ||
130 | } | ||
131 | } | ||
132 | |||
133 | |||
134 | static int mdfld_intel_crtc_cursor_set(struct drm_crtc *crtc, | ||
135 | struct drm_file *file_priv, | ||
136 | uint32_t handle, | ||
137 | uint32_t width, uint32_t height) | ||
138 | { | ||
139 | struct drm_device *dev = crtc->dev; | ||
140 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
141 | int pipe = psb_intel_crtc->pipe; | ||
142 | uint32_t control = CURACNTR; | ||
143 | uint32_t base = CURABASE; | ||
144 | uint32_t temp; | ||
145 | size_t addr = 0; | ||
146 | struct gtt_range *gt; | ||
147 | struct drm_gem_object *obj; | ||
148 | int ret; | ||
149 | |||
150 | switch (pipe) { | ||
151 | case 0: | ||
152 | break; | ||
153 | case 1: | ||
154 | control = CURBCNTR; | ||
155 | base = CURBBASE; | ||
156 | break; | ||
157 | case 2: | ||
158 | control = CURCCNTR; | ||
159 | base = CURCBASE; | ||
160 | break; | ||
161 | default: | ||
162 | dev_err(dev->dev, "Illegal Pipe Number. \n"); | ||
163 | return -EINVAL; | ||
164 | } | ||
165 | |||
166 | #if 1 /* FIXME_JLIU7 can't enalbe cursorB/C HW issue. need to remove after HW fix */ | ||
167 | if (pipe != 0) | ||
168 | return 0; | ||
169 | #endif | ||
170 | /* if we want to turn of the cursor ignore width and height */ | ||
171 | if (!handle) { | ||
172 | dev_dbg(dev->dev, "cursor off\n"); | ||
173 | /* turn off the cursor */ | ||
174 | temp = 0; | ||
175 | temp |= CURSOR_MODE_DISABLE; | ||
176 | |||
177 | if (gma_power_begin(dev, true)) { | ||
178 | REG_WRITE(control, temp); | ||
179 | REG_WRITE(base, 0); | ||
180 | gma_power_end(dev); | ||
181 | } | ||
182 | /* Unpin the old GEM object */ | ||
183 | if (psb_intel_crtc->cursor_obj) { | ||
184 | gt = container_of(psb_intel_crtc->cursor_obj, | ||
185 | struct gtt_range, gem); | ||
186 | psb_gtt_unpin(gt); | ||
187 | drm_gem_object_unreference(psb_intel_crtc->cursor_obj); | ||
188 | psb_intel_crtc->cursor_obj = NULL; | ||
189 | } | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | /* Currently we only support 64x64 cursors */ | ||
194 | if (width != 64 || height != 64) { | ||
195 | DRM_ERROR("we currently only support 64x64 cursors\n"); | ||
196 | return -EINVAL; | ||
197 | } | ||
198 | |||
199 | obj = drm_gem_object_lookup(dev, file_priv, handle); | ||
200 | if (!obj) | ||
201 | return -ENOENT; | ||
202 | |||
203 | if (obj->size < width * height * 4) { | ||
204 | dev_dbg(dev->dev, "buffer is to small\n"); | ||
205 | return -ENOMEM; | ||
206 | } | ||
207 | |||
208 | gt = container_of(obj, struct gtt_range, gem); | ||
209 | |||
210 | /* Pin the memory into the GTT */ | ||
211 | ret = psb_gtt_pin(gt); | ||
212 | if (ret) { | ||
213 | dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); | ||
214 | return ret; | ||
215 | } | ||
216 | |||
217 | |||
218 | addr = gt->offset; /* Or resource.start ??? */ | ||
219 | |||
220 | psb_intel_crtc->cursor_addr = addr; | ||
221 | |||
222 | temp = 0; | ||
223 | /* set the pipe for the cursor */ | ||
224 | temp |= (pipe << 28); | ||
225 | temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; | ||
226 | |||
227 | if (gma_power_begin(dev, true)) { | ||
228 | REG_WRITE(control, temp); | ||
229 | REG_WRITE(base, addr); | ||
230 | gma_power_end(dev); | ||
231 | } | ||
232 | /* unpin the old GEM object */ | ||
233 | if (psb_intel_crtc->cursor_obj) { | ||
234 | gt = container_of(psb_intel_crtc->cursor_obj, | ||
235 | struct gtt_range, gem); | ||
236 | psb_gtt_unpin(gt); | ||
237 | drm_gem_object_unreference(psb_intel_crtc->cursor_obj); | ||
238 | psb_intel_crtc->cursor_obj = obj; | ||
239 | } | ||
240 | return 0; | ||
241 | } | ||
242 | |||
243 | static int mdfld_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | ||
244 | { | ||
245 | struct drm_device *dev = crtc->dev; | ||
246 | struct drm_psb_private * dev_priv = (struct drm_psb_private *)dev->dev_private; | ||
247 | struct mdfld_dbi_dpu_info *dpu_info = dev_priv->dbi_dpu_info; | ||
248 | struct psb_drm_dpu_rect rect; | ||
249 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
250 | int pipe = psb_intel_crtc->pipe; | ||
251 | uint32_t pos = CURAPOS; | ||
252 | uint32_t base = CURABASE; | ||
253 | uint32_t temp = 0; | ||
254 | uint32_t addr; | ||
255 | |||
256 | switch (pipe) { | ||
257 | case 0: | ||
258 | if (dpu_info) { | ||
259 | rect.x = x; | ||
260 | rect.y = y; | ||
261 | |||
262 | mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORA, &rect); | ||
263 | mdfld_dpu_exit_dsr(dev); | ||
264 | } else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_0)) | ||
265 | mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_0); | ||
266 | break; | ||
267 | case 1: | ||
268 | pos = CURBPOS; | ||
269 | base = CURBBASE; | ||
270 | break; | ||
271 | case 2: | ||
272 | if (dpu_info) { | ||
273 | mdfld_dbi_dpu_report_damage(dev, MDFLD_CURSORC, &rect); | ||
274 | mdfld_dpu_exit_dsr(dev); | ||
275 | } else if (!(dev_priv->dsr_fb_update & MDFLD_DSR_CURSOR_2)) | ||
276 | mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_CURSOR_2); | ||
277 | pos = CURCPOS; | ||
278 | base = CURCBASE; | ||
279 | break; | ||
280 | default: | ||
281 | DRM_ERROR("Illegal Pipe Number. \n"); | ||
282 | return -EINVAL; | ||
283 | } | ||
284 | |||
285 | #if 1 /* FIXME_JLIU7 can't enable cursorB/C HW issue. need to remove after HW fix */ | ||
286 | if (pipe != 0) | ||
287 | return 0; | ||
288 | #endif | ||
289 | if (x < 0) { | ||
290 | temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); | ||
291 | x = -x; | ||
292 | } | ||
293 | if (y < 0) { | ||
294 | temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); | ||
295 | y = -y; | ||
296 | } | ||
297 | |||
298 | temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); | ||
299 | temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); | ||
300 | |||
301 | addr = psb_intel_crtc->cursor_addr; | ||
302 | |||
303 | if (gma_power_begin(dev, true)) { | ||
304 | REG_WRITE(pos, temp); | ||
305 | REG_WRITE(base, addr); | ||
306 | gma_power_end(dev); | ||
307 | } | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | const struct drm_crtc_funcs mdfld_intel_crtc_funcs = { | ||
313 | .cursor_set = mdfld_intel_crtc_cursor_set, | ||
314 | .cursor_move = mdfld_intel_crtc_cursor_move, | ||
315 | .gamma_set = psb_intel_crtc_gamma_set, | ||
316 | .set_config = drm_crtc_helper_set_config, | ||
317 | .destroy = psb_intel_crtc_destroy, | ||
318 | }; | ||
319 | |||
320 | static struct drm_device globle_dev; | ||
321 | |||
322 | void mdfld__intel_plane_set_alpha(int enable) | ||
323 | { | ||
324 | struct drm_device *dev = &globle_dev; | ||
325 | int dspcntr_reg = DSPACNTR; | ||
326 | u32 dspcntr; | ||
327 | |||
328 | dspcntr = REG_READ(dspcntr_reg); | ||
329 | |||
330 | if (enable) { | ||
331 | dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA; | ||
332 | dspcntr |= DISPPLANE_32BPP; | ||
333 | } else { | ||
334 | dspcntr &= ~DISPPLANE_32BPP; | ||
335 | dspcntr |= DISPPLANE_32BPP_NO_ALPHA; | ||
336 | } | ||
337 | |||
338 | REG_WRITE(dspcntr_reg, dspcntr); | ||
339 | } | ||
340 | |||
341 | int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y, struct drm_framebuffer *old_fb) | ||
342 | { | ||
343 | struct drm_device *dev = crtc->dev; | ||
344 | /* struct drm_i915_master_private *master_priv; */ | ||
345 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
346 | struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); | ||
347 | int pipe = psb_intel_crtc->pipe; | ||
348 | unsigned long start, offset; | ||
349 | int dsplinoff = DSPALINOFF; | ||
350 | int dspsurf = DSPASURF; | ||
351 | int dspstride = DSPASTRIDE; | ||
352 | int dspcntr_reg = DSPACNTR; | ||
353 | u32 dspcntr; | ||
354 | int ret = 0; | ||
355 | |||
356 | memcpy(&globle_dev, dev, sizeof(struct drm_device)); | ||
357 | |||
358 | if (!gma_power_begin(dev, true)) | ||
359 | return 0; | ||
360 | |||
361 | /* no fb bound */ | ||
362 | if (!crtc->fb) { | ||
363 | dev_err(dev->dev, "No FB bound\n"); | ||
364 | goto psb_intel_pipe_cleaner; | ||
365 | } | ||
366 | |||
367 | switch (pipe) { | ||
368 | case 0: | ||
369 | dsplinoff = DSPALINOFF; | ||
370 | break; | ||
371 | case 1: | ||
372 | dsplinoff = DSPBLINOFF; | ||
373 | dspsurf = DSPBSURF; | ||
374 | dspstride = DSPBSTRIDE; | ||
375 | dspcntr_reg = DSPBCNTR; | ||
376 | break; | ||
377 | case 2: | ||
378 | dsplinoff = DSPCLINOFF; | ||
379 | dspsurf = DSPCSURF; | ||
380 | dspstride = DSPCSTRIDE; | ||
381 | dspcntr_reg = DSPCCNTR; | ||
382 | break; | ||
383 | default: | ||
384 | dev_err(dev->dev, "Illegal Pipe Number.\n"); | ||
385 | return -EINVAL; | ||
386 | } | ||
387 | |||
388 | ret = psb_gtt_pin(psbfb->gtt); | ||
389 | if (ret < 0) | ||
390 | goto psb_intel_pipe_set_base_exit; | ||
391 | |||
392 | start = psbfb->gtt->offset; | ||
393 | offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); | ||
394 | |||
395 | REG_WRITE(dspstride, crtc->fb->pitches[0]); | ||
396 | dspcntr = REG_READ(dspcntr_reg); | ||
397 | dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; | ||
398 | |||
399 | switch (crtc->fb->bits_per_pixel) { | ||
400 | case 8: | ||
401 | dspcntr |= DISPPLANE_8BPP; | ||
402 | break; | ||
403 | case 16: | ||
404 | if (crtc->fb->depth == 15) | ||
405 | dspcntr |= DISPPLANE_15_16BPP; | ||
406 | else | ||
407 | dspcntr |= DISPPLANE_16BPP; | ||
408 | break; | ||
409 | case 24: | ||
410 | case 32: | ||
411 | dspcntr |= DISPPLANE_32BPP_NO_ALPHA; | ||
412 | break; | ||
413 | default: | ||
414 | dev_err(dev->dev, "Unknown color depth\n"); | ||
415 | ret = -EINVAL; | ||
416 | goto psb_intel_pipe_set_base_exit; | ||
417 | } | ||
418 | REG_WRITE(dspcntr_reg, dspcntr); | ||
419 | |||
420 | dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n", | ||
421 | start, offset, x, y); | ||
422 | |||
423 | REG_WRITE(dsplinoff, offset); | ||
424 | REG_READ(dsplinoff); | ||
425 | REG_WRITE(dspsurf, start); | ||
426 | REG_READ(dspsurf); | ||
427 | |||
428 | psb_intel_pipe_cleaner: | ||
429 | /* If there was a previous display we can now unpin it */ | ||
430 | if (old_fb) | ||
431 | psb_gtt_unpin(to_psb_fb(old_fb)->gtt); | ||
432 | |||
433 | psb_intel_pipe_set_base_exit: | ||
434 | gma_power_end(dev); | ||
435 | return ret; | ||
436 | } | ||
437 | |||
438 | /** | ||
439 | * Disable the pipe, plane and pll. | ||
440 | * | ||
441 | */ | ||
442 | void mdfld_disable_crtc (struct drm_device *dev, int pipe) | ||
443 | { | ||
444 | int dpll_reg = MRST_DPLL_A; | ||
445 | int dspcntr_reg = DSPACNTR; | ||
446 | int dspbase_reg = MRST_DSPABASE; | ||
447 | int pipeconf_reg = PIPEACONF; | ||
448 | u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG; | ||
449 | u32 temp; | ||
450 | |||
451 | switch (pipe) { | ||
452 | case 0: | ||
453 | break; | ||
454 | case 1: | ||
455 | dpll_reg = MDFLD_DPLL_B; | ||
456 | dspcntr_reg = DSPBCNTR; | ||
457 | dspbase_reg = DSPBSURF; | ||
458 | pipeconf_reg = PIPEBCONF; | ||
459 | break; | ||
460 | case 2: | ||
461 | dpll_reg = MRST_DPLL_A; | ||
462 | dspcntr_reg = DSPCCNTR; | ||
463 | dspbase_reg = MDFLD_DSPCBASE; | ||
464 | pipeconf_reg = PIPECCONF; | ||
465 | gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET; | ||
466 | break; | ||
467 | default: | ||
468 | dev_err(dev->dev, "Illegal Pipe Number. \n"); | ||
469 | return; | ||
470 | } | ||
471 | |||
472 | if (pipe != 1) | ||
473 | mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); | ||
474 | |||
475 | /* Disable display plane */ | ||
476 | temp = REG_READ(dspcntr_reg); | ||
477 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | ||
478 | REG_WRITE(dspcntr_reg, | ||
479 | temp & ~DISPLAY_PLANE_ENABLE); | ||
480 | /* Flush the plane changes */ | ||
481 | REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); | ||
482 | REG_READ(dspbase_reg); | ||
483 | } | ||
484 | |||
485 | /* FIXME_JLIU7 MDFLD_PO revisit */ | ||
486 | /* Wait for vblank for the disable to take effect */ | ||
487 | /* MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev); */ | ||
488 | |||
489 | /* Next, disable display pipes */ | ||
490 | temp = REG_READ(pipeconf_reg); | ||
491 | if ((temp & PIPEACONF_ENABLE) != 0) { | ||
492 | temp &= ~PIPEACONF_ENABLE; | ||
493 | temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF; | ||
494 | REG_WRITE(pipeconf_reg, temp); | ||
495 | REG_READ(pipeconf_reg); | ||
496 | |||
497 | /* Wait for for the pipe disable to take effect. */ | ||
498 | mdfldWaitForPipeDisable(dev, pipe); | ||
499 | } | ||
500 | |||
501 | temp = REG_READ(dpll_reg); | ||
502 | if (temp & DPLL_VCO_ENABLE) { | ||
503 | if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE)) | ||
504 | || (pipe == 1)){ | ||
505 | temp &= ~(DPLL_VCO_ENABLE); | ||
506 | REG_WRITE(dpll_reg, temp); | ||
507 | REG_READ(dpll_reg); | ||
508 | /* Wait for the clocks to turn off. */ | ||
509 | /* FIXME_MDFLD PO may need more delay */ | ||
510 | udelay(500); | ||
511 | |||
512 | if (!(temp & MDFLD_PWR_GATE_EN)) { | ||
513 | /* gating power of DPLL */ | ||
514 | REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN); | ||
515 | /* FIXME_MDFLD PO - change 500 to 1 after PO */ | ||
516 | udelay(5000); | ||
517 | } | ||
518 | } | ||
519 | } | ||
520 | |||
521 | } | ||
522 | |||
523 | /** | ||
524 | * Sets the power management mode of the pipe and plane. | ||
525 | * | ||
526 | * This code should probably grow support for turning the cursor off and back | ||
527 | * on appropriately at the same time as we're turning the pipe off/on. | ||
528 | */ | ||
529 | static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
530 | { | ||
531 | struct drm_device *dev = crtc->dev; | ||
532 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
533 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
534 | int pipe = psb_intel_crtc->pipe; | ||
535 | int dpll_reg = MRST_DPLL_A; | ||
536 | int dspcntr_reg = DSPACNTR; | ||
537 | int dspbase_reg = MRST_DSPABASE; | ||
538 | int pipeconf_reg = PIPEACONF; | ||
539 | u32 pipestat_reg = PIPEASTAT; | ||
540 | u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG; | ||
541 | u32 pipeconf = dev_priv->pipeconf; | ||
542 | u32 dspcntr = dev_priv->dspcntr; | ||
543 | u32 mipi_enable_reg = MIPIA_DEVICE_READY_REG; | ||
544 | u32 temp; | ||
545 | bool enabled; | ||
546 | int timeout = 0; | ||
547 | |||
548 | if (!gma_power_begin(dev, true)) | ||
549 | return; | ||
550 | |||
551 | /* Ignore if system is already in DSR and in suspended state. */ | ||
552 | if(/*gbgfxsuspended */0 && dev_priv->dispstatus == false && mode == 3){ | ||
553 | if(dev_priv->rpm_enabled && pipe == 1){ | ||
554 | // dev_priv->is_mipi_on = false; | ||
555 | pm_request_idle(&dev->pdev->dev); | ||
556 | } | ||
557 | return; | ||
558 | }else if(mode == 0) { | ||
559 | //do not need to set gbdispstatus=true in crtc. | ||
560 | //this will be set in encoder such as mdfld_dsi_dbi_dpms | ||
561 | //gbdispstatus = true; | ||
562 | } | ||
563 | |||
564 | /* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */ | ||
565 | /* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */ | ||
566 | |||
567 | switch (pipe) { | ||
568 | case 0: | ||
569 | break; | ||
570 | case 1: | ||
571 | dpll_reg = DPLL_B; | ||
572 | dspcntr_reg = DSPBCNTR; | ||
573 | dspbase_reg = MRST_DSPBBASE; | ||
574 | pipeconf_reg = PIPEBCONF; | ||
575 | pipeconf = dev_priv->pipeconf1; | ||
576 | dspcntr = dev_priv->dspcntr1; | ||
577 | dpll_reg = MDFLD_DPLL_B; | ||
578 | break; | ||
579 | case 2: | ||
580 | dpll_reg = MRST_DPLL_A; | ||
581 | dspcntr_reg = DSPCCNTR; | ||
582 | dspbase_reg = MDFLD_DSPCBASE; | ||
583 | pipeconf_reg = PIPECCONF; | ||
584 | pipestat_reg = PIPECSTAT; | ||
585 | pipeconf = dev_priv->pipeconf2; | ||
586 | dspcntr = dev_priv->dspcntr2; | ||
587 | gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET; | ||
588 | mipi_enable_reg = MIPIA_DEVICE_READY_REG + MIPIC_REG_OFFSET; | ||
589 | break; | ||
590 | default: | ||
591 | dev_err(dev->dev, "Illegal Pipe Number.\n"); | ||
592 | return; | ||
593 | } | ||
594 | |||
595 | /* XXX: When our outputs are all unaware of DPMS modes other than off | ||
596 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | ||
597 | */ | ||
598 | switch (mode) { | ||
599 | case DRM_MODE_DPMS_ON: | ||
600 | case DRM_MODE_DPMS_STANDBY: | ||
601 | case DRM_MODE_DPMS_SUSPEND: | ||
602 | /* Enable the DPLL */ | ||
603 | temp = REG_READ(dpll_reg); | ||
604 | |||
605 | if ((temp & DPLL_VCO_ENABLE) == 0) { | ||
606 | /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */ | ||
607 | if (temp & MDFLD_PWR_GATE_EN) { | ||
608 | temp &= ~MDFLD_PWR_GATE_EN; | ||
609 | REG_WRITE(dpll_reg, temp); | ||
610 | /* FIXME_MDFLD PO - change 500 to 1 after PO */ | ||
611 | udelay(500); | ||
612 | } | ||
613 | |||
614 | REG_WRITE(dpll_reg, temp); | ||
615 | REG_READ(dpll_reg); | ||
616 | /* FIXME_MDFLD PO - change 500 to 1 after PO */ | ||
617 | udelay(500); | ||
618 | |||
619 | REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | ||
620 | REG_READ(dpll_reg); | ||
621 | |||
622 | /** | ||
623 | * wait for DSI PLL to lock | ||
624 | * NOTE: only need to poll status of pipe 0 and pipe 1, | ||
625 | * since both MIPI pipes share the same PLL. | ||
626 | */ | ||
627 | while ((pipe != 2) && (timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { | ||
628 | udelay(150); | ||
629 | timeout ++; | ||
630 | } | ||
631 | } | ||
632 | |||
633 | /* Enable the plane */ | ||
634 | temp = REG_READ(dspcntr_reg); | ||
635 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
636 | REG_WRITE(dspcntr_reg, | ||
637 | temp | DISPLAY_PLANE_ENABLE); | ||
638 | /* Flush the plane changes */ | ||
639 | REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); | ||
640 | } | ||
641 | |||
642 | /* Enable the pipe */ | ||
643 | temp = REG_READ(pipeconf_reg); | ||
644 | if ((temp & PIPEACONF_ENABLE) == 0) { | ||
645 | REG_WRITE(pipeconf_reg, pipeconf); | ||
646 | |||
647 | /* Wait for for the pipe enable to take effect. */ | ||
648 | mdfldWaitForPipeEnable(dev, pipe); | ||
649 | } | ||
650 | |||
651 | /*workaround for sighting 3741701 Random X blank display*/ | ||
652 | /*perform w/a in video mode only on pipe A or C*/ | ||
653 | if ((pipe == 0 || pipe == 2) && | ||
654 | (mdfld_panel_dpi(dev) == true)) { | ||
655 | REG_WRITE(pipestat_reg, REG_READ(pipestat_reg)); | ||
656 | msleep(100); | ||
657 | if(PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) { | ||
658 | printk(KERN_ALERT "OK"); | ||
659 | } else { | ||
660 | printk(KERN_ALERT "STUCK!!!!"); | ||
661 | /*shutdown controller*/ | ||
662 | temp = REG_READ(dspcntr_reg); | ||
663 | REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE); | ||
664 | REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); | ||
665 | /*mdfld_dsi_dpi_shut_down(dev, pipe);*/ | ||
666 | REG_WRITE(0xb048, 1); | ||
667 | msleep(100); | ||
668 | temp = REG_READ(pipeconf_reg); | ||
669 | temp &= ~PIPEACONF_ENABLE; | ||
670 | REG_WRITE(pipeconf_reg, temp); | ||
671 | msleep(100); /*wait for pipe disable*/ | ||
672 | /*printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008)); | ||
673 | printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));*/ | ||
674 | REG_WRITE(mipi_enable_reg, 0); | ||
675 | msleep(100); | ||
676 | printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008)); | ||
677 | printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074)); | ||
678 | REG_WRITE(0xb004, REG_READ(0xb004)); | ||
679 | /* try to bring the controller back up again*/ | ||
680 | REG_WRITE(mipi_enable_reg, 1); | ||
681 | temp = REG_READ(dspcntr_reg); | ||
682 | REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE); | ||
683 | REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); | ||
684 | /*mdfld_dsi_dpi_turn_on(dev, pipe);*/ | ||
685 | REG_WRITE(0xb048, 2); | ||
686 | msleep(100); | ||
687 | temp = REG_READ(pipeconf_reg); | ||
688 | temp |= PIPEACONF_ENABLE; | ||
689 | REG_WRITE(pipeconf_reg, temp); | ||
690 | } | ||
691 | } | ||
692 | |||
693 | psb_intel_crtc_load_lut(crtc); | ||
694 | |||
695 | /* Give the overlay scaler a chance to enable | ||
696 | if it's on this pipe */ | ||
697 | /* psb_intel_crtc_dpms_video(crtc, true); TODO */ | ||
698 | |||
699 | break; | ||
700 | case DRM_MODE_DPMS_OFF: | ||
701 | /* Give the overlay scaler a chance to disable | ||
702 | * if it's on this pipe */ | ||
703 | /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ | ||
704 | if (pipe != 1) | ||
705 | mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); | ||
706 | |||
707 | /* Disable the VGA plane that we never use */ | ||
708 | REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); | ||
709 | |||
710 | /* Disable display plane */ | ||
711 | temp = REG_READ(dspcntr_reg); | ||
712 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | ||
713 | REG_WRITE(dspcntr_reg, | ||
714 | temp & ~DISPLAY_PLANE_ENABLE); | ||
715 | /* Flush the plane changes */ | ||
716 | REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); | ||
717 | REG_READ(dspbase_reg); | ||
718 | } | ||
719 | |||
720 | /* FIXME_JLIU7 MDFLD_PO revisit */ | ||
721 | /* Wait for vblank for the disable to take effect */ | ||
722 | // MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev); | ||
723 | |||
724 | /* Next, disable display pipes */ | ||
725 | temp = REG_READ(pipeconf_reg); | ||
726 | if ((temp & PIPEACONF_ENABLE) != 0) { | ||
727 | temp &= ~PIPEACONF_ENABLE; | ||
728 | temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF; | ||
729 | REG_WRITE(pipeconf_reg, temp); | ||
730 | // REG_WRITE(pipeconf_reg, 0); | ||
731 | REG_READ(pipeconf_reg); | ||
732 | |||
733 | /* Wait for for the pipe disable to take effect. */ | ||
734 | mdfldWaitForPipeDisable(dev, pipe); | ||
735 | } | ||
736 | |||
737 | temp = REG_READ(dpll_reg); | ||
738 | if (temp & DPLL_VCO_ENABLE) { | ||
739 | if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE)) | ||
740 | || (pipe == 1)){ | ||
741 | temp &= ~(DPLL_VCO_ENABLE); | ||
742 | REG_WRITE(dpll_reg, temp); | ||
743 | REG_READ(dpll_reg); | ||
744 | /* Wait for the clocks to turn off. */ | ||
745 | /* FIXME_MDFLD PO may need more delay */ | ||
746 | udelay(500); | ||
747 | #if 0 /* MDFLD_PO_JLIU7 */ | ||
748 | if (!(temp & MDFLD_PWR_GATE_EN)) { | ||
749 | /* gating power of DPLL */ | ||
750 | REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN); | ||
751 | /* FIXME_MDFLD PO - change 500 to 1 after PO */ | ||
752 | udelay(5000); | ||
753 | } | ||
754 | #endif /* MDFLD_PO_JLIU7 */ | ||
755 | } | ||
756 | } | ||
757 | break; | ||
758 | } | ||
759 | |||
760 | enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; | ||
761 | |||
762 | #if 0 /* JB: Add vblank support later */ | ||
763 | if (enabled) | ||
764 | dev_priv->vblank_pipe |= (1 << pipe); | ||
765 | else | ||
766 | dev_priv->vblank_pipe &= ~(1 << pipe); | ||
767 | #endif | ||
768 | |||
769 | gma_power_end(dev); | ||
770 | } | ||
771 | |||
772 | |||
773 | #define MDFLD_LIMT_DPLL_19 0 | ||
774 | #define MDFLD_LIMT_DPLL_25 1 | ||
775 | #define MDFLD_LIMT_DPLL_83 2 | ||
776 | #define MDFLD_LIMT_DPLL_100 3 | ||
777 | #define MDFLD_LIMT_DSIPLL_19 4 | ||
778 | #define MDFLD_LIMT_DSIPLL_25 5 | ||
779 | #define MDFLD_LIMT_DSIPLL_83 6 | ||
780 | #define MDFLD_LIMT_DSIPLL_100 7 | ||
781 | |||
782 | #define MDFLD_DOT_MIN 19750 /* FIXME_MDFLD JLIU7 need to find out min & max for MDFLD */ | ||
783 | #define MDFLD_DOT_MAX 120000 | ||
784 | #define MDFLD_DPLL_M_MIN_19 113 | ||
785 | #define MDFLD_DPLL_M_MAX_19 155 | ||
786 | #define MDFLD_DPLL_P1_MIN_19 2 | ||
787 | #define MDFLD_DPLL_P1_MAX_19 10 | ||
788 | #define MDFLD_DPLL_M_MIN_25 101 | ||
789 | #define MDFLD_DPLL_M_MAX_25 130 | ||
790 | #define MDFLD_DPLL_P1_MIN_25 2 | ||
791 | #define MDFLD_DPLL_P1_MAX_25 10 | ||
792 | #define MDFLD_DPLL_M_MIN_83 64 | ||
793 | #define MDFLD_DPLL_M_MAX_83 64 | ||
794 | #define MDFLD_DPLL_P1_MIN_83 2 | ||
795 | #define MDFLD_DPLL_P1_MAX_83 2 | ||
796 | #define MDFLD_DPLL_M_MIN_100 64 | ||
797 | #define MDFLD_DPLL_M_MAX_100 64 | ||
798 | #define MDFLD_DPLL_P1_MIN_100 2 | ||
799 | #define MDFLD_DPLL_P1_MAX_100 2 | ||
800 | #define MDFLD_DSIPLL_M_MIN_19 131 | ||
801 | #define MDFLD_DSIPLL_M_MAX_19 175 | ||
802 | #define MDFLD_DSIPLL_P1_MIN_19 3 | ||
803 | #define MDFLD_DSIPLL_P1_MAX_19 8 | ||
804 | #define MDFLD_DSIPLL_M_MIN_25 97 | ||
805 | #define MDFLD_DSIPLL_M_MAX_25 140 | ||
806 | #define MDFLD_DSIPLL_P1_MIN_25 3 | ||
807 | #define MDFLD_DSIPLL_P1_MAX_25 9 | ||
808 | #define MDFLD_DSIPLL_M_MIN_83 33 | ||
809 | #define MDFLD_DSIPLL_M_MAX_83 92 | ||
810 | #define MDFLD_DSIPLL_P1_MIN_83 2 | ||
811 | #define MDFLD_DSIPLL_P1_MAX_83 3 | ||
812 | #define MDFLD_DSIPLL_M_MIN_100 97 | ||
813 | #define MDFLD_DSIPLL_M_MAX_100 140 | ||
814 | #define MDFLD_DSIPLL_P1_MIN_100 3 | ||
815 | #define MDFLD_DSIPLL_P1_MAX_100 9 | ||
816 | |||
817 | static const struct mdfld_limit_t mdfld_limits[] = { | ||
818 | { /* MDFLD_LIMT_DPLL_19 */ | ||
819 | .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, | ||
820 | .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19}, | ||
821 | .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19}, | ||
822 | }, | ||
823 | { /* MDFLD_LIMT_DPLL_25 */ | ||
824 | .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, | ||
825 | .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25}, | ||
826 | .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25}, | ||
827 | }, | ||
828 | { /* MDFLD_LIMT_DPLL_83 */ | ||
829 | .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, | ||
830 | .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83}, | ||
831 | .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83}, | ||
832 | }, | ||
833 | { /* MDFLD_LIMT_DPLL_100 */ | ||
834 | .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, | ||
835 | .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100}, | ||
836 | .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100}, | ||
837 | }, | ||
838 | { /* MDFLD_LIMT_DSIPLL_19 */ | ||
839 | .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, | ||
840 | .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19}, | ||
841 | .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19}, | ||
842 | }, | ||
843 | { /* MDFLD_LIMT_DSIPLL_25 */ | ||
844 | .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, | ||
845 | .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25}, | ||
846 | .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25}, | ||
847 | }, | ||
848 | { /* MDFLD_LIMT_DSIPLL_83 */ | ||
849 | .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, | ||
850 | .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83}, | ||
851 | .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83}, | ||
852 | }, | ||
853 | { /* MDFLD_LIMT_DSIPLL_100 */ | ||
854 | .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX}, | ||
855 | .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100}, | ||
856 | .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100}, | ||
857 | }, | ||
858 | }; | ||
859 | |||
860 | #define MDFLD_M_MIN 21 | ||
861 | #define MDFLD_M_MAX 180 | ||
862 | static const u32 mdfld_m_converts[] = { | ||
863 | /* M configuration table from 9-bit LFSR table */ | ||
864 | 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */ | ||
865 | 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */ | ||
866 | 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */ | ||
867 | 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */ | ||
868 | 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */ | ||
869 | 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */ | ||
870 | 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */ | ||
871 | 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */ | ||
872 | 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */ | ||
873 | 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */ | ||
874 | 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */ | ||
875 | 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */ | ||
876 | 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */ | ||
877 | 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */ | ||
878 | 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */ | ||
879 | 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */ | ||
880 | }; | ||
881 | |||
882 | static const struct mdfld_limit_t *mdfld_limit(struct drm_crtc *crtc) | ||
883 | { | ||
884 | const struct mdfld_limit_t *limit = NULL; | ||
885 | struct drm_device *dev = crtc->dev; | ||
886 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
887 | |||
888 | if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI) | ||
889 | || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) { | ||
890 | if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) | ||
891 | limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19]; | ||
892 | else if (ksel == KSEL_BYPASS_25) | ||
893 | limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25]; | ||
894 | else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) | ||
895 | limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83]; | ||
896 | else if ((ksel == KSEL_BYPASS_83_100) && | ||
897 | (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) | ||
898 | limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100]; | ||
899 | } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) { | ||
900 | if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) | ||
901 | limit = &mdfld_limits[MDFLD_LIMT_DPLL_19]; | ||
902 | else if (ksel == KSEL_BYPASS_25) | ||
903 | limit = &mdfld_limits[MDFLD_LIMT_DPLL_25]; | ||
904 | else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) | ||
905 | limit = &mdfld_limits[MDFLD_LIMT_DPLL_83]; | ||
906 | else if ((ksel == KSEL_BYPASS_83_100) && | ||
907 | (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) | ||
908 | limit = &mdfld_limits[MDFLD_LIMT_DPLL_100]; | ||
909 | } else { | ||
910 | limit = NULL; | ||
911 | dev_err(dev->dev, "mdfld_limit Wrong display type.\n"); | ||
912 | } | ||
913 | |||
914 | return limit; | ||
915 | } | ||
916 | |||
917 | /** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ | ||
918 | static void mdfld_clock(int refclk, struct mdfld_intel_clock_t *clock) | ||
919 | { | ||
920 | clock->dot = (refclk * clock->m) / clock->p1; | ||
921 | } | ||
922 | |||
923 | /** | ||
924 | * Returns a set of divisors for the desired target clock with the given refclk, | ||
925 | * or FALSE. Divisor values are the actual divisors for | ||
926 | */ | ||
927 | static bool | ||
928 | mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk, | ||
929 | struct mdfld_intel_clock_t *best_clock) | ||
930 | { | ||
931 | struct mdfld_intel_clock_t clock; | ||
932 | const struct mdfld_limit_t *limit = mdfld_limit(crtc); | ||
933 | int err = target; | ||
934 | |||
935 | memset(best_clock, 0, sizeof(*best_clock)); | ||
936 | |||
937 | for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { | ||
938 | for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; | ||
939 | clock.p1++) { | ||
940 | int this_err; | ||
941 | |||
942 | mdfld_clock(refclk, &clock); | ||
943 | |||
944 | this_err = abs(clock.dot - target); | ||
945 | if (this_err < err) { | ||
946 | *best_clock = clock; | ||
947 | err = this_err; | ||
948 | } | ||
949 | } | ||
950 | } | ||
951 | return err != target; | ||
952 | } | ||
953 | |||
954 | /** | ||
955 | * Return the pipe currently connected to the panel fitter, | ||
956 | * or -1 if the panel fitter is not present or not in use | ||
957 | */ | ||
958 | static int mdfld_panel_fitter_pipe(struct drm_device *dev) | ||
959 | { | ||
960 | u32 pfit_control; | ||
961 | |||
962 | pfit_control = REG_READ(PFIT_CONTROL); | ||
963 | |||
964 | /* See if the panel fitter is in use */ | ||
965 | if ((pfit_control & PFIT_ENABLE) == 0) | ||
966 | return -1; | ||
967 | return (pfit_control >> 29) & 3; | ||
968 | } | ||
969 | |||
970 | static int mdfld_crtc_mode_set(struct drm_crtc *crtc, | ||
971 | struct drm_display_mode *mode, | ||
972 | struct drm_display_mode *adjusted_mode, | ||
973 | int x, int y, | ||
974 | struct drm_framebuffer *old_fb) | ||
975 | { | ||
976 | struct drm_device *dev = crtc->dev; | ||
977 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
978 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
979 | int pipe = psb_intel_crtc->pipe; | ||
980 | int fp_reg = MRST_FPA0; | ||
981 | int dpll_reg = MRST_DPLL_A; | ||
982 | int dspcntr_reg = DSPACNTR; | ||
983 | int pipeconf_reg = PIPEACONF; | ||
984 | int htot_reg = HTOTAL_A; | ||
985 | int hblank_reg = HBLANK_A; | ||
986 | int hsync_reg = HSYNC_A; | ||
987 | int vtot_reg = VTOTAL_A; | ||
988 | int vblank_reg = VBLANK_A; | ||
989 | int vsync_reg = VSYNC_A; | ||
990 | int dspsize_reg = DSPASIZE; | ||
991 | int dsppos_reg = DSPAPOS; | ||
992 | int pipesrc_reg = PIPEASRC; | ||
993 | u32 *pipeconf = &dev_priv->pipeconf; | ||
994 | u32 *dspcntr = &dev_priv->dspcntr; | ||
995 | int refclk = 0; | ||
996 | int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, clk_tmp = 0; | ||
997 | struct mdfld_intel_clock_t clock; | ||
998 | bool ok; | ||
999 | u32 dpll = 0, fp = 0; | ||
1000 | bool is_crt = false, is_lvds = false, is_tv = false; | ||
1001 | bool is_mipi = false, is_mipi2 = false, is_hdmi = false; | ||
1002 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
1003 | struct psb_intel_output *psb_intel_output = NULL; | ||
1004 | uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; | ||
1005 | struct drm_encoder *encoder; | ||
1006 | struct drm_connector *connector; | ||
1007 | int timeout = 0; | ||
1008 | |||
1009 | dev_dbg(dev->dev, "pipe = 0x%x \n", pipe); | ||
1010 | |||
1011 | switch (pipe) { | ||
1012 | case 0: | ||
1013 | break; | ||
1014 | case 1: | ||
1015 | fp_reg = FPB0; | ||
1016 | dpll_reg = DPLL_B; | ||
1017 | dspcntr_reg = DSPBCNTR; | ||
1018 | pipeconf_reg = PIPEBCONF; | ||
1019 | htot_reg = HTOTAL_B; | ||
1020 | hblank_reg = HBLANK_B; | ||
1021 | hsync_reg = HSYNC_B; | ||
1022 | vtot_reg = VTOTAL_B; | ||
1023 | vblank_reg = VBLANK_B; | ||
1024 | vsync_reg = VSYNC_B; | ||
1025 | dspsize_reg = DSPBSIZE; | ||
1026 | dsppos_reg = DSPBPOS; | ||
1027 | pipesrc_reg = PIPEBSRC; | ||
1028 | pipeconf = &dev_priv->pipeconf1; | ||
1029 | dspcntr = &dev_priv->dspcntr1; | ||
1030 | fp_reg = MDFLD_DPLL_DIV0; | ||
1031 | dpll_reg = MDFLD_DPLL_B; | ||
1032 | break; | ||
1033 | case 2: | ||
1034 | dpll_reg = MRST_DPLL_A; | ||
1035 | dspcntr_reg = DSPCCNTR; | ||
1036 | pipeconf_reg = PIPECCONF; | ||
1037 | htot_reg = HTOTAL_C; | ||
1038 | hblank_reg = HBLANK_C; | ||
1039 | hsync_reg = HSYNC_C; | ||
1040 | vtot_reg = VTOTAL_C; | ||
1041 | vblank_reg = VBLANK_C; | ||
1042 | vsync_reg = VSYNC_C; | ||
1043 | dspsize_reg = DSPCSIZE; | ||
1044 | dsppos_reg = DSPCPOS; | ||
1045 | pipesrc_reg = PIPECSRC; | ||
1046 | pipeconf = &dev_priv->pipeconf2; | ||
1047 | dspcntr = &dev_priv->dspcntr2; | ||
1048 | break; | ||
1049 | default: | ||
1050 | DRM_ERROR("Illegal Pipe Number. \n"); | ||
1051 | return 0; | ||
1052 | } | ||
1053 | |||
1054 | dev_dbg(dev->dev, "adjusted_hdisplay = %d\n", | ||
1055 | adjusted_mode->hdisplay); | ||
1056 | dev_dbg(dev->dev, "adjusted_vdisplay = %d\n", | ||
1057 | adjusted_mode->vdisplay); | ||
1058 | dev_dbg(dev->dev, "adjusted_hsync_start = %d\n", | ||
1059 | adjusted_mode->hsync_start); | ||
1060 | dev_dbg(dev->dev, "adjusted_hsync_end = %d\n", | ||
1061 | adjusted_mode->hsync_end); | ||
1062 | dev_dbg(dev->dev, "adjusted_htotal = %d\n", | ||
1063 | adjusted_mode->htotal); | ||
1064 | dev_dbg(dev->dev, "adjusted_vsync_start = %d\n", | ||
1065 | adjusted_mode->vsync_start); | ||
1066 | dev_dbg(dev->dev, "adjusted_vsync_end = %d\n", | ||
1067 | adjusted_mode->vsync_end); | ||
1068 | dev_dbg(dev->dev, "adjusted_vtotal = %d\n", | ||
1069 | adjusted_mode->vtotal); | ||
1070 | dev_dbg(dev->dev, "adjusted_clock = %d\n", | ||
1071 | adjusted_mode->clock); | ||
1072 | dev_dbg(dev->dev, "hdisplay = %d\n", | ||
1073 | mode->hdisplay); | ||
1074 | dev_dbg(dev->dev, "vdisplay = %d\n", | ||
1075 | mode->vdisplay); | ||
1076 | |||
1077 | if (!gma_power_begin(dev, true)) | ||
1078 | return 0; | ||
1079 | |||
1080 | memcpy(&psb_intel_crtc->saved_mode, mode, sizeof(struct drm_display_mode)); | ||
1081 | memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, sizeof(struct drm_display_mode)); | ||
1082 | |||
1083 | list_for_each_entry(connector, &mode_config->connector_list, head) { | ||
1084 | |||
1085 | encoder = connector->encoder; | ||
1086 | |||
1087 | if(!encoder) | ||
1088 | continue; | ||
1089 | |||
1090 | if (encoder->crtc != crtc) | ||
1091 | continue; | ||
1092 | |||
1093 | psb_intel_output = to_psb_intel_output(connector); | ||
1094 | |||
1095 | dev_dbg(dev->dev, "output->type = 0x%x \n", psb_intel_output->type); | ||
1096 | |||
1097 | switch (psb_intel_output->type) { | ||
1098 | case INTEL_OUTPUT_LVDS: | ||
1099 | is_lvds = true; | ||
1100 | break; | ||
1101 | case INTEL_OUTPUT_TVOUT: | ||
1102 | is_tv = true; | ||
1103 | break; | ||
1104 | case INTEL_OUTPUT_ANALOG: | ||
1105 | is_crt = true; | ||
1106 | break; | ||
1107 | case INTEL_OUTPUT_MIPI: | ||
1108 | is_mipi = true; | ||
1109 | break; | ||
1110 | case INTEL_OUTPUT_MIPI2: | ||
1111 | is_mipi2 = true; | ||
1112 | break; | ||
1113 | case INTEL_OUTPUT_HDMI: | ||
1114 | is_hdmi = true; | ||
1115 | break; | ||
1116 | } | ||
1117 | } | ||
1118 | |||
1119 | /* Disable the VGA plane that we never use */ | ||
1120 | REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); | ||
1121 | |||
1122 | /* Disable the panel fitter if it was on our pipe */ | ||
1123 | if (mdfld_panel_fitter_pipe(dev) == pipe) | ||
1124 | REG_WRITE(PFIT_CONTROL, 0); | ||
1125 | |||
1126 | /* pipesrc and dspsize control the size that is scaled from, | ||
1127 | * which should always be the user's requested size. | ||
1128 | */ | ||
1129 | if (pipe == 1) { | ||
1130 | /* FIXME: To make HDMI display with 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD), set the sprite | ||
1131 | * width/height and souce image size registers with the adjusted mode for pipe B. */ | ||
1132 | |||
1133 | /* The defined sprite rectangle must always be completely contained within the displayable | ||
1134 | * area of the screen image (frame buffer). */ | ||
1135 | REG_WRITE(dspsize_reg, ((MIN(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16) | ||
1136 | | (MIN(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1)); | ||
1137 | /* Set the CRTC with encoder mode. */ | ||
1138 | REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | ||
1139 | | (mode->crtc_vdisplay - 1)); | ||
1140 | } else { | ||
1141 | REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1)); | ||
1142 | REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1)); | ||
1143 | } | ||
1144 | |||
1145 | REG_WRITE(dsppos_reg, 0); | ||
1146 | |||
1147 | if (psb_intel_output) | ||
1148 | drm_connector_property_get_value(&psb_intel_output->base, | ||
1149 | dev->mode_config.scaling_mode_property, &scalingType); | ||
1150 | |||
1151 | if (scalingType == DRM_MODE_SCALE_NO_SCALE) { | ||
1152 | /* | ||
1153 | * Medfield doesn't have register support for centering so | ||
1154 | * we need to mess with the h/vblank and h/vsync start and | ||
1155 | * ends to get central | ||
1156 | */ | ||
1157 | int offsetX = 0, offsetY = 0; | ||
1158 | |||
1159 | offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2; | ||
1160 | offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2; | ||
1161 | |||
1162 | REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | | ||
1163 | ((adjusted_mode->crtc_htotal - 1) << 16)); | ||
1164 | REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | | ||
1165 | ((adjusted_mode->crtc_vtotal - 1) << 16)); | ||
1166 | REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - offsetX - 1) | | ||
1167 | ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); | ||
1168 | REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - offsetX - 1) | | ||
1169 | ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); | ||
1170 | REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - offsetY - 1) | | ||
1171 | ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); | ||
1172 | REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - offsetY - 1) | | ||
1173 | ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); | ||
1174 | } else { | ||
1175 | REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | | ||
1176 | ((adjusted_mode->crtc_htotal - 1) << 16)); | ||
1177 | REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | | ||
1178 | ((adjusted_mode->crtc_vtotal - 1) << 16)); | ||
1179 | REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | | ||
1180 | ((adjusted_mode->crtc_hblank_end - 1) << 16)); | ||
1181 | REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | | ||
1182 | ((adjusted_mode->crtc_hsync_end - 1) << 16)); | ||
1183 | REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | | ||
1184 | ((adjusted_mode->crtc_vblank_end - 1) << 16)); | ||
1185 | REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | | ||
1186 | ((adjusted_mode->crtc_vsync_end - 1) << 16)); | ||
1187 | } | ||
1188 | |||
1189 | /* Flush the plane changes */ | ||
1190 | { | ||
1191 | struct drm_crtc_helper_funcs *crtc_funcs = | ||
1192 | crtc->helper_private; | ||
1193 | crtc_funcs->mode_set_base(crtc, x, y, old_fb); | ||
1194 | } | ||
1195 | |||
1196 | /* setup pipeconf */ | ||
1197 | *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */ | ||
1198 | |||
1199 | /* Set up the display plane register */ | ||
1200 | *dspcntr = REG_READ(dspcntr_reg); | ||
1201 | *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS; | ||
1202 | *dspcntr |= DISPLAY_PLANE_ENABLE; | ||
1203 | /* MDFLD_PO_JLIU7 dspcntr |= DISPPLANE_BOTTOM; */ | ||
1204 | /* MDFLD_PO_JLIU7 dspcntr |= DISPPLANE_GAMMA_ENABLE; */ | ||
1205 | |||
1206 | if (is_mipi2) | ||
1207 | { | ||
1208 | goto mrst_crtc_mode_set_exit; | ||
1209 | } | ||
1210 | /* FIXME JLIU7 Add MDFLD HDMI supports */ | ||
1211 | /* FIXME_MDFLD JLIU7 DSIPLL clock *= 8? */ | ||
1212 | /* FIXME_MDFLD JLIU7 need to revist for dual MIPI supports */ | ||
1213 | clk = adjusted_mode->clock; | ||
1214 | |||
1215 | if (is_hdmi) { | ||
1216 | if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) | ||
1217 | { | ||
1218 | refclk = 19200; | ||
1219 | |||
1220 | if (is_mipi || is_mipi2) | ||
1221 | { | ||
1222 | clk_n = 1, clk_p2 = 8; | ||
1223 | } else if (is_hdmi) { | ||
1224 | clk_n = 1, clk_p2 = 10; | ||
1225 | } | ||
1226 | } else if (ksel == KSEL_BYPASS_25) { | ||
1227 | refclk = 25000; | ||
1228 | |||
1229 | if (is_mipi || is_mipi2) | ||
1230 | { | ||
1231 | clk_n = 1, clk_p2 = 8; | ||
1232 | } else if (is_hdmi) { | ||
1233 | clk_n = 1, clk_p2 = 10; | ||
1234 | } | ||
1235 | } else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) { | ||
1236 | refclk = 83000; | ||
1237 | |||
1238 | if (is_mipi || is_mipi2) | ||
1239 | { | ||
1240 | clk_n = 4, clk_p2 = 8; | ||
1241 | } else if (is_hdmi) { | ||
1242 | clk_n = 4, clk_p2 = 10; | ||
1243 | } | ||
1244 | } else if ((ksel == KSEL_BYPASS_83_100) && | ||
1245 | (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) { | ||
1246 | refclk = 100000; | ||
1247 | if (is_mipi || is_mipi2) | ||
1248 | { | ||
1249 | clk_n = 4, clk_p2 = 8; | ||
1250 | } else if (is_hdmi) { | ||
1251 | clk_n = 4, clk_p2 = 10; | ||
1252 | } | ||
1253 | } | ||
1254 | |||
1255 | if (is_mipi) | ||
1256 | clk_byte = dev_priv->bpp / 8; | ||
1257 | else if (is_mipi2) | ||
1258 | clk_byte = dev_priv->bpp2 / 8; | ||
1259 | |||
1260 | clk_tmp = clk * clk_n * clk_p2 * clk_byte; | ||
1261 | |||
1262 | dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2); | ||
1263 | dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d. \n", adjusted_mode->clock, clk_tmp); | ||
1264 | |||
1265 | ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock); | ||
1266 | |||
1267 | if (!ok) { | ||
1268 | dev_err(dev->dev, | ||
1269 | "mdfldFindBestPLL fail in mdfld_crtc_mode_set. \n"); | ||
1270 | } else { | ||
1271 | m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)]; | ||
1272 | |||
1273 | dev_dbg(dev->dev, "dot clock = %d," | ||
1274 | "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m, | ||
1275 | clock.p1, m_conv); | ||
1276 | } | ||
1277 | |||
1278 | dpll = REG_READ(dpll_reg); | ||
1279 | |||
1280 | if (dpll & DPLL_VCO_ENABLE) { | ||
1281 | dpll &= ~DPLL_VCO_ENABLE; | ||
1282 | REG_WRITE(dpll_reg, dpll); | ||
1283 | REG_READ(dpll_reg); | ||
1284 | |||
1285 | /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */ | ||
1286 | /* FIXME_MDFLD PO - change 500 to 1 after PO */ | ||
1287 | udelay(500); | ||
1288 | |||
1289 | /* reset M1, N1 & P1 */ | ||
1290 | REG_WRITE(fp_reg, 0); | ||
1291 | dpll &= ~MDFLD_P1_MASK; | ||
1292 | REG_WRITE(dpll_reg, dpll); | ||
1293 | /* FIXME_MDFLD PO - change 500 to 1 after PO */ | ||
1294 | udelay(500); | ||
1295 | } | ||
1296 | |||
1297 | /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */ | ||
1298 | if (dpll & MDFLD_PWR_GATE_EN) { | ||
1299 | dpll &= ~MDFLD_PWR_GATE_EN; | ||
1300 | REG_WRITE(dpll_reg, dpll); | ||
1301 | /* FIXME_MDFLD PO - change 500 to 1 after PO */ | ||
1302 | udelay(500); | ||
1303 | } | ||
1304 | |||
1305 | dpll = 0; | ||
1306 | |||
1307 | #if 0 /* FIXME revisit later */ | ||
1308 | if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19) || (ksel == KSEL_BYPASS_25)) { | ||
1309 | dpll &= ~MDFLD_INPUT_REF_SEL; | ||
1310 | } else if (ksel == KSEL_BYPASS_83_100) { | ||
1311 | dpll |= MDFLD_INPUT_REF_SEL; | ||
1312 | } | ||
1313 | #endif /* FIXME revisit later */ | ||
1314 | |||
1315 | if (is_hdmi) | ||
1316 | dpll |= MDFLD_VCO_SEL; | ||
1317 | |||
1318 | fp = (clk_n / 2) << 16; | ||
1319 | fp |= m_conv; | ||
1320 | |||
1321 | /* compute bitmask from p1 value */ | ||
1322 | dpll |= (1 << (clock.p1 - 2)) << 17; | ||
1323 | |||
1324 | #if 0 /* 1080p30 & 720p */ | ||
1325 | dpll = 0x00050000; | ||
1326 | fp = 0x000001be; | ||
1327 | #endif | ||
1328 | #if 0 /* 480p */ | ||
1329 | dpll = 0x02010000; | ||
1330 | fp = 0x000000d2; | ||
1331 | #endif | ||
1332 | } else { | ||
1333 | #if 0 /*DBI_TPO_480x864*/ | ||
1334 | dpll = 0x00020000; | ||
1335 | fp = 0x00000156; | ||
1336 | #endif /* DBI_TPO_480x864 */ /* get from spec. */ | ||
1337 | |||
1338 | dpll = 0x00800000; | ||
1339 | fp = 0x000000c1; | ||
1340 | } | ||
1341 | |||
1342 | REG_WRITE(fp_reg, fp); | ||
1343 | REG_WRITE(dpll_reg, dpll); | ||
1344 | /* FIXME_MDFLD PO - change 500 to 1 after PO */ | ||
1345 | udelay(500); | ||
1346 | |||
1347 | dpll |= DPLL_VCO_ENABLE; | ||
1348 | REG_WRITE(dpll_reg, dpll); | ||
1349 | REG_READ(dpll_reg); | ||
1350 | |||
1351 | /* wait for DSI PLL to lock */ | ||
1352 | while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) { | ||
1353 | udelay(150); | ||
1354 | timeout ++; | ||
1355 | } | ||
1356 | |||
1357 | if (is_mipi) | ||
1358 | goto mrst_crtc_mode_set_exit; | ||
1359 | |||
1360 | dev_dbg(dev->dev, "is_mipi = 0x%x \n", is_mipi); | ||
1361 | |||
1362 | REG_WRITE(pipeconf_reg, *pipeconf); | ||
1363 | REG_READ(pipeconf_reg); | ||
1364 | |||
1365 | /* Wait for for the pipe enable to take effect. */ | ||
1366 | //FIXME_JLIU7 HDMI mrstWaitForPipeEnable(dev); | ||
1367 | |||
1368 | REG_WRITE(dspcntr_reg, *dspcntr); | ||
1369 | psb_intel_wait_for_vblank(dev); | ||
1370 | |||
1371 | mrst_crtc_mode_set_exit: | ||
1372 | |||
1373 | gma_power_end(dev); | ||
1374 | |||
1375 | return 0; | ||
1376 | } | ||
1377 | |||
1378 | static void mdfld_crtc_prepare(struct drm_crtc *crtc) | ||
1379 | { | ||
1380 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
1381 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); | ||
1382 | } | ||
1383 | |||
1384 | static void mdfld_crtc_commit(struct drm_crtc *crtc) | ||
1385 | { | ||
1386 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
1387 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); | ||
1388 | } | ||
1389 | |||
1390 | static bool mdfld_crtc_mode_fixup(struct drm_crtc *crtc, | ||
1391 | struct drm_display_mode *mode, | ||
1392 | struct drm_display_mode *adjusted_mode) | ||
1393 | { | ||
1394 | return true; | ||
1395 | } | ||
1396 | |||
1397 | const struct drm_crtc_helper_funcs mdfld_helper_funcs = { | ||
1398 | .dpms = mdfld_crtc_dpms, | ||
1399 | .mode_fixup = mdfld_crtc_mode_fixup, | ||
1400 | .mode_set = mdfld_crtc_mode_set, | ||
1401 | .mode_set_base = mdfld__intel_pipe_set_base, | ||
1402 | .prepare = mdfld_crtc_prepare, | ||
1403 | .commit = mdfld_crtc_commit, | ||
1404 | }; | ||
diff --git a/drivers/staging/gma500/mdfld_msic.h b/drivers/staging/gma500/mdfld_msic.h deleted file mode 100644 index a7ad65472491..000000000000 --- a/drivers/staging/gma500/mdfld_msic.h +++ /dev/null | |||
@@ -1,31 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | |||
27 | #define MSIC_PCI_DEVICE_ID 0x831 | ||
28 | |||
29 | int msic_regsiter_driver(void); | ||
30 | int msic_unregister_driver(void); | ||
31 | extern void hpd_notify_um(void); | ||
diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c deleted file mode 100644 index eabf53d58f92..000000000000 --- a/drivers/staging/gma500/mdfld_output.c +++ /dev/null | |||
@@ -1,171 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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, sublicensen | ||
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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #include <linux/init.h> | ||
29 | #include <linux/moduleparam.h> | ||
30 | #include "mdfld_dsi_dbi.h" | ||
31 | #include "mdfld_dsi_dpi.h" | ||
32 | #include "mdfld_dsi_output.h" | ||
33 | #include "mdfld_output.h" | ||
34 | #include "mdfld_dsi_dbi_dpu.h" | ||
35 | |||
36 | #include "displays/tpo_cmd.h" | ||
37 | #include "displays/tpo_vid.h" | ||
38 | #include "displays/tmd_cmd.h" | ||
39 | #include "displays/tmd_vid.h" | ||
40 | #include "displays/pyr_cmd.h" | ||
41 | #include "displays/pyr_vid.h" | ||
42 | /* #include "displays/hdmi.h" */ | ||
43 | |||
44 | static int mdfld_dual_mipi; | ||
45 | static int mdfld_hdmi; | ||
46 | static int mdfld_dpu; | ||
47 | |||
48 | module_param(mdfld_dual_mipi, int, 0600); | ||
49 | MODULE_PARM_DESC(mdfld_dual_mipi, "Enable dual MIPI configuration"); | ||
50 | module_param(mdfld_hdmi, int, 0600); | ||
51 | MODULE_PARM_DESC(mdfld_hdmi, "Enable Medfield HDMI"); | ||
52 | module_param(mdfld_dpu, int, 0600); | ||
53 | MODULE_PARM_DESC(mdfld_dpu, "Enable Medfield DPU"); | ||
54 | |||
55 | /* For now a single type per device is all we cope with */ | ||
56 | int mdfld_get_panel_type(struct drm_device *dev, int pipe) | ||
57 | { | ||
58 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
59 | return dev_priv->panel_id; | ||
60 | } | ||
61 | |||
62 | int mdfld_panel_dpi(struct drm_device *dev) | ||
63 | { | ||
64 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
65 | |||
66 | switch (dev_priv->panel_id) { | ||
67 | case TMD_VID: | ||
68 | case TPO_VID: | ||
69 | case PYR_VID: | ||
70 | return true; | ||
71 | case TMD_CMD: | ||
72 | case TPO_CMD: | ||
73 | case PYR_CMD: | ||
74 | default: | ||
75 | return false; | ||
76 | } | ||
77 | } | ||
78 | |||
79 | static int init_panel(struct drm_device *dev, int mipi_pipe, int p_type) | ||
80 | { | ||
81 | struct panel_funcs *p_cmd_funcs; | ||
82 | struct panel_funcs *p_vid_funcs; | ||
83 | |||
84 | /* Oh boy ... FIXME */ | ||
85 | p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL); | ||
86 | if (p_cmd_funcs == NULL) | ||
87 | return -ENODEV; | ||
88 | p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL); | ||
89 | if (p_vid_funcs == NULL) { | ||
90 | kfree(p_cmd_funcs); | ||
91 | return -ENODEV; | ||
92 | } | ||
93 | |||
94 | switch (p_type) { | ||
95 | case TPO_CMD: | ||
96 | tpo_cmd_init(dev, p_cmd_funcs); | ||
97 | mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL); | ||
98 | break; | ||
99 | case TPO_VID: | ||
100 | tpo_vid_init(dev, p_vid_funcs); | ||
101 | mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs); | ||
102 | break; | ||
103 | case TMD_CMD: | ||
104 | /*tmd_cmd_init(dev, p_cmd_funcs); */ | ||
105 | mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL); | ||
106 | break; | ||
107 | case TMD_VID: | ||
108 | tmd_vid_init(dev, p_vid_funcs); | ||
109 | mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs); | ||
110 | break; | ||
111 | case PYR_CMD: | ||
112 | pyr_cmd_init(dev, p_cmd_funcs); | ||
113 | mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL); | ||
114 | break; | ||
115 | case PYR_VID: | ||
116 | mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs); | ||
117 | break; | ||
118 | case TPO: /* TPO panel supports both cmd & vid interfaces */ | ||
119 | tpo_cmd_init(dev, p_cmd_funcs); | ||
120 | tpo_vid_init(dev, p_vid_funcs); | ||
121 | mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, | ||
122 | p_vid_funcs); | ||
123 | break; | ||
124 | case TMD: | ||
125 | break; | ||
126 | case PYR: | ||
127 | break; | ||
128 | #if 0 | ||
129 | case HDMI: | ||
130 | dev_dbg(dev->dev, "Initializing HDMI"); | ||
131 | mdfld_hdmi_init(dev, &dev_priv->mode_dev); | ||
132 | break; | ||
133 | #endif | ||
134 | default: | ||
135 | dev_err(dev->dev, "Unsupported interface %d", p_type); | ||
136 | return -ENODEV; | ||
137 | } | ||
138 | return 0; | ||
139 | } | ||
140 | |||
141 | int mdfld_output_init(struct drm_device *dev) | ||
142 | { | ||
143 | int type; | ||
144 | |||
145 | /* MIPI panel 1 */ | ||
146 | type = mdfld_get_panel_type(dev, 0); | ||
147 | dev_info(dev->dev, "panel 1: type is %d\n", type); | ||
148 | init_panel(dev, 0, type); | ||
149 | |||
150 | if (mdfld_dual_mipi) { | ||
151 | /* MIPI panel 2 */ | ||
152 | type = mdfld_get_panel_type(dev, 2); | ||
153 | dev_info(dev->dev, "panel 2: type is %d\n", type); | ||
154 | init_panel(dev, 2, type); | ||
155 | } | ||
156 | if (mdfld_hdmi) | ||
157 | /* HDMI panel */ | ||
158 | init_panel(dev, 0, HDMI); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | void mdfld_output_setup(struct drm_device *dev) | ||
163 | { | ||
164 | /* FIXME: this is not the right place for this stuff ! */ | ||
165 | if (IS_MFLD(dev)) { | ||
166 | if (mdfld_dpu) | ||
167 | mdfld_dbi_dpu_init(dev); | ||
168 | else | ||
169 | mdfld_dbi_dsr_init(dev); | ||
170 | } | ||
171 | } | ||
diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h deleted file mode 100644 index daf33e7df9d5..000000000000 --- a/drivers/staging/gma500/mdfld_output.h +++ /dev/null | |||
@@ -1,41 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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, sublicensen | ||
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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #ifndef MDFLD_OUTPUT_H | ||
29 | #define MDFLD_OUTPUT_H | ||
30 | |||
31 | int mdfld_output_init(struct drm_device *dev); | ||
32 | int mdfld_panel_dpi(struct drm_device *dev); | ||
33 | int mdfld_get_panel_type(struct drm_device *dev, int pipe); | ||
34 | void mdfld_disable_crtc (struct drm_device *dev, int pipe); | ||
35 | |||
36 | extern const struct drm_crtc_helper_funcs mdfld_helper_funcs; | ||
37 | extern const struct drm_crtc_funcs mdfld_intel_crtc_funcs; | ||
38 | |||
39 | extern void mdfld_output_setup(struct drm_device *dev); | ||
40 | |||
41 | #endif | ||
diff --git a/drivers/staging/gma500/mdfld_pyr_cmd.c b/drivers/staging/gma500/mdfld_pyr_cmd.c deleted file mode 100644 index 523f2d8fe4f1..000000000000 --- a/drivers/staging/gma500/mdfld_pyr_cmd.c +++ /dev/null | |||
@@ -1,558 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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, sublicensen | ||
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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #include "mdfld_dsi_dbi.h" | ||
29 | #include "mdfld_dsi_dpi.h" | ||
30 | #include "mdfld_dsi_output.h" | ||
31 | #include "mdfld_output.h" | ||
32 | #include "mdfld_dsi_dbi_dpu.h" | ||
33 | #include "mdfld_dsi_pkg_sender.h" | ||
34 | |||
35 | #include "displays/pyr_cmd.h" | ||
36 | |||
37 | static struct drm_display_mode *pyr_cmd_get_config_mode(struct drm_device *dev) | ||
38 | { | ||
39 | struct drm_display_mode *mode; | ||
40 | |||
41 | mode = kzalloc(sizeof(*mode), GFP_KERNEL); | ||
42 | if (!mode) { | ||
43 | dev_err(dev->dev, "Out of memory\n"); | ||
44 | return NULL; | ||
45 | } | ||
46 | |||
47 | dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); | ||
48 | dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); | ||
49 | dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); | ||
50 | dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); | ||
51 | dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); | ||
52 | dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); | ||
53 | dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); | ||
54 | dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); | ||
55 | dev_dbg(dev->dev, "clock is %d\n", mode->clock); | ||
56 | |||
57 | mode->hdisplay = 480; | ||
58 | mode->vdisplay = 864; | ||
59 | mode->hsync_start = 487; | ||
60 | mode->hsync_end = 490; | ||
61 | mode->htotal = 499; | ||
62 | mode->vsync_start = 874; | ||
63 | mode->vsync_end = 878; | ||
64 | mode->vtotal = 886; | ||
65 | mode->clock = 25777; | ||
66 | |||
67 | drm_mode_set_name(mode); | ||
68 | drm_mode_set_crtcinfo(mode, 0); | ||
69 | |||
70 | mode->type |= DRM_MODE_TYPE_PREFERRED; | ||
71 | |||
72 | return mode; | ||
73 | } | ||
74 | |||
75 | static bool pyr_dsi_dbi_mode_fixup(struct drm_encoder *encoder, | ||
76 | struct drm_display_mode *mode, | ||
77 | struct drm_display_mode *adjusted_mode) | ||
78 | { | ||
79 | struct drm_device *dev = encoder->dev; | ||
80 | struct drm_display_mode *fixed_mode = pyr_cmd_get_config_mode(dev); | ||
81 | |||
82 | if (fixed_mode) { | ||
83 | adjusted_mode->hdisplay = fixed_mode->hdisplay; | ||
84 | adjusted_mode->hsync_start = fixed_mode->hsync_start; | ||
85 | adjusted_mode->hsync_end = fixed_mode->hsync_end; | ||
86 | adjusted_mode->htotal = fixed_mode->htotal; | ||
87 | adjusted_mode->vdisplay = fixed_mode->vdisplay; | ||
88 | adjusted_mode->vsync_start = fixed_mode->vsync_start; | ||
89 | adjusted_mode->vsync_end = fixed_mode->vsync_end; | ||
90 | adjusted_mode->vtotal = fixed_mode->vtotal; | ||
91 | adjusted_mode->clock = fixed_mode->clock; | ||
92 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | ||
93 | kfree(fixed_mode); | ||
94 | } | ||
95 | return true; | ||
96 | } | ||
97 | |||
98 | static void pyr_dsi_dbi_set_power(struct drm_encoder *encoder, bool on) | ||
99 | { | ||
100 | int ret = 0; | ||
101 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
102 | struct mdfld_dsi_dbi_output *dbi_output = | ||
103 | MDFLD_DSI_DBI_OUTPUT(dsi_encoder); | ||
104 | struct drm_device *dev = encoder->dev; | ||
105 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
106 | u32 reg_offset = 0; | ||
107 | int pipe = (dbi_output->channel_num == 0) ? 0 : 2; | ||
108 | |||
109 | dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", pipe, | ||
110 | on ? "On" : "Off", | ||
111 | dbi_output->dbi_panel_on ? "True" : "False"); | ||
112 | |||
113 | if (pipe == 2) { | ||
114 | if (on) | ||
115 | dev_priv->dual_mipi = true; | ||
116 | else | ||
117 | dev_priv->dual_mipi = false; | ||
118 | |||
119 | reg_offset = MIPIC_REG_OFFSET; | ||
120 | } else { | ||
121 | if (!on) | ||
122 | dev_priv->dual_mipi = false; | ||
123 | } | ||
124 | |||
125 | if (!gma_power_begin(dev, true)) { | ||
126 | dev_err(dev->dev, "hw begin failed\n"); | ||
127 | return; | ||
128 | } | ||
129 | |||
130 | |||
131 | if (on) { | ||
132 | if (dbi_output->dbi_panel_on) | ||
133 | goto out_err; | ||
134 | |||
135 | ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON); | ||
136 | if (ret) { | ||
137 | dev_err(dev->dev, "power on error\n"); | ||
138 | goto out_err; | ||
139 | } | ||
140 | |||
141 | dbi_output->dbi_panel_on = true; | ||
142 | |||
143 | if (pipe == 2) { | ||
144 | dev_priv->dbi_panel_on2 = true; | ||
145 | } else { | ||
146 | dev_priv->dbi_panel_on = true; | ||
147 | mdfld_enable_te(dev, 0); | ||
148 | } | ||
149 | } else { | ||
150 | if (!dbi_output->dbi_panel_on && !dbi_output->first_boot) | ||
151 | goto out_err; | ||
152 | |||
153 | dbi_output->dbi_panel_on = false; | ||
154 | dbi_output->first_boot = false; | ||
155 | |||
156 | if (pipe == 2) { | ||
157 | dev_priv->dbi_panel_on2 = false; | ||
158 | mdfld_disable_te(dev, 2); | ||
159 | } else { | ||
160 | dev_priv->dbi_panel_on = false; | ||
161 | mdfld_disable_te(dev, 0); | ||
162 | |||
163 | if (dev_priv->dbi_panel_on2) | ||
164 | mdfld_enable_te(dev, 2); | ||
165 | } | ||
166 | |||
167 | ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF); | ||
168 | if (ret) { | ||
169 | dev_err(dev->dev, "power on error\n"); | ||
170 | goto out_err; | ||
171 | } | ||
172 | } | ||
173 | |||
174 | out_err: | ||
175 | gma_power_end(dev); | ||
176 | |||
177 | if (ret) | ||
178 | dev_err(dev->dev, "failed\n"); | ||
179 | } | ||
180 | |||
181 | static void pyr_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config, | ||
182 | int pipe) | ||
183 | { | ||
184 | struct drm_device *dev = dsi_config->dev; | ||
185 | u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0; | ||
186 | int lane_count = dsi_config->lane_count; | ||
187 | u32 val = 0; | ||
188 | |||
189 | dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe); | ||
190 | |||
191 | /* Un-ready device */ | ||
192 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000); | ||
193 | |||
194 | /* Init dsi adapter before kicking off */ | ||
195 | REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018); | ||
196 | |||
197 | /* TODO: figure out how to setup these registers */ | ||
198 | REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c600F); | ||
199 | REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset), | ||
200 | 0x000a0014); | ||
201 | REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400); | ||
202 | REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000); | ||
203 | |||
204 | /* Enable all interrupts */ | ||
205 | REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff); | ||
206 | /* Max value: 20 clock cycles of txclkesc */ | ||
207 | REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f); | ||
208 | /* Min 21 txclkesc, max: ffffh */ | ||
209 | REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff); | ||
210 | /* Min: 7d0 max: 4e20 */ | ||
211 | REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0); | ||
212 | |||
213 | /* Set up func_prg */ | ||
214 | val |= lane_count; | ||
215 | val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET); | ||
216 | val |= DSI_DBI_COLOR_FORMAT_OPTION2; | ||
217 | REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val); | ||
218 | |||
219 | REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff); | ||
220 | REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff); | ||
221 | |||
222 | /* De-assert dbi_stall when half of DBI FIFO is empty */ | ||
223 | /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */ | ||
224 | |||
225 | REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46); | ||
226 | REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000002); | ||
227 | REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004); | ||
228 | REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001); | ||
229 | } | ||
230 | |||
231 | static void pyr_dsi_dbi_mode_set(struct drm_encoder *encoder, | ||
232 | struct drm_display_mode *mode, | ||
233 | struct drm_display_mode *adjusted_mode) | ||
234 | { | ||
235 | int ret = 0; | ||
236 | struct drm_device *dev = encoder->dev; | ||
237 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
238 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
239 | struct mdfld_dsi_dbi_output *dsi_output = | ||
240 | MDFLD_DSI_DBI_OUTPUT(dsi_encoder); | ||
241 | struct mdfld_dsi_config *dsi_config = | ||
242 | mdfld_dsi_encoder_get_config(dsi_encoder); | ||
243 | struct mdfld_dsi_connector *dsi_connector = dsi_config->connector; | ||
244 | int pipe = dsi_connector->pipe; | ||
245 | u8 param = 0; | ||
246 | |||
247 | /* Regs */ | ||
248 | u32 mipi_reg = MIPI; | ||
249 | u32 dspcntr_reg = DSPACNTR; | ||
250 | u32 pipeconf_reg = PIPEACONF; | ||
251 | u32 reg_offset = 0; | ||
252 | |||
253 | /* Values */ | ||
254 | u32 dspcntr_val = dev_priv->dspcntr; | ||
255 | u32 pipeconf_val = dev_priv->pipeconf; | ||
256 | u32 h_active_area = mode->hdisplay; | ||
257 | u32 v_active_area = mode->vdisplay; | ||
258 | u32 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX | | ||
259 | TE_TRIGGER_GPIO_PIN); | ||
260 | |||
261 | dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val); | ||
262 | |||
263 | dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI"); | ||
264 | dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay); | ||
265 | |||
266 | if (pipe == 2) { | ||
267 | mipi_reg = MIPI_C; | ||
268 | dspcntr_reg = DSPCCNTR; | ||
269 | pipeconf_reg = PIPECCONF; | ||
270 | |||
271 | reg_offset = MIPIC_REG_OFFSET; | ||
272 | |||
273 | dspcntr_val = dev_priv->dspcntr2; | ||
274 | pipeconf_val = dev_priv->pipeconf2; | ||
275 | } else { | ||
276 | mipi_val |= 0x2; /* Two lanes for port A and C respectively */ | ||
277 | } | ||
278 | |||
279 | if (!gma_power_begin(dev, true)) { | ||
280 | dev_err(dev->dev, "hw begin failed\n"); | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | /* Set up pipe related registers */ | ||
285 | REG_WRITE(mipi_reg, mipi_val); | ||
286 | REG_READ(mipi_reg); | ||
287 | |||
288 | pyr_dsi_controller_dbi_init(dsi_config, pipe); | ||
289 | |||
290 | msleep(20); | ||
291 | |||
292 | REG_WRITE(dspcntr_reg, dspcntr_val); | ||
293 | REG_READ(dspcntr_reg); | ||
294 | |||
295 | /* 20ms delay before sending exit_sleep_mode */ | ||
296 | msleep(20); | ||
297 | |||
298 | /* Send exit_sleep_mode DCS */ | ||
299 | ret = mdfld_dsi_dbi_send_dcs(dsi_output, exit_sleep_mode, NULL, | ||
300 | 0, CMD_DATA_SRC_SYSTEM_MEM); | ||
301 | if (ret) { | ||
302 | dev_err(dev->dev, "sent exit_sleep_mode faild\n"); | ||
303 | goto out_err; | ||
304 | } | ||
305 | |||
306 | /*send set_tear_on DCS*/ | ||
307 | ret = mdfld_dsi_dbi_send_dcs(dsi_output, set_tear_on, | ||
308 | ¶m, 1, CMD_DATA_SRC_SYSTEM_MEM); | ||
309 | if (ret) { | ||
310 | dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__); | ||
311 | goto out_err; | ||
312 | } | ||
313 | |||
314 | /* Do some init stuff */ | ||
315 | mdfld_dsi_brightness_init(dsi_config, pipe); | ||
316 | mdfld_dsi_gen_fifo_ready(dev, (MIPIA_GEN_FIFO_STAT_REG + reg_offset), | ||
317 | HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); | ||
318 | |||
319 | REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR); | ||
320 | REG_READ(pipeconf_reg); | ||
321 | |||
322 | /* TODO: this looks ugly, try to move it to CRTC mode setting */ | ||
323 | if (pipe == 2) | ||
324 | dev_priv->pipeconf2 |= PIPEACONF_DSR; | ||
325 | else | ||
326 | dev_priv->pipeconf |= PIPEACONF_DSR; | ||
327 | |||
328 | dev_dbg(dev->dev, "pipeconf %x\n", REG_READ(pipeconf_reg)); | ||
329 | |||
330 | ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0, | ||
331 | h_active_area - 1, v_active_area - 1); | ||
332 | if (ret) { | ||
333 | dev_err(dev->dev, "update area failed\n"); | ||
334 | goto out_err; | ||
335 | } | ||
336 | |||
337 | out_err: | ||
338 | gma_power_end(dev); | ||
339 | |||
340 | if (ret) | ||
341 | dev_err(dev->dev, "mode set failed\n"); | ||
342 | else | ||
343 | dev_dbg(dev->dev, "mode set done successfully\n"); | ||
344 | } | ||
345 | |||
346 | static void pyr_dsi_dbi_prepare(struct drm_encoder *encoder) | ||
347 | { | ||
348 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
349 | struct mdfld_dsi_dbi_output *dbi_output = | ||
350 | MDFLD_DSI_DBI_OUTPUT(dsi_encoder); | ||
351 | |||
352 | dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER; | ||
353 | dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE; | ||
354 | |||
355 | pyr_dsi_dbi_set_power(encoder, false); | ||
356 | } | ||
357 | |||
358 | static void pyr_dsi_dbi_commit(struct drm_encoder *encoder) | ||
359 | { | ||
360 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
361 | struct mdfld_dsi_dbi_output *dbi_output = | ||
362 | MDFLD_DSI_DBI_OUTPUT(dsi_encoder); | ||
363 | struct drm_device *dev = dbi_output->dev; | ||
364 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
365 | struct psb_drm_dpu_rect rect; | ||
366 | |||
367 | pyr_dsi_dbi_set_power(encoder, true); | ||
368 | |||
369 | dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER; | ||
370 | |||
371 | rect.x = rect.y = 0; | ||
372 | rect.width = 864; | ||
373 | rect.height = 480; | ||
374 | |||
375 | if (dbi_output->channel_num == 1) { | ||
376 | dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2; | ||
377 | /* If DPU enabled report a fullscreen damage */ | ||
378 | mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect); | ||
379 | } else { | ||
380 | dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0; | ||
381 | mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect); | ||
382 | } | ||
383 | dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE; | ||
384 | } | ||
385 | |||
386 | static void pyr_dsi_dbi_dpms(struct drm_encoder *encoder, int mode) | ||
387 | { | ||
388 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
389 | struct mdfld_dsi_dbi_output *dbi_output = | ||
390 | MDFLD_DSI_DBI_OUTPUT(dsi_encoder); | ||
391 | struct drm_device *dev = dbi_output->dev; | ||
392 | |||
393 | dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off")); | ||
394 | |||
395 | if (mode == DRM_MODE_DPMS_ON) | ||
396 | pyr_dsi_dbi_set_power(encoder, true); | ||
397 | else | ||
398 | pyr_dsi_dbi_set_power(encoder, false); | ||
399 | } | ||
400 | |||
401 | /* | ||
402 | * Update the DBI MIPI Panel Frame Buffer. | ||
403 | */ | ||
404 | static void pyr_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output, | ||
405 | int pipe) | ||
406 | { | ||
407 | struct mdfld_dsi_pkg_sender *sender = | ||
408 | mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); | ||
409 | struct drm_device *dev = dbi_output->dev; | ||
410 | struct drm_crtc *crtc = dbi_output->base.base.crtc; | ||
411 | struct psb_intel_crtc *psb_crtc = (crtc) ? | ||
412 | to_psb_intel_crtc(crtc) : NULL; | ||
413 | |||
414 | u32 dpll_reg = MRST_DPLL_A; | ||
415 | u32 dspcntr_reg = DSPACNTR; | ||
416 | u32 pipeconf_reg = PIPEACONF; | ||
417 | u32 dsplinoff_reg = DSPALINOFF; | ||
418 | u32 dspsurf_reg = DSPASURF; | ||
419 | u32 hs_gen_ctrl_reg = HS_GEN_CTRL_REG; | ||
420 | u32 gen_fifo_stat_reg = GEN_FIFO_STAT_REG; | ||
421 | u32 reg_offset = 0; | ||
422 | |||
423 | u32 intr_status; | ||
424 | u32 fifo_stat_reg_val; | ||
425 | u32 dpll_reg_val; | ||
426 | u32 dspcntr_reg_val; | ||
427 | u32 pipeconf_reg_val; | ||
428 | |||
429 | /* If mode setting on-going, back off */ | ||
430 | if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || | ||
431 | (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) || | ||
432 | !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE)) | ||
433 | return; | ||
434 | |||
435 | /* | ||
436 | * Look for errors here. In particular we're checking for whatever | ||
437 | * error status might have appeared during the last frame transmit | ||
438 | * (memory write). | ||
439 | * | ||
440 | * Normally, the bits we're testing here would be set infrequently, | ||
441 | * if at all. However, one panel (at least) returns at least one | ||
442 | * error bit on most frames. So we've disabled the kernel message | ||
443 | * for now. | ||
444 | * | ||
445 | * Still clear whatever error bits are set, except don't clear the | ||
446 | * ones that would make the Penwell DSI controller reset if we | ||
447 | * cleared them. | ||
448 | */ | ||
449 | intr_status = REG_READ(INTR_STAT_REG); | ||
450 | if ((intr_status & 0x26FFFFFF) != 0) { | ||
451 | /* dev_err(dev->dev, "DSI status: 0x%08X\n", intr_status); */ | ||
452 | intr_status &= 0x26F3FFFF; | ||
453 | REG_WRITE(INTR_STAT_REG, intr_status); | ||
454 | } | ||
455 | |||
456 | if (pipe == 2) { | ||
457 | dspcntr_reg = DSPCCNTR; | ||
458 | pipeconf_reg = PIPECCONF; | ||
459 | dsplinoff_reg = DSPCLINOFF; | ||
460 | dspsurf_reg = DSPCSURF; | ||
461 | |||
462 | hs_gen_ctrl_reg = HS_GEN_CTRL_REG + MIPIC_REG_OFFSET; | ||
463 | gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET, | ||
464 | |||
465 | reg_offset = MIPIC_REG_OFFSET; | ||
466 | } | ||
467 | |||
468 | if (!gma_power_begin(dev, true)) { | ||
469 | dev_err(dev->dev, "hw begin failed\n"); | ||
470 | return; | ||
471 | } | ||
472 | |||
473 | fifo_stat_reg_val = REG_READ(MIPIA_GEN_FIFO_STAT_REG + reg_offset); | ||
474 | dpll_reg_val = REG_READ(dpll_reg); | ||
475 | dspcntr_reg_val = REG_READ(dspcntr_reg); | ||
476 | pipeconf_reg_val = REG_READ(pipeconf_reg); | ||
477 | |||
478 | if (!(fifo_stat_reg_val & (1 << 27)) || | ||
479 | (dpll_reg_val & DPLL_VCO_ENABLE) || | ||
480 | !(dspcntr_reg_val & DISPLAY_PLANE_ENABLE) || | ||
481 | !(pipeconf_reg_val & DISPLAY_PLANE_ENABLE)) { | ||
482 | goto update_fb_out0; | ||
483 | } | ||
484 | |||
485 | /* Refresh plane changes */ | ||
486 | REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg)); | ||
487 | REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); | ||
488 | REG_READ(dspsurf_reg); | ||
489 | |||
490 | mdfld_dsi_send_dcs(sender, | ||
491 | write_mem_start, | ||
492 | NULL, | ||
493 | 0, | ||
494 | CMD_DATA_SRC_PIPE, | ||
495 | MDFLD_DSI_SEND_PACKAGE); | ||
496 | |||
497 | /* | ||
498 | * The idea here is to transmit a Generic Read command after the | ||
499 | * Write Memory Start/Continue commands finish. This asks for | ||
500 | * the panel to return an "ACK No Errors," or (if it has errors | ||
501 | * to report) an Error Report. This allows us to monitor the | ||
502 | * panel's perception of the health of the DSI. | ||
503 | */ | ||
504 | mdfld_dsi_gen_fifo_ready(dev, gen_fifo_stat_reg, | ||
505 | HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY); | ||
506 | REG_WRITE(hs_gen_ctrl_reg, (1 << WORD_COUNTS_POS) | GEN_READ_0); | ||
507 | |||
508 | dbi_output->dsr_fb_update_done = true; | ||
509 | update_fb_out0: | ||
510 | gma_power_end(dev); | ||
511 | } | ||
512 | |||
513 | /* | ||
514 | * TODO: will be removed later, should work out display interfaces for power | ||
515 | */ | ||
516 | void pyr_dsi_adapter_init(struct mdfld_dsi_config *dsi_config, int pipe) | ||
517 | { | ||
518 | if (!dsi_config || (pipe != 0 && pipe != 2)) { | ||
519 | WARN_ON(1); | ||
520 | return; | ||
521 | } | ||
522 | pyr_dsi_controller_dbi_init(dsi_config, pipe); | ||
523 | } | ||
524 | |||
525 | static int pyr_cmd_get_panel_info(struct drm_device *dev, int pipe, | ||
526 | struct panel_info *pi) | ||
527 | { | ||
528 | if (!dev || !pi) | ||
529 | return -EINVAL; | ||
530 | |||
531 | pi->width_mm = PYR_PANEL_WIDTH; | ||
532 | pi->height_mm = PYR_PANEL_HEIGHT; | ||
533 | |||
534 | return 0; | ||
535 | } | ||
536 | |||
537 | /* PYR DBI encoder helper funcs */ | ||
538 | static const struct drm_encoder_helper_funcs pyr_dsi_dbi_helper_funcs = { | ||
539 | .dpms = pyr_dsi_dbi_dpms, | ||
540 | .mode_fixup = pyr_dsi_dbi_mode_fixup, | ||
541 | .prepare = pyr_dsi_dbi_prepare, | ||
542 | .mode_set = pyr_dsi_dbi_mode_set, | ||
543 | .commit = pyr_dsi_dbi_commit, | ||
544 | }; | ||
545 | |||
546 | /* PYR DBI encoder funcs */ | ||
547 | static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = { | ||
548 | .destroy = drm_encoder_cleanup, | ||
549 | }; | ||
550 | |||
551 | void pyr_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs) | ||
552 | { | ||
553 | p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs; | ||
554 | p_funcs->encoder_helper_funcs = &pyr_dsi_dbi_helper_funcs; | ||
555 | p_funcs->get_config_mode = &pyr_cmd_get_config_mode; | ||
556 | p_funcs->update_fb = pyr_dsi_dbi_update_fb; | ||
557 | p_funcs->get_panel_info = pyr_cmd_get_panel_info; | ||
558 | } | ||
diff --git a/drivers/staging/gma500/mdfld_tmd_vid.c b/drivers/staging/gma500/mdfld_tmd_vid.c deleted file mode 100644 index affdc09c6769..000000000000 --- a/drivers/staging/gma500/mdfld_tmd_vid.c +++ /dev/null | |||
@@ -1,206 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
26 | * Gideon Eaton <eaton. | ||
27 | * Scott Rowe <scott.m.rowe@intel.com> | ||
28 | */ | ||
29 | |||
30 | #include "mdfld_dsi_dbi.h" | ||
31 | #include "mdfld_dsi_dpi.h" | ||
32 | #include "mdfld_dsi_output.h" | ||
33 | #include "mdfld_output.h" | ||
34 | |||
35 | #include "mdfld_dsi_pkg_sender.h" | ||
36 | |||
37 | #include "displays/tmd_vid.h" | ||
38 | |||
39 | /* FIXME: static ? */ | ||
40 | struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev) | ||
41 | { | ||
42 | struct drm_display_mode *mode; | ||
43 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
44 | struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; | ||
45 | bool use_gct = false; /*Disable GCT for now*/ | ||
46 | |||
47 | mode = kzalloc(sizeof(*mode), GFP_KERNEL); | ||
48 | if (!mode) { | ||
49 | dev_err(dev->dev, "Out of memory\n"); | ||
50 | return NULL; | ||
51 | } | ||
52 | |||
53 | if (use_gct) { | ||
54 | dev_dbg(dev->dev, "gct find MIPI panel.\n"); | ||
55 | |||
56 | mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; | ||
57 | mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; | ||
58 | mode->hsync_start = mode->hdisplay + | ||
59 | ((ti->hsync_offset_hi << 8) | | ||
60 | ti->hsync_offset_lo); | ||
61 | mode->hsync_end = mode->hsync_start + | ||
62 | ((ti->hsync_pulse_width_hi << 8) | | ||
63 | ti->hsync_pulse_width_lo); | ||
64 | mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | | ||
65 | ti->hblank_lo); | ||
66 | mode->vsync_start = \ | ||
67 | mode->vdisplay + ((ti->vsync_offset_hi << 8) | | ||
68 | ti->vsync_offset_lo); | ||
69 | mode->vsync_end = \ | ||
70 | mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ | ||
71 | ti->vsync_pulse_width_lo); | ||
72 | mode->vtotal = mode->vdisplay + | ||
73 | ((ti->vblank_hi << 8) | ti->vblank_lo); | ||
74 | mode->clock = ti->pixel_clock * 10; | ||
75 | |||
76 | dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); | ||
77 | dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); | ||
78 | dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); | ||
79 | dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); | ||
80 | dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); | ||
81 | dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); | ||
82 | dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); | ||
83 | dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); | ||
84 | dev_dbg(dev->dev, "clock is %d\n", mode->clock); | ||
85 | } else { | ||
86 | mode->hdisplay = 480; | ||
87 | mode->vdisplay = 854; | ||
88 | mode->hsync_start = 487; | ||
89 | mode->hsync_end = 490; | ||
90 | mode->htotal = 499; | ||
91 | mode->vsync_start = 861; | ||
92 | mode->vsync_end = 865; | ||
93 | mode->vtotal = 873; | ||
94 | mode->clock = 33264; | ||
95 | } | ||
96 | drm_mode_set_name(mode); | ||
97 | drm_mode_set_crtcinfo(mode, 0); | ||
98 | |||
99 | mode->type |= DRM_MODE_TYPE_PREFERRED; | ||
100 | |||
101 | return mode; | ||
102 | } | ||
103 | |||
104 | static int tmd_vid_get_panel_info(struct drm_device *dev, | ||
105 | int pipe, | ||
106 | struct panel_info *pi) | ||
107 | { | ||
108 | if (!dev || !pi) | ||
109 | return -EINVAL; | ||
110 | |||
111 | pi->width_mm = TMD_PANEL_WIDTH; | ||
112 | pi->height_mm = TMD_PANEL_HEIGHT; | ||
113 | |||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | /* | ||
118 | * mdfld_init_TMD_MIPI - initialise a TMD interface | ||
119 | * @dsi_config: configuration | ||
120 | * @pipe: pipe to configure | ||
121 | * | ||
122 | * This function is called only by mrst_dsi_mode_set and | ||
123 | * restore_display_registers. since this function does not | ||
124 | * acquire the mutex, it is important that the calling function | ||
125 | * does! | ||
126 | */ | ||
127 | |||
128 | |||
129 | static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config, | ||
130 | int pipe) | ||
131 | { | ||
132 | static u32 tmd_cmd_mcap_off[] = {0x000000b2}; | ||
133 | static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef}; | ||
134 | static u32 tmd_cmd_set_lane_num[] = {0x006360ef}; | ||
135 | static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef}; | ||
136 | static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef}; | ||
137 | static u32 tmd_cmd_set_mode[] = {0x000000b3}; | ||
138 | static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef}; | ||
139 | static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df}; | ||
140 | static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055}; | ||
141 | static u32 tmd_cmd_set_video_mode[] = {0x00000153}; | ||
142 | /*no auto_bl,need add in furture*/ | ||
143 | static u32 tmd_cmd_enable_backlight[] = {0x00005ab4}; | ||
144 | static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd}; | ||
145 | |||
146 | struct mdfld_dsi_pkg_sender *sender | ||
147 | = mdfld_dsi_get_pkg_sender(dsi_config); | ||
148 | |||
149 | DRM_INFO("Enter mdfld init TMD MIPI display.\n"); | ||
150 | |||
151 | if (!sender) { | ||
152 | DRM_ERROR("Cannot get sender\n"); | ||
153 | return; | ||
154 | } | ||
155 | |||
156 | if (dsi_config->dvr_ic_inited) | ||
157 | return; | ||
158 | |||
159 | msleep(3); | ||
160 | |||
161 | mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_mcap_off, 1, 0); | ||
162 | mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_lane_switch, 1, 0); | ||
163 | mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_lane_num, 1, 0); | ||
164 | mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock0, 1, 0); | ||
165 | mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_pushing_clock1, 1, 0); | ||
166 | mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_mode, 1, 0); | ||
167 | mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_sync_pulse_mode, 1, 0); | ||
168 | mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_column, 2, 0); | ||
169 | mdfld_dsi_send_mcs_long_lp(sender, tmd_cmd_set_page, 2, 0); | ||
170 | mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_video_mode, 1, 0); | ||
171 | mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_enable_backlight, 1, 0); | ||
172 | mdfld_dsi_send_gen_long_lp(sender, tmd_cmd_set_backlight_dimming, 1, 0); | ||
173 | |||
174 | dsi_config->dvr_ic_inited = 1; | ||
175 | } | ||
176 | |||
177 | /* TMD DPI encoder helper funcs */ | ||
178 | static const struct drm_encoder_helper_funcs | ||
179 | mdfld_tpo_dpi_encoder_helper_funcs = { | ||
180 | .dpms = mdfld_dsi_dpi_dpms, | ||
181 | .mode_fixup = mdfld_dsi_dpi_mode_fixup, | ||
182 | .prepare = mdfld_dsi_dpi_prepare, | ||
183 | .mode_set = mdfld_dsi_dpi_mode_set, | ||
184 | .commit = mdfld_dsi_dpi_commit, | ||
185 | }; | ||
186 | |||
187 | /* TMD DPI encoder funcs */ | ||
188 | static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = { | ||
189 | .destroy = drm_encoder_cleanup, | ||
190 | }; | ||
191 | |||
192 | void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs) | ||
193 | { | ||
194 | if (!dev || !p_funcs) { | ||
195 | dev_err(dev->dev, "Invalid parameters\n"); | ||
196 | return; | ||
197 | } | ||
198 | |||
199 | p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs; | ||
200 | p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs; | ||
201 | p_funcs->get_config_mode = &tmd_vid_get_config_mode; | ||
202 | p_funcs->update_fb = NULL; | ||
203 | p_funcs->get_panel_info = tmd_vid_get_panel_info; | ||
204 | p_funcs->reset = mdfld_dsi_panel_reset; | ||
205 | p_funcs->drv_ic_init = mdfld_dsi_tmd_drv_ic_init; | ||
206 | } | ||
diff --git a/drivers/staging/gma500/mdfld_tpo_cmd.c b/drivers/staging/gma500/mdfld_tpo_cmd.c deleted file mode 100644 index c7f7c9c19bc1..000000000000 --- a/drivers/staging/gma500/mdfld_tpo_cmd.c +++ /dev/null | |||
@@ -1,509 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 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, sublicensen | ||
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 | * Thomas Eaton <thomas.g.eaton@intel.com> | ||
25 | * Scott Rowe <scott.m.rowe@intel.com> | ||
26 | */ | ||
27 | |||
28 | #include "mdfld_dsi_dbi.h" | ||
29 | #include "mdfld_dsi_dpi.h" | ||
30 | #include "mdfld_dsi_output.h" | ||
31 | #include "mdfld_output.h" | ||
32 | #include "mdfld_dsi_dbi_dpu.h" | ||
33 | #include "mdfld_dsi_pkg_sender.h" | ||
34 | |||
35 | #include "displays/tpo_cmd.h" | ||
36 | |||
37 | static struct drm_display_mode *tpo_cmd_get_config_mode(struct drm_device *dev) | ||
38 | { | ||
39 | struct drm_display_mode *mode; | ||
40 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
41 | struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; | ||
42 | bool use_gct = false; | ||
43 | |||
44 | mode = kzalloc(sizeof(*mode), GFP_KERNEL); | ||
45 | if (!mode) | ||
46 | return NULL; | ||
47 | |||
48 | if (use_gct) { | ||
49 | dev_dbg(dev->dev, "gct find MIPI panel.\n"); | ||
50 | |||
51 | mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; | ||
52 | mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; | ||
53 | mode->hsync_start = mode->hdisplay + \ | ||
54 | ((ti->hsync_offset_hi << 8) | \ | ||
55 | ti->hsync_offset_lo); | ||
56 | mode->hsync_end = mode->hsync_start + \ | ||
57 | ((ti->hsync_pulse_width_hi << 8) | \ | ||
58 | ti->hsync_pulse_width_lo); | ||
59 | mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ | ||
60 | ti->hblank_lo); | ||
61 | mode->vsync_start = \ | ||
62 | mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ | ||
63 | ti->vsync_offset_lo); | ||
64 | mode->vsync_end = \ | ||
65 | mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ | ||
66 | ti->vsync_pulse_width_lo); | ||
67 | mode->vtotal = mode->vdisplay + \ | ||
68 | ((ti->vblank_hi << 8) | ti->vblank_lo); | ||
69 | mode->clock = ti->pixel_clock * 10; | ||
70 | |||
71 | dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); | ||
72 | dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); | ||
73 | dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); | ||
74 | dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); | ||
75 | dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); | ||
76 | dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); | ||
77 | dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); | ||
78 | dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); | ||
79 | dev_dbg(dev->dev, "clock is %d\n", mode->clock); | ||
80 | } else { | ||
81 | mode->hdisplay = 864; | ||
82 | mode->vdisplay = 480; | ||
83 | mode->hsync_start = 872; | ||
84 | mode->hsync_end = 876; | ||
85 | mode->htotal = 884; | ||
86 | mode->vsync_start = 482; | ||
87 | mode->vsync_end = 494; | ||
88 | mode->vtotal = 486; | ||
89 | mode->clock = 25777; | ||
90 | } | ||
91 | |||
92 | drm_mode_set_name(mode); | ||
93 | drm_mode_set_crtcinfo(mode, 0); | ||
94 | |||
95 | mode->type |= DRM_MODE_TYPE_PREFERRED; | ||
96 | |||
97 | return mode; | ||
98 | } | ||
99 | |||
100 | static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder *encoder, | ||
101 | struct drm_display_mode *mode, | ||
102 | struct drm_display_mode *adjusted_mode) | ||
103 | { | ||
104 | struct drm_device *dev = encoder->dev; | ||
105 | struct drm_display_mode *fixed_mode = tpo_cmd_get_config_mode(dev); | ||
106 | |||
107 | if (fixed_mode) { | ||
108 | adjusted_mode->hdisplay = fixed_mode->hdisplay; | ||
109 | adjusted_mode->hsync_start = fixed_mode->hsync_start; | ||
110 | adjusted_mode->hsync_end = fixed_mode->hsync_end; | ||
111 | adjusted_mode->htotal = fixed_mode->htotal; | ||
112 | adjusted_mode->vdisplay = fixed_mode->vdisplay; | ||
113 | adjusted_mode->vsync_start = fixed_mode->vsync_start; | ||
114 | adjusted_mode->vsync_end = fixed_mode->vsync_end; | ||
115 | adjusted_mode->vtotal = fixed_mode->vtotal; | ||
116 | adjusted_mode->clock = fixed_mode->clock; | ||
117 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | ||
118 | kfree(fixed_mode); | ||
119 | } | ||
120 | return true; | ||
121 | } | ||
122 | |||
123 | static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on) | ||
124 | { | ||
125 | int ret = 0; | ||
126 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
127 | struct mdfld_dsi_dbi_output *dbi_output = | ||
128 | MDFLD_DSI_DBI_OUTPUT(dsi_encoder); | ||
129 | struct mdfld_dsi_config *dsi_config = | ||
130 | mdfld_dsi_encoder_get_config(dsi_encoder); | ||
131 | struct mdfld_dsi_pkg_sender *sender = | ||
132 | mdfld_dsi_encoder_get_pkg_sender(dsi_encoder); | ||
133 | struct drm_device *dev = encoder->dev; | ||
134 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
135 | u32 reg_offset = 0; | ||
136 | int pipe = (dbi_output->channel_num == 0) ? 0 : 2; | ||
137 | u32 data = 0; | ||
138 | |||
139 | dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n", | ||
140 | pipe, on ? "On" : "Off", | ||
141 | dbi_output->dbi_panel_on ? "True" : "False"); | ||
142 | |||
143 | if (pipe == 2) { | ||
144 | if (on) | ||
145 | dev_priv->dual_mipi = true; | ||
146 | else | ||
147 | dev_priv->dual_mipi = false; | ||
148 | reg_offset = MIPIC_REG_OFFSET; | ||
149 | } else { | ||
150 | if (!on) | ||
151 | dev_priv->dual_mipi = false; | ||
152 | } | ||
153 | |||
154 | if (!gma_power_begin(dev, true)) { | ||
155 | dev_err(dev->dev, "hw begin failed\n"); | ||
156 | return; | ||
157 | } | ||
158 | |||
159 | if (on) { | ||
160 | if (dbi_output->dbi_panel_on) | ||
161 | goto out_err; | ||
162 | |||
163 | ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON); | ||
164 | if (ret) { | ||
165 | dev_err(dev->dev, "power on error\n"); | ||
166 | goto out_err; | ||
167 | } | ||
168 | |||
169 | dbi_output->dbi_panel_on = true; | ||
170 | |||
171 | if (pipe == 2) | ||
172 | dev_priv->dbi_panel_on2 = true; | ||
173 | else | ||
174 | dev_priv->dbi_panel_on = true; | ||
175 | mdfld_enable_te(dev, pipe); | ||
176 | } else { | ||
177 | if (!dbi_output->dbi_panel_on && !dbi_output->first_boot) | ||
178 | goto out_err; | ||
179 | |||
180 | dbi_output->dbi_panel_on = false; | ||
181 | dbi_output->first_boot = false; | ||
182 | |||
183 | if (pipe == 2) | ||
184 | dev_priv->dbi_panel_on2 = false; | ||
185 | else | ||
186 | dev_priv->dbi_panel_on = false; | ||
187 | |||
188 | mdfld_disable_te(dev, pipe); | ||
189 | |||
190 | ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF); | ||
191 | if (ret) { | ||
192 | dev_err(dev->dev, "power on error\n"); | ||
193 | goto out_err; | ||
194 | } | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * FIXME: this is a WA for TPO panel crash on DPMS on & off around | ||
199 | * 83 times. the root cause of this issue is that Booster in | ||
200 | * drvIC crashed. Add this WA so that we can resume the driver IC | ||
201 | * once we found that booster has a fault | ||
202 | */ | ||
203 | mdfld_dsi_get_power_mode(dsi_config, | ||
204 | &data, | ||
205 | MDFLD_DSI_HS_TRANSMISSION); | ||
206 | |||
207 | if (on && data && !(data & (1 << 7))) { | ||
208 | /* Soft reset */ | ||
209 | mdfld_dsi_send_dcs(sender, | ||
210 | DCS_SOFT_RESET, | ||
211 | NULL, | ||
212 | 0, | ||
213 | CMD_DATA_SRC_PIPE, | ||
214 | MDFLD_DSI_SEND_PACKAGE); | ||
215 | |||
216 | /* Init drvIC */ | ||
217 | if (dbi_output->p_funcs->drv_ic_init) | ||
218 | dbi_output->p_funcs->drv_ic_init(dsi_config, | ||
219 | pipe); | ||
220 | } | ||
221 | |||
222 | out_err: | ||
223 | gma_power_end(dev); | ||
224 | if (ret) | ||
225 | dev_err(dev->dev, "failed\n"); | ||
226 | } | ||
227 | |||
228 | |||
229 | static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder, | ||
230 | struct drm_display_mode *mode, | ||
231 | struct drm_display_mode *adjusted_mode) | ||
232 | { | ||
233 | int ret = 0; | ||
234 | struct drm_device *dev = encoder->dev; | ||
235 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
236 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
237 | struct mdfld_dsi_dbi_output *dsi_output = | ||
238 | MDFLD_DSI_DBI_OUTPUT(dsi_encoder); | ||
239 | struct mdfld_dsi_config *dsi_config = | ||
240 | mdfld_dsi_encoder_get_config(dsi_encoder); | ||
241 | struct mdfld_dsi_connector *dsi_connector = dsi_config->connector; | ||
242 | int pipe = dsi_connector->pipe; | ||
243 | u8 param = 0; | ||
244 | |||
245 | /* Regs */ | ||
246 | u32 mipi_reg = MIPI; | ||
247 | u32 dspcntr_reg = DSPACNTR; | ||
248 | u32 pipeconf_reg = PIPEACONF; | ||
249 | u32 reg_offset = 0; | ||
250 | |||
251 | /* Values */ | ||
252 | u32 dspcntr_val = dev_priv->dspcntr; | ||
253 | u32 pipeconf_val = dev_priv->pipeconf; | ||
254 | u32 h_active_area = mode->hdisplay; | ||
255 | u32 v_active_area = mode->vdisplay; | ||
256 | u32 mipi_val; | ||
257 | |||
258 | mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX | | ||
259 | TE_TRIGGER_GPIO_PIN); | ||
260 | |||
261 | dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val); | ||
262 | |||
263 | dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI"); | ||
264 | dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay); | ||
265 | |||
266 | if (pipe == 2) { | ||
267 | mipi_reg = MIPI_C; | ||
268 | dspcntr_reg = DSPCCNTR; | ||
269 | pipeconf_reg = PIPECCONF; | ||
270 | |||
271 | reg_offset = MIPIC_REG_OFFSET; | ||
272 | |||
273 | dspcntr_val = dev_priv->dspcntr2; | ||
274 | pipeconf_val = dev_priv->pipeconf2; | ||
275 | } else { | ||
276 | mipi_val |= 0x2; /*two lanes for port A and C respectively*/ | ||
277 | } | ||
278 | |||
279 | if (!gma_power_begin(dev, true)) { | ||
280 | dev_err(dev->dev, "hw begin failed\n"); | ||
281 | return; | ||
282 | } | ||
283 | |||
284 | REG_WRITE(dspcntr_reg, dspcntr_val); | ||
285 | REG_READ(dspcntr_reg); | ||
286 | |||
287 | /* 20ms delay before sending exit_sleep_mode */ | ||
288 | msleep(20); | ||
289 | |||
290 | /* Send exit_sleep_mode DCS */ | ||
291 | ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_EXIT_SLEEP_MODE, | ||
292 | NULL, 0, CMD_DATA_SRC_SYSTEM_MEM); | ||
293 | if (ret) { | ||
294 | dev_err(dev->dev, "sent exit_sleep_mode faild\n"); | ||
295 | goto out_err; | ||
296 | } | ||
297 | |||
298 | /* Send set_tear_on DCS */ | ||
299 | ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_SET_TEAR_ON, | ||
300 | ¶m, 1, CMD_DATA_SRC_SYSTEM_MEM); | ||
301 | if (ret) { | ||
302 | dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__); | ||
303 | goto out_err; | ||
304 | } | ||
305 | |||
306 | /* Do some init stuff */ | ||
307 | REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR); | ||
308 | REG_READ(pipeconf_reg); | ||
309 | |||
310 | /* TODO: this looks ugly, try to move it to CRTC mode setting*/ | ||
311 | if (pipe == 2) | ||
312 | dev_priv->pipeconf2 |= PIPEACONF_DSR; | ||
313 | else | ||
314 | dev_priv->pipeconf |= PIPEACONF_DSR; | ||
315 | |||
316 | dev_dbg(dev->dev, "pipeconf %x\n", REG_READ(pipeconf_reg)); | ||
317 | |||
318 | ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0, | ||
319 | h_active_area - 1, v_active_area - 1); | ||
320 | if (ret) { | ||
321 | dev_err(dev->dev, "update area failed\n"); | ||
322 | goto out_err; | ||
323 | } | ||
324 | |||
325 | out_err: | ||
326 | gma_power_end(dev); | ||
327 | |||
328 | if (ret) | ||
329 | dev_err(dev->dev, "mode set failed\n"); | ||
330 | } | ||
331 | |||
332 | static void mdfld_dsi_dbi_prepare(struct drm_encoder *encoder) | ||
333 | { | ||
334 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
335 | struct mdfld_dsi_dbi_output *dbi_output | ||
336 | = MDFLD_DSI_DBI_OUTPUT(dsi_encoder); | ||
337 | |||
338 | dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER; | ||
339 | dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE; | ||
340 | |||
341 | mdfld_dsi_dbi_set_power(encoder, false); | ||
342 | } | ||
343 | |||
344 | static void mdfld_dsi_dbi_commit(struct drm_encoder *encoder) | ||
345 | { | ||
346 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
347 | struct mdfld_dsi_dbi_output *dbi_output = | ||
348 | MDFLD_DSI_DBI_OUTPUT(dsi_encoder); | ||
349 | struct drm_device *dev = dbi_output->dev; | ||
350 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
351 | struct psb_drm_dpu_rect rect; | ||
352 | |||
353 | mdfld_dsi_dbi_set_power(encoder, true); | ||
354 | dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER; | ||
355 | |||
356 | rect.x = rect.y = 0; | ||
357 | rect.width = 864; | ||
358 | rect.height = 480; | ||
359 | |||
360 | if (dbi_output->channel_num == 1) { | ||
361 | dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2; | ||
362 | /*if dpu enabled report a fullscreen damage*/ | ||
363 | mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect); | ||
364 | } else { | ||
365 | dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0; | ||
366 | mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect); | ||
367 | } | ||
368 | dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE; | ||
369 | } | ||
370 | |||
371 | static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode) | ||
372 | { | ||
373 | struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder); | ||
374 | struct mdfld_dsi_dbi_output *dbi_output | ||
375 | = MDFLD_DSI_DBI_OUTPUT(dsi_encoder); | ||
376 | struct drm_device *dev = dbi_output->dev; | ||
377 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
378 | static bool bdispoff; | ||
379 | |||
380 | dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off")); | ||
381 | |||
382 | if (mode == DRM_MODE_DPMS_ON) { | ||
383 | /* | ||
384 | * FIXME: in case I am wrong! | ||
385 | * we don't need to exit dsr here to wake up plane/pipe/pll | ||
386 | * if everything goes right, hw_begin will resume them all | ||
387 | * during set_power. | ||
388 | */ | ||
389 | if (bdispoff /* FIXME && gbgfxsuspended */) { | ||
390 | mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D); | ||
391 | bdispoff = false; | ||
392 | dev_priv->dispstatus = true; | ||
393 | } | ||
394 | |||
395 | mdfld_dsi_dbi_set_power(encoder, true); | ||
396 | /* FIXME if (gbgfxsuspended) | ||
397 | gbgfxsuspended = false; */ | ||
398 | } else { | ||
399 | /* | ||
400 | * I am not sure whether this is the perfect place to | ||
401 | * turn rpm on since we still have a lot of CRTC turnning | ||
402 | * on work to do. | ||
403 | */ | ||
404 | bdispoff = true; | ||
405 | dev_priv->dispstatus = false; | ||
406 | mdfld_dsi_dbi_set_power(encoder, false); | ||
407 | } | ||
408 | } | ||
409 | |||
410 | |||
411 | /* | ||
412 | * Update the DBI MIPI Panel Frame Buffer. | ||
413 | */ | ||
414 | static void mdfld_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output, | ||
415 | int pipe) | ||
416 | { | ||
417 | struct mdfld_dsi_pkg_sender *sender = | ||
418 | mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base); | ||
419 | struct drm_device *dev = dbi_output->dev; | ||
420 | struct drm_crtc *crtc = dbi_output->base.base.crtc; | ||
421 | struct psb_intel_crtc *psb_crtc = (crtc) ? | ||
422 | to_psb_intel_crtc(crtc) : NULL; | ||
423 | u32 dpll_reg = MRST_DPLL_A; | ||
424 | u32 dspcntr_reg = DSPACNTR; | ||
425 | u32 pipeconf_reg = PIPEACONF; | ||
426 | u32 dsplinoff_reg = DSPALINOFF; | ||
427 | u32 dspsurf_reg = DSPASURF; | ||
428 | u32 reg_offset = 0; | ||
429 | |||
430 | /* If mode setting on-going, back off */ | ||
431 | if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) || | ||
432 | (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) || | ||
433 | !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE)) | ||
434 | return; | ||
435 | |||
436 | if (pipe == 2) { | ||
437 | dspcntr_reg = DSPCCNTR; | ||
438 | pipeconf_reg = PIPECCONF; | ||
439 | dsplinoff_reg = DSPCLINOFF; | ||
440 | dspsurf_reg = DSPCSURF; | ||
441 | reg_offset = MIPIC_REG_OFFSET; | ||
442 | } | ||
443 | |||
444 | if (!gma_power_begin(dev, true)) { | ||
445 | dev_err(dev->dev, "hw begin failed\n"); | ||
446 | return; | ||
447 | } | ||
448 | |||
449 | /* Check DBI FIFO status */ | ||
450 | if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) || | ||
451 | !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) || | ||
452 | !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE)) | ||
453 | goto update_fb_out0; | ||
454 | |||
455 | /* Refresh plane changes */ | ||
456 | REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg)); | ||
457 | REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg)); | ||
458 | REG_READ(dspsurf_reg); | ||
459 | |||
460 | mdfld_dsi_send_dcs(sender, | ||
461 | DCS_WRITE_MEM_START, | ||
462 | NULL, | ||
463 | 0, | ||
464 | CMD_DATA_SRC_PIPE, | ||
465 | MDFLD_DSI_SEND_PACKAGE); | ||
466 | |||
467 | dbi_output->dsr_fb_update_done = true; | ||
468 | update_fb_out0: | ||
469 | gma_power_end(dev); | ||
470 | } | ||
471 | |||
472 | static int tpo_cmd_get_panel_info(struct drm_device *dev, | ||
473 | int pipe, | ||
474 | struct panel_info *pi) | ||
475 | { | ||
476 | if (!dev || !pi) | ||
477 | return -EINVAL; | ||
478 | |||
479 | pi->width_mm = TPO_PANEL_WIDTH; | ||
480 | pi->height_mm = TPO_PANEL_HEIGHT; | ||
481 | |||
482 | return 0; | ||
483 | } | ||
484 | |||
485 | |||
486 | /* TPO DBI encoder helper funcs */ | ||
487 | static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = { | ||
488 | .dpms = mdfld_dsi_dbi_dpms, | ||
489 | .mode_fixup = mdfld_dsi_dbi_mode_fixup, | ||
490 | .prepare = mdfld_dsi_dbi_prepare, | ||
491 | .mode_set = mdfld_dsi_dbi_mode_set, | ||
492 | .commit = mdfld_dsi_dbi_commit, | ||
493 | }; | ||
494 | |||
495 | /* TPO DBI encoder funcs */ | ||
496 | static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = { | ||
497 | .destroy = drm_encoder_cleanup, | ||
498 | }; | ||
499 | |||
500 | void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs) | ||
501 | { | ||
502 | p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs; | ||
503 | p_funcs->encoder_helper_funcs = &mdfld_dsi_dbi_helper_funcs; | ||
504 | p_funcs->get_config_mode = &tpo_cmd_get_config_mode; | ||
505 | p_funcs->update_fb = mdfld_dsi_dbi_update_fb; | ||
506 | p_funcs->get_panel_info = tpo_cmd_get_panel_info; | ||
507 | p_funcs->reset = mdfld_dsi_panel_reset; | ||
508 | p_funcs->drv_ic_init = mdfld_dsi_brightness_init; | ||
509 | } | ||
diff --git a/drivers/staging/gma500/mdfld_tpo_vid.c b/drivers/staging/gma500/mdfld_tpo_vid.c deleted file mode 100644 index 954901751760..000000000000 --- a/drivers/staging/gma500/mdfld_tpo_vid.c +++ /dev/null | |||
@@ -1,140 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Jackie Li<yaodong.li@intel.com> | ||
26 | */ | ||
27 | |||
28 | #include "mdfld_dsi_dbi.h" | ||
29 | #include "mdfld_dsi_dpi.h" | ||
30 | #include "mdfld_dsi_output.h" | ||
31 | #include "mdfld_output.h" | ||
32 | |||
33 | #include "mdfld_dsi_pkg_sender.h" | ||
34 | |||
35 | #include "displays/tpo_vid.h" | ||
36 | |||
37 | static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev) | ||
38 | { | ||
39 | struct drm_display_mode *mode; | ||
40 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
41 | struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; | ||
42 | bool use_gct = false; | ||
43 | |||
44 | mode = kzalloc(sizeof(*mode), GFP_KERNEL); | ||
45 | if (!mode) { | ||
46 | dev_err(dev->dev, "out of memory\n"); | ||
47 | return NULL; | ||
48 | } | ||
49 | |||
50 | if (use_gct) { | ||
51 | mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; | ||
52 | mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; | ||
53 | mode->hsync_start = mode->hdisplay + \ | ||
54 | ((ti->hsync_offset_hi << 8) | \ | ||
55 | ti->hsync_offset_lo); | ||
56 | mode->hsync_end = mode->hsync_start + \ | ||
57 | ((ti->hsync_pulse_width_hi << 8) | \ | ||
58 | ti->hsync_pulse_width_lo); | ||
59 | mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ | ||
60 | ti->hblank_lo); | ||
61 | mode->vsync_start = \ | ||
62 | mode->vdisplay + ((ti->vsync_offset_hi << 8) | \ | ||
63 | ti->vsync_offset_lo); | ||
64 | mode->vsync_end = \ | ||
65 | mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \ | ||
66 | ti->vsync_pulse_width_lo); | ||
67 | mode->vtotal = mode->vdisplay + \ | ||
68 | ((ti->vblank_hi << 8) | ti->vblank_lo); | ||
69 | mode->clock = ti->pixel_clock * 10; | ||
70 | |||
71 | dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay); | ||
72 | dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay); | ||
73 | dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start); | ||
74 | dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end); | ||
75 | dev_dbg(dev->dev, "htotal is %d\n", mode->htotal); | ||
76 | dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start); | ||
77 | dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end); | ||
78 | dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal); | ||
79 | dev_dbg(dev->dev, "clock is %d\n", mode->clock); | ||
80 | } else { | ||
81 | mode->hdisplay = 864; | ||
82 | mode->vdisplay = 480; | ||
83 | mode->hsync_start = 873; | ||
84 | mode->hsync_end = 876; | ||
85 | mode->htotal = 887; | ||
86 | mode->vsync_start = 487; | ||
87 | mode->vsync_end = 490; | ||
88 | mode->vtotal = 499; | ||
89 | mode->clock = 33264; | ||
90 | } | ||
91 | |||
92 | drm_mode_set_name(mode); | ||
93 | drm_mode_set_crtcinfo(mode, 0); | ||
94 | |||
95 | mode->type |= DRM_MODE_TYPE_PREFERRED; | ||
96 | |||
97 | return mode; | ||
98 | } | ||
99 | |||
100 | static int tpo_vid_get_panel_info(struct drm_device *dev, | ||
101 | int pipe, | ||
102 | struct panel_info *pi) | ||
103 | { | ||
104 | if (!dev || !pi) | ||
105 | return -EINVAL; | ||
106 | |||
107 | pi->width_mm = TPO_PANEL_WIDTH; | ||
108 | pi->height_mm = TPO_PANEL_HEIGHT; | ||
109 | |||
110 | return 0; | ||
111 | } | ||
112 | |||
113 | /*TPO DPI encoder helper funcs*/ | ||
114 | static const struct drm_encoder_helper_funcs | ||
115 | mdfld_tpo_dpi_encoder_helper_funcs = { | ||
116 | .dpms = mdfld_dsi_dpi_dpms, | ||
117 | .mode_fixup = mdfld_dsi_dpi_mode_fixup, | ||
118 | .prepare = mdfld_dsi_dpi_prepare, | ||
119 | .mode_set = mdfld_dsi_dpi_mode_set, | ||
120 | .commit = mdfld_dsi_dpi_commit, | ||
121 | }; | ||
122 | |||
123 | /*TPO DPI encoder funcs*/ | ||
124 | static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = { | ||
125 | .destroy = drm_encoder_cleanup, | ||
126 | }; | ||
127 | |||
128 | void tpo_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs) | ||
129 | { | ||
130 | if (!dev || !p_funcs) { | ||
131 | dev_err(dev->dev, "tpo_vid_init: Invalid parameters\n"); | ||
132 | return; | ||
133 | } | ||
134 | |||
135 | p_funcs->encoder_funcs = &mdfld_tpo_dpi_encoder_funcs; | ||
136 | p_funcs->encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs; | ||
137 | p_funcs->get_config_mode = &tpo_vid_get_config_mode; | ||
138 | p_funcs->update_fb = NULL; | ||
139 | p_funcs->get_panel_info = tpo_vid_get_panel_info; | ||
140 | } | ||
diff --git a/drivers/staging/gma500/medfield.h b/drivers/staging/gma500/medfield.h deleted file mode 100644 index 09e9687431f1..000000000000 --- a/drivers/staging/gma500/medfield.h +++ /dev/null | |||
@@ -1,268 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 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 | |||
24 | /* Medfield DSI controller registers */ | ||
25 | |||
26 | #define MIPIA_DEVICE_READY_REG 0xb000 | ||
27 | #define MIPIA_INTR_STAT_REG 0xb004 | ||
28 | #define MIPIA_INTR_EN_REG 0xb008 | ||
29 | #define MIPIA_DSI_FUNC_PRG_REG 0xb00c | ||
30 | #define MIPIA_HS_TX_TIMEOUT_REG 0xb010 | ||
31 | #define MIPIA_LP_RX_TIMEOUT_REG 0xb014 | ||
32 | #define MIPIA_TURN_AROUND_TIMEOUT_REG 0xb018 | ||
33 | #define MIPIA_DEVICE_RESET_TIMER_REG 0xb01c | ||
34 | #define MIPIA_DPI_RESOLUTION_REG 0xb020 | ||
35 | #define MIPIA_DBI_FIFO_THROTTLE_REG 0xb024 | ||
36 | #define MIPIA_HSYNC_COUNT_REG 0xb028 | ||
37 | #define MIPIA_HBP_COUNT_REG 0xb02c | ||
38 | #define MIPIA_HFP_COUNT_REG 0xb030 | ||
39 | #define MIPIA_HACTIVE_COUNT_REG 0xb034 | ||
40 | #define MIPIA_VSYNC_COUNT_REG 0xb038 | ||
41 | #define MIPIA_VBP_COUNT_REG 0xb03c | ||
42 | #define MIPIA_VFP_COUNT_REG 0xb040 | ||
43 | #define MIPIA_HIGH_LOW_SWITCH_COUNT_REG 0xb044 | ||
44 | #define MIPIA_DPI_CONTROL_REG 0xb048 | ||
45 | #define MIPIA_DPI_DATA_REG 0xb04c | ||
46 | #define MIPIA_INIT_COUNT_REG 0xb050 | ||
47 | #define MIPIA_MAX_RETURN_PACK_SIZE_REG 0xb054 | ||
48 | #define MIPIA_VIDEO_MODE_FORMAT_REG 0xb058 | ||
49 | #define MIPIA_EOT_DISABLE_REG 0xb05c | ||
50 | #define MIPIA_LP_BYTECLK_REG 0xb060 | ||
51 | #define MIPIA_LP_GEN_DATA_REG 0xb064 | ||
52 | #define MIPIA_HS_GEN_DATA_REG 0xb068 | ||
53 | #define MIPIA_LP_GEN_CTRL_REG 0xb06c | ||
54 | #define MIPIA_HS_GEN_CTRL_REG 0xb070 | ||
55 | #define MIPIA_GEN_FIFO_STAT_REG 0xb074 | ||
56 | #define MIPIA_HS_LS_DBI_ENABLE_REG 0xb078 | ||
57 | #define MIPIA_DPHY_PARAM_REG 0xb080 | ||
58 | #define MIPIA_DBI_BW_CTRL_REG 0xb084 | ||
59 | #define MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG 0xb088 | ||
60 | |||
61 | #define DSI_DEVICE_READY (0x1) | ||
62 | #define DSI_POWER_STATE_ULPS_ENTER (0x2 << 1) | ||
63 | #define DSI_POWER_STATE_ULPS_EXIT (0x1 << 1) | ||
64 | #define DSI_POWER_STATE_ULPS_OFFSET (0x1) | ||
65 | |||
66 | |||
67 | #define DSI_ONE_DATA_LANE (0x1) | ||
68 | #define DSI_TWO_DATA_LANE (0x2) | ||
69 | #define DSI_THREE_DATA_LANE (0X3) | ||
70 | #define DSI_FOUR_DATA_LANE (0x4) | ||
71 | #define DSI_DPI_VIRT_CHANNEL_OFFSET (0x3) | ||
72 | #define DSI_DBI_VIRT_CHANNEL_OFFSET (0x5) | ||
73 | #define DSI_DPI_COLOR_FORMAT_RGB565 (0x01 << 7) | ||
74 | #define DSI_DPI_COLOR_FORMAT_RGB666 (0x02 << 7) | ||
75 | #define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK (0x03 << 7) | ||
76 | #define DSI_DPI_COLOR_FORMAT_RGB888 (0x04 << 7) | ||
77 | #define DSI_DBI_COLOR_FORMAT_OPTION2 (0x05 << 13) | ||
78 | |||
79 | #define DSI_INTR_STATE_RXSOTERROR 1 | ||
80 | |||
81 | #define DSI_INTR_STATE_SPL_PKG_SENT (1 << 30) | ||
82 | #define DSI_INTR_STATE_TE (1 << 31) | ||
83 | |||
84 | #define DSI_HS_TX_TIMEOUT_MASK (0xffffff) | ||
85 | |||
86 | #define DSI_LP_RX_TIMEOUT_MASK (0xffffff) | ||
87 | |||
88 | #define DSI_TURN_AROUND_TIMEOUT_MASK (0x3f) | ||
89 | |||
90 | #define DSI_RESET_TIMER_MASK (0xffff) | ||
91 | |||
92 | #define DSI_DBI_FIFO_WM_HALF (0x0) | ||
93 | #define DSI_DBI_FIFO_WM_QUARTER (0x1) | ||
94 | #define DSI_DBI_FIFO_WM_LOW (0x2) | ||
95 | |||
96 | #define DSI_DPI_TIMING_MASK (0xffff) | ||
97 | |||
98 | #define DSI_INIT_TIMER_MASK (0xffff) | ||
99 | |||
100 | #define DSI_DBI_RETURN_PACK_SIZE_MASK (0x3ff) | ||
101 | |||
102 | #define DSI_LP_BYTECLK_MASK (0x0ffff) | ||
103 | |||
104 | #define DSI_HS_CTRL_GEN_SHORT_W0 (0x03) | ||
105 | #define DSI_HS_CTRL_GEN_SHORT_W1 (0x13) | ||
106 | #define DSI_HS_CTRL_GEN_SHORT_W2 (0x23) | ||
107 | #define DSI_HS_CTRL_GEN_R0 (0x04) | ||
108 | #define DSI_HS_CTRL_GEN_R1 (0x14) | ||
109 | #define DSI_HS_CTRL_GEN_R2 (0x24) | ||
110 | #define DSI_HS_CTRL_GEN_LONG_W (0x29) | ||
111 | #define DSI_HS_CTRL_MCS_SHORT_W0 (0x05) | ||
112 | #define DSI_HS_CTRL_MCS_SHORT_W1 (0x15) | ||
113 | #define DSI_HS_CTRL_MCS_R0 (0x06) | ||
114 | #define DSI_HS_CTRL_MCS_LONG_W (0x39) | ||
115 | #define DSI_HS_CTRL_VC_OFFSET (0x06) | ||
116 | #define DSI_HS_CTRL_WC_OFFSET (0x08) | ||
117 | |||
118 | #define DSI_FIFO_GEN_HS_DATA_FULL (1 << 0) | ||
119 | #define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY (1 << 1) | ||
120 | #define DSI_FIFO_GEN_HS_DATA_EMPTY (1 << 2) | ||
121 | #define DSI_FIFO_GEN_LP_DATA_FULL (1 << 8) | ||
122 | #define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY (1 << 9) | ||
123 | #define DSI_FIFO_GEN_LP_DATA_EMPTY (1 << 10) | ||
124 | #define DSI_FIFO_GEN_HS_CTRL_FULL (1 << 16) | ||
125 | #define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY (1 << 17) | ||
126 | #define DSI_FIFO_GEN_HS_CTRL_EMPTY (1 << 18) | ||
127 | #define DSI_FIFO_GEN_LP_CTRL_FULL (1 << 24) | ||
128 | #define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY (1 << 25) | ||
129 | #define DSI_FIFO_GEN_LP_CTRL_EMPTY (1 << 26) | ||
130 | #define DSI_FIFO_DBI_EMPTY (1 << 27) | ||
131 | #define DSI_FIFO_DPI_EMPTY (1 << 28) | ||
132 | |||
133 | #define DSI_DBI_HS_LP_SWITCH_MASK (0x1) | ||
134 | |||
135 | #define DSI_HS_LP_SWITCH_COUNTER_OFFSET (0x0) | ||
136 | #define DSI_LP_HS_SWITCH_COUNTER_OFFSET (0x16) | ||
137 | |||
138 | #define DSI_DPI_CTRL_HS_SHUTDOWN (0x00000001) | ||
139 | #define DSI_DPI_CTRL_HS_TURN_ON (0x00000002) | ||
140 | |||
141 | /* Medfield DSI adapter registers */ | ||
142 | #define MIPIA_CONTROL_REG 0xb104 | ||
143 | #define MIPIA_DATA_ADD_REG 0xb108 | ||
144 | #define MIPIA_DATA_LEN_REG 0xb10c | ||
145 | #define MIPIA_CMD_ADD_REG 0xb110 | ||
146 | #define MIPIA_CMD_LEN_REG 0xb114 | ||
147 | |||
148 | /*dsi power modes*/ | ||
149 | #define DSI_POWER_MODE_DISPLAY_ON (1 << 2) | ||
150 | #define DSI_POWER_MODE_NORMAL_ON (1 << 3) | ||
151 | #define DSI_POWER_MODE_SLEEP_OUT (1 << 4) | ||
152 | #define DSI_POWER_MODE_PARTIAL_ON (1 << 5) | ||
153 | #define DSI_POWER_MODE_IDLE_ON (1 << 6) | ||
154 | |||
155 | enum { | ||
156 | MDFLD_DSI_ENCODER_DBI = 0, | ||
157 | MDFLD_DSI_ENCODER_DPI, | ||
158 | }; | ||
159 | |||
160 | enum { | ||
161 | MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1, | ||
162 | MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2, | ||
163 | MDFLD_DSI_VIDEO_BURST_MODE = 3, | ||
164 | }; | ||
165 | |||
166 | #define DSI_DPI_COMPLETE_LAST_LINE (1 << 2) | ||
167 | #define DSI_DPI_DISABLE_BTA (1 << 3) | ||
168 | /* Panel types */ | ||
169 | enum { | ||
170 | TPO_CMD, | ||
171 | TPO_VID, | ||
172 | TMD_CMD, | ||
173 | TMD_VID, | ||
174 | PYR_CMD, | ||
175 | PYR_VID, | ||
176 | TPO, | ||
177 | TMD, | ||
178 | PYR, | ||
179 | HDMI, | ||
180 | GCT_DETECT | ||
181 | }; | ||
182 | |||
183 | /* Junk that belongs elsewhere */ | ||
184 | #define TPO_PANEL_WIDTH 84 | ||
185 | #define TPO_PANEL_HEIGHT 46 | ||
186 | #define TMD_PANEL_WIDTH 39 | ||
187 | #define TMD_PANEL_HEIGHT 71 | ||
188 | #define PYR_PANEL_WIDTH 53 | ||
189 | #define PYR_PANEL_HEIGHT 95 | ||
190 | |||
191 | /* Panel interface */ | ||
192 | struct panel_info { | ||
193 | u32 width_mm; | ||
194 | u32 height_mm; | ||
195 | }; | ||
196 | |||
197 | struct mdfld_dsi_dbi_output; | ||
198 | |||
199 | struct mdfld_dsi_connector_state { | ||
200 | u32 mipi_ctrl_reg; | ||
201 | }; | ||
202 | |||
203 | struct mdfld_dsi_encoder_state { | ||
204 | |||
205 | }; | ||
206 | |||
207 | struct mdfld_dsi_connector { | ||
208 | /* | ||
209 | * This is ugly, but I have to use connector in it! :-( | ||
210 | * FIXME: use drm_connector instead. | ||
211 | */ | ||
212 | struct psb_intel_output base; | ||
213 | |||
214 | int pipe; | ||
215 | void *private; | ||
216 | void *pkg_sender; | ||
217 | |||
218 | /* Connection status */ | ||
219 | enum drm_connector_status status; | ||
220 | }; | ||
221 | |||
222 | struct mdfld_dsi_encoder { | ||
223 | struct drm_encoder base; | ||
224 | void *private; | ||
225 | }; | ||
226 | |||
227 | /* | ||
228 | * DSI config, consists of one DSI connector, two DSI encoders. | ||
229 | * DRM will pick up on DSI encoder basing on differents configs. | ||
230 | */ | ||
231 | struct mdfld_dsi_config { | ||
232 | struct drm_device *dev; | ||
233 | struct drm_display_mode *fixed_mode; | ||
234 | struct drm_display_mode *mode; | ||
235 | |||
236 | struct mdfld_dsi_connector *connector; | ||
237 | struct mdfld_dsi_encoder *encoders[DRM_CONNECTOR_MAX_ENCODER]; | ||
238 | struct mdfld_dsi_encoder *encoder; | ||
239 | |||
240 | int changed; | ||
241 | |||
242 | int bpp; | ||
243 | int type; | ||
244 | int lane_count; | ||
245 | /*Virtual channel number for this encoder*/ | ||
246 | int channel_num; | ||
247 | /*video mode configure*/ | ||
248 | int video_mode; | ||
249 | |||
250 | int dvr_ic_inited; | ||
251 | }; | ||
252 | |||
253 | #define MDFLD_DSI_CONNECTOR(psb_output) \ | ||
254 | (container_of(psb_output, struct mdfld_dsi_connector, base)) | ||
255 | |||
256 | #define MDFLD_DSI_ENCODER(encoder) \ | ||
257 | (container_of(encoder, struct mdfld_dsi_encoder, base)) | ||
258 | |||
259 | struct panel_funcs { | ||
260 | const struct drm_encoder_funcs *encoder_funcs; | ||
261 | const struct drm_encoder_helper_funcs *encoder_helper_funcs; | ||
262 | struct drm_display_mode *(*get_config_mode) (struct drm_device *); | ||
263 | void (*update_fb) (struct mdfld_dsi_dbi_output *, int); | ||
264 | int (*get_panel_info) (struct drm_device *, int, struct panel_info *); | ||
265 | int (*reset)(int pipe); | ||
266 | void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe); | ||
267 | }; | ||
268 | |||
diff --git a/drivers/staging/gma500/mid_bios.c b/drivers/staging/gma500/mid_bios.c deleted file mode 100644 index ee3c0368e320..000000000000 --- a/drivers/staging/gma500/mid_bios.c +++ /dev/null | |||
@@ -1,270 +0,0 @@ | |||
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 | /* TODO | ||
21 | * - Split functions by vbt type | ||
22 | * - Make them all take drm_device | ||
23 | * - Check ioremap failures | ||
24 | */ | ||
25 | |||
26 | #include <linux/moduleparam.h> | ||
27 | #include <drm/drmP.h> | ||
28 | #include <drm/drm.h> | ||
29 | #include "psb_drm.h" | ||
30 | #include "psb_drv.h" | ||
31 | #include "mid_bios.h" | ||
32 | #include "mdfld_output.h" | ||
33 | |||
34 | static int panel_id = GCT_DETECT; | ||
35 | module_param_named(panel_id, panel_id, int, 0600); | ||
36 | MODULE_PARM_DESC(panel_id, "Panel Identifier"); | ||
37 | |||
38 | |||
39 | static void mid_get_fuse_settings(struct drm_device *dev) | ||
40 | { | ||
41 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
42 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | ||
43 | uint32_t fuse_value = 0; | ||
44 | uint32_t fuse_value_tmp = 0; | ||
45 | |||
46 | #define FB_REG06 0xD0810600 | ||
47 | #define FB_MIPI_DISABLE (1 << 11) | ||
48 | #define FB_REG09 0xD0810900 | ||
49 | #define FB_REG09 0xD0810900 | ||
50 | #define FB_SKU_MASK 0x7000 | ||
51 | #define FB_SKU_SHIFT 12 | ||
52 | #define FB_SKU_100 0 | ||
53 | #define FB_SKU_100L 1 | ||
54 | #define FB_SKU_83 2 | ||
55 | pci_write_config_dword(pci_root, 0xD0, FB_REG06); | ||
56 | pci_read_config_dword(pci_root, 0xD4, &fuse_value); | ||
57 | |||
58 | /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */ | ||
59 | if (IS_MRST(dev)) | ||
60 | dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE; | ||
61 | |||
62 | DRM_INFO("internal display is %s\n", | ||
63 | dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display"); | ||
64 | |||
65 | /* Prevent runtime suspend at start*/ | ||
66 | if (dev_priv->iLVDS_enable) { | ||
67 | dev_priv->is_lvds_on = true; | ||
68 | dev_priv->is_mipi_on = false; | ||
69 | } else { | ||
70 | dev_priv->is_mipi_on = true; | ||
71 | dev_priv->is_lvds_on = false; | ||
72 | } | ||
73 | |||
74 | dev_priv->video_device_fuse = fuse_value; | ||
75 | |||
76 | pci_write_config_dword(pci_root, 0xD0, FB_REG09); | ||
77 | pci_read_config_dword(pci_root, 0xD4, &fuse_value); | ||
78 | |||
79 | dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value); | ||
80 | fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT; | ||
81 | |||
82 | dev_priv->fuse_reg_value = fuse_value; | ||
83 | |||
84 | switch (fuse_value_tmp) { | ||
85 | case FB_SKU_100: | ||
86 | dev_priv->core_freq = 200; | ||
87 | break; | ||
88 | case FB_SKU_100L: | ||
89 | dev_priv->core_freq = 100; | ||
90 | break; | ||
91 | case FB_SKU_83: | ||
92 | dev_priv->core_freq = 166; | ||
93 | break; | ||
94 | default: | ||
95 | dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n", | ||
96 | fuse_value_tmp); | ||
97 | dev_priv->core_freq = 0; | ||
98 | } | ||
99 | dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq); | ||
100 | pci_dev_put(pci_root); | ||
101 | } | ||
102 | |||
103 | /* | ||
104 | * Get the revison ID, B0:D2:F0;0x08 | ||
105 | */ | ||
106 | static void mid_get_pci_revID(struct drm_psb_private *dev_priv) | ||
107 | { | ||
108 | uint32_t platform_rev_id = 0; | ||
109 | struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); | ||
110 | |||
111 | pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); | ||
112 | dev_priv->platform_rev_id = (uint8_t) platform_rev_id; | ||
113 | pci_dev_put(pci_gfx_root); | ||
114 | dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n", | ||
115 | dev_priv->platform_rev_id); | ||
116 | } | ||
117 | |||
118 | static void mid_get_vbt_data(struct drm_psb_private *dev_priv) | ||
119 | { | ||
120 | struct drm_device *dev = dev_priv->dev; | ||
121 | struct mrst_vbt *vbt = &dev_priv->vbt_data; | ||
122 | u32 addr; | ||
123 | u16 new_size; | ||
124 | u8 *vbt_virtual; | ||
125 | u8 bpi; | ||
126 | u8 number_desc = 0; | ||
127 | struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD; | ||
128 | struct gct_r10_timing_info ti; | ||
129 | void *pGCT; | ||
130 | struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); | ||
131 | |||
132 | /* Get the address of the platform config vbt, B0:D2:F0;0xFC */ | ||
133 | pci_read_config_dword(pci_gfx_root, 0xFC, &addr); | ||
134 | pci_dev_put(pci_gfx_root); | ||
135 | |||
136 | dev_dbg(dev->dev, "drm platform config address is %x\n", addr); | ||
137 | |||
138 | /* check for platform config address == 0. */ | ||
139 | /* this means fw doesn't support vbt */ | ||
140 | |||
141 | if (addr == 0) { | ||
142 | vbt->size = 0; | ||
143 | return; | ||
144 | } | ||
145 | |||
146 | /* get the virtual address of the vbt */ | ||
147 | vbt_virtual = ioremap(addr, sizeof(*vbt)); | ||
148 | |||
149 | memcpy(vbt, vbt_virtual, sizeof(*vbt)); | ||
150 | iounmap(vbt_virtual); /* Free virtual address space */ | ||
151 | |||
152 | dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision); | ||
153 | |||
154 | switch (vbt->revision) { | ||
155 | case 0: | ||
156 | vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4, | ||
157 | vbt->size - sizeof(*vbt) + 4); | ||
158 | pGCT = vbt->mrst_gct; | ||
159 | bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex; | ||
160 | dev_priv->gct_data.bpi = bpi; | ||
161 | dev_priv->gct_data.pt = | ||
162 | ((struct mrst_gct_v1 *)pGCT)->PD.PanelType; | ||
163 | memcpy(&dev_priv->gct_data.DTD, | ||
164 | &((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD, | ||
165 | sizeof(struct mrst_timing_info)); | ||
166 | dev_priv->gct_data.Panel_Port_Control = | ||
167 | ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control; | ||
168 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
169 | ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; | ||
170 | break; | ||
171 | case 1: | ||
172 | vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4, | ||
173 | vbt->size - sizeof(*vbt) + 4); | ||
174 | pGCT = vbt->mrst_gct; | ||
175 | bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex; | ||
176 | dev_priv->gct_data.bpi = bpi; | ||
177 | dev_priv->gct_data.pt = | ||
178 | ((struct mrst_gct_v2 *)pGCT)->PD.PanelType; | ||
179 | memcpy(&dev_priv->gct_data.DTD, | ||
180 | &((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD, | ||
181 | sizeof(struct mrst_timing_info)); | ||
182 | dev_priv->gct_data.Panel_Port_Control = | ||
183 | ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control; | ||
184 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
185 | ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; | ||
186 | break; | ||
187 | case 0x10: | ||
188 | /*header definition changed from rev 01 (v2) to rev 10h. */ | ||
189 | /*so, some values have changed location*/ | ||
190 | new_size = vbt->checksum; /*checksum contains lo size byte*/ | ||
191 | /*LSB of mrst_gct contains hi size byte*/ | ||
192 | new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8; | ||
193 | |||
194 | vbt->checksum = vbt->size; /*size contains the checksum*/ | ||
195 | if (new_size > 0xff) | ||
196 | vbt->size = 0xff; /*restrict size to 255*/ | ||
197 | else | ||
198 | vbt->size = new_size; | ||
199 | |||
200 | /* number of descriptors defined in the GCT */ | ||
201 | number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8; | ||
202 | bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16; | ||
203 | vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE, | ||
204 | GCT_R10_DISPLAY_DESC_SIZE * number_desc); | ||
205 | pGCT = vbt->mrst_gct; | ||
206 | pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE); | ||
207 | dev_priv->gct_data.bpi = bpi; /*save boot panel id*/ | ||
208 | |||
209 | /*copy the GCT display timings into a temp structure*/ | ||
210 | memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info)); | ||
211 | |||
212 | /*now copy the temp struct into the dev_priv->gct_data*/ | ||
213 | dp_ti->pixel_clock = ti.pixel_clock; | ||
214 | dp_ti->hactive_hi = ti.hactive_hi; | ||
215 | dp_ti->hactive_lo = ti.hactive_lo; | ||
216 | dp_ti->hblank_hi = ti.hblank_hi; | ||
217 | dp_ti->hblank_lo = ti.hblank_lo; | ||
218 | dp_ti->hsync_offset_hi = ti.hsync_offset_hi; | ||
219 | dp_ti->hsync_offset_lo = ti.hsync_offset_lo; | ||
220 | dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi; | ||
221 | dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo; | ||
222 | dp_ti->vactive_hi = ti.vactive_hi; | ||
223 | dp_ti->vactive_lo = ti.vactive_lo; | ||
224 | dp_ti->vblank_hi = ti.vblank_hi; | ||
225 | dp_ti->vblank_lo = ti.vblank_lo; | ||
226 | dp_ti->vsync_offset_hi = ti.vsync_offset_hi; | ||
227 | dp_ti->vsync_offset_lo = ti.vsync_offset_lo; | ||
228 | dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi; | ||
229 | dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo; | ||
230 | |||
231 | /* Move the MIPI_Display_Descriptor data from GCT to dev priv */ | ||
232 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
233 | *((u8 *)pGCT + 0x0d); | ||
234 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor |= | ||
235 | (*((u8 *)pGCT + 0x0e)) << 8; | ||
236 | break; | ||
237 | default: | ||
238 | dev_err(dev->dev, "Unknown revision of GCT!\n"); | ||
239 | vbt->size = 0; | ||
240 | } | ||
241 | if (IS_MFLD(dev_priv->dev)) { | ||
242 | if (panel_id == GCT_DETECT) { | ||
243 | if (dev_priv->gct_data.bpi == 2) { | ||
244 | dev_info(dev->dev, "[GFX] PYR Panel Detected\n"); | ||
245 | dev_priv->panel_id = PYR_CMD; | ||
246 | panel_id = PYR_CMD; | ||
247 | } else if (dev_priv->gct_data.bpi == 0) { | ||
248 | dev_info(dev->dev, "[GFX] TMD Panel Detected.\n"); | ||
249 | dev_priv->panel_id = TMD_VID; | ||
250 | panel_id = TMD_VID; | ||
251 | } else { | ||
252 | dev_info(dev->dev, "[GFX] Default Panel (TPO)\n"); | ||
253 | dev_priv->panel_id = TPO_CMD; | ||
254 | panel_id = TPO_CMD; | ||
255 | } | ||
256 | } else { | ||
257 | dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n"); | ||
258 | dev_priv->panel_id = panel_id; | ||
259 | } | ||
260 | } | ||
261 | } | ||
262 | |||
263 | int mid_chip_setup(struct drm_device *dev) | ||
264 | { | ||
265 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
266 | mid_get_fuse_settings(dev); | ||
267 | mid_get_vbt_data(dev_priv); | ||
268 | mid_get_pci_revID(dev_priv); | ||
269 | return 0; | ||
270 | } | ||
diff --git a/drivers/staging/gma500/mid_bios.h b/drivers/staging/gma500/mid_bios.h deleted file mode 100644 index 00e7d564b7eb..000000000000 --- a/drivers/staging/gma500/mid_bios.h +++ /dev/null | |||
@@ -1,21 +0,0 @@ | |||
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 | extern int mid_chip_setup(struct drm_device *dev); | ||
21 | |||
diff --git a/drivers/staging/gma500/mmu.c b/drivers/staging/gma500/mmu.c deleted file mode 100644 index c904d73b1de3..000000000000 --- a/drivers/staging/gma500/mmu.c +++ /dev/null | |||
@@ -1,858 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2007, 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 | **************************************************************************/ | ||
18 | #include <drm/drmP.h> | ||
19 | #include "psb_drv.h" | ||
20 | #include "psb_reg.h" | ||
21 | |||
22 | /* | ||
23 | * Code for the SGX MMU: | ||
24 | */ | ||
25 | |||
26 | /* | ||
27 | * clflush on one processor only: | ||
28 | * clflush should apparently flush the cache line on all processors in an | ||
29 | * SMP system. | ||
30 | */ | ||
31 | |||
32 | /* | ||
33 | * kmap atomic: | ||
34 | * The usage of the slots must be completely encapsulated within a spinlock, and | ||
35 | * no other functions that may be using the locks for other purposed may be | ||
36 | * called from within the locked region. | ||
37 | * Since the slots are per processor, this will guarantee that we are the only | ||
38 | * user. | ||
39 | */ | ||
40 | |||
41 | /* | ||
42 | * TODO: Inserting ptes from an interrupt handler: | ||
43 | * This may be desirable for some SGX functionality where the GPU can fault in | ||
44 | * needed pages. For that, we need to make an atomic insert_pages function, that | ||
45 | * may fail. | ||
46 | * If it fails, the caller need to insert the page using a workqueue function, | ||
47 | * but on average it should be fast. | ||
48 | */ | ||
49 | |||
50 | struct psb_mmu_driver { | ||
51 | /* protects driver- and pd structures. Always take in read mode | ||
52 | * before taking the page table spinlock. | ||
53 | */ | ||
54 | struct rw_semaphore sem; | ||
55 | |||
56 | /* protects page tables, directory tables and pt tables. | ||
57 | * and pt structures. | ||
58 | */ | ||
59 | spinlock_t lock; | ||
60 | |||
61 | atomic_t needs_tlbflush; | ||
62 | |||
63 | uint8_t __iomem *register_map; | ||
64 | struct psb_mmu_pd *default_pd; | ||
65 | /*uint32_t bif_ctrl;*/ | ||
66 | int has_clflush; | ||
67 | int clflush_add; | ||
68 | unsigned long clflush_mask; | ||
69 | |||
70 | struct drm_psb_private *dev_priv; | ||
71 | }; | ||
72 | |||
73 | struct psb_mmu_pd; | ||
74 | |||
75 | struct psb_mmu_pt { | ||
76 | struct psb_mmu_pd *pd; | ||
77 | uint32_t index; | ||
78 | uint32_t count; | ||
79 | struct page *p; | ||
80 | uint32_t *v; | ||
81 | }; | ||
82 | |||
83 | struct psb_mmu_pd { | ||
84 | struct psb_mmu_driver *driver; | ||
85 | int hw_context; | ||
86 | struct psb_mmu_pt **tables; | ||
87 | struct page *p; | ||
88 | struct page *dummy_pt; | ||
89 | struct page *dummy_page; | ||
90 | uint32_t pd_mask; | ||
91 | uint32_t invalid_pde; | ||
92 | uint32_t invalid_pte; | ||
93 | }; | ||
94 | |||
95 | static inline uint32_t psb_mmu_pt_index(uint32_t offset) | ||
96 | { | ||
97 | return (offset >> PSB_PTE_SHIFT) & 0x3FF; | ||
98 | } | ||
99 | |||
100 | static inline uint32_t psb_mmu_pd_index(uint32_t offset) | ||
101 | { | ||
102 | return offset >> PSB_PDE_SHIFT; | ||
103 | } | ||
104 | |||
105 | static inline void psb_clflush(void *addr) | ||
106 | { | ||
107 | __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory"); | ||
108 | } | ||
109 | |||
110 | static inline void psb_mmu_clflush(struct psb_mmu_driver *driver, | ||
111 | void *addr) | ||
112 | { | ||
113 | if (!driver->has_clflush) | ||
114 | return; | ||
115 | |||
116 | mb(); | ||
117 | psb_clflush(addr); | ||
118 | mb(); | ||
119 | } | ||
120 | |||
121 | static void psb_page_clflush(struct psb_mmu_driver *driver, struct page* page) | ||
122 | { | ||
123 | uint32_t clflush_add = driver->clflush_add >> PAGE_SHIFT; | ||
124 | uint32_t clflush_count = PAGE_SIZE / clflush_add; | ||
125 | int i; | ||
126 | uint8_t *clf; | ||
127 | |||
128 | clf = kmap_atomic(page, KM_USER0); | ||
129 | mb(); | ||
130 | for (i = 0; i < clflush_count; ++i) { | ||
131 | psb_clflush(clf); | ||
132 | clf += clflush_add; | ||
133 | } | ||
134 | mb(); | ||
135 | kunmap_atomic(clf, KM_USER0); | ||
136 | } | ||
137 | |||
138 | static void psb_pages_clflush(struct psb_mmu_driver *driver, | ||
139 | struct page *page[], unsigned long num_pages) | ||
140 | { | ||
141 | int i; | ||
142 | |||
143 | if (!driver->has_clflush) | ||
144 | return ; | ||
145 | |||
146 | for (i = 0; i < num_pages; i++) | ||
147 | psb_page_clflush(driver, *page++); | ||
148 | } | ||
149 | |||
150 | static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver, | ||
151 | int force) | ||
152 | { | ||
153 | atomic_set(&driver->needs_tlbflush, 0); | ||
154 | } | ||
155 | |||
156 | static void psb_mmu_flush_pd(struct psb_mmu_driver *driver, int force) | ||
157 | { | ||
158 | down_write(&driver->sem); | ||
159 | psb_mmu_flush_pd_locked(driver, force); | ||
160 | up_write(&driver->sem); | ||
161 | } | ||
162 | |||
163 | void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot) | ||
164 | { | ||
165 | if (rc_prot) | ||
166 | down_write(&driver->sem); | ||
167 | if (rc_prot) | ||
168 | up_write(&driver->sem); | ||
169 | } | ||
170 | |||
171 | void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context) | ||
172 | { | ||
173 | /*ttm_tt_cache_flush(&pd->p, 1);*/ | ||
174 | psb_pages_clflush(pd->driver, &pd->p, 1); | ||
175 | down_write(&pd->driver->sem); | ||
176 | wmb(); | ||
177 | psb_mmu_flush_pd_locked(pd->driver, 1); | ||
178 | pd->hw_context = hw_context; | ||
179 | up_write(&pd->driver->sem); | ||
180 | |||
181 | } | ||
182 | |||
183 | static inline unsigned long psb_pd_addr_end(unsigned long addr, | ||
184 | unsigned long end) | ||
185 | { | ||
186 | |||
187 | addr = (addr + PSB_PDE_MASK + 1) & ~PSB_PDE_MASK; | ||
188 | return (addr < end) ? addr : end; | ||
189 | } | ||
190 | |||
191 | static inline uint32_t psb_mmu_mask_pte(uint32_t pfn, int type) | ||
192 | { | ||
193 | uint32_t mask = PSB_PTE_VALID; | ||
194 | |||
195 | if (type & PSB_MMU_CACHED_MEMORY) | ||
196 | mask |= PSB_PTE_CACHED; | ||
197 | if (type & PSB_MMU_RO_MEMORY) | ||
198 | mask |= PSB_PTE_RO; | ||
199 | if (type & PSB_MMU_WO_MEMORY) | ||
200 | mask |= PSB_PTE_WO; | ||
201 | |||
202 | return (pfn << PAGE_SHIFT) | mask; | ||
203 | } | ||
204 | |||
205 | struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, | ||
206 | int trap_pagefaults, int invalid_type) | ||
207 | { | ||
208 | struct psb_mmu_pd *pd = kmalloc(sizeof(*pd), GFP_KERNEL); | ||
209 | uint32_t *v; | ||
210 | int i; | ||
211 | |||
212 | if (!pd) | ||
213 | return NULL; | ||
214 | |||
215 | pd->p = alloc_page(GFP_DMA32); | ||
216 | if (!pd->p) | ||
217 | goto out_err1; | ||
218 | pd->dummy_pt = alloc_page(GFP_DMA32); | ||
219 | if (!pd->dummy_pt) | ||
220 | goto out_err2; | ||
221 | pd->dummy_page = alloc_page(GFP_DMA32); | ||
222 | if (!pd->dummy_page) | ||
223 | goto out_err3; | ||
224 | |||
225 | if (!trap_pagefaults) { | ||
226 | pd->invalid_pde = | ||
227 | psb_mmu_mask_pte(page_to_pfn(pd->dummy_pt), | ||
228 | invalid_type); | ||
229 | pd->invalid_pte = | ||
230 | psb_mmu_mask_pte(page_to_pfn(pd->dummy_page), | ||
231 | invalid_type); | ||
232 | } else { | ||
233 | pd->invalid_pde = 0; | ||
234 | pd->invalid_pte = 0; | ||
235 | } | ||
236 | |||
237 | v = kmap(pd->dummy_pt); | ||
238 | for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) | ||
239 | v[i] = pd->invalid_pte; | ||
240 | |||
241 | kunmap(pd->dummy_pt); | ||
242 | |||
243 | v = kmap(pd->p); | ||
244 | for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) | ||
245 | v[i] = pd->invalid_pde; | ||
246 | |||
247 | kunmap(pd->p); | ||
248 | |||
249 | clear_page(kmap(pd->dummy_page)); | ||
250 | kunmap(pd->dummy_page); | ||
251 | |||
252 | pd->tables = vmalloc_user(sizeof(struct psb_mmu_pt *) * 1024); | ||
253 | if (!pd->tables) | ||
254 | goto out_err4; | ||
255 | |||
256 | pd->hw_context = -1; | ||
257 | pd->pd_mask = PSB_PTE_VALID; | ||
258 | pd->driver = driver; | ||
259 | |||
260 | return pd; | ||
261 | |||
262 | out_err4: | ||
263 | __free_page(pd->dummy_page); | ||
264 | out_err3: | ||
265 | __free_page(pd->dummy_pt); | ||
266 | out_err2: | ||
267 | __free_page(pd->p); | ||
268 | out_err1: | ||
269 | kfree(pd); | ||
270 | return NULL; | ||
271 | } | ||
272 | |||
273 | void psb_mmu_free_pt(struct psb_mmu_pt *pt) | ||
274 | { | ||
275 | __free_page(pt->p); | ||
276 | kfree(pt); | ||
277 | } | ||
278 | |||
279 | void psb_mmu_free_pagedir(struct psb_mmu_pd *pd) | ||
280 | { | ||
281 | struct psb_mmu_driver *driver = pd->driver; | ||
282 | struct psb_mmu_pt *pt; | ||
283 | int i; | ||
284 | |||
285 | down_write(&driver->sem); | ||
286 | if (pd->hw_context != -1) | ||
287 | psb_mmu_flush_pd_locked(driver, 1); | ||
288 | |||
289 | /* Should take the spinlock here, but we don't need to do that | ||
290 | since we have the semaphore in write mode. */ | ||
291 | |||
292 | for (i = 0; i < 1024; ++i) { | ||
293 | pt = pd->tables[i]; | ||
294 | if (pt) | ||
295 | psb_mmu_free_pt(pt); | ||
296 | } | ||
297 | |||
298 | vfree(pd->tables); | ||
299 | __free_page(pd->dummy_page); | ||
300 | __free_page(pd->dummy_pt); | ||
301 | __free_page(pd->p); | ||
302 | kfree(pd); | ||
303 | up_write(&driver->sem); | ||
304 | } | ||
305 | |||
306 | static struct psb_mmu_pt *psb_mmu_alloc_pt(struct psb_mmu_pd *pd) | ||
307 | { | ||
308 | struct psb_mmu_pt *pt = kmalloc(sizeof(*pt), GFP_KERNEL); | ||
309 | void *v; | ||
310 | uint32_t clflush_add = pd->driver->clflush_add >> PAGE_SHIFT; | ||
311 | uint32_t clflush_count = PAGE_SIZE / clflush_add; | ||
312 | spinlock_t *lock = &pd->driver->lock; | ||
313 | uint8_t *clf; | ||
314 | uint32_t *ptes; | ||
315 | int i; | ||
316 | |||
317 | if (!pt) | ||
318 | return NULL; | ||
319 | |||
320 | pt->p = alloc_page(GFP_DMA32); | ||
321 | if (!pt->p) { | ||
322 | kfree(pt); | ||
323 | return NULL; | ||
324 | } | ||
325 | |||
326 | spin_lock(lock); | ||
327 | |||
328 | v = kmap_atomic(pt->p, KM_USER0); | ||
329 | clf = (uint8_t *) v; | ||
330 | ptes = (uint32_t *) v; | ||
331 | for (i = 0; i < (PAGE_SIZE / sizeof(uint32_t)); ++i) | ||
332 | *ptes++ = pd->invalid_pte; | ||
333 | |||
334 | |||
335 | if (pd->driver->has_clflush && pd->hw_context != -1) { | ||
336 | mb(); | ||
337 | for (i = 0; i < clflush_count; ++i) { | ||
338 | psb_clflush(clf); | ||
339 | clf += clflush_add; | ||
340 | } | ||
341 | mb(); | ||
342 | } | ||
343 | |||
344 | kunmap_atomic(v, KM_USER0); | ||
345 | spin_unlock(lock); | ||
346 | |||
347 | pt->count = 0; | ||
348 | pt->pd = pd; | ||
349 | pt->index = 0; | ||
350 | |||
351 | return pt; | ||
352 | } | ||
353 | |||
354 | struct psb_mmu_pt *psb_mmu_pt_alloc_map_lock(struct psb_mmu_pd *pd, | ||
355 | unsigned long addr) | ||
356 | { | ||
357 | uint32_t index = psb_mmu_pd_index(addr); | ||
358 | struct psb_mmu_pt *pt; | ||
359 | uint32_t *v; | ||
360 | spinlock_t *lock = &pd->driver->lock; | ||
361 | |||
362 | spin_lock(lock); | ||
363 | pt = pd->tables[index]; | ||
364 | while (!pt) { | ||
365 | spin_unlock(lock); | ||
366 | pt = psb_mmu_alloc_pt(pd); | ||
367 | if (!pt) | ||
368 | return NULL; | ||
369 | spin_lock(lock); | ||
370 | |||
371 | if (pd->tables[index]) { | ||
372 | spin_unlock(lock); | ||
373 | psb_mmu_free_pt(pt); | ||
374 | spin_lock(lock); | ||
375 | pt = pd->tables[index]; | ||
376 | continue; | ||
377 | } | ||
378 | |||
379 | v = kmap_atomic(pd->p, KM_USER0); | ||
380 | pd->tables[index] = pt; | ||
381 | v[index] = (page_to_pfn(pt->p) << 12) | pd->pd_mask; | ||
382 | pt->index = index; | ||
383 | kunmap_atomic((void *) v, KM_USER0); | ||
384 | |||
385 | if (pd->hw_context != -1) { | ||
386 | psb_mmu_clflush(pd->driver, (void *) &v[index]); | ||
387 | atomic_set(&pd->driver->needs_tlbflush, 1); | ||
388 | } | ||
389 | } | ||
390 | pt->v = kmap_atomic(pt->p, KM_USER0); | ||
391 | return pt; | ||
392 | } | ||
393 | |||
394 | static struct psb_mmu_pt *psb_mmu_pt_map_lock(struct psb_mmu_pd *pd, | ||
395 | unsigned long addr) | ||
396 | { | ||
397 | uint32_t index = psb_mmu_pd_index(addr); | ||
398 | struct psb_mmu_pt *pt; | ||
399 | spinlock_t *lock = &pd->driver->lock; | ||
400 | |||
401 | spin_lock(lock); | ||
402 | pt = pd->tables[index]; | ||
403 | if (!pt) { | ||
404 | spin_unlock(lock); | ||
405 | return NULL; | ||
406 | } | ||
407 | pt->v = kmap_atomic(pt->p, KM_USER0); | ||
408 | return pt; | ||
409 | } | ||
410 | |||
411 | static void psb_mmu_pt_unmap_unlock(struct psb_mmu_pt *pt) | ||
412 | { | ||
413 | struct psb_mmu_pd *pd = pt->pd; | ||
414 | uint32_t *v; | ||
415 | |||
416 | kunmap_atomic(pt->v, KM_USER0); | ||
417 | if (pt->count == 0) { | ||
418 | v = kmap_atomic(pd->p, KM_USER0); | ||
419 | v[pt->index] = pd->invalid_pde; | ||
420 | pd->tables[pt->index] = NULL; | ||
421 | |||
422 | if (pd->hw_context != -1) { | ||
423 | psb_mmu_clflush(pd->driver, | ||
424 | (void *) &v[pt->index]); | ||
425 | atomic_set(&pd->driver->needs_tlbflush, 1); | ||
426 | } | ||
427 | kunmap_atomic(pt->v, KM_USER0); | ||
428 | spin_unlock(&pd->driver->lock); | ||
429 | psb_mmu_free_pt(pt); | ||
430 | return; | ||
431 | } | ||
432 | spin_unlock(&pd->driver->lock); | ||
433 | } | ||
434 | |||
435 | static inline void psb_mmu_set_pte(struct psb_mmu_pt *pt, | ||
436 | unsigned long addr, uint32_t pte) | ||
437 | { | ||
438 | pt->v[psb_mmu_pt_index(addr)] = pte; | ||
439 | } | ||
440 | |||
441 | static inline void psb_mmu_invalidate_pte(struct psb_mmu_pt *pt, | ||
442 | unsigned long addr) | ||
443 | { | ||
444 | pt->v[psb_mmu_pt_index(addr)] = pt->pd->invalid_pte; | ||
445 | } | ||
446 | |||
447 | |||
448 | void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, | ||
449 | uint32_t mmu_offset, uint32_t gtt_start, | ||
450 | uint32_t gtt_pages) | ||
451 | { | ||
452 | uint32_t *v; | ||
453 | uint32_t start = psb_mmu_pd_index(mmu_offset); | ||
454 | struct psb_mmu_driver *driver = pd->driver; | ||
455 | int num_pages = gtt_pages; | ||
456 | |||
457 | down_read(&driver->sem); | ||
458 | spin_lock(&driver->lock); | ||
459 | |||
460 | v = kmap_atomic(pd->p, KM_USER0); | ||
461 | v += start; | ||
462 | |||
463 | while (gtt_pages--) { | ||
464 | *v++ = gtt_start | pd->pd_mask; | ||
465 | gtt_start += PAGE_SIZE; | ||
466 | } | ||
467 | |||
468 | /*ttm_tt_cache_flush(&pd->p, num_pages);*/ | ||
469 | psb_pages_clflush(pd->driver, &pd->p, num_pages); | ||
470 | kunmap_atomic(v, KM_USER0); | ||
471 | spin_unlock(&driver->lock); | ||
472 | |||
473 | if (pd->hw_context != -1) | ||
474 | atomic_set(&pd->driver->needs_tlbflush, 1); | ||
475 | |||
476 | up_read(&pd->driver->sem); | ||
477 | psb_mmu_flush_pd(pd->driver, 0); | ||
478 | } | ||
479 | |||
480 | struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver *driver) | ||
481 | { | ||
482 | struct psb_mmu_pd *pd; | ||
483 | |||
484 | /* down_read(&driver->sem); */ | ||
485 | pd = driver->default_pd; | ||
486 | /* up_read(&driver->sem); */ | ||
487 | |||
488 | return pd; | ||
489 | } | ||
490 | |||
491 | /* Returns the physical address of the PD shared by sgx/msvdx */ | ||
492 | uint32_t psb_get_default_pd_addr(struct psb_mmu_driver *driver) | ||
493 | { | ||
494 | struct psb_mmu_pd *pd; | ||
495 | |||
496 | pd = psb_mmu_get_default_pd(driver); | ||
497 | return page_to_pfn(pd->p) << PAGE_SHIFT; | ||
498 | } | ||
499 | |||
500 | void psb_mmu_driver_takedown(struct psb_mmu_driver *driver) | ||
501 | { | ||
502 | psb_mmu_free_pagedir(driver->default_pd); | ||
503 | kfree(driver); | ||
504 | } | ||
505 | |||
506 | struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, | ||
507 | int trap_pagefaults, | ||
508 | int invalid_type, | ||
509 | struct drm_psb_private *dev_priv) | ||
510 | { | ||
511 | struct psb_mmu_driver *driver; | ||
512 | |||
513 | driver = kmalloc(sizeof(*driver), GFP_KERNEL); | ||
514 | |||
515 | if (!driver) | ||
516 | return NULL; | ||
517 | driver->dev_priv = dev_priv; | ||
518 | |||
519 | driver->default_pd = psb_mmu_alloc_pd(driver, trap_pagefaults, | ||
520 | invalid_type); | ||
521 | if (!driver->default_pd) | ||
522 | goto out_err1; | ||
523 | |||
524 | spin_lock_init(&driver->lock); | ||
525 | init_rwsem(&driver->sem); | ||
526 | down_write(&driver->sem); | ||
527 | driver->register_map = registers; | ||
528 | atomic_set(&driver->needs_tlbflush, 1); | ||
529 | |||
530 | driver->has_clflush = 0; | ||
531 | |||
532 | if (boot_cpu_has(X86_FEATURE_CLFLSH)) { | ||
533 | uint32_t tfms, misc, cap0, cap4, clflush_size; | ||
534 | |||
535 | /* | ||
536 | * clflush size is determined at kernel setup for x86_64 | ||
537 | * but not for i386. We have to do it here. | ||
538 | */ | ||
539 | |||
540 | cpuid(0x00000001, &tfms, &misc, &cap0, &cap4); | ||
541 | clflush_size = ((misc >> 8) & 0xff) * 8; | ||
542 | driver->has_clflush = 1; | ||
543 | driver->clflush_add = | ||
544 | PAGE_SIZE * clflush_size / sizeof(uint32_t); | ||
545 | driver->clflush_mask = driver->clflush_add - 1; | ||
546 | driver->clflush_mask = ~driver->clflush_mask; | ||
547 | } | ||
548 | |||
549 | up_write(&driver->sem); | ||
550 | return driver; | ||
551 | |||
552 | out_err1: | ||
553 | kfree(driver); | ||
554 | return NULL; | ||
555 | } | ||
556 | |||
557 | static void psb_mmu_flush_ptes(struct psb_mmu_pd *pd, | ||
558 | unsigned long address, uint32_t num_pages, | ||
559 | uint32_t desired_tile_stride, | ||
560 | uint32_t hw_tile_stride) | ||
561 | { | ||
562 | struct psb_mmu_pt *pt; | ||
563 | uint32_t rows = 1; | ||
564 | uint32_t i; | ||
565 | unsigned long addr; | ||
566 | unsigned long end; | ||
567 | unsigned long next; | ||
568 | unsigned long add; | ||
569 | unsigned long row_add; | ||
570 | unsigned long clflush_add = pd->driver->clflush_add; | ||
571 | unsigned long clflush_mask = pd->driver->clflush_mask; | ||
572 | |||
573 | if (!pd->driver->has_clflush) { | ||
574 | /*ttm_tt_cache_flush(&pd->p, num_pages);*/ | ||
575 | psb_pages_clflush(pd->driver, &pd->p, num_pages); | ||
576 | return; | ||
577 | } | ||
578 | |||
579 | if (hw_tile_stride) | ||
580 | rows = num_pages / desired_tile_stride; | ||
581 | else | ||
582 | desired_tile_stride = num_pages; | ||
583 | |||
584 | add = desired_tile_stride << PAGE_SHIFT; | ||
585 | row_add = hw_tile_stride << PAGE_SHIFT; | ||
586 | mb(); | ||
587 | for (i = 0; i < rows; ++i) { | ||
588 | |||
589 | addr = address; | ||
590 | end = addr + add; | ||
591 | |||
592 | do { | ||
593 | next = psb_pd_addr_end(addr, end); | ||
594 | pt = psb_mmu_pt_map_lock(pd, addr); | ||
595 | if (!pt) | ||
596 | continue; | ||
597 | do { | ||
598 | psb_clflush(&pt->v | ||
599 | [psb_mmu_pt_index(addr)]); | ||
600 | } while (addr += | ||
601 | clflush_add, | ||
602 | (addr & clflush_mask) < next); | ||
603 | |||
604 | psb_mmu_pt_unmap_unlock(pt); | ||
605 | } while (addr = next, next != end); | ||
606 | address += row_add; | ||
607 | } | ||
608 | mb(); | ||
609 | } | ||
610 | |||
611 | void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, | ||
612 | unsigned long address, uint32_t num_pages) | ||
613 | { | ||
614 | struct psb_mmu_pt *pt; | ||
615 | unsigned long addr; | ||
616 | unsigned long end; | ||
617 | unsigned long next; | ||
618 | unsigned long f_address = address; | ||
619 | |||
620 | down_read(&pd->driver->sem); | ||
621 | |||
622 | addr = address; | ||
623 | end = addr + (num_pages << PAGE_SHIFT); | ||
624 | |||
625 | do { | ||
626 | next = psb_pd_addr_end(addr, end); | ||
627 | pt = psb_mmu_pt_alloc_map_lock(pd, addr); | ||
628 | if (!pt) | ||
629 | goto out; | ||
630 | do { | ||
631 | psb_mmu_invalidate_pte(pt, addr); | ||
632 | --pt->count; | ||
633 | } while (addr += PAGE_SIZE, addr < next); | ||
634 | psb_mmu_pt_unmap_unlock(pt); | ||
635 | |||
636 | } while (addr = next, next != end); | ||
637 | |||
638 | out: | ||
639 | if (pd->hw_context != -1) | ||
640 | psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); | ||
641 | |||
642 | up_read(&pd->driver->sem); | ||
643 | |||
644 | if (pd->hw_context != -1) | ||
645 | psb_mmu_flush(pd->driver, 0); | ||
646 | |||
647 | return; | ||
648 | } | ||
649 | |||
650 | void psb_mmu_remove_pages(struct psb_mmu_pd *pd, unsigned long address, | ||
651 | uint32_t num_pages, uint32_t desired_tile_stride, | ||
652 | uint32_t hw_tile_stride) | ||
653 | { | ||
654 | struct psb_mmu_pt *pt; | ||
655 | uint32_t rows = 1; | ||
656 | uint32_t i; | ||
657 | unsigned long addr; | ||
658 | unsigned long end; | ||
659 | unsigned long next; | ||
660 | unsigned long add; | ||
661 | unsigned long row_add; | ||
662 | unsigned long f_address = address; | ||
663 | |||
664 | if (hw_tile_stride) | ||
665 | rows = num_pages / desired_tile_stride; | ||
666 | else | ||
667 | desired_tile_stride = num_pages; | ||
668 | |||
669 | add = desired_tile_stride << PAGE_SHIFT; | ||
670 | row_add = hw_tile_stride << PAGE_SHIFT; | ||
671 | |||
672 | /* down_read(&pd->driver->sem); */ | ||
673 | |||
674 | /* Make sure we only need to flush this processor's cache */ | ||
675 | |||
676 | for (i = 0; i < rows; ++i) { | ||
677 | |||
678 | addr = address; | ||
679 | end = addr + add; | ||
680 | |||
681 | do { | ||
682 | next = psb_pd_addr_end(addr, end); | ||
683 | pt = psb_mmu_pt_map_lock(pd, addr); | ||
684 | if (!pt) | ||
685 | continue; | ||
686 | do { | ||
687 | psb_mmu_invalidate_pte(pt, addr); | ||
688 | --pt->count; | ||
689 | |||
690 | } while (addr += PAGE_SIZE, addr < next); | ||
691 | psb_mmu_pt_unmap_unlock(pt); | ||
692 | |||
693 | } while (addr = next, next != end); | ||
694 | address += row_add; | ||
695 | } | ||
696 | if (pd->hw_context != -1) | ||
697 | psb_mmu_flush_ptes(pd, f_address, num_pages, | ||
698 | desired_tile_stride, hw_tile_stride); | ||
699 | |||
700 | /* up_read(&pd->driver->sem); */ | ||
701 | |||
702 | if (pd->hw_context != -1) | ||
703 | psb_mmu_flush(pd->driver, 0); | ||
704 | } | ||
705 | |||
706 | int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, uint32_t start_pfn, | ||
707 | unsigned long address, uint32_t num_pages, | ||
708 | int type) | ||
709 | { | ||
710 | struct psb_mmu_pt *pt; | ||
711 | uint32_t pte; | ||
712 | unsigned long addr; | ||
713 | unsigned long end; | ||
714 | unsigned long next; | ||
715 | unsigned long f_address = address; | ||
716 | int ret = 0; | ||
717 | |||
718 | down_read(&pd->driver->sem); | ||
719 | |||
720 | addr = address; | ||
721 | end = addr + (num_pages << PAGE_SHIFT); | ||
722 | |||
723 | do { | ||
724 | next = psb_pd_addr_end(addr, end); | ||
725 | pt = psb_mmu_pt_alloc_map_lock(pd, addr); | ||
726 | if (!pt) { | ||
727 | ret = -ENOMEM; | ||
728 | goto out; | ||
729 | } | ||
730 | do { | ||
731 | pte = psb_mmu_mask_pte(start_pfn++, type); | ||
732 | psb_mmu_set_pte(pt, addr, pte); | ||
733 | pt->count++; | ||
734 | } while (addr += PAGE_SIZE, addr < next); | ||
735 | psb_mmu_pt_unmap_unlock(pt); | ||
736 | |||
737 | } while (addr = next, next != end); | ||
738 | |||
739 | out: | ||
740 | if (pd->hw_context != -1) | ||
741 | psb_mmu_flush_ptes(pd, f_address, num_pages, 1, 1); | ||
742 | |||
743 | up_read(&pd->driver->sem); | ||
744 | |||
745 | if (pd->hw_context != -1) | ||
746 | psb_mmu_flush(pd->driver, 1); | ||
747 | |||
748 | return ret; | ||
749 | } | ||
750 | |||
751 | int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, | ||
752 | unsigned long address, uint32_t num_pages, | ||
753 | uint32_t desired_tile_stride, | ||
754 | uint32_t hw_tile_stride, int type) | ||
755 | { | ||
756 | struct psb_mmu_pt *pt; | ||
757 | uint32_t rows = 1; | ||
758 | uint32_t i; | ||
759 | uint32_t pte; | ||
760 | unsigned long addr; | ||
761 | unsigned long end; | ||
762 | unsigned long next; | ||
763 | unsigned long add; | ||
764 | unsigned long row_add; | ||
765 | unsigned long f_address = address; | ||
766 | int ret = 0; | ||
767 | |||
768 | if (hw_tile_stride) { | ||
769 | if (num_pages % desired_tile_stride != 0) | ||
770 | return -EINVAL; | ||
771 | rows = num_pages / desired_tile_stride; | ||
772 | } else { | ||
773 | desired_tile_stride = num_pages; | ||
774 | } | ||
775 | |||
776 | add = desired_tile_stride << PAGE_SHIFT; | ||
777 | row_add = hw_tile_stride << PAGE_SHIFT; | ||
778 | |||
779 | down_read(&pd->driver->sem); | ||
780 | |||
781 | for (i = 0; i < rows; ++i) { | ||
782 | |||
783 | addr = address; | ||
784 | end = addr + add; | ||
785 | |||
786 | do { | ||
787 | next = psb_pd_addr_end(addr, end); | ||
788 | pt = psb_mmu_pt_alloc_map_lock(pd, addr); | ||
789 | if (!pt) { | ||
790 | ret = -ENOMEM; | ||
791 | goto out; | ||
792 | } | ||
793 | do { | ||
794 | pte = | ||
795 | psb_mmu_mask_pte(page_to_pfn(*pages++), | ||
796 | type); | ||
797 | psb_mmu_set_pte(pt, addr, pte); | ||
798 | pt->count++; | ||
799 | } while (addr += PAGE_SIZE, addr < next); | ||
800 | psb_mmu_pt_unmap_unlock(pt); | ||
801 | |||
802 | } while (addr = next, next != end); | ||
803 | |||
804 | address += row_add; | ||
805 | } | ||
806 | out: | ||
807 | if (pd->hw_context != -1) | ||
808 | psb_mmu_flush_ptes(pd, f_address, num_pages, | ||
809 | desired_tile_stride, hw_tile_stride); | ||
810 | |||
811 | up_read(&pd->driver->sem); | ||
812 | |||
813 | if (pd->hw_context != -1) | ||
814 | psb_mmu_flush(pd->driver, 1); | ||
815 | |||
816 | return ret; | ||
817 | } | ||
818 | |||
819 | int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, | ||
820 | unsigned long *pfn) | ||
821 | { | ||
822 | int ret; | ||
823 | struct psb_mmu_pt *pt; | ||
824 | uint32_t tmp; | ||
825 | spinlock_t *lock = &pd->driver->lock; | ||
826 | |||
827 | down_read(&pd->driver->sem); | ||
828 | pt = psb_mmu_pt_map_lock(pd, virtual); | ||
829 | if (!pt) { | ||
830 | uint32_t *v; | ||
831 | |||
832 | spin_lock(lock); | ||
833 | v = kmap_atomic(pd->p, KM_USER0); | ||
834 | tmp = v[psb_mmu_pd_index(virtual)]; | ||
835 | kunmap_atomic(v, KM_USER0); | ||
836 | spin_unlock(lock); | ||
837 | |||
838 | if (tmp != pd->invalid_pde || !(tmp & PSB_PTE_VALID) || | ||
839 | !(pd->invalid_pte & PSB_PTE_VALID)) { | ||
840 | ret = -EINVAL; | ||
841 | goto out; | ||
842 | } | ||
843 | ret = 0; | ||
844 | *pfn = pd->invalid_pte >> PAGE_SHIFT; | ||
845 | goto out; | ||
846 | } | ||
847 | tmp = pt->v[psb_mmu_pt_index(virtual)]; | ||
848 | if (!(tmp & PSB_PTE_VALID)) { | ||
849 | ret = -EINVAL; | ||
850 | } else { | ||
851 | ret = 0; | ||
852 | *pfn = tmp >> PAGE_SHIFT; | ||
853 | } | ||
854 | psb_mmu_pt_unmap_unlock(pt); | ||
855 | out: | ||
856 | up_read(&pd->driver->sem); | ||
857 | return ret; | ||
858 | } | ||
diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h deleted file mode 100644 index b563dbc73104..000000000000 --- a/drivers/staging/gma500/mrst.h +++ /dev/null | |||
@@ -1,252 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2007-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 | /* MID device specific descriptors */ | ||
21 | |||
22 | struct mrst_vbt { | ||
23 | s8 signature[4]; /*4 bytes,"$GCT" */ | ||
24 | u8 revision; | ||
25 | u8 size; | ||
26 | u8 checksum; | ||
27 | void *mrst_gct; | ||
28 | } __packed; | ||
29 | |||
30 | struct mrst_timing_info { | ||
31 | u16 pixel_clock; | ||
32 | u8 hactive_lo; | ||
33 | u8 hblank_lo; | ||
34 | u8 hblank_hi:4; | ||
35 | u8 hactive_hi:4; | ||
36 | u8 vactive_lo; | ||
37 | u8 vblank_lo; | ||
38 | u8 vblank_hi:4; | ||
39 | u8 vactive_hi:4; | ||
40 | u8 hsync_offset_lo; | ||
41 | u8 hsync_pulse_width_lo; | ||
42 | u8 vsync_pulse_width_lo:4; | ||
43 | u8 vsync_offset_lo:4; | ||
44 | u8 vsync_pulse_width_hi:2; | ||
45 | u8 vsync_offset_hi:2; | ||
46 | u8 hsync_pulse_width_hi:2; | ||
47 | u8 hsync_offset_hi:2; | ||
48 | u8 width_mm_lo; | ||
49 | u8 height_mm_lo; | ||
50 | u8 height_mm_hi:4; | ||
51 | u8 width_mm_hi:4; | ||
52 | u8 hborder; | ||
53 | u8 vborder; | ||
54 | u8 unknown0:1; | ||
55 | u8 hsync_positive:1; | ||
56 | u8 vsync_positive:1; | ||
57 | u8 separate_sync:2; | ||
58 | u8 stereo:1; | ||
59 | u8 unknown6:1; | ||
60 | u8 interlaced:1; | ||
61 | } __packed; | ||
62 | |||
63 | struct gct_r10_timing_info { | ||
64 | u16 pixel_clock; | ||
65 | u32 hactive_lo:8; | ||
66 | u32 hactive_hi:4; | ||
67 | u32 hblank_lo:8; | ||
68 | u32 hblank_hi:4; | ||
69 | u32 hsync_offset_lo:8; | ||
70 | u16 hsync_offset_hi:2; | ||
71 | u16 hsync_pulse_width_lo:8; | ||
72 | u16 hsync_pulse_width_hi:2; | ||
73 | u16 hsync_positive:1; | ||
74 | u16 rsvd_1:3; | ||
75 | u8 vactive_lo:8; | ||
76 | u16 vactive_hi:4; | ||
77 | u16 vblank_lo:8; | ||
78 | u16 vblank_hi:4; | ||
79 | u16 vsync_offset_lo:4; | ||
80 | u16 vsync_offset_hi:2; | ||
81 | u16 vsync_pulse_width_lo:4; | ||
82 | u16 vsync_pulse_width_hi:2; | ||
83 | u16 vsync_positive:1; | ||
84 | u16 rsvd_2:3; | ||
85 | } __packed; | ||
86 | |||
87 | struct mrst_panel_descriptor_v1 { | ||
88 | u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ | ||
89 | /* 0x61190 if MIPI */ | ||
90 | u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ | ||
91 | u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ | ||
92 | u32 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 dword */ | ||
93 | /* Register 0x61210 */ | ||
94 | struct mrst_timing_info DTD;/*18 bytes, Standard definition */ | ||
95 | u16 Panel_Backlight_Inverter_Descriptor;/* 16 bits, as follows */ | ||
96 | /* Bit 0, Frequency, 15 bits,0 - 32767Hz */ | ||
97 | /* Bit 15, Polarity, 1 bit, 0: Normal, 1: Inverted */ | ||
98 | u16 Panel_MIPI_Display_Descriptor; | ||
99 | /*16 bits, Defined as follows: */ | ||
100 | /* if MIPI, 0x0000 if LVDS */ | ||
101 | /* Bit 0, Type, 2 bits, */ | ||
102 | /* 0: Type-1, */ | ||
103 | /* 1: Type-2, */ | ||
104 | /* 2: Type-3, */ | ||
105 | /* 3: Type-4 */ | ||
106 | /* Bit 2, Pixel Format, 4 bits */ | ||
107 | /* Bit0: 16bpp (not supported in LNC), */ | ||
108 | /* Bit1: 18bpp loosely packed, */ | ||
109 | /* Bit2: 18bpp packed, */ | ||
110 | /* Bit3: 24bpp */ | ||
111 | /* Bit 6, Reserved, 2 bits, 00b */ | ||
112 | /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ | ||
113 | /* Bit 14, Reserved, 2 bits, 00b */ | ||
114 | } __packed; | ||
115 | |||
116 | struct mrst_panel_descriptor_v2 { | ||
117 | u32 Panel_Port_Control; /* 1 dword, Register 0x61180 if LVDS */ | ||
118 | /* 0x61190 if MIPI */ | ||
119 | u32 Panel_Power_On_Sequencing;/*1 dword,Register 0x61208,*/ | ||
120 | u32 Panel_Power_Off_Sequencing;/*1 dword,Register 0x6120C,*/ | ||
121 | u8 Panel_Power_Cycle_Delay_and_Reference_Divisor;/* 1 byte */ | ||
122 | /* Register 0x61210 */ | ||
123 | struct mrst_timing_info DTD;/*18 bytes, Standard definition */ | ||
124 | u16 Panel_Backlight_Inverter_Descriptor;/*16 bits, as follows*/ | ||
125 | /*Bit 0, Frequency, 16 bits, 0 - 32767Hz*/ | ||
126 | u8 Panel_Initial_Brightness;/* [7:0] 0 - 100% */ | ||
127 | /*Bit 7, Polarity, 1 bit,0: Normal, 1: Inverted*/ | ||
128 | u16 Panel_MIPI_Display_Descriptor; | ||
129 | /*16 bits, Defined as follows: */ | ||
130 | /* if MIPI, 0x0000 if LVDS */ | ||
131 | /* Bit 0, Type, 2 bits, */ | ||
132 | /* 0: Type-1, */ | ||
133 | /* 1: Type-2, */ | ||
134 | /* 2: Type-3, */ | ||
135 | /* 3: Type-4 */ | ||
136 | /* Bit 2, Pixel Format, 4 bits */ | ||
137 | /* Bit0: 16bpp (not supported in LNC), */ | ||
138 | /* Bit1: 18bpp loosely packed, */ | ||
139 | /* Bit2: 18bpp packed, */ | ||
140 | /* Bit3: 24bpp */ | ||
141 | /* Bit 6, Reserved, 2 bits, 00b */ | ||
142 | /* Bit 8, Minimum Supported Frame Rate, 6 bits, 0 - 63Hz */ | ||
143 | /* Bit 14, Reserved, 2 bits, 00b */ | ||
144 | } __packed; | ||
145 | |||
146 | union mrst_panel_rx { | ||
147 | struct { | ||
148 | u16 NumberOfLanes:2; /*Num of Lanes, 2 bits,0 = 1 lane,*/ | ||
149 | /* 1 = 2 lanes, 2 = 3 lanes, 3 = 4 lanes. */ | ||
150 | u16 MaxLaneFreq:3; /* 0: 100MHz, 1: 200MHz, 2: 300MHz, */ | ||
151 | /*3: 400MHz, 4: 500MHz, 5: 600MHz, 6: 700MHz, 7: 800MHz.*/ | ||
152 | u16 SupportedVideoTransferMode:2; /*0: Non-burst only */ | ||
153 | /* 1: Burst and non-burst */ | ||
154 | /* 2/3: Reserved */ | ||
155 | u16 HSClkBehavior:1; /*0: Continuous, 1: Non-continuous*/ | ||
156 | u16 DuoDisplaySupport:1; /*1 bit,0: No, 1: Yes*/ | ||
157 | u16 ECC_ChecksumCapabilities:1;/*1 bit,0: No, 1: Yes*/ | ||
158 | u16 BidirectionalCommunication:1;/*1 bit,0: No, 1: Yes */ | ||
159 | u16 Rsvd:5;/*5 bits,00000b */ | ||
160 | } panelrx; | ||
161 | u16 panel_receiver; | ||
162 | } __packed; | ||
163 | |||
164 | struct mrst_gct_v1 { | ||
165 | union { /*8 bits,Defined as follows: */ | ||
166 | struct { | ||
167 | u8 PanelType:4; /*4 bits, Bit field for panels*/ | ||
168 | /* 0 - 3: 0 = LVDS, 1 = MIPI*/ | ||
169 | /*2 bits,Specifies which of the*/ | ||
170 | u8 BootPanelIndex:2; | ||
171 | /* 4 panels to use by default*/ | ||
172 | u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ | ||
173 | /* the 4 MIPI DSI receivers to use*/ | ||
174 | } PD; | ||
175 | u8 PanelDescriptor; | ||
176 | }; | ||
177 | struct mrst_panel_descriptor_v1 panel[4];/*panel descrs,38 bytes each*/ | ||
178 | union mrst_panel_rx panelrx[4]; /* panel receivers*/ | ||
179 | } __packed; | ||
180 | |||
181 | struct mrst_gct_v2 { | ||
182 | union { /*8 bits,Defined as follows: */ | ||
183 | struct { | ||
184 | u8 PanelType:4; /*4 bits, Bit field for panels*/ | ||
185 | /* 0 - 3: 0 = LVDS, 1 = MIPI*/ | ||
186 | /*2 bits,Specifies which of the*/ | ||
187 | u8 BootPanelIndex:2; | ||
188 | /* 4 panels to use by default*/ | ||
189 | u8 BootMIPI_DSI_RxIndex:2;/*Specifies which of*/ | ||
190 | /* the 4 MIPI DSI receivers to use*/ | ||
191 | } PD; | ||
192 | u8 PanelDescriptor; | ||
193 | }; | ||
194 | struct mrst_panel_descriptor_v2 panel[4];/*panel descrs,38 bytes each*/ | ||
195 | union mrst_panel_rx panelrx[4]; /* panel receivers*/ | ||
196 | } __packed; | ||
197 | |||
198 | struct mrst_gct_data { | ||
199 | u8 bpi; /* boot panel index, number of panel used during boot */ | ||
200 | u8 pt; /* panel type, 4 bit field, 0=lvds, 1=mipi */ | ||
201 | struct mrst_timing_info DTD; /* timing info for the selected panel */ | ||
202 | u32 Panel_Port_Control; | ||
203 | u32 PP_On_Sequencing;/*1 dword,Register 0x61208,*/ | ||
204 | u32 PP_Off_Sequencing;/*1 dword,Register 0x6120C,*/ | ||
205 | u32 PP_Cycle_Delay; | ||
206 | u16 Panel_Backlight_Inverter_Descriptor; | ||
207 | u16 Panel_MIPI_Display_Descriptor; | ||
208 | } __packed; | ||
209 | |||
210 | #define MODE_SETTING_IN_CRTC 0x1 | ||
211 | #define MODE_SETTING_IN_ENCODER 0x2 | ||
212 | #define MODE_SETTING_ON_GOING 0x3 | ||
213 | #define MODE_SETTING_IN_DSR 0x4 | ||
214 | #define MODE_SETTING_ENCODER_DONE 0x8 | ||
215 | |||
216 | #define GCT_R10_HEADER_SIZE 16 | ||
217 | #define GCT_R10_DISPLAY_DESC_SIZE 28 | ||
218 | |||
219 | /* | ||
220 | * Moorestown HDMI interfaces | ||
221 | */ | ||
222 | |||
223 | struct mrst_hdmi_dev { | ||
224 | struct pci_dev *dev; | ||
225 | void __iomem *regs; | ||
226 | unsigned int mmio, mmio_len; | ||
227 | int dpms_mode; | ||
228 | struct hdmi_i2c_dev *i2c_dev; | ||
229 | |||
230 | /* register state */ | ||
231 | u32 saveDPLL_CTRL; | ||
232 | u32 saveDPLL_DIV_CTRL; | ||
233 | u32 saveDPLL_ADJUST; | ||
234 | u32 saveDPLL_UPDATE; | ||
235 | u32 saveDPLL_CLK_ENABLE; | ||
236 | u32 savePCH_HTOTAL_B; | ||
237 | u32 savePCH_HBLANK_B; | ||
238 | u32 savePCH_HSYNC_B; | ||
239 | u32 savePCH_VTOTAL_B; | ||
240 | u32 savePCH_VBLANK_B; | ||
241 | u32 savePCH_VSYNC_B; | ||
242 | u32 savePCH_PIPEBCONF; | ||
243 | u32 savePCH_PIPEBSRC; | ||
244 | }; | ||
245 | |||
246 | extern void mrst_hdmi_setup(struct drm_device *dev); | ||
247 | extern void mrst_hdmi_teardown(struct drm_device *dev); | ||
248 | extern int mrst_hdmi_i2c_init(struct pci_dev *dev); | ||
249 | extern void mrst_hdmi_i2c_exit(struct pci_dev *dev); | ||
250 | extern void mrst_hdmi_save(struct drm_device *dev); | ||
251 | extern void mrst_hdmi_restore(struct drm_device *dev); | ||
252 | extern void mrst_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev); | ||
diff --git a/drivers/staging/gma500/mrst_crtc.c b/drivers/staging/gma500/mrst_crtc.c deleted file mode 100644 index 980837e37d80..000000000000 --- a/drivers/staging/gma500/mrst_crtc.c +++ /dev/null | |||
@@ -1,604 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2009 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 | |||
18 | #include <linux/i2c.h> | ||
19 | #include <linux/pm_runtime.h> | ||
20 | |||
21 | #include <drm/drmP.h> | ||
22 | #include "framebuffer.h" | ||
23 | #include "psb_drv.h" | ||
24 | #include "psb_intel_drv.h" | ||
25 | #include "psb_intel_reg.h" | ||
26 | #include "psb_intel_display.h" | ||
27 | #include "power.h" | ||
28 | |||
29 | struct psb_intel_range_t { | ||
30 | int min, max; | ||
31 | }; | ||
32 | |||
33 | struct mrst_limit_t { | ||
34 | struct psb_intel_range_t dot, m, p1; | ||
35 | }; | ||
36 | |||
37 | struct mrst_clock_t { | ||
38 | /* derived values */ | ||
39 | int dot; | ||
40 | int m; | ||
41 | int p1; | ||
42 | }; | ||
43 | |||
44 | #define MRST_LIMIT_LVDS_100L 0 | ||
45 | #define MRST_LIMIT_LVDS_83 1 | ||
46 | #define MRST_LIMIT_LVDS_100 2 | ||
47 | |||
48 | #define MRST_DOT_MIN 19750 | ||
49 | #define MRST_DOT_MAX 120000 | ||
50 | #define MRST_M_MIN_100L 20 | ||
51 | #define MRST_M_MIN_100 10 | ||
52 | #define MRST_M_MIN_83 12 | ||
53 | #define MRST_M_MAX_100L 34 | ||
54 | #define MRST_M_MAX_100 17 | ||
55 | #define MRST_M_MAX_83 20 | ||
56 | #define MRST_P1_MIN 2 | ||
57 | #define MRST_P1_MAX_0 7 | ||
58 | #define MRST_P1_MAX_1 8 | ||
59 | |||
60 | static const struct mrst_limit_t mrst_limits[] = { | ||
61 | { /* MRST_LIMIT_LVDS_100L */ | ||
62 | .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, | ||
63 | .m = {.min = MRST_M_MIN_100L, .max = MRST_M_MAX_100L}, | ||
64 | .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, | ||
65 | }, | ||
66 | { /* MRST_LIMIT_LVDS_83L */ | ||
67 | .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, | ||
68 | .m = {.min = MRST_M_MIN_83, .max = MRST_M_MAX_83}, | ||
69 | .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_0}, | ||
70 | }, | ||
71 | { /* MRST_LIMIT_LVDS_100 */ | ||
72 | .dot = {.min = MRST_DOT_MIN, .max = MRST_DOT_MAX}, | ||
73 | .m = {.min = MRST_M_MIN_100, .max = MRST_M_MAX_100}, | ||
74 | .p1 = {.min = MRST_P1_MIN, .max = MRST_P1_MAX_1}, | ||
75 | }, | ||
76 | }; | ||
77 | |||
78 | #define MRST_M_MIN 10 | ||
79 | static const u32 mrst_m_converts[] = { | ||
80 | 0x2B, 0x15, 0x2A, 0x35, 0x1A, 0x0D, 0x26, 0x33, 0x19, 0x2C, | ||
81 | 0x36, 0x3B, 0x1D, 0x2E, 0x37, 0x1B, 0x2D, 0x16, 0x0B, 0x25, | ||
82 | 0x12, 0x09, 0x24, 0x32, 0x39, 0x1c, | ||
83 | }; | ||
84 | |||
85 | static const struct mrst_limit_t *mrst_limit(struct drm_crtc *crtc) | ||
86 | { | ||
87 | const struct mrst_limit_t *limit = NULL; | ||
88 | struct drm_device *dev = crtc->dev; | ||
89 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
90 | |||
91 | if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) | ||
92 | || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)) { | ||
93 | switch (dev_priv->core_freq) { | ||
94 | case 100: | ||
95 | limit = &mrst_limits[MRST_LIMIT_LVDS_100L]; | ||
96 | break; | ||
97 | case 166: | ||
98 | limit = &mrst_limits[MRST_LIMIT_LVDS_83]; | ||
99 | break; | ||
100 | case 200: | ||
101 | limit = &mrst_limits[MRST_LIMIT_LVDS_100]; | ||
102 | break; | ||
103 | } | ||
104 | } else { | ||
105 | limit = NULL; | ||
106 | dev_err(dev->dev, "mrst_limit Wrong display type.\n"); | ||
107 | } | ||
108 | |||
109 | return limit; | ||
110 | } | ||
111 | |||
112 | /** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ | ||
113 | static void mrst_clock(int refclk, struct mrst_clock_t *clock) | ||
114 | { | ||
115 | clock->dot = (refclk * clock->m) / (14 * clock->p1); | ||
116 | } | ||
117 | |||
118 | void mrstPrintPll(char *prefix, struct mrst_clock_t *clock) | ||
119 | { | ||
120 | pr_debug("%s: dotclock = %d, m = %d, p1 = %d.\n", | ||
121 | prefix, clock->dot, clock->m, clock->p1); | ||
122 | } | ||
123 | |||
124 | /** | ||
125 | * Returns a set of divisors for the desired target clock with the given refclk, | ||
126 | * or FALSE. Divisor values are the actual divisors for | ||
127 | */ | ||
128 | static bool | ||
129 | mrstFindBestPLL(struct drm_crtc *crtc, int target, int refclk, | ||
130 | struct mrst_clock_t *best_clock) | ||
131 | { | ||
132 | struct mrst_clock_t clock; | ||
133 | const struct mrst_limit_t *limit = mrst_limit(crtc); | ||
134 | int err = target; | ||
135 | |||
136 | memset(best_clock, 0, sizeof(*best_clock)); | ||
137 | |||
138 | for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) { | ||
139 | for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max; | ||
140 | clock.p1++) { | ||
141 | int this_err; | ||
142 | |||
143 | mrst_clock(refclk, &clock); | ||
144 | |||
145 | this_err = abs(clock.dot - target); | ||
146 | if (this_err < err) { | ||
147 | *best_clock = clock; | ||
148 | err = this_err; | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | dev_dbg(crtc->dev->dev, "mrstFindBestPLL err = %d.\n", err); | ||
153 | return err != target; | ||
154 | } | ||
155 | |||
156 | /** | ||
157 | * Sets the power management mode of the pipe and plane. | ||
158 | * | ||
159 | * This code should probably grow support for turning the cursor off and back | ||
160 | * on appropriately at the same time as we're turning the pipe off/on. | ||
161 | */ | ||
162 | static void mrst_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
163 | { | ||
164 | struct drm_device *dev = crtc->dev; | ||
165 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
166 | int pipe = psb_intel_crtc->pipe; | ||
167 | int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; | ||
168 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
169 | int dspbase_reg = (pipe == 0) ? MRST_DSPABASE : DSPBBASE; | ||
170 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
171 | u32 temp; | ||
172 | bool enabled; | ||
173 | |||
174 | if (!gma_power_begin(dev, true)) | ||
175 | return; | ||
176 | |||
177 | /* XXX: When our outputs are all unaware of DPMS modes other than off | ||
178 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | ||
179 | */ | ||
180 | switch (mode) { | ||
181 | case DRM_MODE_DPMS_ON: | ||
182 | case DRM_MODE_DPMS_STANDBY: | ||
183 | case DRM_MODE_DPMS_SUSPEND: | ||
184 | /* Enable the DPLL */ | ||
185 | temp = REG_READ(dpll_reg); | ||
186 | if ((temp & DPLL_VCO_ENABLE) == 0) { | ||
187 | REG_WRITE(dpll_reg, temp); | ||
188 | REG_READ(dpll_reg); | ||
189 | /* Wait for the clocks to stabilize. */ | ||
190 | udelay(150); | ||
191 | REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | ||
192 | REG_READ(dpll_reg); | ||
193 | /* Wait for the clocks to stabilize. */ | ||
194 | udelay(150); | ||
195 | REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | ||
196 | REG_READ(dpll_reg); | ||
197 | /* Wait for the clocks to stabilize. */ | ||
198 | udelay(150); | ||
199 | } | ||
200 | /* Enable the pipe */ | ||
201 | temp = REG_READ(pipeconf_reg); | ||
202 | if ((temp & PIPEACONF_ENABLE) == 0) | ||
203 | REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); | ||
204 | /* Enable the plane */ | ||
205 | temp = REG_READ(dspcntr_reg); | ||
206 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
207 | REG_WRITE(dspcntr_reg, | ||
208 | temp | DISPLAY_PLANE_ENABLE); | ||
209 | /* Flush the plane changes */ | ||
210 | REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); | ||
211 | } | ||
212 | |||
213 | psb_intel_crtc_load_lut(crtc); | ||
214 | |||
215 | /* Give the overlay scaler a chance to enable | ||
216 | if it's on this pipe */ | ||
217 | /* psb_intel_crtc_dpms_video(crtc, true); TODO */ | ||
218 | break; | ||
219 | case DRM_MODE_DPMS_OFF: | ||
220 | /* Give the overlay scaler a chance to disable | ||
221 | * if it's on this pipe */ | ||
222 | /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ | ||
223 | |||
224 | /* Disable the VGA plane that we never use */ | ||
225 | REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); | ||
226 | /* Disable display plane */ | ||
227 | temp = REG_READ(dspcntr_reg); | ||
228 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | ||
229 | REG_WRITE(dspcntr_reg, | ||
230 | temp & ~DISPLAY_PLANE_ENABLE); | ||
231 | /* Flush the plane changes */ | ||
232 | REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); | ||
233 | REG_READ(dspbase_reg); | ||
234 | } | ||
235 | |||
236 | /* Next, disable display pipes */ | ||
237 | temp = REG_READ(pipeconf_reg); | ||
238 | if ((temp & PIPEACONF_ENABLE) != 0) { | ||
239 | REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); | ||
240 | REG_READ(pipeconf_reg); | ||
241 | } | ||
242 | /* Wait for for the pipe disable to take effect. */ | ||
243 | psb_intel_wait_for_vblank(dev); | ||
244 | |||
245 | temp = REG_READ(dpll_reg); | ||
246 | if ((temp & DPLL_VCO_ENABLE) != 0) { | ||
247 | REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); | ||
248 | REG_READ(dpll_reg); | ||
249 | } | ||
250 | |||
251 | /* Wait for the clocks to turn off. */ | ||
252 | udelay(150); | ||
253 | break; | ||
254 | } | ||
255 | |||
256 | enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; | ||
257 | |||
258 | /*Set FIFO Watermarks*/ | ||
259 | REG_WRITE(DSPARB, 0x3FFF); | ||
260 | REG_WRITE(DSPFW1, 0x3F88080A); | ||
261 | REG_WRITE(DSPFW2, 0x0b060808); | ||
262 | REG_WRITE(DSPFW3, 0x0); | ||
263 | REG_WRITE(DSPFW4, 0x08030404); | ||
264 | REG_WRITE(DSPFW5, 0x04040404); | ||
265 | REG_WRITE(DSPFW6, 0x78); | ||
266 | REG_WRITE(0x70400, REG_READ(0x70400) | 0x4000); | ||
267 | /* Must write Bit 14 of the Chicken Bit Register */ | ||
268 | |||
269 | gma_power_end(dev); | ||
270 | } | ||
271 | |||
272 | /** | ||
273 | * Return the pipe currently connected to the panel fitter, | ||
274 | * or -1 if the panel fitter is not present or not in use | ||
275 | */ | ||
276 | static int mrst_panel_fitter_pipe(struct drm_device *dev) | ||
277 | { | ||
278 | u32 pfit_control; | ||
279 | |||
280 | pfit_control = REG_READ(PFIT_CONTROL); | ||
281 | |||
282 | /* See if the panel fitter is in use */ | ||
283 | if ((pfit_control & PFIT_ENABLE) == 0) | ||
284 | return -1; | ||
285 | return (pfit_control >> 29) & 3; | ||
286 | } | ||
287 | |||
288 | static int mrst_crtc_mode_set(struct drm_crtc *crtc, | ||
289 | struct drm_display_mode *mode, | ||
290 | struct drm_display_mode *adjusted_mode, | ||
291 | int x, int y, | ||
292 | struct drm_framebuffer *old_fb) | ||
293 | { | ||
294 | struct drm_device *dev = crtc->dev; | ||
295 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
296 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
297 | int pipe = psb_intel_crtc->pipe; | ||
298 | int fp_reg = (pipe == 0) ? MRST_FPA0 : FPB0; | ||
299 | int dpll_reg = (pipe == 0) ? MRST_DPLL_A : DPLL_B; | ||
300 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
301 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
302 | int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
303 | int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
304 | int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
305 | int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
306 | int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
307 | int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
308 | int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | ||
309 | int refclk = 0; | ||
310 | struct mrst_clock_t clock; | ||
311 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; | ||
312 | bool ok, is_sdvo = false; | ||
313 | bool is_crt = false, is_lvds = false, is_tv = false; | ||
314 | bool is_mipi = false; | ||
315 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
316 | struct psb_intel_output *psb_intel_output = NULL; | ||
317 | uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; | ||
318 | struct drm_encoder *encoder; | ||
319 | |||
320 | if (!gma_power_begin(dev, true)) | ||
321 | return 0; | ||
322 | |||
323 | memcpy(&psb_intel_crtc->saved_mode, | ||
324 | mode, | ||
325 | sizeof(struct drm_display_mode)); | ||
326 | memcpy(&psb_intel_crtc->saved_adjusted_mode, | ||
327 | adjusted_mode, | ||
328 | sizeof(struct drm_display_mode)); | ||
329 | |||
330 | list_for_each_entry(encoder, &mode_config->encoder_list, head) { | ||
331 | |||
332 | if (encoder->crtc != crtc) | ||
333 | continue; | ||
334 | |||
335 | psb_intel_output = enc_to_psb_intel_output(encoder); | ||
336 | switch (psb_intel_output->type) { | ||
337 | case INTEL_OUTPUT_LVDS: | ||
338 | is_lvds = true; | ||
339 | break; | ||
340 | case INTEL_OUTPUT_SDVO: | ||
341 | is_sdvo = true; | ||
342 | break; | ||
343 | case INTEL_OUTPUT_TVOUT: | ||
344 | is_tv = true; | ||
345 | break; | ||
346 | case INTEL_OUTPUT_ANALOG: | ||
347 | is_crt = true; | ||
348 | break; | ||
349 | case INTEL_OUTPUT_MIPI: | ||
350 | is_mipi = true; | ||
351 | break; | ||
352 | } | ||
353 | } | ||
354 | |||
355 | /* Disable the VGA plane that we never use */ | ||
356 | REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); | ||
357 | |||
358 | /* Disable the panel fitter if it was on our pipe */ | ||
359 | if (mrst_panel_fitter_pipe(dev) == pipe) | ||
360 | REG_WRITE(PFIT_CONTROL, 0); | ||
361 | |||
362 | REG_WRITE(pipesrc_reg, | ||
363 | ((mode->crtc_hdisplay - 1) << 16) | | ||
364 | (mode->crtc_vdisplay - 1)); | ||
365 | |||
366 | if (psb_intel_output) | ||
367 | drm_connector_property_get_value(&psb_intel_output->base, | ||
368 | dev->mode_config.scaling_mode_property, &scalingType); | ||
369 | |||
370 | if (scalingType == DRM_MODE_SCALE_NO_SCALE) { | ||
371 | /* Moorestown doesn't have register support for centering so | ||
372 | * we need to mess with the h/vblank and h/vsync start and | ||
373 | * ends to get centering */ | ||
374 | int offsetX = 0, offsetY = 0; | ||
375 | |||
376 | offsetX = (adjusted_mode->crtc_hdisplay - | ||
377 | mode->crtc_hdisplay) / 2; | ||
378 | offsetY = (adjusted_mode->crtc_vdisplay - | ||
379 | mode->crtc_vdisplay) / 2; | ||
380 | |||
381 | REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) | | ||
382 | ((adjusted_mode->crtc_htotal - 1) << 16)); | ||
383 | REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) | | ||
384 | ((adjusted_mode->crtc_vtotal - 1) << 16)); | ||
385 | REG_WRITE(hblank_reg, | ||
386 | (adjusted_mode->crtc_hblank_start - offsetX - 1) | | ||
387 | ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16)); | ||
388 | REG_WRITE(hsync_reg, | ||
389 | (adjusted_mode->crtc_hsync_start - offsetX - 1) | | ||
390 | ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16)); | ||
391 | REG_WRITE(vblank_reg, | ||
392 | (adjusted_mode->crtc_vblank_start - offsetY - 1) | | ||
393 | ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16)); | ||
394 | REG_WRITE(vsync_reg, | ||
395 | (adjusted_mode->crtc_vsync_start - offsetY - 1) | | ||
396 | ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16)); | ||
397 | } else { | ||
398 | REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | | ||
399 | ((adjusted_mode->crtc_htotal - 1) << 16)); | ||
400 | REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | | ||
401 | ((adjusted_mode->crtc_vtotal - 1) << 16)); | ||
402 | REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | | ||
403 | ((adjusted_mode->crtc_hblank_end - 1) << 16)); | ||
404 | REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | | ||
405 | ((adjusted_mode->crtc_hsync_end - 1) << 16)); | ||
406 | REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | | ||
407 | ((adjusted_mode->crtc_vblank_end - 1) << 16)); | ||
408 | REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | | ||
409 | ((adjusted_mode->crtc_vsync_end - 1) << 16)); | ||
410 | } | ||
411 | |||
412 | /* Flush the plane changes */ | ||
413 | { | ||
414 | struct drm_crtc_helper_funcs *crtc_funcs = | ||
415 | crtc->helper_private; | ||
416 | crtc_funcs->mode_set_base(crtc, x, y, old_fb); | ||
417 | } | ||
418 | |||
419 | /* setup pipeconf */ | ||
420 | pipeconf = REG_READ(pipeconf_reg); | ||
421 | |||
422 | /* Set up the display plane register */ | ||
423 | dspcntr = REG_READ(dspcntr_reg); | ||
424 | dspcntr |= DISPPLANE_GAMMA_ENABLE; | ||
425 | |||
426 | if (pipe == 0) | ||
427 | dspcntr |= DISPPLANE_SEL_PIPE_A; | ||
428 | else | ||
429 | dspcntr |= DISPPLANE_SEL_PIPE_B; | ||
430 | |||
431 | dev_priv->dspcntr = dspcntr |= DISPLAY_PLANE_ENABLE; | ||
432 | dev_priv->pipeconf = pipeconf |= PIPEACONF_ENABLE; | ||
433 | |||
434 | if (is_mipi) | ||
435 | goto mrst_crtc_mode_set_exit; | ||
436 | |||
437 | refclk = dev_priv->core_freq * 1000; | ||
438 | |||
439 | dpll = 0; /*BIT16 = 0 for 100MHz reference */ | ||
440 | |||
441 | ok = mrstFindBestPLL(crtc, adjusted_mode->clock, refclk, &clock); | ||
442 | |||
443 | if (!ok) { | ||
444 | dev_dbg(dev->dev, "mrstFindBestPLL fail in mrst_crtc_mode_set.\n"); | ||
445 | } else { | ||
446 | dev_dbg(dev->dev, "mrst_crtc_mode_set pixel clock = %d," | ||
447 | "m = %x, p1 = %x.\n", clock.dot, clock.m, | ||
448 | clock.p1); | ||
449 | } | ||
450 | |||
451 | fp = mrst_m_converts[(clock.m - MRST_M_MIN)] << 8; | ||
452 | |||
453 | dpll |= DPLL_VGA_MODE_DIS; | ||
454 | |||
455 | |||
456 | dpll |= DPLL_VCO_ENABLE; | ||
457 | |||
458 | if (is_lvds) | ||
459 | dpll |= DPLLA_MODE_LVDS; | ||
460 | else | ||
461 | dpll |= DPLLB_MODE_DAC_SERIAL; | ||
462 | |||
463 | if (is_sdvo) { | ||
464 | int sdvo_pixel_multiply = | ||
465 | adjusted_mode->clock / mode->clock; | ||
466 | |||
467 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
468 | dpll |= | ||
469 | (sdvo_pixel_multiply - | ||
470 | 1) << SDVO_MULTIPLIER_SHIFT_HIRES; | ||
471 | } | ||
472 | |||
473 | |||
474 | /* compute bitmask from p1 value */ | ||
475 | dpll |= (1 << (clock.p1 - 2)) << 17; | ||
476 | |||
477 | dpll |= DPLL_VCO_ENABLE; | ||
478 | |||
479 | mrstPrintPll("chosen", &clock); | ||
480 | |||
481 | if (dpll & DPLL_VCO_ENABLE) { | ||
482 | REG_WRITE(fp_reg, fp); | ||
483 | REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); | ||
484 | REG_READ(dpll_reg); | ||
485 | /* Check the DPLLA lock bit PIPEACONF[29] */ | ||
486 | udelay(150); | ||
487 | } | ||
488 | |||
489 | REG_WRITE(fp_reg, fp); | ||
490 | REG_WRITE(dpll_reg, dpll); | ||
491 | REG_READ(dpll_reg); | ||
492 | /* Wait for the clocks to stabilize. */ | ||
493 | udelay(150); | ||
494 | |||
495 | /* write it again -- the BIOS does, after all */ | ||
496 | REG_WRITE(dpll_reg, dpll); | ||
497 | REG_READ(dpll_reg); | ||
498 | /* Wait for the clocks to stabilize. */ | ||
499 | udelay(150); | ||
500 | |||
501 | REG_WRITE(pipeconf_reg, pipeconf); | ||
502 | REG_READ(pipeconf_reg); | ||
503 | psb_intel_wait_for_vblank(dev); | ||
504 | |||
505 | REG_WRITE(dspcntr_reg, dspcntr); | ||
506 | psb_intel_wait_for_vblank(dev); | ||
507 | |||
508 | mrst_crtc_mode_set_exit: | ||
509 | gma_power_end(dev); | ||
510 | return 0; | ||
511 | } | ||
512 | |||
513 | static bool mrst_crtc_mode_fixup(struct drm_crtc *crtc, | ||
514 | struct drm_display_mode *mode, | ||
515 | struct drm_display_mode *adjusted_mode) | ||
516 | { | ||
517 | return true; | ||
518 | } | ||
519 | |||
520 | int mrst_pipe_set_base(struct drm_crtc *crtc, | ||
521 | int x, int y, struct drm_framebuffer *old_fb) | ||
522 | { | ||
523 | struct drm_device *dev = crtc->dev; | ||
524 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
525 | struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); | ||
526 | int pipe = psb_intel_crtc->pipe; | ||
527 | unsigned long start, offset; | ||
528 | |||
529 | int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE); | ||
530 | int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); | ||
531 | int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | ||
532 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
533 | u32 dspcntr; | ||
534 | int ret = 0; | ||
535 | |||
536 | /* no fb bound */ | ||
537 | if (!crtc->fb) { | ||
538 | dev_dbg(dev->dev, "No FB bound\n"); | ||
539 | return 0; | ||
540 | } | ||
541 | |||
542 | if (!gma_power_begin(dev, true)) | ||
543 | return 0; | ||
544 | |||
545 | start = psbfb->gtt->offset; | ||
546 | offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); | ||
547 | |||
548 | REG_WRITE(dspstride, crtc->fb->pitches[0]); | ||
549 | |||
550 | dspcntr = REG_READ(dspcntr_reg); | ||
551 | dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; | ||
552 | |||
553 | switch (crtc->fb->bits_per_pixel) { | ||
554 | case 8: | ||
555 | dspcntr |= DISPPLANE_8BPP; | ||
556 | break; | ||
557 | case 16: | ||
558 | if (crtc->fb->depth == 15) | ||
559 | dspcntr |= DISPPLANE_15_16BPP; | ||
560 | else | ||
561 | dspcntr |= DISPPLANE_16BPP; | ||
562 | break; | ||
563 | case 24: | ||
564 | case 32: | ||
565 | dspcntr |= DISPPLANE_32BPP_NO_ALPHA; | ||
566 | break; | ||
567 | default: | ||
568 | dev_err(dev->dev, "Unknown color depth\n"); | ||
569 | ret = -EINVAL; | ||
570 | goto pipe_set_base_exit; | ||
571 | } | ||
572 | REG_WRITE(dspcntr_reg, dspcntr); | ||
573 | |||
574 | REG_WRITE(dspbase, offset); | ||
575 | REG_READ(dspbase); | ||
576 | REG_WRITE(dspsurf, start); | ||
577 | REG_READ(dspsurf); | ||
578 | |||
579 | pipe_set_base_exit: | ||
580 | gma_power_end(dev); | ||
581 | return ret; | ||
582 | } | ||
583 | |||
584 | static void mrst_crtc_prepare(struct drm_crtc *crtc) | ||
585 | { | ||
586 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
587 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); | ||
588 | } | ||
589 | |||
590 | static void mrst_crtc_commit(struct drm_crtc *crtc) | ||
591 | { | ||
592 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
593 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); | ||
594 | } | ||
595 | |||
596 | const struct drm_crtc_helper_funcs mrst_helper_funcs = { | ||
597 | .dpms = mrst_crtc_dpms, | ||
598 | .mode_fixup = mrst_crtc_mode_fixup, | ||
599 | .mode_set = mrst_crtc_mode_set, | ||
600 | .mode_set_base = mrst_pipe_set_base, | ||
601 | .prepare = mrst_crtc_prepare, | ||
602 | .commit = mrst_crtc_commit, | ||
603 | }; | ||
604 | |||
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c deleted file mode 100644 index 6707fafbfa1e..000000000000 --- a/drivers/staging/gma500/mrst_device.c +++ /dev/null | |||
@@ -1,634 +0,0 @@ | |||
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 <linux/module.h> | ||
22 | #include <linux/dmi.h> | ||
23 | #include <drm/drmP.h> | ||
24 | #include <drm/drm.h> | ||
25 | #include "psb_drm.h" | ||
26 | #include "psb_drv.h" | ||
27 | #include "psb_reg.h" | ||
28 | #include "psb_intel_reg.h" | ||
29 | #include <asm/mrst.h> | ||
30 | #include <asm/intel_scu_ipc.h> | ||
31 | #include "mid_bios.h" | ||
32 | |||
33 | static int devtype; | ||
34 | |||
35 | module_param_named(type, devtype, int, 0600); | ||
36 | MODULE_PARM_DESC(type, "Moorestown/Oaktrail device type"); | ||
37 | |||
38 | #define DEVICE_MOORESTOWN 1 | ||
39 | #define DEVICE_OAKTRAIL 2 | ||
40 | #define DEVICE_MOORESTOWN_MM 3 | ||
41 | |||
42 | static int mrst_device_ident(struct drm_device *dev) | ||
43 | { | ||
44 | /* User forced */ | ||
45 | if (devtype) | ||
46 | return devtype; | ||
47 | if (dmi_match(DMI_PRODUCT_NAME, "OakTrail") || | ||
48 | dmi_match(DMI_PRODUCT_NAME, "OakTrail platform")) | ||
49 | return DEVICE_OAKTRAIL; | ||
50 | #if defined(CONFIG_X86_MRST) | ||
51 | if (dmi_match(DMI_PRODUCT_NAME, "MM") || | ||
52 | dmi_match(DMI_PRODUCT_NAME, "MM 10")) | ||
53 | return DEVICE_MOORESTOWN_MM; | ||
54 | if (mrst_identify_cpu()) | ||
55 | return DEVICE_MOORESTOWN; | ||
56 | #endif | ||
57 | return DEVICE_OAKTRAIL; | ||
58 | } | ||
59 | |||
60 | |||
61 | /* IPC message and command defines used to enable/disable mipi panel voltages */ | ||
62 | #define IPC_MSG_PANEL_ON_OFF 0xE9 | ||
63 | #define IPC_CMD_PANEL_ON 1 | ||
64 | #define IPC_CMD_PANEL_OFF 0 | ||
65 | |||
66 | static int mrst_output_init(struct drm_device *dev) | ||
67 | { | ||
68 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
69 | if (dev_priv->iLVDS_enable) | ||
70 | mrst_lvds_init(dev, &dev_priv->mode_dev); | ||
71 | else | ||
72 | dev_err(dev->dev, "DSI is not supported\n"); | ||
73 | if (dev_priv->hdmi_priv) | ||
74 | mrst_hdmi_init(dev, &dev_priv->mode_dev); | ||
75 | return 0; | ||
76 | } | ||
77 | |||
78 | /* | ||
79 | * Provide the low level interfaces for the Moorestown backlight | ||
80 | */ | ||
81 | |||
82 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
83 | |||
84 | #define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF | ||
85 | #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ | ||
86 | #define BLC_PWM_FREQ_CALC_CONSTANT 32 | ||
87 | #define MHz 1000000 | ||
88 | #define BLC_ADJUSTMENT_MAX 100 | ||
89 | |||
90 | static struct backlight_device *mrst_backlight_device; | ||
91 | static int mrst_brightness; | ||
92 | |||
93 | static int mrst_set_brightness(struct backlight_device *bd) | ||
94 | { | ||
95 | struct drm_device *dev = bl_get_data(mrst_backlight_device); | ||
96 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
97 | int level = bd->props.brightness; | ||
98 | u32 blc_pwm_ctl; | ||
99 | u32 max_pwm_blc; | ||
100 | |||
101 | /* Percentage 1-100% being valid */ | ||
102 | if (level < 1) | ||
103 | level = 1; | ||
104 | |||
105 | if (gma_power_begin(dev, 0)) { | ||
106 | /* Calculate and set the brightness value */ | ||
107 | max_pwm_blc = REG_READ(BLC_PWM_CTL) >> 16; | ||
108 | blc_pwm_ctl = level * max_pwm_blc / 100; | ||
109 | |||
110 | /* Adjust the backlight level with the percent in | ||
111 | * dev_priv->blc_adj1; | ||
112 | */ | ||
113 | blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj1; | ||
114 | blc_pwm_ctl = blc_pwm_ctl / 100; | ||
115 | |||
116 | /* Adjust the backlight level with the percent in | ||
117 | * dev_priv->blc_adj2; | ||
118 | */ | ||
119 | blc_pwm_ctl = blc_pwm_ctl * dev_priv->blc_adj2; | ||
120 | blc_pwm_ctl = blc_pwm_ctl / 100; | ||
121 | |||
122 | /* force PWM bit on */ | ||
123 | REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); | ||
124 | REG_WRITE(BLC_PWM_CTL, (max_pwm_blc << 16) | blc_pwm_ctl); | ||
125 | gma_power_end(dev); | ||
126 | } | ||
127 | mrst_brightness = level; | ||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static int mrst_get_brightness(struct backlight_device *bd) | ||
132 | { | ||
133 | /* return locally cached var instead of HW read (due to DPST etc.) */ | ||
134 | /* FIXME: ideally return actual value in case firmware fiddled with | ||
135 | it */ | ||
136 | return mrst_brightness; | ||
137 | } | ||
138 | |||
139 | static int device_backlight_init(struct drm_device *dev) | ||
140 | { | ||
141 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
142 | unsigned long core_clock; | ||
143 | u16 bl_max_freq; | ||
144 | uint32_t value; | ||
145 | uint32_t blc_pwm_precision_factor; | ||
146 | |||
147 | dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX; | ||
148 | dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX; | ||
149 | bl_max_freq = 256; | ||
150 | /* this needs to be set elsewhere */ | ||
151 | blc_pwm_precision_factor = BLC_PWM_PRECISION_FACTOR; | ||
152 | |||
153 | core_clock = dev_priv->core_freq; | ||
154 | |||
155 | value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; | ||
156 | value *= blc_pwm_precision_factor; | ||
157 | value /= bl_max_freq; | ||
158 | value /= blc_pwm_precision_factor; | ||
159 | |||
160 | if (value > (unsigned long long)MRST_BLC_MAX_PWM_REG_FREQ) | ||
161 | return -ERANGE; | ||
162 | |||
163 | if (gma_power_begin(dev, false)) { | ||
164 | REG_WRITE(BLC_PWM_CTL2, (0x80000000 | REG_READ(BLC_PWM_CTL2))); | ||
165 | REG_WRITE(BLC_PWM_CTL, value | (value << 16)); | ||
166 | gma_power_end(dev); | ||
167 | } | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static const struct backlight_ops mrst_ops = { | ||
172 | .get_brightness = mrst_get_brightness, | ||
173 | .update_status = mrst_set_brightness, | ||
174 | }; | ||
175 | |||
176 | int mrst_backlight_init(struct drm_device *dev) | ||
177 | { | ||
178 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
179 | int ret; | ||
180 | struct backlight_properties props; | ||
181 | |||
182 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
183 | props.max_brightness = 100; | ||
184 | props.type = BACKLIGHT_PLATFORM; | ||
185 | |||
186 | mrst_backlight_device = backlight_device_register("mrst-bl", | ||
187 | NULL, (void *)dev, &mrst_ops, &props); | ||
188 | |||
189 | if (IS_ERR(mrst_backlight_device)) | ||
190 | return PTR_ERR(mrst_backlight_device); | ||
191 | |||
192 | ret = device_backlight_init(dev); | ||
193 | if (ret < 0) { | ||
194 | backlight_device_unregister(mrst_backlight_device); | ||
195 | return ret; | ||
196 | } | ||
197 | mrst_backlight_device->props.brightness = 100; | ||
198 | mrst_backlight_device->props.max_brightness = 100; | ||
199 | backlight_update_status(mrst_backlight_device); | ||
200 | dev_priv->backlight_device = mrst_backlight_device; | ||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | #endif | ||
205 | |||
206 | /* | ||
207 | * Provide the Moorestown specific chip logic and low level methods | ||
208 | * for power management | ||
209 | */ | ||
210 | |||
211 | static void mrst_init_pm(struct drm_device *dev) | ||
212 | { | ||
213 | } | ||
214 | |||
215 | /** | ||
216 | * mrst_save_display_registers - save registers lost on suspend | ||
217 | * @dev: our DRM device | ||
218 | * | ||
219 | * Save the state we need in order to be able to restore the interface | ||
220 | * upon resume from suspend | ||
221 | */ | ||
222 | static int mrst_save_display_registers(struct drm_device *dev) | ||
223 | { | ||
224 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
225 | int i; | ||
226 | u32 pp_stat; | ||
227 | |||
228 | /* Display arbitration control + watermarks */ | ||
229 | dev_priv->saveDSPARB = PSB_RVDC32(DSPARB); | ||
230 | dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1); | ||
231 | dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2); | ||
232 | dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3); | ||
233 | dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4); | ||
234 | dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5); | ||
235 | dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6); | ||
236 | dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); | ||
237 | |||
238 | /* Pipe & plane A info */ | ||
239 | dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF); | ||
240 | dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC); | ||
241 | dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0); | ||
242 | dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1); | ||
243 | dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A); | ||
244 | dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A); | ||
245 | dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A); | ||
246 | dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A); | ||
247 | dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A); | ||
248 | dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A); | ||
249 | dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A); | ||
250 | dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A); | ||
251 | dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR); | ||
252 | dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE); | ||
253 | dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE); | ||
254 | dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF); | ||
255 | dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF); | ||
256 | dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF); | ||
257 | |||
258 | /* Save cursor regs */ | ||
259 | dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR); | ||
260 | dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE); | ||
261 | dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS); | ||
262 | |||
263 | /* Save palette (gamma) */ | ||
264 | for (i = 0; i < 256; i++) | ||
265 | dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2)); | ||
266 | |||
267 | if (dev_priv->hdmi_priv) | ||
268 | mrst_hdmi_save(dev); | ||
269 | |||
270 | /* Save performance state */ | ||
271 | dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE); | ||
272 | |||
273 | /* LVDS state */ | ||
274 | dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL); | ||
275 | dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS); | ||
276 | dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS); | ||
277 | dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL); | ||
278 | dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2); | ||
279 | dev_priv->saveLVDS = PSB_RVDC32(LVDS); | ||
280 | dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL); | ||
281 | dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON); | ||
282 | dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF); | ||
283 | dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE); | ||
284 | |||
285 | /* HW overlay */ | ||
286 | dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD); | ||
287 | dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0); | ||
288 | dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1); | ||
289 | dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2); | ||
290 | dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3); | ||
291 | dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4); | ||
292 | dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5); | ||
293 | |||
294 | /* DPST registers */ | ||
295 | dev_priv->saveHISTOGRAM_INT_CONTROL_REG = | ||
296 | PSB_RVDC32(HISTOGRAM_INT_CONTROL); | ||
297 | dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG = | ||
298 | PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); | ||
299 | dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC); | ||
300 | |||
301 | if (dev_priv->iLVDS_enable) { | ||
302 | /* Shut down the panel */ | ||
303 | PSB_WVDC32(0, PP_CONTROL); | ||
304 | |||
305 | do { | ||
306 | pp_stat = PSB_RVDC32(PP_STATUS); | ||
307 | } while (pp_stat & 0x80000000); | ||
308 | |||
309 | /* Turn off the plane */ | ||
310 | PSB_WVDC32(0x58000000, DSPACNTR); | ||
311 | /* Trigger the plane disable */ | ||
312 | PSB_WVDC32(0, DSPASURF); | ||
313 | |||
314 | /* Wait ~4 ticks */ | ||
315 | msleep(4); | ||
316 | |||
317 | /* Turn off pipe */ | ||
318 | PSB_WVDC32(0x0, PIPEACONF); | ||
319 | /* Wait ~8 ticks */ | ||
320 | msleep(8); | ||
321 | |||
322 | /* Turn off PLLs */ | ||
323 | PSB_WVDC32(0, MRST_DPLL_A); | ||
324 | } | ||
325 | return 0; | ||
326 | } | ||
327 | |||
328 | /** | ||
329 | * mrst_restore_display_registers - restore lost register state | ||
330 | * @dev: our DRM device | ||
331 | * | ||
332 | * Restore register state that was lost during suspend and resume. | ||
333 | */ | ||
334 | static int mrst_restore_display_registers(struct drm_device *dev) | ||
335 | { | ||
336 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
337 | u32 pp_stat; | ||
338 | int i; | ||
339 | |||
340 | /* Display arbitration + watermarks */ | ||
341 | PSB_WVDC32(dev_priv->saveDSPARB, DSPARB); | ||
342 | PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1); | ||
343 | PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2); | ||
344 | PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3); | ||
345 | PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4); | ||
346 | PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5); | ||
347 | PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6); | ||
348 | PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT); | ||
349 | |||
350 | /* Make sure VGA plane is off. it initializes to on after reset!*/ | ||
351 | PSB_WVDC32(0x80000000, VGACNTRL); | ||
352 | |||
353 | /* set the plls */ | ||
354 | PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0); | ||
355 | PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1); | ||
356 | |||
357 | /* Actually enable it */ | ||
358 | PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A); | ||
359 | DRM_UDELAY(150); | ||
360 | |||
361 | /* Restore mode */ | ||
362 | PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A); | ||
363 | PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A); | ||
364 | PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A); | ||
365 | PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A); | ||
366 | PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A); | ||
367 | PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A); | ||
368 | PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC); | ||
369 | PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A); | ||
370 | |||
371 | /* Restore performance mode*/ | ||
372 | PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE); | ||
373 | |||
374 | /* Enable the pipe*/ | ||
375 | if (dev_priv->iLVDS_enable) | ||
376 | PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF); | ||
377 | |||
378 | /* Set up the plane*/ | ||
379 | PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF); | ||
380 | PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE); | ||
381 | PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF); | ||
382 | |||
383 | /* Enable the plane */ | ||
384 | PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR); | ||
385 | PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF); | ||
386 | |||
387 | /* Enable Cursor A */ | ||
388 | PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR); | ||
389 | PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS); | ||
390 | PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE); | ||
391 | |||
392 | /* Restore palette (gamma) */ | ||
393 | for (i = 0; i < 256; i++) | ||
394 | PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2)); | ||
395 | |||
396 | if (dev_priv->hdmi_priv) | ||
397 | mrst_hdmi_restore(dev); | ||
398 | |||
399 | if (dev_priv->iLVDS_enable) { | ||
400 | PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2); | ||
401 | PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/ | ||
402 | PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL); | ||
403 | PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS); | ||
404 | PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS); | ||
405 | PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL); | ||
406 | PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON); | ||
407 | PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF); | ||
408 | PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE); | ||
409 | PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL); | ||
410 | } | ||
411 | |||
412 | /* Wait for cycle delay */ | ||
413 | do { | ||
414 | pp_stat = PSB_RVDC32(PP_STATUS); | ||
415 | } while (pp_stat & 0x08000000); | ||
416 | |||
417 | /* Wait for panel power up */ | ||
418 | do { | ||
419 | pp_stat = PSB_RVDC32(PP_STATUS); | ||
420 | } while (pp_stat & 0x10000000); | ||
421 | |||
422 | /* Restore HW overlay */ | ||
423 | PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD); | ||
424 | PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0); | ||
425 | PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1); | ||
426 | PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2); | ||
427 | PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3); | ||
428 | PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4); | ||
429 | PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5); | ||
430 | |||
431 | /* DPST registers */ | ||
432 | PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG, | ||
433 | HISTOGRAM_INT_CONTROL); | ||
434 | PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG, | ||
435 | HISTOGRAM_LOGIC_CONTROL); | ||
436 | PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC); | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | |||
441 | /** | ||
442 | * mrst_power_down - power down the display island | ||
443 | * @dev: our DRM device | ||
444 | * | ||
445 | * Power down the display interface of our device | ||
446 | */ | ||
447 | static int mrst_power_down(struct drm_device *dev) | ||
448 | { | ||
449 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
450 | u32 pwr_mask ; | ||
451 | u32 pwr_sts; | ||
452 | |||
453 | pwr_mask = PSB_PWRGT_DISPLAY_MASK; | ||
454 | outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC); | ||
455 | |||
456 | while (true) { | ||
457 | pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); | ||
458 | if ((pwr_sts & pwr_mask) == pwr_mask) | ||
459 | break; | ||
460 | else | ||
461 | udelay(10); | ||
462 | } | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | /* | ||
467 | * mrst_power_up | ||
468 | * | ||
469 | * Restore power to the specified island(s) (powergating) | ||
470 | */ | ||
471 | static int mrst_power_up(struct drm_device *dev) | ||
472 | { | ||
473 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
474 | u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK; | ||
475 | u32 pwr_sts, pwr_cnt; | ||
476 | |||
477 | pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC); | ||
478 | pwr_cnt &= ~pwr_mask; | ||
479 | outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC)); | ||
480 | |||
481 | while (true) { | ||
482 | pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS); | ||
483 | if ((pwr_sts & pwr_mask) == 0) | ||
484 | break; | ||
485 | else | ||
486 | udelay(10); | ||
487 | } | ||
488 | return 0; | ||
489 | } | ||
490 | |||
491 | #if defined(CONFIG_X86_MRST) | ||
492 | static void mrst_lvds_cache_bl(struct drm_device *dev) | ||
493 | { | ||
494 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
495 | |||
496 | intel_scu_ipc_ioread8(0x28, &(dev_priv->saveBKLTCNT)); | ||
497 | intel_scu_ipc_ioread8(0x29, &(dev_priv->saveBKLTREQ)); | ||
498 | intel_scu_ipc_ioread8(0x2A, &(dev_priv->saveBKLTBRTL)); | ||
499 | } | ||
500 | |||
501 | static void mrst_mm_bl_power(struct drm_device *dev, bool on) | ||
502 | { | ||
503 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
504 | |||
505 | if (on) { | ||
506 | intel_scu_ipc_iowrite8(0x2A, dev_priv->saveBKLTBRTL); | ||
507 | intel_scu_ipc_iowrite8(0x28, dev_priv->saveBKLTCNT); | ||
508 | intel_scu_ipc_iowrite8(0x29, dev_priv->saveBKLTREQ); | ||
509 | } else { | ||
510 | intel_scu_ipc_iowrite8(0x2A, 0); | ||
511 | intel_scu_ipc_iowrite8(0x28, 0); | ||
512 | intel_scu_ipc_iowrite8(0x29, 0); | ||
513 | } | ||
514 | } | ||
515 | |||
516 | static const struct psb_ops mrst_mm_chip_ops = { | ||
517 | .name = "Moorestown MM ", | ||
518 | .accel_2d = 1, | ||
519 | .pipes = 1, | ||
520 | .crtcs = 1, | ||
521 | .sgx_offset = MRST_SGX_OFFSET, | ||
522 | |||
523 | .crtc_helper = &mrst_helper_funcs, | ||
524 | .crtc_funcs = &psb_intel_crtc_funcs, | ||
525 | |||
526 | .output_init = mrst_output_init, | ||
527 | |||
528 | .lvds_bl_power = mrst_mm_bl_power, | ||
529 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
530 | .backlight_init = mrst_backlight_init, | ||
531 | #endif | ||
532 | |||
533 | .init_pm = mrst_init_pm, | ||
534 | .save_regs = mrst_save_display_registers, | ||
535 | .restore_regs = mrst_restore_display_registers, | ||
536 | .power_down = mrst_power_down, | ||
537 | .power_up = mrst_power_up, | ||
538 | |||
539 | .i2c_bus = 0, | ||
540 | }; | ||
541 | |||
542 | #endif | ||
543 | |||
544 | static void oaktrail_teardown(struct drm_device *dev) | ||
545 | { | ||
546 | mrst_hdmi_teardown(dev); | ||
547 | } | ||
548 | |||
549 | static const struct psb_ops oaktrail_chip_ops = { | ||
550 | .name = "Oaktrail", | ||
551 | .accel_2d = 1, | ||
552 | .pipes = 2, | ||
553 | .crtcs = 2, | ||
554 | .sgx_offset = MRST_SGX_OFFSET, | ||
555 | |||
556 | .chip_setup = mid_chip_setup, | ||
557 | .chip_teardown = oaktrail_teardown, | ||
558 | .crtc_helper = &mrst_helper_funcs, | ||
559 | .crtc_funcs = &psb_intel_crtc_funcs, | ||
560 | |||
561 | .output_init = mrst_output_init, | ||
562 | |||
563 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
564 | .backlight_init = mrst_backlight_init, | ||
565 | #endif | ||
566 | |||
567 | .init_pm = mrst_init_pm, | ||
568 | .save_regs = mrst_save_display_registers, | ||
569 | .restore_regs = mrst_restore_display_registers, | ||
570 | .power_down = mrst_power_down, | ||
571 | .power_up = mrst_power_up, | ||
572 | |||
573 | .i2c_bus = 1, | ||
574 | }; | ||
575 | |||
576 | /** | ||
577 | * mrst_chip_setup - perform the initial chip init | ||
578 | * @dev: Our drm_device | ||
579 | * | ||
580 | * Figure out which incarnation we are and then scan the firmware for | ||
581 | * tables and information. | ||
582 | */ | ||
583 | static int mrst_chip_setup(struct drm_device *dev) | ||
584 | { | ||
585 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
586 | |||
587 | switch (mrst_device_ident(dev)) { | ||
588 | case DEVICE_OAKTRAIL: | ||
589 | /* Dual CRTC, PC compatible, HDMI, I2C #2 */ | ||
590 | dev_priv->ops = &oaktrail_chip_ops; | ||
591 | mrst_hdmi_setup(dev); | ||
592 | return mid_chip_setup(dev); | ||
593 | #if defined(CONFIG_X86_MRST) | ||
594 | case DEVICE_MOORESTOWN_MM: | ||
595 | /* Single CRTC, No HDMI, I2C #0, BL control */ | ||
596 | mrst_lvds_cache_bl(dev); | ||
597 | dev_priv->ops = &mrst_mm_chip_ops; | ||
598 | return mid_chip_setup(dev); | ||
599 | case DEVICE_MOORESTOWN: | ||
600 | /* Dual CRTC, No HDMI(?), I2C #1 */ | ||
601 | return mid_chip_setup(dev); | ||
602 | #endif | ||
603 | default: | ||
604 | dev_err(dev->dev, "unsupported device type.\n"); | ||
605 | return -ENODEV; | ||
606 | } | ||
607 | } | ||
608 | |||
609 | const struct psb_ops mrst_chip_ops = { | ||
610 | .name = "Moorestown", | ||
611 | .accel_2d = 1, | ||
612 | .pipes = 2, | ||
613 | .crtcs = 2, | ||
614 | .sgx_offset = MRST_SGX_OFFSET, | ||
615 | |||
616 | .chip_setup = mrst_chip_setup, | ||
617 | .crtc_helper = &mrst_helper_funcs, | ||
618 | .crtc_funcs = &psb_intel_crtc_funcs, | ||
619 | |||
620 | .output_init = mrst_output_init, | ||
621 | |||
622 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
623 | .backlight_init = mrst_backlight_init, | ||
624 | #endif | ||
625 | |||
626 | .init_pm = mrst_init_pm, | ||
627 | .save_regs = mrst_save_display_registers, | ||
628 | .restore_regs = mrst_restore_display_registers, | ||
629 | .power_down = mrst_power_down, | ||
630 | .power_up = mrst_power_up, | ||
631 | |||
632 | .i2c_bus = 2, | ||
633 | }; | ||
634 | |||
diff --git a/drivers/staging/gma500/mrst_hdmi.c b/drivers/staging/gma500/mrst_hdmi.c deleted file mode 100644 index e66607eb3d3e..000000000000 --- a/drivers/staging/gma500/mrst_hdmi.c +++ /dev/null | |||
@@ -1,852 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Li Peng <peng.li@intel.com> | ||
25 | */ | ||
26 | |||
27 | #include <drm/drmP.h> | ||
28 | #include <drm/drm.h> | ||
29 | #include "psb_intel_drv.h" | ||
30 | #include "psb_intel_reg.h" | ||
31 | #include "psb_drv.h" | ||
32 | |||
33 | #define HDMI_READ(reg) readl(hdmi_dev->regs + (reg)) | ||
34 | #define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg)) | ||
35 | |||
36 | #define HDMI_HCR 0x1000 | ||
37 | #define HCR_ENABLE_HDCP (1 << 5) | ||
38 | #define HCR_ENABLE_AUDIO (1 << 2) | ||
39 | #define HCR_ENABLE_PIXEL (1 << 1) | ||
40 | #define HCR_ENABLE_TMDS (1 << 0) | ||
41 | |||
42 | #define HDMI_HICR 0x1004 | ||
43 | #define HDMI_HSR 0x1008 | ||
44 | #define HDMI_HISR 0x100C | ||
45 | #define HDMI_DETECT_HDP (1 << 0) | ||
46 | |||
47 | #define HDMI_VIDEO_REG 0x3000 | ||
48 | #define HDMI_UNIT_EN (1 << 7) | ||
49 | #define HDMI_MODE_OUTPUT (1 << 0) | ||
50 | #define HDMI_HBLANK_A 0x3100 | ||
51 | |||
52 | #define HDMI_AUDIO_CTRL 0x4000 | ||
53 | #define HDMI_ENABLE_AUDIO (1 << 0) | ||
54 | |||
55 | #define PCH_HTOTAL_B 0x3100 | ||
56 | #define PCH_HBLANK_B 0x3104 | ||
57 | #define PCH_HSYNC_B 0x3108 | ||
58 | #define PCH_VTOTAL_B 0x310C | ||
59 | #define PCH_VBLANK_B 0x3110 | ||
60 | #define PCH_VSYNC_B 0x3114 | ||
61 | #define PCH_PIPEBSRC 0x311C | ||
62 | |||
63 | #define PCH_PIPEB_DSL 0x3800 | ||
64 | #define PCH_PIPEB_SLC 0x3804 | ||
65 | #define PCH_PIPEBCONF 0x3808 | ||
66 | #define PCH_PIPEBSTAT 0x3824 | ||
67 | |||
68 | #define CDVO_DFT 0x5000 | ||
69 | #define CDVO_SLEWRATE 0x5004 | ||
70 | #define CDVO_STRENGTH 0x5008 | ||
71 | #define CDVO_RCOMP 0x500C | ||
72 | |||
73 | #define DPLL_CTRL 0x6000 | ||
74 | #define DPLL_PDIV_SHIFT 16 | ||
75 | #define DPLL_PDIV_MASK (0xf << 16) | ||
76 | #define DPLL_PWRDN (1 << 4) | ||
77 | #define DPLL_RESET (1 << 3) | ||
78 | #define DPLL_FASTEN (1 << 2) | ||
79 | #define DPLL_ENSTAT (1 << 1) | ||
80 | #define DPLL_DITHEN (1 << 0) | ||
81 | |||
82 | #define DPLL_DIV_CTRL 0x6004 | ||
83 | #define DPLL_CLKF_MASK 0xffffffc0 | ||
84 | #define DPLL_CLKR_MASK (0x3f) | ||
85 | |||
86 | #define DPLL_CLK_ENABLE 0x6008 | ||
87 | #define DPLL_EN_DISP (1 << 31) | ||
88 | #define DPLL_SEL_HDMI (1 << 8) | ||
89 | #define DPLL_EN_HDMI (1 << 1) | ||
90 | #define DPLL_EN_VGA (1 << 0) | ||
91 | |||
92 | #define DPLL_ADJUST 0x600C | ||
93 | #define DPLL_STATUS 0x6010 | ||
94 | #define DPLL_UPDATE 0x6014 | ||
95 | #define DPLL_DFT 0x6020 | ||
96 | |||
97 | struct intel_range { | ||
98 | int min, max; | ||
99 | }; | ||
100 | |||
101 | struct mrst_hdmi_limit { | ||
102 | struct intel_range vco, np, nr, nf; | ||
103 | }; | ||
104 | |||
105 | struct mrst_hdmi_clock { | ||
106 | int np; | ||
107 | int nr; | ||
108 | int nf; | ||
109 | int dot; | ||
110 | }; | ||
111 | |||
112 | #define VCO_MIN 320000 | ||
113 | #define VCO_MAX 1650000 | ||
114 | #define NP_MIN 1 | ||
115 | #define NP_MAX 15 | ||
116 | #define NR_MIN 1 | ||
117 | #define NR_MAX 64 | ||
118 | #define NF_MIN 2 | ||
119 | #define NF_MAX 4095 | ||
120 | |||
121 | static const struct mrst_hdmi_limit mrst_hdmi_limit = { | ||
122 | .vco = { .min = VCO_MIN, .max = VCO_MAX }, | ||
123 | .np = { .min = NP_MIN, .max = NP_MAX }, | ||
124 | .nr = { .min = NR_MIN, .max = NR_MAX }, | ||
125 | .nf = { .min = NF_MIN, .max = NF_MAX }, | ||
126 | }; | ||
127 | |||
128 | static void wait_for_vblank(struct drm_device *dev) | ||
129 | { | ||
130 | /* FIXME: Can we do this as a sleep ? */ | ||
131 | /* Wait for 20ms, i.e. one cycle at 50hz. */ | ||
132 | mdelay(20); | ||
133 | } | ||
134 | |||
135 | static void scu_busy_loop(void *scu_base) | ||
136 | { | ||
137 | u32 status = 0; | ||
138 | u32 loop_count = 0; | ||
139 | |||
140 | status = readl(scu_base + 0x04); | ||
141 | while (status & 1) { | ||
142 | udelay(1); /* scu processing time is in few u secods */ | ||
143 | status = readl(scu_base + 0x04); | ||
144 | loop_count++; | ||
145 | /* break if scu doesn't reset busy bit after huge retry */ | ||
146 | if (loop_count > 1000) { | ||
147 | DRM_DEBUG_KMS("SCU IPC timed out"); | ||
148 | return; | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | |||
153 | static void mrst_hdmi_reset(struct drm_device *dev) | ||
154 | { | ||
155 | void *base; | ||
156 | /* FIXME: at least make these defines */ | ||
157 | unsigned int scu_ipc_mmio = 0xff11c000; | ||
158 | int scu_len = 1024; | ||
159 | |||
160 | base = ioremap((resource_size_t)scu_ipc_mmio, scu_len); | ||
161 | if (base == NULL) { | ||
162 | DRM_ERROR("failed to map SCU mmio\n"); | ||
163 | return; | ||
164 | } | ||
165 | |||
166 | /* scu ipc: assert hdmi controller reset */ | ||
167 | writel(0xff11d118, base + 0x0c); | ||
168 | writel(0x7fffffdf, base + 0x80); | ||
169 | writel(0x42005, base + 0x0); | ||
170 | scu_busy_loop(base); | ||
171 | |||
172 | /* scu ipc: de-assert hdmi controller reset */ | ||
173 | writel(0xff11d118, base + 0x0c); | ||
174 | writel(0x7fffffff, base + 0x80); | ||
175 | writel(0x42005, base + 0x0); | ||
176 | scu_busy_loop(base); | ||
177 | |||
178 | iounmap(base); | ||
179 | } | ||
180 | |||
181 | static void mrst_hdmi_audio_enable(struct drm_device *dev) | ||
182 | { | ||
183 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
184 | struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; | ||
185 | |||
186 | HDMI_WRITE(HDMI_HCR, 0x67); | ||
187 | HDMI_READ(HDMI_HCR); | ||
188 | |||
189 | HDMI_WRITE(0x51a8, 0x10); | ||
190 | HDMI_READ(0x51a8); | ||
191 | |||
192 | HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1); | ||
193 | HDMI_READ(HDMI_AUDIO_CTRL); | ||
194 | } | ||
195 | |||
196 | static void mrst_hdmi_audio_disable(struct drm_device *dev) | ||
197 | { | ||
198 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
199 | struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; | ||
200 | |||
201 | HDMI_WRITE(0x51a8, 0x0); | ||
202 | HDMI_READ(0x51a8); | ||
203 | |||
204 | HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0); | ||
205 | HDMI_READ(HDMI_AUDIO_CTRL); | ||
206 | |||
207 | HDMI_WRITE(HDMI_HCR, 0x47); | ||
208 | HDMI_READ(HDMI_HCR); | ||
209 | } | ||
210 | |||
211 | void mrst_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode) | ||
212 | { | ||
213 | struct drm_device *dev = crtc->dev; | ||
214 | u32 temp; | ||
215 | |||
216 | switch (mode) { | ||
217 | case DRM_MODE_DPMS_OFF: | ||
218 | /* Disable VGACNTRL */ | ||
219 | REG_WRITE(VGACNTRL, 0x80000000); | ||
220 | |||
221 | /* Disable plane */ | ||
222 | temp = REG_READ(DSPBCNTR); | ||
223 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | ||
224 | REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE); | ||
225 | REG_READ(DSPBCNTR); | ||
226 | /* Flush the plane changes */ | ||
227 | REG_WRITE(DSPBSURF, REG_READ(DSPBSURF)); | ||
228 | REG_READ(DSPBSURF); | ||
229 | } | ||
230 | |||
231 | /* Disable pipe B */ | ||
232 | temp = REG_READ(PIPEBCONF); | ||
233 | if ((temp & PIPEACONF_ENABLE) != 0) { | ||
234 | REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE); | ||
235 | REG_READ(PIPEBCONF); | ||
236 | } | ||
237 | |||
238 | /* Disable LNW Pipes, etc */ | ||
239 | temp = REG_READ(PCH_PIPEBCONF); | ||
240 | if ((temp & PIPEACONF_ENABLE) != 0) { | ||
241 | REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE); | ||
242 | REG_READ(PCH_PIPEBCONF); | ||
243 | } | ||
244 | /* wait for pipe off */ | ||
245 | udelay(150); | ||
246 | /* Disable dpll */ | ||
247 | temp = REG_READ(DPLL_CTRL); | ||
248 | if ((temp & DPLL_PWRDN) == 0) { | ||
249 | REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET)); | ||
250 | REG_WRITE(DPLL_STATUS, 0x1); | ||
251 | } | ||
252 | /* wait for dpll off */ | ||
253 | udelay(150); | ||
254 | break; | ||
255 | case DRM_MODE_DPMS_ON: | ||
256 | case DRM_MODE_DPMS_STANDBY: | ||
257 | case DRM_MODE_DPMS_SUSPEND: | ||
258 | /* Enable dpll */ | ||
259 | temp = REG_READ(DPLL_CTRL); | ||
260 | if ((temp & DPLL_PWRDN) != 0) { | ||
261 | REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET)); | ||
262 | temp = REG_READ(DPLL_CLK_ENABLE); | ||
263 | REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI); | ||
264 | REG_READ(DPLL_CLK_ENABLE); | ||
265 | } | ||
266 | /* wait for dpll warm up */ | ||
267 | udelay(150); | ||
268 | |||
269 | /* Enable pipe B */ | ||
270 | temp = REG_READ(PIPEBCONF); | ||
271 | if ((temp & PIPEACONF_ENABLE) == 0) { | ||
272 | REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE); | ||
273 | REG_READ(PIPEBCONF); | ||
274 | } | ||
275 | |||
276 | /* Enable LNW Pipe B */ | ||
277 | temp = REG_READ(PCH_PIPEBCONF); | ||
278 | if ((temp & PIPEACONF_ENABLE) == 0) { | ||
279 | REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE); | ||
280 | REG_READ(PCH_PIPEBCONF); | ||
281 | } | ||
282 | wait_for_vblank(dev); | ||
283 | |||
284 | /* Enable plane */ | ||
285 | temp = REG_READ(DSPBCNTR); | ||
286 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
287 | REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE); | ||
288 | /* Flush the plane changes */ | ||
289 | REG_WRITE(DSPBSURF, REG_READ(DSPBSURF)); | ||
290 | REG_READ(DSPBSURF); | ||
291 | } | ||
292 | psb_intel_crtc_load_lut(crtc); | ||
293 | } | ||
294 | /* DSPARB */ | ||
295 | REG_WRITE(DSPARB, 0x00003fbf); | ||
296 | /* FW1 */ | ||
297 | REG_WRITE(0x70034, 0x3f880a0a); | ||
298 | /* FW2 */ | ||
299 | REG_WRITE(0x70038, 0x0b060808); | ||
300 | /* FW4 */ | ||
301 | REG_WRITE(0x70050, 0x08030404); | ||
302 | /* FW5 */ | ||
303 | REG_WRITE(0x70054, 0x04040404); | ||
304 | /* LNC Chicken Bits */ | ||
305 | REG_WRITE(0x70400, 0x4000); | ||
306 | } | ||
307 | |||
308 | |||
309 | static void mrst_hdmi_dpms(struct drm_encoder *encoder, int mode) | ||
310 | { | ||
311 | static int dpms_mode = -1; | ||
312 | |||
313 | struct drm_device *dev = encoder->dev; | ||
314 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
315 | struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; | ||
316 | u32 temp; | ||
317 | |||
318 | if (dpms_mode == mode) | ||
319 | return; | ||
320 | |||
321 | if (mode != DRM_MODE_DPMS_ON) | ||
322 | temp = 0x0; | ||
323 | else | ||
324 | temp = 0x99; | ||
325 | |||
326 | dpms_mode = mode; | ||
327 | HDMI_WRITE(HDMI_VIDEO_REG, temp); | ||
328 | } | ||
329 | |||
330 | static unsigned int htotal_calculate(struct drm_display_mode *mode) | ||
331 | { | ||
332 | u32 htotal, new_crtc_htotal; | ||
333 | |||
334 | htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16); | ||
335 | |||
336 | /* | ||
337 | * 1024 x 768 new_crtc_htotal = 0x1024; | ||
338 | * 1280 x 1024 new_crtc_htotal = 0x0c34; | ||
339 | */ | ||
340 | new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock; | ||
341 | |||
342 | return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16); | ||
343 | } | ||
344 | |||
345 | static void mrst_hdmi_find_dpll(struct drm_crtc *crtc, int target, | ||
346 | int refclk, struct mrst_hdmi_clock *best_clock) | ||
347 | { | ||
348 | int np_min, np_max, nr_min, nr_max; | ||
349 | int np, nr, nf; | ||
350 | |||
351 | np_min = DIV_ROUND_UP(mrst_hdmi_limit.vco.min, target * 10); | ||
352 | np_max = mrst_hdmi_limit.vco.max / (target * 10); | ||
353 | if (np_min < mrst_hdmi_limit.np.min) | ||
354 | np_min = mrst_hdmi_limit.np.min; | ||
355 | if (np_max > mrst_hdmi_limit.np.max) | ||
356 | np_max = mrst_hdmi_limit.np.max; | ||
357 | |||
358 | nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max)); | ||
359 | nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min)); | ||
360 | if (nr_min < mrst_hdmi_limit.nr.min) | ||
361 | nr_min = mrst_hdmi_limit.nr.min; | ||
362 | if (nr_max > mrst_hdmi_limit.nr.max) | ||
363 | nr_max = mrst_hdmi_limit.nr.max; | ||
364 | |||
365 | np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max)); | ||
366 | nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np)); | ||
367 | nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk); | ||
368 | DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf); | ||
369 | |||
370 | /* | ||
371 | * 1024 x 768 np = 1; nr = 0x26; nf = 0x0fd8000; | ||
372 | * 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000; | ||
373 | */ | ||
374 | best_clock->np = np; | ||
375 | best_clock->nr = nr - 1; | ||
376 | best_clock->nf = (nf << 14); | ||
377 | } | ||
378 | |||
379 | int mrst_crtc_hdmi_mode_set(struct drm_crtc *crtc, | ||
380 | struct drm_display_mode *mode, | ||
381 | struct drm_display_mode *adjusted_mode, | ||
382 | int x, int y, | ||
383 | struct drm_framebuffer *old_fb) | ||
384 | { | ||
385 | struct drm_device *dev = crtc->dev; | ||
386 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
387 | struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; | ||
388 | int pipe = 1; | ||
389 | int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
390 | int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
391 | int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
392 | int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
393 | int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
394 | int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
395 | int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; | ||
396 | int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; | ||
397 | int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | ||
398 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
399 | int refclk; | ||
400 | struct mrst_hdmi_clock clock; | ||
401 | u32 dspcntr, pipeconf, dpll, temp; | ||
402 | int dspcntr_reg = DSPBCNTR; | ||
403 | |||
404 | /* Disable the VGA plane that we never use */ | ||
405 | REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); | ||
406 | |||
407 | /* XXX: Disable the panel fitter if it was on our pipe */ | ||
408 | |||
409 | /* Disable dpll if necessary */ | ||
410 | dpll = REG_READ(DPLL_CTRL); | ||
411 | if ((dpll & DPLL_PWRDN) == 0) { | ||
412 | REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET)); | ||
413 | REG_WRITE(DPLL_DIV_CTRL, 0x00000000); | ||
414 | REG_WRITE(DPLL_STATUS, 0x1); | ||
415 | } | ||
416 | udelay(150); | ||
417 | |||
418 | /* reset controller: FIXME - can we sort out the ioremap mess ? */ | ||
419 | iounmap(hdmi_dev->regs); | ||
420 | mrst_hdmi_reset(dev); | ||
421 | |||
422 | /* program and enable dpll */ | ||
423 | refclk = 25000; | ||
424 | mrst_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock); | ||
425 | |||
426 | /* Setting DPLL */ | ||
427 | dpll = REG_READ(DPLL_CTRL); | ||
428 | dpll &= ~DPLL_PDIV_MASK; | ||
429 | dpll &= ~(DPLL_PWRDN | DPLL_RESET); | ||
430 | REG_WRITE(DPLL_CTRL, 0x00000008); | ||
431 | REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr)); | ||
432 | REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1)); | ||
433 | REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN)); | ||
434 | REG_WRITE(DPLL_UPDATE, 0x80000000); | ||
435 | REG_WRITE(DPLL_CLK_ENABLE, 0x80050102); | ||
436 | udelay(150); | ||
437 | |||
438 | hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len); | ||
439 | if (hdmi_dev->regs == NULL) { | ||
440 | DRM_ERROR("failed to do hdmi mmio mapping\n"); | ||
441 | return -ENOMEM; | ||
442 | } | ||
443 | |||
444 | /* configure HDMI */ | ||
445 | HDMI_WRITE(0x1004, 0x1fd); | ||
446 | HDMI_WRITE(0x2000, 0x1); | ||
447 | HDMI_WRITE(0x2008, 0x0); | ||
448 | HDMI_WRITE(0x3130, 0x8); | ||
449 | HDMI_WRITE(0x101c, 0x1800810); | ||
450 | |||
451 | temp = htotal_calculate(adjusted_mode); | ||
452 | REG_WRITE(htot_reg, temp); | ||
453 | REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16)); | ||
454 | REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16)); | ||
455 | REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16)); | ||
456 | REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16)); | ||
457 | REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16)); | ||
458 | REG_WRITE(pipesrc_reg, | ||
459 | ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1)); | ||
460 | |||
461 | REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16)); | ||
462 | REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16)); | ||
463 | REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16)); | ||
464 | REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16)); | ||
465 | REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16)); | ||
466 | REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16)); | ||
467 | REG_WRITE(PCH_PIPEBSRC, | ||
468 | ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1)); | ||
469 | |||
470 | temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start; | ||
471 | HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) | temp); | ||
472 | |||
473 | REG_WRITE(dspsize_reg, | ||
474 | ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); | ||
475 | REG_WRITE(dsppos_reg, 0); | ||
476 | |||
477 | /* Flush the plane changes */ | ||
478 | { | ||
479 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
480 | crtc_funcs->mode_set_base(crtc, x, y, old_fb); | ||
481 | } | ||
482 | |||
483 | /* Set up the display plane register */ | ||
484 | dspcntr = REG_READ(dspcntr_reg); | ||
485 | dspcntr |= DISPPLANE_GAMMA_ENABLE; | ||
486 | dspcntr |= DISPPLANE_SEL_PIPE_B; | ||
487 | dspcntr |= DISPLAY_PLANE_ENABLE; | ||
488 | |||
489 | /* setup pipeconf */ | ||
490 | pipeconf = REG_READ(pipeconf_reg); | ||
491 | pipeconf |= PIPEACONF_ENABLE; | ||
492 | |||
493 | REG_WRITE(pipeconf_reg, pipeconf); | ||
494 | REG_READ(pipeconf_reg); | ||
495 | |||
496 | REG_WRITE(PCH_PIPEBCONF, pipeconf); | ||
497 | REG_READ(PCH_PIPEBCONF); | ||
498 | wait_for_vblank(dev); | ||
499 | |||
500 | REG_WRITE(dspcntr_reg, dspcntr); | ||
501 | wait_for_vblank(dev); | ||
502 | |||
503 | return 0; | ||
504 | } | ||
505 | |||
506 | static int mrst_hdmi_mode_valid(struct drm_connector *connector, | ||
507 | struct drm_display_mode *mode) | ||
508 | { | ||
509 | if (mode->clock > 165000) | ||
510 | return MODE_CLOCK_HIGH; | ||
511 | if (mode->clock < 20000) | ||
512 | return MODE_CLOCK_LOW; | ||
513 | |||
514 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
515 | return MODE_NO_DBLESCAN; | ||
516 | |||
517 | return MODE_OK; | ||
518 | } | ||
519 | |||
520 | static bool mrst_hdmi_mode_fixup(struct drm_encoder *encoder, | ||
521 | struct drm_display_mode *mode, | ||
522 | struct drm_display_mode *adjusted_mode) | ||
523 | { | ||
524 | return true; | ||
525 | } | ||
526 | |||
527 | static enum drm_connector_status | ||
528 | mrst_hdmi_detect(struct drm_connector *connector, bool force) | ||
529 | { | ||
530 | enum drm_connector_status status; | ||
531 | struct drm_device *dev = connector->dev; | ||
532 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
533 | struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; | ||
534 | u32 temp; | ||
535 | |||
536 | temp = HDMI_READ(HDMI_HSR); | ||
537 | DRM_DEBUG_KMS("HDMI_HSR %x\n", temp); | ||
538 | |||
539 | if ((temp & HDMI_DETECT_HDP) != 0) | ||
540 | status = connector_status_connected; | ||
541 | else | ||
542 | status = connector_status_disconnected; | ||
543 | |||
544 | return status; | ||
545 | } | ||
546 | |||
547 | static const unsigned char raw_edid[] = { | ||
548 | 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0, | ||
549 | 0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78, | ||
550 | 0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5, | ||
551 | 0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01, | ||
552 | 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0, | ||
553 | 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a, | ||
554 | 0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35, | ||
555 | 0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44, | ||
556 | 0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20, | ||
557 | 0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a, | ||
558 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d | ||
559 | }; | ||
560 | |||
561 | static int mrst_hdmi_get_modes(struct drm_connector *connector) | ||
562 | { | ||
563 | struct drm_device *dev = connector->dev; | ||
564 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
565 | struct i2c_adapter *i2c_adap; | ||
566 | struct edid *edid; | ||
567 | struct drm_display_mode *mode, *t; | ||
568 | int i = 0, ret = 0; | ||
569 | |||
570 | i2c_adap = i2c_get_adapter(3); | ||
571 | if (i2c_adap == NULL) { | ||
572 | DRM_ERROR("No ddc adapter available!\n"); | ||
573 | edid = (struct edid *)raw_edid; | ||
574 | } else { | ||
575 | edid = (struct edid *)raw_edid; | ||
576 | /* FIXME ? edid = drm_get_edid(connector, i2c_adap); */ | ||
577 | } | ||
578 | |||
579 | if (edid) { | ||
580 | drm_mode_connector_update_edid_property(connector, edid); | ||
581 | ret = drm_add_edid_modes(connector, edid); | ||
582 | connector->display_info.raw_edid = NULL; | ||
583 | } | ||
584 | |||
585 | /* | ||
586 | * prune modes that require frame buffer bigger than stolen mem | ||
587 | */ | ||
588 | list_for_each_entry_safe(mode, t, &connector->probed_modes, head) { | ||
589 | if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) { | ||
590 | i++; | ||
591 | drm_mode_remove(connector, mode); | ||
592 | } | ||
593 | } | ||
594 | return ret - i; | ||
595 | } | ||
596 | |||
597 | static void mrst_hdmi_mode_set(struct drm_encoder *encoder, | ||
598 | struct drm_display_mode *mode, | ||
599 | struct drm_display_mode *adjusted_mode) | ||
600 | { | ||
601 | struct drm_device *dev = encoder->dev; | ||
602 | |||
603 | mrst_hdmi_audio_enable(dev); | ||
604 | return; | ||
605 | } | ||
606 | |||
607 | static void mrst_hdmi_destroy(struct drm_connector *connector) | ||
608 | { | ||
609 | return; | ||
610 | } | ||
611 | |||
612 | static const struct drm_encoder_helper_funcs mrst_hdmi_helper_funcs = { | ||
613 | .dpms = mrst_hdmi_dpms, | ||
614 | .mode_fixup = mrst_hdmi_mode_fixup, | ||
615 | .prepare = psb_intel_encoder_prepare, | ||
616 | .mode_set = mrst_hdmi_mode_set, | ||
617 | .commit = psb_intel_encoder_commit, | ||
618 | }; | ||
619 | |||
620 | static const struct drm_connector_helper_funcs | ||
621 | mrst_hdmi_connector_helper_funcs = { | ||
622 | .get_modes = mrst_hdmi_get_modes, | ||
623 | .mode_valid = mrst_hdmi_mode_valid, | ||
624 | .best_encoder = psb_intel_best_encoder, | ||
625 | }; | ||
626 | |||
627 | static const struct drm_connector_funcs mrst_hdmi_connector_funcs = { | ||
628 | .dpms = drm_helper_connector_dpms, | ||
629 | .detect = mrst_hdmi_detect, | ||
630 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
631 | .destroy = mrst_hdmi_destroy, | ||
632 | }; | ||
633 | |||
634 | static void mrst_hdmi_enc_destroy(struct drm_encoder *encoder) | ||
635 | { | ||
636 | drm_encoder_cleanup(encoder); | ||
637 | } | ||
638 | |||
639 | static const struct drm_encoder_funcs mrst_hdmi_enc_funcs = { | ||
640 | .destroy = mrst_hdmi_enc_destroy, | ||
641 | }; | ||
642 | |||
643 | void mrst_hdmi_init(struct drm_device *dev, | ||
644 | struct psb_intel_mode_device *mode_dev) | ||
645 | { | ||
646 | struct psb_intel_output *psb_intel_output; | ||
647 | struct drm_connector *connector; | ||
648 | struct drm_encoder *encoder; | ||
649 | |||
650 | psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); | ||
651 | if (!psb_intel_output) | ||
652 | return; | ||
653 | |||
654 | psb_intel_output->mode_dev = mode_dev; | ||
655 | connector = &psb_intel_output->base; | ||
656 | encoder = &psb_intel_output->enc; | ||
657 | drm_connector_init(dev, &psb_intel_output->base, | ||
658 | &mrst_hdmi_connector_funcs, | ||
659 | DRM_MODE_CONNECTOR_DVID); | ||
660 | |||
661 | drm_encoder_init(dev, &psb_intel_output->enc, | ||
662 | &mrst_hdmi_enc_funcs, | ||
663 | DRM_MODE_ENCODER_TMDS); | ||
664 | |||
665 | drm_mode_connector_attach_encoder(&psb_intel_output->base, | ||
666 | &psb_intel_output->enc); | ||
667 | |||
668 | psb_intel_output->type = INTEL_OUTPUT_HDMI; | ||
669 | drm_encoder_helper_add(encoder, &mrst_hdmi_helper_funcs); | ||
670 | drm_connector_helper_add(connector, &mrst_hdmi_connector_helper_funcs); | ||
671 | |||
672 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | ||
673 | connector->interlace_allowed = false; | ||
674 | connector->doublescan_allowed = false; | ||
675 | drm_sysfs_connector_add(connector); | ||
676 | |||
677 | return; | ||
678 | } | ||
679 | |||
680 | static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = { | ||
681 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) }, | ||
682 | {} | ||
683 | }; | ||
684 | |||
685 | void mrst_hdmi_setup(struct drm_device *dev) | ||
686 | { | ||
687 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
688 | struct pci_dev *pdev; | ||
689 | struct mrst_hdmi_dev *hdmi_dev; | ||
690 | int ret; | ||
691 | |||
692 | pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL); | ||
693 | if (!pdev) | ||
694 | return; | ||
695 | |||
696 | hdmi_dev = kzalloc(sizeof(struct mrst_hdmi_dev), GFP_KERNEL); | ||
697 | if (!hdmi_dev) { | ||
698 | dev_err(dev->dev, "failed to allocate memory\n"); | ||
699 | goto out; | ||
700 | } | ||
701 | |||
702 | |||
703 | ret = pci_enable_device(pdev); | ||
704 | if (ret) { | ||
705 | dev_err(dev->dev, "failed to enable hdmi controller\n"); | ||
706 | goto free; | ||
707 | } | ||
708 | |||
709 | hdmi_dev->mmio = pci_resource_start(pdev, 0); | ||
710 | hdmi_dev->mmio_len = pci_resource_len(pdev, 0); | ||
711 | hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len); | ||
712 | if (!hdmi_dev->regs) { | ||
713 | dev_err(dev->dev, "failed to map hdmi mmio\n"); | ||
714 | goto free; | ||
715 | } | ||
716 | |||
717 | hdmi_dev->dev = pdev; | ||
718 | pci_set_drvdata(pdev, hdmi_dev); | ||
719 | |||
720 | /* Initialize i2c controller */ | ||
721 | ret = mrst_hdmi_i2c_init(hdmi_dev->dev); | ||
722 | if (ret) | ||
723 | dev_err(dev->dev, "HDMI I2C initialization failed\n"); | ||
724 | |||
725 | dev_priv->hdmi_priv = hdmi_dev; | ||
726 | mrst_hdmi_audio_disable(dev); | ||
727 | return; | ||
728 | |||
729 | free: | ||
730 | kfree(hdmi_dev); | ||
731 | out: | ||
732 | return; | ||
733 | } | ||
734 | |||
735 | void mrst_hdmi_teardown(struct drm_device *dev) | ||
736 | { | ||
737 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
738 | struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; | ||
739 | struct pci_dev *pdev; | ||
740 | |||
741 | if (hdmi_dev) { | ||
742 | pdev = hdmi_dev->dev; | ||
743 | pci_set_drvdata(pdev, NULL); | ||
744 | mrst_hdmi_i2c_exit(pdev); | ||
745 | iounmap(hdmi_dev->regs); | ||
746 | kfree(hdmi_dev); | ||
747 | pci_dev_put(pdev); | ||
748 | } | ||
749 | } | ||
750 | |||
751 | /* save HDMI register state */ | ||
752 | void mrst_hdmi_save(struct drm_device *dev) | ||
753 | { | ||
754 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
755 | struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; | ||
756 | int i; | ||
757 | |||
758 | /* dpll */ | ||
759 | hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL); | ||
760 | hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL); | ||
761 | hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST); | ||
762 | hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE); | ||
763 | hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE); | ||
764 | |||
765 | /* pipe B */ | ||
766 | dev_priv->savePIPEBCONF = PSB_RVDC32(PIPEBCONF); | ||
767 | dev_priv->savePIPEBSRC = PSB_RVDC32(PIPEBSRC); | ||
768 | dev_priv->saveHTOTAL_B = PSB_RVDC32(HTOTAL_B); | ||
769 | dev_priv->saveHBLANK_B = PSB_RVDC32(HBLANK_B); | ||
770 | dev_priv->saveHSYNC_B = PSB_RVDC32(HSYNC_B); | ||
771 | dev_priv->saveVTOTAL_B = PSB_RVDC32(VTOTAL_B); | ||
772 | dev_priv->saveVBLANK_B = PSB_RVDC32(VBLANK_B); | ||
773 | dev_priv->saveVSYNC_B = PSB_RVDC32(VSYNC_B); | ||
774 | |||
775 | hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF); | ||
776 | hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC); | ||
777 | hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B); | ||
778 | hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B); | ||
779 | hdmi_dev->savePCH_HSYNC_B = PSB_RVDC32(PCH_HSYNC_B); | ||
780 | hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B); | ||
781 | hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B); | ||
782 | hdmi_dev->savePCH_VSYNC_B = PSB_RVDC32(PCH_VSYNC_B); | ||
783 | |||
784 | /* plane */ | ||
785 | dev_priv->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR); | ||
786 | dev_priv->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE); | ||
787 | dev_priv->saveDSPBADDR = PSB_RVDC32(DSPBBASE); | ||
788 | dev_priv->saveDSPBSURF = PSB_RVDC32(DSPBSURF); | ||
789 | dev_priv->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF); | ||
790 | dev_priv->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF); | ||
791 | |||
792 | /* cursor B */ | ||
793 | dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR); | ||
794 | dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE); | ||
795 | dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS); | ||
796 | |||
797 | /* save palette */ | ||
798 | for (i = 0; i < 256; i++) | ||
799 | dev_priv->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2)); | ||
800 | } | ||
801 | |||
802 | /* restore HDMI register state */ | ||
803 | void mrst_hdmi_restore(struct drm_device *dev) | ||
804 | { | ||
805 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
806 | struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv; | ||
807 | int i; | ||
808 | |||
809 | /* dpll */ | ||
810 | PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL); | ||
811 | PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL); | ||
812 | PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST); | ||
813 | PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE); | ||
814 | PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE); | ||
815 | DRM_UDELAY(150); | ||
816 | |||
817 | /* pipe */ | ||
818 | PSB_WVDC32(dev_priv->savePIPEBSRC, PIPEBSRC); | ||
819 | PSB_WVDC32(dev_priv->saveHTOTAL_B, HTOTAL_B); | ||
820 | PSB_WVDC32(dev_priv->saveHBLANK_B, HBLANK_B); | ||
821 | PSB_WVDC32(dev_priv->saveHSYNC_B, HSYNC_B); | ||
822 | PSB_WVDC32(dev_priv->saveVTOTAL_B, VTOTAL_B); | ||
823 | PSB_WVDC32(dev_priv->saveVBLANK_B, VBLANK_B); | ||
824 | PSB_WVDC32(dev_priv->saveVSYNC_B, VSYNC_B); | ||
825 | |||
826 | PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC); | ||
827 | PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B); | ||
828 | PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B); | ||
829 | PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B, PCH_HSYNC_B); | ||
830 | PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B); | ||
831 | PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B); | ||
832 | PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B, PCH_VSYNC_B); | ||
833 | |||
834 | PSB_WVDC32(dev_priv->savePIPEBCONF, PIPEBCONF); | ||
835 | PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF); | ||
836 | |||
837 | /* plane */ | ||
838 | PSB_WVDC32(dev_priv->saveDSPBLINOFF, DSPBLINOFF); | ||
839 | PSB_WVDC32(dev_priv->saveDSPBSTRIDE, DSPBSTRIDE); | ||
840 | PSB_WVDC32(dev_priv->saveDSPBTILEOFF, DSPBTILEOFF); | ||
841 | PSB_WVDC32(dev_priv->saveDSPBCNTR, DSPBCNTR); | ||
842 | PSB_WVDC32(dev_priv->saveDSPBSURF, DSPBSURF); | ||
843 | |||
844 | /* cursor B */ | ||
845 | PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR); | ||
846 | PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS); | ||
847 | PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE); | ||
848 | |||
849 | /* restore palette */ | ||
850 | for (i = 0; i < 256; i++) | ||
851 | PSB_WVDC32(dev_priv->save_palette_b[i], PALETTE_B + (i << 2)); | ||
852 | } | ||
diff --git a/drivers/staging/gma500/mrst_hdmi_i2c.c b/drivers/staging/gma500/mrst_hdmi_i2c.c deleted file mode 100644 index 36e7edc4d14c..000000000000 --- a/drivers/staging/gma500/mrst_hdmi_i2c.c +++ /dev/null | |||
@@ -1,328 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2010 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 | * Li Peng <peng.li@intel.com> | ||
25 | */ | ||
26 | |||
27 | #include <linux/mutex.h> | ||
28 | #include <linux/pci.h> | ||
29 | #include <linux/i2c.h> | ||
30 | #include <linux/interrupt.h> | ||
31 | #include <linux/delay.h> | ||
32 | #include <linux/export.h> | ||
33 | #include "psb_drv.h" | ||
34 | |||
35 | #define HDMI_READ(reg) readl(hdmi_dev->regs + (reg)) | ||
36 | #define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg)) | ||
37 | |||
38 | #define HDMI_HCR 0x1000 | ||
39 | #define HCR_DETECT_HDP (1 << 6) | ||
40 | #define HCR_ENABLE_HDCP (1 << 5) | ||
41 | #define HCR_ENABLE_AUDIO (1 << 2) | ||
42 | #define HCR_ENABLE_PIXEL (1 << 1) | ||
43 | #define HCR_ENABLE_TMDS (1 << 0) | ||
44 | #define HDMI_HICR 0x1004 | ||
45 | #define HDMI_INTR_I2C_ERROR (1 << 4) | ||
46 | #define HDMI_INTR_I2C_FULL (1 << 3) | ||
47 | #define HDMI_INTR_I2C_DONE (1 << 2) | ||
48 | #define HDMI_INTR_HPD (1 << 0) | ||
49 | #define HDMI_HSR 0x1008 | ||
50 | #define HDMI_HISR 0x100C | ||
51 | #define HDMI_HI2CRDB0 0x1200 | ||
52 | #define HDMI_HI2CHCR 0x1240 | ||
53 | #define HI2C_HDCP_WRITE (0 << 2) | ||
54 | #define HI2C_HDCP_RI_READ (1 << 2) | ||
55 | #define HI2C_HDCP_READ (2 << 2) | ||
56 | #define HI2C_EDID_READ (3 << 2) | ||
57 | #define HI2C_READ_CONTINUE (1 << 1) | ||
58 | #define HI2C_ENABLE_TRANSACTION (1 << 0) | ||
59 | |||
60 | #define HDMI_ICRH 0x1100 | ||
61 | #define HDMI_HI2CTDR0 0x1244 | ||
62 | #define HDMI_HI2CTDR1 0x1248 | ||
63 | |||
64 | #define I2C_STAT_INIT 0 | ||
65 | #define I2C_READ_DONE 1 | ||
66 | #define I2C_TRANSACTION_DONE 2 | ||
67 | |||
68 | struct hdmi_i2c_dev { | ||
69 | struct i2c_adapter *adap; | ||
70 | struct mutex i2c_lock; | ||
71 | struct completion complete; | ||
72 | int status; | ||
73 | struct i2c_msg *msg; | ||
74 | int buf_offset; | ||
75 | }; | ||
76 | |||
77 | static void hdmi_i2c_irq_enable(struct mrst_hdmi_dev *hdmi_dev) | ||
78 | { | ||
79 | u32 temp; | ||
80 | |||
81 | temp = HDMI_READ(HDMI_HICR); | ||
82 | temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE); | ||
83 | HDMI_WRITE(HDMI_HICR, temp); | ||
84 | HDMI_READ(HDMI_HICR); | ||
85 | } | ||
86 | |||
87 | static void hdmi_i2c_irq_disable(struct mrst_hdmi_dev *hdmi_dev) | ||
88 | { | ||
89 | HDMI_WRITE(HDMI_HICR, 0x0); | ||
90 | HDMI_READ(HDMI_HICR); | ||
91 | } | ||
92 | |||
93 | static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg) | ||
94 | { | ||
95 | struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); | ||
96 | struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; | ||
97 | u32 temp; | ||
98 | |||
99 | i2c_dev->status = I2C_STAT_INIT; | ||
100 | i2c_dev->msg = pmsg; | ||
101 | i2c_dev->buf_offset = 0; | ||
102 | INIT_COMPLETION(i2c_dev->complete); | ||
103 | |||
104 | /* Enable I2C transaction */ | ||
105 | temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION; | ||
106 | HDMI_WRITE(HDMI_HI2CHCR, temp); | ||
107 | HDMI_READ(HDMI_HI2CHCR); | ||
108 | |||
109 | while (i2c_dev->status != I2C_TRANSACTION_DONE) | ||
110 | wait_for_completion_interruptible_timeout(&i2c_dev->complete, | ||
111 | 10 * HZ); | ||
112 | |||
113 | return 0; | ||
114 | } | ||
115 | |||
116 | static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg) | ||
117 | { | ||
118 | /* | ||
119 | * XXX: i2c write seems isn't useful for EDID probe, don't do anything | ||
120 | */ | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | static int mrst_hdmi_i2c_access(struct i2c_adapter *adap, | ||
125 | struct i2c_msg *pmsg, | ||
126 | int num) | ||
127 | { | ||
128 | struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap); | ||
129 | struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; | ||
130 | int i, err = 0; | ||
131 | |||
132 | mutex_lock(&i2c_dev->i2c_lock); | ||
133 | |||
134 | /* Enable i2c unit */ | ||
135 | HDMI_WRITE(HDMI_ICRH, 0x00008760); | ||
136 | |||
137 | /* Enable irq */ | ||
138 | hdmi_i2c_irq_enable(hdmi_dev); | ||
139 | for (i = 0; i < num; i++) { | ||
140 | if (pmsg->len && pmsg->buf) { | ||
141 | if (pmsg->flags & I2C_M_RD) | ||
142 | err = xfer_read(adap, pmsg); | ||
143 | else | ||
144 | err = xfer_write(adap, pmsg); | ||
145 | } | ||
146 | pmsg++; /* next message */ | ||
147 | } | ||
148 | |||
149 | /* Disable irq */ | ||
150 | hdmi_i2c_irq_disable(hdmi_dev); | ||
151 | |||
152 | mutex_unlock(&i2c_dev->i2c_lock); | ||
153 | |||
154 | return i; | ||
155 | } | ||
156 | |||
157 | static u32 mrst_hdmi_i2c_func(struct i2c_adapter *adapter) | ||
158 | { | ||
159 | return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; | ||
160 | } | ||
161 | |||
162 | static const struct i2c_algorithm mrst_hdmi_i2c_algorithm = { | ||
163 | .master_xfer = mrst_hdmi_i2c_access, | ||
164 | .functionality = mrst_hdmi_i2c_func, | ||
165 | }; | ||
166 | |||
167 | static struct i2c_adapter mrst_hdmi_i2c_adapter = { | ||
168 | .name = "mrst_hdmi_i2c", | ||
169 | .nr = 3, | ||
170 | .owner = THIS_MODULE, | ||
171 | .class = I2C_CLASS_DDC, | ||
172 | .algo = &mrst_hdmi_i2c_algorithm, | ||
173 | }; | ||
174 | |||
175 | static void hdmi_i2c_read(struct mrst_hdmi_dev *hdmi_dev) | ||
176 | { | ||
177 | struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; | ||
178 | struct i2c_msg *msg = i2c_dev->msg; | ||
179 | u8 *buf = msg->buf; | ||
180 | u32 temp; | ||
181 | int i, offset; | ||
182 | |||
183 | offset = i2c_dev->buf_offset; | ||
184 | for (i = 0; i < 0x10; i++) { | ||
185 | temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4)); | ||
186 | memcpy(buf + (offset + i * 4), &temp, 4); | ||
187 | } | ||
188 | i2c_dev->buf_offset += (0x10 * 4); | ||
189 | |||
190 | /* clearing read buffer full intr */ | ||
191 | temp = HDMI_READ(HDMI_HISR); | ||
192 | HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL); | ||
193 | HDMI_READ(HDMI_HISR); | ||
194 | |||
195 | /* continue read transaction */ | ||
196 | temp = HDMI_READ(HDMI_HI2CHCR); | ||
197 | HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE); | ||
198 | HDMI_READ(HDMI_HI2CHCR); | ||
199 | |||
200 | i2c_dev->status = I2C_READ_DONE; | ||
201 | return; | ||
202 | } | ||
203 | |||
204 | static void hdmi_i2c_transaction_done(struct mrst_hdmi_dev *hdmi_dev) | ||
205 | { | ||
206 | struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; | ||
207 | u32 temp; | ||
208 | |||
209 | /* clear transaction done intr */ | ||
210 | temp = HDMI_READ(HDMI_HISR); | ||
211 | HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE); | ||
212 | HDMI_READ(HDMI_HISR); | ||
213 | |||
214 | |||
215 | temp = HDMI_READ(HDMI_HI2CHCR); | ||
216 | HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION); | ||
217 | HDMI_READ(HDMI_HI2CHCR); | ||
218 | |||
219 | i2c_dev->status = I2C_TRANSACTION_DONE; | ||
220 | return; | ||
221 | } | ||
222 | |||
223 | static irqreturn_t mrst_hdmi_i2c_handler(int this_irq, void *dev) | ||
224 | { | ||
225 | struct mrst_hdmi_dev *hdmi_dev = dev; | ||
226 | struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev; | ||
227 | u32 stat; | ||
228 | |||
229 | stat = HDMI_READ(HDMI_HISR); | ||
230 | |||
231 | if (stat & HDMI_INTR_HPD) { | ||
232 | HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD); | ||
233 | HDMI_READ(HDMI_HISR); | ||
234 | } | ||
235 | |||
236 | if (stat & HDMI_INTR_I2C_FULL) | ||
237 | hdmi_i2c_read(hdmi_dev); | ||
238 | |||
239 | if (stat & HDMI_INTR_I2C_DONE) | ||
240 | hdmi_i2c_transaction_done(hdmi_dev); | ||
241 | |||
242 | complete(&i2c_dev->complete); | ||
243 | |||
244 | return IRQ_HANDLED; | ||
245 | } | ||
246 | |||
247 | /* | ||
248 | * choose alternate function 2 of GPIO pin 52, 53, | ||
249 | * which is used by HDMI I2C logic | ||
250 | */ | ||
251 | static void mrst_hdmi_i2c_gpio_fix(void) | ||
252 | { | ||
253 | void *base; | ||
254 | unsigned int gpio_base = 0xff12c000; | ||
255 | int gpio_len = 0x1000; | ||
256 | u32 temp; | ||
257 | |||
258 | base = ioremap((resource_size_t)gpio_base, gpio_len); | ||
259 | if (base == NULL) { | ||
260 | DRM_ERROR("gpio ioremap fail\n"); | ||
261 | return; | ||
262 | } | ||
263 | |||
264 | temp = readl(base + 0x44); | ||
265 | DRM_DEBUG_DRIVER("old gpio val %x\n", temp); | ||
266 | writel((temp | 0x00000a00), (base + 0x44)); | ||
267 | temp = readl(base + 0x44); | ||
268 | DRM_DEBUG_DRIVER("new gpio val %x\n", temp); | ||
269 | |||
270 | iounmap(base); | ||
271 | } | ||
272 | |||
273 | int mrst_hdmi_i2c_init(struct pci_dev *dev) | ||
274 | { | ||
275 | struct mrst_hdmi_dev *hdmi_dev; | ||
276 | struct hdmi_i2c_dev *i2c_dev; | ||
277 | int ret; | ||
278 | |||
279 | hdmi_dev = pci_get_drvdata(dev); | ||
280 | |||
281 | i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL); | ||
282 | if (i2c_dev == NULL) { | ||
283 | DRM_ERROR("Can't allocate interface\n"); | ||
284 | ret = -ENOMEM; | ||
285 | goto exit; | ||
286 | } | ||
287 | |||
288 | i2c_dev->adap = &mrst_hdmi_i2c_adapter; | ||
289 | i2c_dev->status = I2C_STAT_INIT; | ||
290 | init_completion(&i2c_dev->complete); | ||
291 | mutex_init(&i2c_dev->i2c_lock); | ||
292 | i2c_set_adapdata(&mrst_hdmi_i2c_adapter, hdmi_dev); | ||
293 | hdmi_dev->i2c_dev = i2c_dev; | ||
294 | |||
295 | /* Enable HDMI I2C function on gpio */ | ||
296 | mrst_hdmi_i2c_gpio_fix(); | ||
297 | |||
298 | /* request irq */ | ||
299 | ret = request_irq(dev->irq, mrst_hdmi_i2c_handler, IRQF_SHARED, | ||
300 | mrst_hdmi_i2c_adapter.name, hdmi_dev); | ||
301 | if (ret) { | ||
302 | DRM_ERROR("Failed to request IRQ for I2C controller\n"); | ||
303 | goto err; | ||
304 | } | ||
305 | |||
306 | /* Adapter registration */ | ||
307 | ret = i2c_add_numbered_adapter(&mrst_hdmi_i2c_adapter); | ||
308 | return ret; | ||
309 | |||
310 | err: | ||
311 | kfree(i2c_dev); | ||
312 | exit: | ||
313 | return ret; | ||
314 | } | ||
315 | |||
316 | void mrst_hdmi_i2c_exit(struct pci_dev *dev) | ||
317 | { | ||
318 | struct mrst_hdmi_dev *hdmi_dev; | ||
319 | struct hdmi_i2c_dev *i2c_dev; | ||
320 | |||
321 | hdmi_dev = pci_get_drvdata(dev); | ||
322 | if (i2c_del_adapter(&mrst_hdmi_i2c_adapter)) | ||
323 | DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n"); | ||
324 | |||
325 | i2c_dev = hdmi_dev->i2c_dev; | ||
326 | kfree(i2c_dev); | ||
327 | free_irq(dev->irq, hdmi_dev); | ||
328 | } | ||
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c deleted file mode 100644 index e7999a2a3796..000000000000 --- a/drivers/staging/gma500/mrst_lvds.c +++ /dev/null | |||
@@ -1,407 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2006-2009 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 <drm/drmP.h> | ||
25 | #include <asm/mrst.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 | |||
34 | /* The max/min PWM frequency in BPCR[31:17] - */ | ||
35 | /* The smallest number is 1 (not 0) that can fit in the | ||
36 | * 15-bit field of the and then*/ | ||
37 | /* shifts to the left by one bit to get the actual 16-bit | ||
38 | * value that the 15-bits correspond to.*/ | ||
39 | #define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF | ||
40 | #define BRIGHTNESS_MAX_LEVEL 100 | ||
41 | |||
42 | /** | ||
43 | * Sets the power state for the panel. | ||
44 | */ | ||
45 | static void mrst_lvds_set_power(struct drm_device *dev, | ||
46 | struct psb_intel_output *output, bool on) | ||
47 | { | ||
48 | u32 pp_status; | ||
49 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
50 | |||
51 | if (!gma_power_begin(dev, true)) | ||
52 | return; | ||
53 | |||
54 | if (on) { | ||
55 | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | | ||
56 | POWER_TARGET_ON); | ||
57 | do { | ||
58 | pp_status = REG_READ(PP_STATUS); | ||
59 | } while ((pp_status & (PP_ON | PP_READY)) == PP_READY); | ||
60 | dev_priv->is_lvds_on = true; | ||
61 | if (dev_priv->ops->lvds_bl_power) | ||
62 | dev_priv->ops->lvds_bl_power(dev, true); | ||
63 | } else { | ||
64 | if (dev_priv->ops->lvds_bl_power) | ||
65 | dev_priv->ops->lvds_bl_power(dev, false); | ||
66 | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & | ||
67 | ~POWER_TARGET_ON); | ||
68 | do { | ||
69 | pp_status = REG_READ(PP_STATUS); | ||
70 | } while (pp_status & PP_ON); | ||
71 | dev_priv->is_lvds_on = false; | ||
72 | pm_request_idle(&dev->pdev->dev); | ||
73 | } | ||
74 | gma_power_end(dev); | ||
75 | } | ||
76 | |||
77 | static void mrst_lvds_dpms(struct drm_encoder *encoder, int mode) | ||
78 | { | ||
79 | struct drm_device *dev = encoder->dev; | ||
80 | struct psb_intel_output *output = enc_to_psb_intel_output(encoder); | ||
81 | |||
82 | if (mode == DRM_MODE_DPMS_ON) | ||
83 | mrst_lvds_set_power(dev, output, true); | ||
84 | else | ||
85 | mrst_lvds_set_power(dev, output, false); | ||
86 | |||
87 | /* XXX: We never power down the LVDS pairs. */ | ||
88 | } | ||
89 | |||
90 | static void mrst_lvds_mode_set(struct drm_encoder *encoder, | ||
91 | struct drm_display_mode *mode, | ||
92 | struct drm_display_mode *adjusted_mode) | ||
93 | { | ||
94 | struct psb_intel_mode_device *mode_dev = | ||
95 | enc_to_psb_intel_output(encoder)->mode_dev; | ||
96 | struct drm_device *dev = encoder->dev; | ||
97 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
98 | u32 lvds_port; | ||
99 | uint64_t v = DRM_MODE_SCALE_FULLSCREEN; | ||
100 | |||
101 | if (!gma_power_begin(dev, true)) | ||
102 | return; | ||
103 | |||
104 | /* | ||
105 | * The LVDS pin pair will already have been turned on in the | ||
106 | * psb_intel_crtc_mode_set since it has a large impact on the DPLL | ||
107 | * settings. | ||
108 | */ | ||
109 | lvds_port = (REG_READ(LVDS) & | ||
110 | (~LVDS_PIPEB_SELECT)) | | ||
111 | LVDS_PORT_EN | | ||
112 | LVDS_BORDER_EN; | ||
113 | |||
114 | /* If the firmware says dither on Moorestown, or the BIOS does | ||
115 | on Oaktrail then enable dithering */ | ||
116 | if (mode_dev->panel_wants_dither || dev_priv->lvds_dither) | ||
117 | lvds_port |= MRST_PANEL_8TO6_DITHER_ENABLE; | ||
118 | |||
119 | REG_WRITE(LVDS, lvds_port); | ||
120 | |||
121 | drm_connector_property_get_value( | ||
122 | &enc_to_psb_intel_output(encoder)->base, | ||
123 | dev->mode_config.scaling_mode_property, | ||
124 | &v); | ||
125 | |||
126 | if (v == DRM_MODE_SCALE_NO_SCALE) | ||
127 | REG_WRITE(PFIT_CONTROL, 0); | ||
128 | else if (v == DRM_MODE_SCALE_ASPECT) { | ||
129 | if ((mode->vdisplay != adjusted_mode->crtc_vdisplay) || | ||
130 | (mode->hdisplay != adjusted_mode->crtc_hdisplay)) { | ||
131 | if ((adjusted_mode->crtc_hdisplay * mode->vdisplay) == | ||
132 | (mode->hdisplay * adjusted_mode->crtc_vdisplay)) | ||
133 | REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); | ||
134 | else if ((adjusted_mode->crtc_hdisplay * | ||
135 | mode->vdisplay) > (mode->hdisplay * | ||
136 | adjusted_mode->crtc_vdisplay)) | ||
137 | REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | | ||
138 | PFIT_SCALING_MODE_PILLARBOX); | ||
139 | else | ||
140 | REG_WRITE(PFIT_CONTROL, PFIT_ENABLE | | ||
141 | PFIT_SCALING_MODE_LETTERBOX); | ||
142 | } else | ||
143 | REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); | ||
144 | } else /*(v == DRM_MODE_SCALE_FULLSCREEN)*/ | ||
145 | REG_WRITE(PFIT_CONTROL, PFIT_ENABLE); | ||
146 | |||
147 | gma_power_end(dev); | ||
148 | } | ||
149 | |||
150 | static void mrst_lvds_prepare(struct drm_encoder *encoder) | ||
151 | { | ||
152 | struct drm_device *dev = encoder->dev; | ||
153 | struct psb_intel_output *output = enc_to_psb_intel_output(encoder); | ||
154 | struct psb_intel_mode_device *mode_dev = output->mode_dev; | ||
155 | |||
156 | if (!gma_power_begin(dev, true)) | ||
157 | return; | ||
158 | |||
159 | mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); | ||
160 | mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & | ||
161 | BACKLIGHT_DUTY_CYCLE_MASK); | ||
162 | mrst_lvds_set_power(dev, output, false); | ||
163 | gma_power_end(dev); | ||
164 | } | ||
165 | |||
166 | static u32 mrst_lvds_get_max_backlight(struct drm_device *dev) | ||
167 | { | ||
168 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
169 | u32 ret; | ||
170 | |||
171 | if (gma_power_begin(dev, false)) { | ||
172 | ret = ((REG_READ(BLC_PWM_CTL) & | ||
173 | BACKLIGHT_MODULATION_FREQ_MASK) >> | ||
174 | BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; | ||
175 | |||
176 | gma_power_end(dev); | ||
177 | } else | ||
178 | ret = ((dev_priv->saveBLC_PWM_CTL & | ||
179 | BACKLIGHT_MODULATION_FREQ_MASK) >> | ||
180 | BACKLIGHT_MODULATION_FREQ_SHIFT) * 2; | ||
181 | |||
182 | return ret; | ||
183 | } | ||
184 | |||
185 | static void mrst_lvds_commit(struct drm_encoder *encoder) | ||
186 | { | ||
187 | struct drm_device *dev = encoder->dev; | ||
188 | struct psb_intel_output *output = enc_to_psb_intel_output(encoder); | ||
189 | struct psb_intel_mode_device *mode_dev = output->mode_dev; | ||
190 | |||
191 | if (mode_dev->backlight_duty_cycle == 0) | ||
192 | mode_dev->backlight_duty_cycle = | ||
193 | mrst_lvds_get_max_backlight(dev); | ||
194 | mrst_lvds_set_power(dev, output, true); | ||
195 | } | ||
196 | |||
197 | static const struct drm_encoder_helper_funcs mrst_lvds_helper_funcs = { | ||
198 | .dpms = mrst_lvds_dpms, | ||
199 | .mode_fixup = psb_intel_lvds_mode_fixup, | ||
200 | .prepare = mrst_lvds_prepare, | ||
201 | .mode_set = mrst_lvds_mode_set, | ||
202 | .commit = mrst_lvds_commit, | ||
203 | }; | ||
204 | |||
205 | static struct drm_display_mode lvds_configuration_modes[] = { | ||
206 | /* hard coded fixed mode for TPO LTPS LPJ040K001A */ | ||
207 | { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 33264, 800, 836, | ||
208 | 846, 1056, 0, 480, 489, 491, 525, 0, 0) }, | ||
209 | /* hard coded fixed mode for LVDS 800x480 */ | ||
210 | { DRM_MODE("800x480", DRM_MODE_TYPE_DRIVER, 30994, 800, 801, | ||
211 | 802, 1024, 0, 480, 481, 482, 525, 0, 0) }, | ||
212 | /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ | ||
213 | { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1072, | ||
214 | 1104, 1184, 0, 600, 603, 604, 608, 0, 0) }, | ||
215 | /* hard coded fixed mode for Samsung 480wsvga LVDS 1024x600@75 */ | ||
216 | { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 53990, 1024, 1104, | ||
217 | 1136, 1184, 0, 600, 603, 604, 608, 0, 0) }, | ||
218 | /* hard coded fixed mode for Sharp wsvga LVDS 1024x600 */ | ||
219 | { DRM_MODE("1024x600", DRM_MODE_TYPE_DRIVER, 48885, 1024, 1124, | ||
220 | 1204, 1312, 0, 600, 607, 610, 621, 0, 0) }, | ||
221 | /* hard coded fixed mode for LVDS 1024x768 */ | ||
222 | { DRM_MODE("1024x768", DRM_MODE_TYPE_DRIVER, 65000, 1024, 1048, | ||
223 | 1184, 1344, 0, 768, 771, 777, 806, 0, 0) }, | ||
224 | /* hard coded fixed mode for LVDS 1366x768 */ | ||
225 | { DRM_MODE("1366x768", DRM_MODE_TYPE_DRIVER, 77500, 1366, 1430, | ||
226 | 1558, 1664, 0, 768, 769, 770, 776, 0, 0) }, | ||
227 | }; | ||
228 | |||
229 | /* Returns the panel fixed mode from configuration. */ | ||
230 | |||
231 | static struct drm_display_mode * | ||
232 | mrst_lvds_get_configuration_mode(struct drm_device *dev) | ||
233 | { | ||
234 | struct drm_display_mode *mode = NULL; | ||
235 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
236 | struct mrst_timing_info *ti = &dev_priv->gct_data.DTD; | ||
237 | |||
238 | if (dev_priv->vbt_data.size != 0x00) { /*if non-zero, then use vbt*/ | ||
239 | mode = kzalloc(sizeof(*mode), GFP_KERNEL); | ||
240 | if (!mode) | ||
241 | return NULL; | ||
242 | |||
243 | mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo; | ||
244 | mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo; | ||
245 | mode->hsync_start = mode->hdisplay + \ | ||
246 | ((ti->hsync_offset_hi << 8) | \ | ||
247 | ti->hsync_offset_lo); | ||
248 | mode->hsync_end = mode->hsync_start + \ | ||
249 | ((ti->hsync_pulse_width_hi << 8) | \ | ||
250 | ti->hsync_pulse_width_lo); | ||
251 | mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \ | ||
252 | ti->hblank_lo); | ||
253 | mode->vsync_start = \ | ||
254 | mode->vdisplay + ((ti->vsync_offset_hi << 4) | \ | ||
255 | ti->vsync_offset_lo); | ||
256 | mode->vsync_end = \ | ||
257 | mode->vsync_start + ((ti->vsync_pulse_width_hi << 4) | \ | ||
258 | ti->vsync_pulse_width_lo); | ||
259 | mode->vtotal = mode->vdisplay + \ | ||
260 | ((ti->vblank_hi << 8) | ti->vblank_lo); | ||
261 | mode->clock = ti->pixel_clock * 10; | ||
262 | #if 0 | ||
263 | printk(KERN_INFO "hdisplay is %d\n", mode->hdisplay); | ||
264 | printk(KERN_INFO "vdisplay is %d\n", mode->vdisplay); | ||
265 | printk(KERN_INFO "HSS is %d\n", mode->hsync_start); | ||
266 | printk(KERN_INFO "HSE is %d\n", mode->hsync_end); | ||
267 | printk(KERN_INFO "htotal is %d\n", mode->htotal); | ||
268 | printk(KERN_INFO "VSS is %d\n", mode->vsync_start); | ||
269 | printk(KERN_INFO "VSE is %d\n", mode->vsync_end); | ||
270 | printk(KERN_INFO "vtotal is %d\n", mode->vtotal); | ||
271 | printk(KERN_INFO "clock is %d\n", mode->clock); | ||
272 | #endif | ||
273 | } else | ||
274 | mode = drm_mode_duplicate(dev, &lvds_configuration_modes[2]); | ||
275 | |||
276 | drm_mode_set_name(mode); | ||
277 | drm_mode_set_crtcinfo(mode, 0); | ||
278 | |||
279 | return mode; | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * mrst_lvds_init - setup LVDS connectors on this device | ||
284 | * @dev: drm device | ||
285 | * | ||
286 | * Create the connector, register the LVDS DDC bus, and try to figure out what | ||
287 | * modes we can display on the LVDS panel (if present). | ||
288 | */ | ||
289 | void mrst_lvds_init(struct drm_device *dev, | ||
290 | struct psb_intel_mode_device *mode_dev) | ||
291 | { | ||
292 | struct psb_intel_output *psb_intel_output; | ||
293 | struct drm_connector *connector; | ||
294 | struct drm_encoder *encoder; | ||
295 | struct drm_psb_private *dev_priv = | ||
296 | (struct drm_psb_private *) dev->dev_private; | ||
297 | struct edid *edid; | ||
298 | int ret = 0; | ||
299 | struct i2c_adapter *i2c_adap; | ||
300 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | ||
301 | |||
302 | psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); | ||
303 | if (!psb_intel_output) | ||
304 | return; | ||
305 | |||
306 | psb_intel_output->mode_dev = mode_dev; | ||
307 | connector = &psb_intel_output->base; | ||
308 | encoder = &psb_intel_output->enc; | ||
309 | dev_priv->is_lvds_on = true; | ||
310 | drm_connector_init(dev, &psb_intel_output->base, | ||
311 | &psb_intel_lvds_connector_funcs, | ||
312 | DRM_MODE_CONNECTOR_LVDS); | ||
313 | |||
314 | drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs, | ||
315 | DRM_MODE_ENCODER_LVDS); | ||
316 | |||
317 | drm_mode_connector_attach_encoder(&psb_intel_output->base, | ||
318 | &psb_intel_output->enc); | ||
319 | psb_intel_output->type = INTEL_OUTPUT_LVDS; | ||
320 | |||
321 | drm_encoder_helper_add(encoder, &mrst_lvds_helper_funcs); | ||
322 | drm_connector_helper_add(connector, | ||
323 | &psb_intel_lvds_connector_helper_funcs); | ||
324 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | ||
325 | connector->interlace_allowed = false; | ||
326 | connector->doublescan_allowed = false; | ||
327 | |||
328 | drm_connector_attach_property(connector, | ||
329 | dev->mode_config.scaling_mode_property, | ||
330 | DRM_MODE_SCALE_FULLSCREEN); | ||
331 | drm_connector_attach_property(connector, | ||
332 | dev_priv->backlight_property, | ||
333 | BRIGHTNESS_MAX_LEVEL); | ||
334 | |||
335 | mode_dev->panel_wants_dither = false; | ||
336 | if (dev_priv->vbt_data.size != 0x00) | ||
337 | mode_dev->panel_wants_dither = (dev_priv->gct_data. | ||
338 | Panel_Port_Control & MRST_PANEL_8TO6_DITHER_ENABLE); | ||
339 | |||
340 | /* | ||
341 | * LVDS discovery: | ||
342 | * 1) check for EDID on DDC | ||
343 | * 2) check for VBT data | ||
344 | * 3) check to see if LVDS is already on | ||
345 | * if none of the above, no panel | ||
346 | * 4) make sure lid is open | ||
347 | * if closed, act like it's not there for now | ||
348 | */ | ||
349 | |||
350 | i2c_adap = i2c_get_adapter(dev_priv->ops->i2c_bus); | ||
351 | |||
352 | if (i2c_adap == NULL) | ||
353 | dev_err(dev->dev, "No ddc adapter available!\n"); | ||
354 | /* | ||
355 | * Attempt to get the fixed panel mode from DDC. Assume that the | ||
356 | * preferred mode is the right one. | ||
357 | */ | ||
358 | if (i2c_adap) { | ||
359 | edid = drm_get_edid(connector, i2c_adap); | ||
360 | if (edid) { | ||
361 | drm_mode_connector_update_edid_property(connector, | ||
362 | edid); | ||
363 | ret = drm_add_edid_modes(connector, edid); | ||
364 | kfree(edid); | ||
365 | } | ||
366 | |||
367 | list_for_each_entry(scan, &connector->probed_modes, head) { | ||
368 | if (scan->type & DRM_MODE_TYPE_PREFERRED) { | ||
369 | mode_dev->panel_fixed_mode = | ||
370 | drm_mode_duplicate(dev, scan); | ||
371 | goto out; /* FIXME: check for quirks */ | ||
372 | } | ||
373 | } | ||
374 | } | ||
375 | /* | ||
376 | * If we didn't get EDID, try geting panel timing | ||
377 | * from configuration data | ||
378 | */ | ||
379 | mode_dev->panel_fixed_mode = mrst_lvds_get_configuration_mode(dev); | ||
380 | |||
381 | if (mode_dev->panel_fixed_mode) { | ||
382 | mode_dev->panel_fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; | ||
383 | goto out; /* FIXME: check for quirks */ | ||
384 | } | ||
385 | |||
386 | /* If we still don't have a mode after all that, give up. */ | ||
387 | if (!mode_dev->panel_fixed_mode) { | ||
388 | dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); | ||
389 | goto failed_find; | ||
390 | } | ||
391 | |||
392 | out: | ||
393 | drm_sysfs_connector_add(connector); | ||
394 | return; | ||
395 | |||
396 | failed_find: | ||
397 | dev_dbg(dev->dev, "No LVDS modes found, disabling.\n"); | ||
398 | if (psb_intel_output->ddc_bus) | ||
399 | psb_intel_i2c_destroy(psb_intel_output->ddc_bus); | ||
400 | |||
401 | /* failed_ddc: */ | ||
402 | |||
403 | drm_encoder_cleanup(encoder); | ||
404 | drm_connector_cleanup(connector); | ||
405 | kfree(connector); | ||
406 | } | ||
407 | |||
diff --git a/drivers/staging/gma500/power.c b/drivers/staging/gma500/power.c deleted file mode 100644 index 408257038335..000000000000 --- a/drivers/staging/gma500/power.c +++ /dev/null | |||
@@ -1,318 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2009-2011, Intel Corporation. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice (including the next | ||
13 | * paragraph) shall be included in all copies or substantial portions of the | ||
14 | * Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
22 | * SOFTWARE. | ||
23 | * | ||
24 | * Authors: | ||
25 | * Benjamin Defnet <benjamin.r.defnet@intel.com> | ||
26 | * Rajesh Poornachandran <rajesh.poornachandran@intel.com> | ||
27 | * Massively reworked | ||
28 | * Alan Cox <alan@linux.intel.com> | ||
29 | */ | ||
30 | |||
31 | #include "power.h" | ||
32 | #include "psb_drv.h" | ||
33 | #include "psb_reg.h" | ||
34 | #include "psb_intel_reg.h" | ||
35 | #include <linux/mutex.h> | ||
36 | #include <linux/pm_runtime.h> | ||
37 | |||
38 | static struct mutex power_mutex; /* Serialize power ops */ | ||
39 | static spinlock_t power_ctrl_lock; /* Serialize power claim */ | ||
40 | |||
41 | /** | ||
42 | * gma_power_init - initialise power manager | ||
43 | * @dev: our device | ||
44 | * | ||
45 | * Set up for power management tracking of our hardware. | ||
46 | */ | ||
47 | void gma_power_init(struct drm_device *dev) | ||
48 | { | ||
49 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
50 | |||
51 | /* FIXME: Move APM/OSPM base into relevant device code */ | ||
52 | dev_priv->apm_base = dev_priv->apm_reg & 0xffff; | ||
53 | dev_priv->ospm_base &= 0xffff; | ||
54 | |||
55 | dev_priv->display_power = true; /* We start active */ | ||
56 | dev_priv->display_count = 0; /* Currently no users */ | ||
57 | dev_priv->suspended = false; /* And not suspended */ | ||
58 | spin_lock_init(&power_ctrl_lock); | ||
59 | mutex_init(&power_mutex); | ||
60 | |||
61 | dev_priv->ops->init_pm(dev); | ||
62 | } | ||
63 | |||
64 | /** | ||
65 | * gma_power_uninit - end power manager | ||
66 | * @dev: device to end for | ||
67 | * | ||
68 | * Undo the effects of gma_power_init | ||
69 | */ | ||
70 | void gma_power_uninit(struct drm_device *dev) | ||
71 | { | ||
72 | pm_runtime_disable(&dev->pdev->dev); | ||
73 | pm_runtime_set_suspended(&dev->pdev->dev); | ||
74 | } | ||
75 | |||
76 | /** | ||
77 | * gma_suspend_display - suspend the display logic | ||
78 | * @dev: our DRM device | ||
79 | * | ||
80 | * Suspend the display logic of the graphics interface | ||
81 | */ | ||
82 | static void gma_suspend_display(struct drm_device *dev) | ||
83 | { | ||
84 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
85 | |||
86 | if (!dev_priv->display_power) | ||
87 | return; | ||
88 | dev_priv->ops->save_regs(dev); | ||
89 | dev_priv->ops->power_down(dev); | ||
90 | dev_priv->display_power = false; | ||
91 | } | ||
92 | |||
93 | /** | ||
94 | * gma_resume_display - resume display side logic | ||
95 | * | ||
96 | * Resume the display hardware restoring state and enabling | ||
97 | * as necessary. | ||
98 | */ | ||
99 | static void gma_resume_display(struct pci_dev *pdev) | ||
100 | { | ||
101 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
102 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
103 | |||
104 | if (dev_priv->display_power) | ||
105 | return; | ||
106 | |||
107 | /* turn on the display power island */ | ||
108 | dev_priv->ops->power_up(dev); | ||
109 | dev_priv->suspended = false; | ||
110 | dev_priv->display_power = true; | ||
111 | |||
112 | PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL); | ||
113 | pci_write_config_word(pdev, PSB_GMCH_CTRL, | ||
114 | dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED); | ||
115 | dev_priv->ops->restore_regs(dev); | ||
116 | } | ||
117 | |||
118 | /** | ||
119 | * gma_suspend_pci - suspend PCI side | ||
120 | * @pdev: PCI device | ||
121 | * | ||
122 | * Perform the suspend processing on our PCI device state | ||
123 | */ | ||
124 | static void gma_suspend_pci(struct pci_dev *pdev) | ||
125 | { | ||
126 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
127 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
128 | int bsm, vbt; | ||
129 | |||
130 | if (dev_priv->suspended) | ||
131 | return; | ||
132 | |||
133 | pci_save_state(pdev); | ||
134 | pci_read_config_dword(pdev, 0x5C, &bsm); | ||
135 | dev_priv->saveBSM = bsm; | ||
136 | pci_read_config_dword(pdev, 0xFC, &vbt); | ||
137 | dev_priv->saveVBT = vbt; | ||
138 | pci_read_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, &dev_priv->msi_addr); | ||
139 | pci_read_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, &dev_priv->msi_data); | ||
140 | |||
141 | pci_disable_device(pdev); | ||
142 | pci_set_power_state(pdev, PCI_D3hot); | ||
143 | |||
144 | dev_priv->suspended = true; | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * gma_resume_pci - resume helper | ||
149 | * @dev: our PCI device | ||
150 | * | ||
151 | * Perform the resume processing on our PCI device state - rewrite | ||
152 | * register state and re-enable the PCI device | ||
153 | */ | ||
154 | static bool gma_resume_pci(struct pci_dev *pdev) | ||
155 | { | ||
156 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
157 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
158 | int ret; | ||
159 | |||
160 | if (!dev_priv->suspended) | ||
161 | return true; | ||
162 | |||
163 | pci_set_power_state(pdev, PCI_D0); | ||
164 | pci_restore_state(pdev); | ||
165 | pci_write_config_dword(pdev, 0x5c, dev_priv->saveBSM); | ||
166 | pci_write_config_dword(pdev, 0xFC, dev_priv->saveVBT); | ||
167 | /* restoring MSI address and data in PCIx space */ | ||
168 | pci_write_config_dword(pdev, PSB_PCIx_MSI_ADDR_LOC, dev_priv->msi_addr); | ||
169 | pci_write_config_dword(pdev, PSB_PCIx_MSI_DATA_LOC, dev_priv->msi_data); | ||
170 | ret = pci_enable_device(pdev); | ||
171 | |||
172 | if (ret != 0) | ||
173 | dev_err(&pdev->dev, "pci_enable failed: %d\n", ret); | ||
174 | else | ||
175 | dev_priv->suspended = false; | ||
176 | return !dev_priv->suspended; | ||
177 | } | ||
178 | |||
179 | /** | ||
180 | * gma_power_suspend - bus callback for suspend | ||
181 | * @pdev: our PCI device | ||
182 | * @state: suspend type | ||
183 | * | ||
184 | * Called back by the PCI layer during a suspend of the system. We | ||
185 | * perform the necessary shut down steps and save enough state that | ||
186 | * we can undo this when resume is called. | ||
187 | */ | ||
188 | int gma_power_suspend(struct device *_dev) | ||
189 | { | ||
190 | struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); | ||
191 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
192 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
193 | |||
194 | mutex_lock(&power_mutex); | ||
195 | if (!dev_priv->suspended) { | ||
196 | if (dev_priv->display_count) { | ||
197 | mutex_unlock(&power_mutex); | ||
198 | return -EBUSY; | ||
199 | } | ||
200 | psb_irq_uninstall(dev); | ||
201 | gma_suspend_display(dev); | ||
202 | gma_suspend_pci(pdev); | ||
203 | } | ||
204 | mutex_unlock(&power_mutex); | ||
205 | return 0; | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * gma_power_resume - resume power | ||
210 | * @pdev: PCI device | ||
211 | * | ||
212 | * Resume the PCI side of the graphics and then the displays | ||
213 | */ | ||
214 | int gma_power_resume(struct device *_dev) | ||
215 | { | ||
216 | struct pci_dev *pdev = container_of(_dev, struct pci_dev, dev); | ||
217 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
218 | |||
219 | mutex_lock(&power_mutex); | ||
220 | gma_resume_pci(pdev); | ||
221 | gma_resume_display(pdev); | ||
222 | psb_irq_preinstall(dev); | ||
223 | psb_irq_postinstall(dev); | ||
224 | mutex_unlock(&power_mutex); | ||
225 | return 0; | ||
226 | } | ||
227 | |||
228 | /** | ||
229 | * gma_power_is_on - returne true if power is on | ||
230 | * @dev: our DRM device | ||
231 | * | ||
232 | * Returns true if the display island power is on at this moment | ||
233 | */ | ||
234 | bool gma_power_is_on(struct drm_device *dev) | ||
235 | { | ||
236 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
237 | return dev_priv->display_power; | ||
238 | } | ||
239 | |||
240 | /** | ||
241 | * gma_power_begin - begin requiring power | ||
242 | * @dev: our DRM device | ||
243 | * @force_on: true to force power on | ||
244 | * | ||
245 | * Begin an action that requires the display power island is enabled. | ||
246 | * We refcount the islands. | ||
247 | */ | ||
248 | bool gma_power_begin(struct drm_device *dev, bool force_on) | ||
249 | { | ||
250 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
251 | int ret; | ||
252 | unsigned long flags; | ||
253 | |||
254 | spin_lock_irqsave(&power_ctrl_lock, flags); | ||
255 | /* Power already on ? */ | ||
256 | if (dev_priv->display_power) { | ||
257 | dev_priv->display_count++; | ||
258 | pm_runtime_get(&dev->pdev->dev); | ||
259 | spin_unlock_irqrestore(&power_ctrl_lock, flags); | ||
260 | return true; | ||
261 | } | ||
262 | if (force_on == false) | ||
263 | goto out_false; | ||
264 | |||
265 | /* Ok power up needed */ | ||
266 | ret = gma_resume_pci(dev->pdev); | ||
267 | if (ret == 0) { | ||
268 | /* FIXME: we want to defer this for Medfield/Oaktrail */ | ||
269 | gma_resume_display(dev->pdev); | ||
270 | psb_irq_preinstall(dev); | ||
271 | psb_irq_postinstall(dev); | ||
272 | pm_runtime_get(&dev->pdev->dev); | ||
273 | dev_priv->display_count++; | ||
274 | spin_unlock_irqrestore(&power_ctrl_lock, flags); | ||
275 | return true; | ||
276 | } | ||
277 | out_false: | ||
278 | spin_unlock_irqrestore(&power_ctrl_lock, flags); | ||
279 | return false; | ||
280 | } | ||
281 | |||
282 | /** | ||
283 | * gma_power_end - end use of power | ||
284 | * @dev: Our DRM device | ||
285 | * | ||
286 | * Indicate that one of our gma_power_begin() requested periods when | ||
287 | * the diplay island power is needed has completed. | ||
288 | */ | ||
289 | void gma_power_end(struct drm_device *dev) | ||
290 | { | ||
291 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
292 | unsigned long flags; | ||
293 | spin_lock_irqsave(&power_ctrl_lock, flags); | ||
294 | dev_priv->display_count--; | ||
295 | WARN_ON(dev_priv->display_count < 0); | ||
296 | spin_unlock_irqrestore(&power_ctrl_lock, flags); | ||
297 | pm_runtime_put(&dev->pdev->dev); | ||
298 | } | ||
299 | |||
300 | int psb_runtime_suspend(struct device *dev) | ||
301 | { | ||
302 | return gma_power_suspend(dev); | ||
303 | } | ||
304 | |||
305 | int psb_runtime_resume(struct device *dev) | ||
306 | { | ||
307 | return gma_power_resume(dev);; | ||
308 | } | ||
309 | |||
310 | int psb_runtime_idle(struct device *dev) | ||
311 | { | ||
312 | struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev)); | ||
313 | struct drm_psb_private *dev_priv = drmdev->dev_private; | ||
314 | if (dev_priv->display_count) | ||
315 | return 0; | ||
316 | else | ||
317 | return 1; | ||
318 | } | ||
diff --git a/drivers/staging/gma500/power.h b/drivers/staging/gma500/power.h deleted file mode 100644 index 1969d2ecb328..000000000000 --- a/drivers/staging/gma500/power.h +++ /dev/null | |||
@@ -1,67 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2009-2011, Intel Corporation. | ||
3 | * All Rights Reserved. | ||
4 | |||
5 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
6 | * copy of this software and associated documentation files (the "Software"), | ||
7 | * to deal in the Software without restriction, including without limitation | ||
8 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
9 | * and/or sell copies of the Software, and to permit persons to whom the | ||
10 | * Software is furnished to do so, subject to the following conditions: | ||
11 | * | ||
12 | * The above copyright notice and this permission notice (including the next | ||
13 | * paragraph) shall be included in all copies or substantial portions of the | ||
14 | * Software. | ||
15 | * | ||
16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
19 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
22 | * SOFTWARE. | ||
23 | * | ||
24 | * Authors: | ||
25 | * Benjamin Defnet <benjamin.r.defnet@intel.com> | ||
26 | * Rajesh Poornachandran <rajesh.poornachandran@intel.com> | ||
27 | * Massively reworked | ||
28 | * Alan Cox <alan@linux.intel.com> | ||
29 | */ | ||
30 | #ifndef _PSB_POWERMGMT_H_ | ||
31 | #define _PSB_POWERMGMT_H_ | ||
32 | |||
33 | #include <linux/pci.h> | ||
34 | #include <drm/drmP.h> | ||
35 | |||
36 | void gma_power_init(struct drm_device *dev); | ||
37 | void gma_power_uninit(struct drm_device *dev); | ||
38 | |||
39 | /* | ||
40 | * The kernel bus power management will call these functions | ||
41 | */ | ||
42 | int gma_power_suspend(struct device *dev); | ||
43 | int gma_power_resume(struct device *dev); | ||
44 | |||
45 | /* | ||
46 | * These are the functions the driver should use to wrap all hw access | ||
47 | * (i.e. register reads and writes) | ||
48 | */ | ||
49 | bool gma_power_begin(struct drm_device *dev, bool force); | ||
50 | void gma_power_end(struct drm_device *dev); | ||
51 | |||
52 | /* | ||
53 | * Use this function to do an instantaneous check for if the hw is on. | ||
54 | * Only use this in cases where you know the mutex is already held such | ||
55 | * as in irq install/uninstall and you need to | ||
56 | * prevent a deadlock situation. Otherwise use gma_power_begin(). | ||
57 | */ | ||
58 | bool gma_power_is_on(struct drm_device *dev); | ||
59 | |||
60 | /* | ||
61 | * GFX-Runtime PM callbacks | ||
62 | */ | ||
63 | int psb_runtime_suspend(struct device *dev); | ||
64 | int psb_runtime_resume(struct device *dev); | ||
65 | int psb_runtime_idle(struct device *dev); | ||
66 | |||
67 | #endif /*_PSB_POWERMGMT_H_*/ | ||
diff --git a/drivers/staging/gma500/psb_device.c b/drivers/staging/gma500/psb_device.c deleted file mode 100644 index b97aa78519f2..000000000000 --- a/drivers/staging/gma500/psb_device.c +++ /dev/null | |||
@@ -1,321 +0,0 @@ | |||
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 | |||
29 | |||
30 | static int psb_output_init(struct drm_device *dev) | ||
31 | { | ||
32 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
33 | psb_intel_lvds_init(dev, &dev_priv->mode_dev); | ||
34 | psb_intel_sdvo_init(dev, SDVOB); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
39 | |||
40 | /* | ||
41 | * Poulsbo Backlight Interfaces | ||
42 | */ | ||
43 | |||
44 | #define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */ | ||
45 | #define BLC_PWM_FREQ_CALC_CONSTANT 32 | ||
46 | #define MHz 1000000 | ||
47 | |||
48 | #define PSB_BLC_PWM_PRECISION_FACTOR 10 | ||
49 | #define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE | ||
50 | #define PSB_BLC_MIN_PWM_REG_FREQ 0x2 | ||
51 | |||
52 | #define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) | ||
53 | #define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) | ||
54 | |||
55 | static int psb_brightness; | ||
56 | static struct backlight_device *psb_backlight_device; | ||
57 | |||
58 | static int psb_get_brightness(struct backlight_device *bd) | ||
59 | { | ||
60 | /* return locally cached var instead of HW read (due to DPST etc.) */ | ||
61 | /* FIXME: ideally return actual value in case firmware fiddled with | ||
62 | it */ | ||
63 | return psb_brightness; | ||
64 | } | ||
65 | |||
66 | |||
67 | static int psb_backlight_setup(struct drm_device *dev) | ||
68 | { | ||
69 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
70 | unsigned long core_clock; | ||
71 | /* u32 bl_max_freq; */ | ||
72 | /* unsigned long value; */ | ||
73 | u16 bl_max_freq; | ||
74 | uint32_t value; | ||
75 | uint32_t blc_pwm_precision_factor; | ||
76 | |||
77 | /* get bl_max_freq and pol from dev_priv*/ | ||
78 | if (!dev_priv->lvds_bl) { | ||
79 | dev_err(dev->dev, "Has no valid LVDS backlight info\n"); | ||
80 | return -ENOENT; | ||
81 | } | ||
82 | bl_max_freq = dev_priv->lvds_bl->freq; | ||
83 | blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR; | ||
84 | |||
85 | core_clock = dev_priv->core_freq; | ||
86 | |||
87 | value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT; | ||
88 | value *= blc_pwm_precision_factor; | ||
89 | value /= bl_max_freq; | ||
90 | value /= blc_pwm_precision_factor; | ||
91 | |||
92 | if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ || | ||
93 | value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ) | ||
94 | return -ERANGE; | ||
95 | else { | ||
96 | value &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; | ||
97 | REG_WRITE(BLC_PWM_CTL, | ||
98 | (value << PSB_BACKLIGHT_PWM_CTL_SHIFT) | (value)); | ||
99 | } | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | static int psb_set_brightness(struct backlight_device *bd) | ||
104 | { | ||
105 | struct drm_device *dev = bl_get_data(psb_backlight_device); | ||
106 | int level = bd->props.brightness; | ||
107 | |||
108 | /* Percentage 1-100% being valid */ | ||
109 | if (level < 1) | ||
110 | level = 1; | ||
111 | |||
112 | psb_intel_lvds_set_brightness(dev, level); | ||
113 | psb_brightness = level; | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static const struct backlight_ops psb_ops = { | ||
118 | .get_brightness = psb_get_brightness, | ||
119 | .update_status = psb_set_brightness, | ||
120 | }; | ||
121 | |||
122 | static int psb_backlight_init(struct drm_device *dev) | ||
123 | { | ||
124 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
125 | int ret; | ||
126 | struct backlight_properties props; | ||
127 | |||
128 | memset(&props, 0, sizeof(struct backlight_properties)); | ||
129 | props.max_brightness = 100; | ||
130 | props.type = BACKLIGHT_PLATFORM; | ||
131 | |||
132 | psb_backlight_device = backlight_device_register("psb-bl", | ||
133 | NULL, (void *)dev, &psb_ops, &props); | ||
134 | if (IS_ERR(psb_backlight_device)) | ||
135 | return PTR_ERR(psb_backlight_device); | ||
136 | |||
137 | ret = psb_backlight_setup(dev); | ||
138 | if (ret < 0) { | ||
139 | backlight_device_unregister(psb_backlight_device); | ||
140 | psb_backlight_device = NULL; | ||
141 | return ret; | ||
142 | } | ||
143 | psb_backlight_device->props.brightness = 100; | ||
144 | psb_backlight_device->props.max_brightness = 100; | ||
145 | backlight_update_status(psb_backlight_device); | ||
146 | dev_priv->backlight_device = psb_backlight_device; | ||
147 | return 0; | ||
148 | } | ||
149 | |||
150 | #endif | ||
151 | |||
152 | /* | ||
153 | * Provide the Poulsbo specific chip logic and low level methods | ||
154 | * for power management | ||
155 | */ | ||
156 | |||
157 | static void psb_init_pm(struct drm_device *dev) | ||
158 | { | ||
159 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
160 | |||
161 | u32 gating = PSB_RSGX32(PSB_CR_CLKGATECTL); | ||
162 | gating &= ~3; /* Disable 2D clock gating */ | ||
163 | gating |= 1; | ||
164 | PSB_WSGX32(gating, PSB_CR_CLKGATECTL); | ||
165 | PSB_RSGX32(PSB_CR_CLKGATECTL); | ||
166 | } | ||
167 | |||
168 | /** | ||
169 | * psb_save_display_registers - save registers lost on suspend | ||
170 | * @dev: our DRM device | ||
171 | * | ||
172 | * Save the state we need in order to be able to restore the interface | ||
173 | * upon resume from suspend | ||
174 | */ | ||
175 | static int psb_save_display_registers(struct drm_device *dev) | ||
176 | { | ||
177 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
178 | struct drm_crtc *crtc; | ||
179 | struct drm_connector *connector; | ||
180 | |||
181 | /* Display arbitration control + watermarks */ | ||
182 | dev_priv->saveDSPARB = PSB_RVDC32(DSPARB); | ||
183 | dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1); | ||
184 | dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2); | ||
185 | dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3); | ||
186 | dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4); | ||
187 | dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5); | ||
188 | dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6); | ||
189 | dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); | ||
190 | |||
191 | /* Save crtc and output state */ | ||
192 | mutex_lock(&dev->mode_config.mutex); | ||
193 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
194 | if (drm_helper_crtc_in_use(crtc)) | ||
195 | crtc->funcs->save(crtc); | ||
196 | } | ||
197 | |||
198 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | ||
199 | connector->funcs->save(connector); | ||
200 | |||
201 | mutex_unlock(&dev->mode_config.mutex); | ||
202 | return 0; | ||
203 | } | ||
204 | |||
205 | /** | ||
206 | * psb_restore_display_registers - restore lost register state | ||
207 | * @dev: our DRM device | ||
208 | * | ||
209 | * Restore register state that was lost during suspend and resume. | ||
210 | */ | ||
211 | static int psb_restore_display_registers(struct drm_device *dev) | ||
212 | { | ||
213 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
214 | struct drm_crtc *crtc; | ||
215 | struct drm_connector *connector; | ||
216 | |||
217 | /* Display arbitration + watermarks */ | ||
218 | PSB_WVDC32(dev_priv->saveDSPARB, DSPARB); | ||
219 | PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1); | ||
220 | PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2); | ||
221 | PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3); | ||
222 | PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4); | ||
223 | PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5); | ||
224 | PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6); | ||
225 | PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT); | ||
226 | |||
227 | /*make sure VGA plane is off. it initializes to on after reset!*/ | ||
228 | PSB_WVDC32(0x80000000, VGACNTRL); | ||
229 | |||
230 | mutex_lock(&dev->mode_config.mutex); | ||
231 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | ||
232 | if (drm_helper_crtc_in_use(crtc)) | ||
233 | crtc->funcs->restore(crtc); | ||
234 | |||
235 | list_for_each_entry(connector, &dev->mode_config.connector_list, head) | ||
236 | connector->funcs->restore(connector); | ||
237 | |||
238 | mutex_unlock(&dev->mode_config.mutex); | ||
239 | return 0; | ||
240 | } | ||
241 | |||
242 | static int psb_power_down(struct drm_device *dev) | ||
243 | { | ||
244 | return 0; | ||
245 | } | ||
246 | |||
247 | static int psb_power_up(struct drm_device *dev) | ||
248 | { | ||
249 | return 0; | ||
250 | } | ||
251 | |||
252 | static void psb_get_core_freq(struct drm_device *dev) | ||
253 | { | ||
254 | uint32_t clock; | ||
255 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | ||
256 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
257 | |||
258 | /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/ | ||
259 | /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/ | ||
260 | |||
261 | pci_write_config_dword(pci_root, 0xD0, 0xD0050300); | ||
262 | pci_read_config_dword(pci_root, 0xD4, &clock); | ||
263 | pci_dev_put(pci_root); | ||
264 | |||
265 | switch (clock & 0x07) { | ||
266 | case 0: | ||
267 | dev_priv->core_freq = 100; | ||
268 | break; | ||
269 | case 1: | ||
270 | dev_priv->core_freq = 133; | ||
271 | break; | ||
272 | case 2: | ||
273 | dev_priv->core_freq = 150; | ||
274 | break; | ||
275 | case 3: | ||
276 | dev_priv->core_freq = 178; | ||
277 | break; | ||
278 | case 4: | ||
279 | dev_priv->core_freq = 200; | ||
280 | break; | ||
281 | case 5: | ||
282 | case 6: | ||
283 | case 7: | ||
284 | dev_priv->core_freq = 266; | ||
285 | default: | ||
286 | dev_priv->core_freq = 0; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | static int psb_chip_setup(struct drm_device *dev) | ||
291 | { | ||
292 | psb_get_core_freq(dev); | ||
293 | gma_intel_opregion_init(dev); | ||
294 | psb_intel_init_bios(dev); | ||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | const struct psb_ops psb_chip_ops = { | ||
299 | .name = "Poulsbo", | ||
300 | .accel_2d = 1, | ||
301 | .pipes = 2, | ||
302 | .crtcs = 2, | ||
303 | .sgx_offset = PSB_SGX_OFFSET, | ||
304 | .chip_setup = psb_chip_setup, | ||
305 | |||
306 | .crtc_helper = &psb_intel_helper_funcs, | ||
307 | .crtc_funcs = &psb_intel_crtc_funcs, | ||
308 | |||
309 | .output_init = psb_output_init, | ||
310 | |||
311 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
312 | .backlight_init = psb_backlight_init, | ||
313 | #endif | ||
314 | |||
315 | .init_pm = psb_init_pm, | ||
316 | .save_regs = psb_save_display_registers, | ||
317 | .restore_regs = psb_restore_display_registers, | ||
318 | .power_down = psb_power_down, | ||
319 | .power_up = psb_power_up, | ||
320 | }; | ||
321 | |||
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h deleted file mode 100644 index 0da846835688..000000000000 --- a/drivers/staging/gma500/psb_drm.h +++ /dev/null | |||
@@ -1,219 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2007-2011, Intel Corporation. | ||
3 | * All Rights Reserved. | ||
4 | * Copyright (c) 2008, Tungsten Graphics Inc. Cedar Park, TX., USA. | ||
5 | * All Rights Reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms and conditions of the GNU General Public License, | ||
9 | * version 2, as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | * | ||
20 | **************************************************************************/ | ||
21 | |||
22 | #ifndef _PSB_DRM_H_ | ||
23 | #define _PSB_DRM_H_ | ||
24 | |||
25 | #define PSB_NUM_PIPE 3 | ||
26 | |||
27 | #define PSB_GPU_ACCESS_READ (1ULL << 32) | ||
28 | #define PSB_GPU_ACCESS_WRITE (1ULL << 33) | ||
29 | #define PSB_GPU_ACCESS_MASK (PSB_GPU_ACCESS_READ | PSB_GPU_ACCESS_WRITE) | ||
30 | |||
31 | #define PSB_BO_FLAG_COMMAND (1ULL << 52) | ||
32 | |||
33 | /* | ||
34 | * Feedback components: | ||
35 | */ | ||
36 | |||
37 | struct drm_psb_sizes_arg { | ||
38 | u32 ta_mem_size; | ||
39 | u32 mmu_size; | ||
40 | u32 pds_size; | ||
41 | u32 rastgeom_size; | ||
42 | u32 tt_size; | ||
43 | u32 vram_size; | ||
44 | }; | ||
45 | |||
46 | struct drm_psb_dpst_lut_arg { | ||
47 | uint8_t lut[256]; | ||
48 | int output_id; | ||
49 | }; | ||
50 | |||
51 | #define PSB_DC_CRTC_SAVE 0x01 | ||
52 | #define PSB_DC_CRTC_RESTORE 0x02 | ||
53 | #define PSB_DC_OUTPUT_SAVE 0x04 | ||
54 | #define PSB_DC_OUTPUT_RESTORE 0x08 | ||
55 | #define PSB_DC_CRTC_MASK 0x03 | ||
56 | #define PSB_DC_OUTPUT_MASK 0x0C | ||
57 | |||
58 | struct drm_psb_dc_state_arg { | ||
59 | u32 flags; | ||
60 | u32 obj_id; | ||
61 | }; | ||
62 | |||
63 | struct drm_psb_mode_operation_arg { | ||
64 | u32 obj_id; | ||
65 | u16 operation; | ||
66 | struct drm_mode_modeinfo mode; | ||
67 | void *data; | ||
68 | }; | ||
69 | |||
70 | struct drm_psb_stolen_memory_arg { | ||
71 | u32 base; | ||
72 | u32 size; | ||
73 | }; | ||
74 | |||
75 | /*Display Register Bits*/ | ||
76 | #define REGRWBITS_PFIT_CONTROLS (1 << 0) | ||
77 | #define REGRWBITS_PFIT_AUTOSCALE_RATIOS (1 << 1) | ||
78 | #define REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS (1 << 2) | ||
79 | #define REGRWBITS_PIPEASRC (1 << 3) | ||
80 | #define REGRWBITS_PIPEBSRC (1 << 4) | ||
81 | #define REGRWBITS_VTOTAL_A (1 << 5) | ||
82 | #define REGRWBITS_VTOTAL_B (1 << 6) | ||
83 | #define REGRWBITS_DSPACNTR (1 << 8) | ||
84 | #define REGRWBITS_DSPBCNTR (1 << 9) | ||
85 | #define REGRWBITS_DSPCCNTR (1 << 10) | ||
86 | |||
87 | /*Overlay Register Bits*/ | ||
88 | #define OV_REGRWBITS_OVADD (1 << 0) | ||
89 | #define OV_REGRWBITS_OGAM_ALL (1 << 1) | ||
90 | |||
91 | #define OVC_REGRWBITS_OVADD (1 << 2) | ||
92 | #define OVC_REGRWBITS_OGAM_ALL (1 << 3) | ||
93 | |||
94 | struct drm_psb_register_rw_arg { | ||
95 | u32 b_force_hw_on; | ||
96 | |||
97 | u32 display_read_mask; | ||
98 | u32 display_write_mask; | ||
99 | |||
100 | struct { | ||
101 | u32 pfit_controls; | ||
102 | u32 pfit_autoscale_ratios; | ||
103 | u32 pfit_programmed_scale_ratios; | ||
104 | u32 pipeasrc; | ||
105 | u32 pipebsrc; | ||
106 | u32 vtotal_a; | ||
107 | u32 vtotal_b; | ||
108 | } display; | ||
109 | |||
110 | u32 overlay_read_mask; | ||
111 | u32 overlay_write_mask; | ||
112 | |||
113 | struct { | ||
114 | u32 OVADD; | ||
115 | u32 OGAMC0; | ||
116 | u32 OGAMC1; | ||
117 | u32 OGAMC2; | ||
118 | u32 OGAMC3; | ||
119 | u32 OGAMC4; | ||
120 | u32 OGAMC5; | ||
121 | u32 IEP_ENABLED; | ||
122 | u32 IEP_BLE_MINMAX; | ||
123 | u32 IEP_BSSCC_CONTROL; | ||
124 | u32 b_wait_vblank; | ||
125 | } overlay; | ||
126 | |||
127 | u32 sprite_enable_mask; | ||
128 | u32 sprite_disable_mask; | ||
129 | |||
130 | struct { | ||
131 | u32 dspa_control; | ||
132 | u32 dspa_key_value; | ||
133 | u32 dspa_key_mask; | ||
134 | u32 dspc_control; | ||
135 | u32 dspc_stride; | ||
136 | u32 dspc_position; | ||
137 | u32 dspc_linear_offset; | ||
138 | u32 dspc_size; | ||
139 | u32 dspc_surface; | ||
140 | } sprite; | ||
141 | |||
142 | u32 subpicture_enable_mask; | ||
143 | u32 subpicture_disable_mask; | ||
144 | }; | ||
145 | |||
146 | /* Controlling the kernel modesetting buffers */ | ||
147 | |||
148 | #define DRM_PSB_SIZES 0x07 | ||
149 | #define DRM_PSB_FUSE_REG 0x08 | ||
150 | #define DRM_PSB_DC_STATE 0x0A | ||
151 | #define DRM_PSB_ADB 0x0B | ||
152 | #define DRM_PSB_MODE_OPERATION 0x0C | ||
153 | #define DRM_PSB_STOLEN_MEMORY 0x0D | ||
154 | #define DRM_PSB_REGISTER_RW 0x0E | ||
155 | |||
156 | /* | ||
157 | * NOTE: Add new commands here, but increment | ||
158 | * the values below and increment their | ||
159 | * corresponding defines where they're | ||
160 | * defined elsewhere. | ||
161 | */ | ||
162 | |||
163 | #define DRM_PSB_GEM_CREATE 0x10 | ||
164 | #define DRM_PSB_2D_OP 0x11 | ||
165 | #define DRM_PSB_GEM_MMAP 0x12 | ||
166 | #define DRM_PSB_DPST 0x1B | ||
167 | #define DRM_PSB_GAMMA 0x1C | ||
168 | #define DRM_PSB_DPST_BL 0x1D | ||
169 | #define DRM_PSB_GET_PIPE_FROM_CRTC_ID 0x1F | ||
170 | |||
171 | #define PSB_MODE_OPERATION_MODE_VALID 0x01 | ||
172 | #define PSB_MODE_OPERATION_SET_DC_BASE 0x02 | ||
173 | |||
174 | struct drm_psb_get_pipe_from_crtc_id_arg { | ||
175 | /** ID of CRTC being requested **/ | ||
176 | u32 crtc_id; | ||
177 | |||
178 | /** pipe of requested CRTC **/ | ||
179 | u32 pipe; | ||
180 | }; | ||
181 | |||
182 | /* FIXME: move this into a medfield header once we are sure it isn't needed for an | ||
183 | ioctl */ | ||
184 | struct psb_drm_dpu_rect { | ||
185 | int x, y; | ||
186 | int width, height; | ||
187 | }; | ||
188 | |||
189 | struct drm_psb_gem_create { | ||
190 | __u64 size; | ||
191 | __u32 handle; | ||
192 | __u32 flags; | ||
193 | #define PSB_GEM_CREATE_STOLEN 1 /* Stolen memory can be used */ | ||
194 | }; | ||
195 | |||
196 | #define PSB_2D_OP_BUFLEN 16 | ||
197 | |||
198 | struct drm_psb_2d_op { | ||
199 | __u32 src; /* Handles, only src supported right now */ | ||
200 | __u32 dst; | ||
201 | __u32 mask; | ||
202 | __u32 pat; | ||
203 | __u32 size; /* In dwords of command */ | ||
204 | __u32 spare; /* And bumps array to u64 align */ | ||
205 | __u32 cmd[PSB_2D_OP_BUFLEN]; | ||
206 | }; | ||
207 | |||
208 | struct drm_psb_gem_mmap { | ||
209 | __u32 handle; | ||
210 | __u32 pad; | ||
211 | /** | ||
212 | * Fake offset to use for subsequent mmap call | ||
213 | * | ||
214 | * This is a fixed-size type for 32/64 compatibility. | ||
215 | */ | ||
216 | __u64 offset; | ||
217 | }; | ||
218 | |||
219 | #endif | ||
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c deleted file mode 100644 index 95816808f867..000000000000 --- a/drivers/staging/gma500/psb_drv.c +++ /dev/null | |||
@@ -1,1230 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2007-2011, Intel Corporation. | ||
3 | * All Rights Reserved. | ||
4 | * Copyright (c) 2008, Tungsten Graphics, Inc. Cedar Park, TX., USA. | ||
5 | * All Rights Reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms and conditions of the GNU General Public License, | ||
9 | * version 2, as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | * | ||
20 | **************************************************************************/ | ||
21 | |||
22 | #include <drm/drmP.h> | ||
23 | #include <drm/drm.h> | ||
24 | #include "psb_drm.h" | ||
25 | #include "psb_drv.h" | ||
26 | #include "framebuffer.h" | ||
27 | #include "psb_reg.h" | ||
28 | #include "psb_intel_reg.h" | ||
29 | #include "intel_bios.h" | ||
30 | #include "mid_bios.h" | ||
31 | #include "mdfld_dsi_dbi.h" | ||
32 | #include <drm/drm_pciids.h> | ||
33 | #include "power.h" | ||
34 | #include <linux/cpu.h> | ||
35 | #include <linux/notifier.h> | ||
36 | #include <linux/spinlock.h> | ||
37 | #include <linux/pm_runtime.h> | ||
38 | #include <linux/module.h> | ||
39 | #include <acpi/video.h> | ||
40 | |||
41 | static int drm_psb_trap_pagefaults; | ||
42 | |||
43 | int drm_psb_no_fb; | ||
44 | |||
45 | static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent); | ||
46 | |||
47 | MODULE_PARM_DESC(no_fb, "Disable FBdev"); | ||
48 | MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults"); | ||
49 | module_param_named(no_fb, drm_psb_no_fb, int, 0600); | ||
50 | module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600); | ||
51 | |||
52 | |||
53 | static DEFINE_PCI_DEVICE_TABLE(pciidlist) = { | ||
54 | { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, | ||
55 | { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops }, | ||
56 | #if defined(CONFIG_DRM_PSB_MRST) | ||
57 | { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, | ||
58 | { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, | ||
59 | { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, | ||
60 | { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, | ||
61 | { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, | ||
62 | { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, | ||
63 | { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, | ||
64 | { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops}, | ||
65 | #endif | ||
66 | #if defined(CONFIG_DRM_PSB_MFLD) | ||
67 | { 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, | ||
68 | { 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, | ||
69 | { 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, | ||
70 | { 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, | ||
71 | { 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, | ||
72 | { 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, | ||
73 | { 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, | ||
74 | { 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops}, | ||
75 | #endif | ||
76 | #if defined(CONFIG_DRM_PSB_CDV) | ||
77 | { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, | ||
78 | { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, | ||
79 | { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, | ||
80 | { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, | ||
81 | { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, | ||
82 | { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, | ||
83 | { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, | ||
84 | { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, | ||
85 | #endif | ||
86 | { 0, 0, 0} | ||
87 | }; | ||
88 | MODULE_DEVICE_TABLE(pci, pciidlist); | ||
89 | |||
90 | /* | ||
91 | * Standard IOCTLs. | ||
92 | */ | ||
93 | |||
94 | #define DRM_IOCTL_PSB_SIZES \ | ||
95 | DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \ | ||
96 | struct drm_psb_sizes_arg) | ||
97 | #define DRM_IOCTL_PSB_FUSE_REG \ | ||
98 | DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t) | ||
99 | #define DRM_IOCTL_PSB_DC_STATE \ | ||
100 | DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \ | ||
101 | struct drm_psb_dc_state_arg) | ||
102 | #define DRM_IOCTL_PSB_ADB \ | ||
103 | DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t) | ||
104 | #define DRM_IOCTL_PSB_MODE_OPERATION \ | ||
105 | DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \ | ||
106 | struct drm_psb_mode_operation_arg) | ||
107 | #define DRM_IOCTL_PSB_STOLEN_MEMORY \ | ||
108 | DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \ | ||
109 | struct drm_psb_stolen_memory_arg) | ||
110 | #define DRM_IOCTL_PSB_REGISTER_RW \ | ||
111 | DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \ | ||
112 | struct drm_psb_register_rw_arg) | ||
113 | #define DRM_IOCTL_PSB_DPST \ | ||
114 | DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \ | ||
115 | uint32_t) | ||
116 | #define DRM_IOCTL_PSB_GAMMA \ | ||
117 | DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \ | ||
118 | struct drm_psb_dpst_lut_arg) | ||
119 | #define DRM_IOCTL_PSB_DPST_BL \ | ||
120 | DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \ | ||
121 | uint32_t) | ||
122 | #define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID \ | ||
123 | DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \ | ||
124 | struct drm_psb_get_pipe_from_crtc_id_arg) | ||
125 | #define DRM_IOCTL_PSB_GEM_CREATE \ | ||
126 | DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \ | ||
127 | struct drm_psb_gem_create) | ||
128 | #define DRM_IOCTL_PSB_2D_OP \ | ||
129 | DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \ | ||
130 | struct drm_psb_2d_op) | ||
131 | #define DRM_IOCTL_PSB_GEM_MMAP \ | ||
132 | DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \ | ||
133 | struct drm_psb_gem_mmap) | ||
134 | |||
135 | static int psb_sizes_ioctl(struct drm_device *dev, void *data, | ||
136 | struct drm_file *file_priv); | ||
137 | static int psb_dc_state_ioctl(struct drm_device *dev, void * data, | ||
138 | struct drm_file *file_priv); | ||
139 | static int psb_adb_ioctl(struct drm_device *dev, void *data, | ||
140 | struct drm_file *file_priv); | ||
141 | static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, | ||
142 | struct drm_file *file_priv); | ||
143 | static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, | ||
144 | struct drm_file *file_priv); | ||
145 | static int psb_register_rw_ioctl(struct drm_device *dev, void *data, | ||
146 | struct drm_file *file_priv); | ||
147 | static int psb_dpst_ioctl(struct drm_device *dev, void *data, | ||
148 | struct drm_file *file_priv); | ||
149 | static int psb_gamma_ioctl(struct drm_device *dev, void *data, | ||
150 | struct drm_file *file_priv); | ||
151 | static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, | ||
152 | struct drm_file *file_priv); | ||
153 | |||
154 | #define PSB_IOCTL_DEF(ioctl, func, flags) \ | ||
155 | [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func} | ||
156 | |||
157 | static struct drm_ioctl_desc psb_ioctls[] = { | ||
158 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH), | ||
159 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH), | ||
160 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH), | ||
161 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl, | ||
162 | DRM_AUTH), | ||
163 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl, | ||
164 | DRM_AUTH), | ||
165 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl, | ||
166 | DRM_AUTH), | ||
167 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH), | ||
168 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH), | ||
169 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH), | ||
170 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID, | ||
171 | psb_intel_get_pipe_from_crtc_id, 0), | ||
172 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl, | ||
173 | DRM_UNLOCKED | DRM_AUTH), | ||
174 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl, | ||
175 | DRM_UNLOCKED| DRM_AUTH), | ||
176 | PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_MMAP, psb_gem_mmap_ioctl, | ||
177 | DRM_UNLOCKED | DRM_AUTH), | ||
178 | }; | ||
179 | |||
180 | static void psb_lastclose(struct drm_device *dev) | ||
181 | { | ||
182 | return; | ||
183 | } | ||
184 | |||
185 | static void psb_do_takedown(struct drm_device *dev) | ||
186 | { | ||
187 | } | ||
188 | |||
189 | static int psb_do_init(struct drm_device *dev) | ||
190 | { | ||
191 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
192 | struct psb_gtt *pg = &dev_priv->gtt; | ||
193 | |||
194 | uint32_t stolen_gtt; | ||
195 | |||
196 | int ret = -ENOMEM; | ||
197 | |||
198 | if (pg->mmu_gatt_start & 0x0FFFFFFF) { | ||
199 | dev_err(dev->dev, "Gatt must be 256M aligned. This is a bug.\n"); | ||
200 | ret = -EINVAL; | ||
201 | goto out_err; | ||
202 | } | ||
203 | |||
204 | |||
205 | stolen_gtt = (pg->stolen_size >> PAGE_SHIFT) * 4; | ||
206 | stolen_gtt = (stolen_gtt + PAGE_SIZE - 1) >> PAGE_SHIFT; | ||
207 | stolen_gtt = | ||
208 | (stolen_gtt < pg->gtt_pages) ? stolen_gtt : pg->gtt_pages; | ||
209 | |||
210 | dev_priv->gatt_free_offset = pg->mmu_gatt_start + | ||
211 | (stolen_gtt << PAGE_SHIFT) * 1024; | ||
212 | |||
213 | if (1 || drm_debug) { | ||
214 | uint32_t core_id = PSB_RSGX32(PSB_CR_CORE_ID); | ||
215 | uint32_t core_rev = PSB_RSGX32(PSB_CR_CORE_REVISION); | ||
216 | DRM_INFO("SGX core id = 0x%08x\n", core_id); | ||
217 | DRM_INFO("SGX core rev major = 0x%02x, minor = 0x%02x\n", | ||
218 | (core_rev & _PSB_CC_REVISION_MAJOR_MASK) >> | ||
219 | _PSB_CC_REVISION_MAJOR_SHIFT, | ||
220 | (core_rev & _PSB_CC_REVISION_MINOR_MASK) >> | ||
221 | _PSB_CC_REVISION_MINOR_SHIFT); | ||
222 | DRM_INFO | ||
223 | ("SGX core rev maintenance = 0x%02x, designer = 0x%02x\n", | ||
224 | (core_rev & _PSB_CC_REVISION_MAINTENANCE_MASK) >> | ||
225 | _PSB_CC_REVISION_MAINTENANCE_SHIFT, | ||
226 | (core_rev & _PSB_CC_REVISION_DESIGNER_MASK) >> | ||
227 | _PSB_CC_REVISION_DESIGNER_SHIFT); | ||
228 | } | ||
229 | |||
230 | |||
231 | spin_lock_init(&dev_priv->irqmask_lock); | ||
232 | spin_lock_init(&dev_priv->lock_2d); | ||
233 | |||
234 | PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK0); | ||
235 | PSB_WSGX32(0x00000000, PSB_CR_BIF_BANK1); | ||
236 | PSB_RSGX32(PSB_CR_BIF_BANK1); | ||
237 | PSB_WSGX32(PSB_RSGX32(PSB_CR_BIF_CTRL) | _PSB_MMU_ER_MASK, | ||
238 | PSB_CR_BIF_CTRL); | ||
239 | psb_spank(dev_priv); | ||
240 | |||
241 | /* mmu_gatt ?? */ | ||
242 | PSB_WSGX32(pg->gatt_start, PSB_CR_BIF_TWOD_REQ_BASE); | ||
243 | return 0; | ||
244 | out_err: | ||
245 | psb_do_takedown(dev); | ||
246 | return ret; | ||
247 | } | ||
248 | |||
249 | static int psb_driver_unload(struct drm_device *dev) | ||
250 | { | ||
251 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
252 | |||
253 | /* Kill vblank etc here */ | ||
254 | |||
255 | gma_backlight_exit(dev); | ||
256 | |||
257 | if (drm_psb_no_fb == 0) | ||
258 | psb_modeset_cleanup(dev); | ||
259 | |||
260 | if (dev_priv) { | ||
261 | psb_lid_timer_takedown(dev_priv); | ||
262 | gma_intel_opregion_exit(dev); | ||
263 | |||
264 | if (dev_priv->ops->chip_teardown) | ||
265 | dev_priv->ops->chip_teardown(dev); | ||
266 | psb_do_takedown(dev); | ||
267 | |||
268 | |||
269 | if (dev_priv->pf_pd) { | ||
270 | psb_mmu_free_pagedir(dev_priv->pf_pd); | ||
271 | dev_priv->pf_pd = NULL; | ||
272 | } | ||
273 | if (dev_priv->mmu) { | ||
274 | struct psb_gtt *pg = &dev_priv->gtt; | ||
275 | |||
276 | down_read(&pg->sem); | ||
277 | psb_mmu_remove_pfn_sequence( | ||
278 | psb_mmu_get_default_pd | ||
279 | (dev_priv->mmu), | ||
280 | pg->mmu_gatt_start, | ||
281 | dev_priv->vram_stolen_size >> PAGE_SHIFT); | ||
282 | up_read(&pg->sem); | ||
283 | psb_mmu_driver_takedown(dev_priv->mmu); | ||
284 | dev_priv->mmu = NULL; | ||
285 | } | ||
286 | psb_gtt_takedown(dev); | ||
287 | if (dev_priv->scratch_page) { | ||
288 | __free_page(dev_priv->scratch_page); | ||
289 | dev_priv->scratch_page = NULL; | ||
290 | } | ||
291 | if (dev_priv->vdc_reg) { | ||
292 | iounmap(dev_priv->vdc_reg); | ||
293 | dev_priv->vdc_reg = NULL; | ||
294 | } | ||
295 | if (dev_priv->sgx_reg) { | ||
296 | iounmap(dev_priv->sgx_reg); | ||
297 | dev_priv->sgx_reg = NULL; | ||
298 | } | ||
299 | |||
300 | kfree(dev_priv); | ||
301 | dev->dev_private = NULL; | ||
302 | |||
303 | /*destroy VBT data*/ | ||
304 | psb_intel_destroy_bios(dev); | ||
305 | } | ||
306 | |||
307 | gma_power_uninit(dev); | ||
308 | |||
309 | return 0; | ||
310 | } | ||
311 | |||
312 | |||
313 | static int psb_driver_load(struct drm_device *dev, unsigned long chipset) | ||
314 | { | ||
315 | struct drm_psb_private *dev_priv; | ||
316 | unsigned long resource_start; | ||
317 | struct psb_gtt *pg; | ||
318 | unsigned long irqflags; | ||
319 | int ret = -ENOMEM; | ||
320 | uint32_t tt_pages; | ||
321 | struct drm_connector *connector; | ||
322 | struct psb_intel_output *psb_intel_output; | ||
323 | |||
324 | dev_priv = kzalloc(sizeof(*dev_priv), GFP_KERNEL); | ||
325 | if (dev_priv == NULL) | ||
326 | return -ENOMEM; | ||
327 | |||
328 | dev_priv->ops = (struct psb_ops *)chipset; | ||
329 | dev_priv->dev = dev; | ||
330 | dev->dev_private = (void *) dev_priv; | ||
331 | |||
332 | if (!IS_PSB(dev)) { | ||
333 | if (pci_enable_msi(dev->pdev)) | ||
334 | dev_warn(dev->dev, "Enabling MSI failed!\n"); | ||
335 | } | ||
336 | |||
337 | dev_priv->num_pipe = dev_priv->ops->pipes; | ||
338 | |||
339 | resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE); | ||
340 | |||
341 | dev_priv->vdc_reg = | ||
342 | ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE); | ||
343 | if (!dev_priv->vdc_reg) | ||
344 | goto out_err; | ||
345 | |||
346 | dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset, | ||
347 | PSB_SGX_SIZE); | ||
348 | if (!dev_priv->sgx_reg) | ||
349 | goto out_err; | ||
350 | |||
351 | ret = dev_priv->ops->chip_setup(dev); | ||
352 | if (ret) | ||
353 | goto out_err; | ||
354 | |||
355 | /* Init OSPM support */ | ||
356 | gma_power_init(dev); | ||
357 | |||
358 | ret = -ENOMEM; | ||
359 | |||
360 | dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO); | ||
361 | if (!dev_priv->scratch_page) | ||
362 | goto out_err; | ||
363 | |||
364 | set_pages_uc(dev_priv->scratch_page, 1); | ||
365 | |||
366 | ret = psb_gtt_init(dev, 0); | ||
367 | if (ret) | ||
368 | goto out_err; | ||
369 | |||
370 | dev_priv->mmu = psb_mmu_driver_init((void *)0, | ||
371 | drm_psb_trap_pagefaults, 0, | ||
372 | dev_priv); | ||
373 | if (!dev_priv->mmu) | ||
374 | goto out_err; | ||
375 | |||
376 | pg = &dev_priv->gtt; | ||
377 | |||
378 | tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ? | ||
379 | (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT; | ||
380 | |||
381 | |||
382 | dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0); | ||
383 | if (!dev_priv->pf_pd) | ||
384 | goto out_err; | ||
385 | |||
386 | psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0); | ||
387 | psb_mmu_set_pd_context(dev_priv->pf_pd, 1); | ||
388 | |||
389 | ret = psb_do_init(dev); | ||
390 | if (ret) | ||
391 | return ret; | ||
392 | |||
393 | PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE); | ||
394 | PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE); | ||
395 | |||
396 | /* igd_opregion_init(&dev_priv->opregion_dev); */ | ||
397 | acpi_video_register(); | ||
398 | if (dev_priv->lid_state) | ||
399 | psb_lid_timer_init(dev_priv); | ||
400 | |||
401 | ret = drm_vblank_init(dev, dev_priv->num_pipe); | ||
402 | if (ret) | ||
403 | goto out_err; | ||
404 | |||
405 | /* | ||
406 | * Install interrupt handlers prior to powering off SGX or else we will | ||
407 | * crash. | ||
408 | */ | ||
409 | dev_priv->vdc_irq_mask = 0; | ||
410 | dev_priv->pipestat[0] = 0; | ||
411 | dev_priv->pipestat[1] = 0; | ||
412 | dev_priv->pipestat[2] = 0; | ||
413 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | ||
414 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); | ||
415 | PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R); | ||
416 | PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R); | ||
417 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | ||
418 | if (IS_PSB(dev) && drm_core_check_feature(dev, DRIVER_MODESET)) | ||
419 | drm_irq_install(dev); | ||
420 | |||
421 | dev->vblank_disable_allowed = 1; | ||
422 | |||
423 | dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ | ||
424 | |||
425 | dev->driver->get_vblank_counter = psb_get_vblank_counter; | ||
426 | |||
427 | #if defined(CONFIG_DRM_PSB_MFLD) | ||
428 | /* FIXME: this is not the right place for this stuff ! */ | ||
429 | mdfld_output_setup(dev); | ||
430 | #endif | ||
431 | if (drm_psb_no_fb == 0) { | ||
432 | psb_modeset_init(dev); | ||
433 | psb_fbdev_init(dev); | ||
434 | drm_kms_helper_poll_init(dev); | ||
435 | } | ||
436 | |||
437 | /* Only add backlight support if we have LVDS output */ | ||
438 | list_for_each_entry(connector, &dev->mode_config.connector_list, | ||
439 | head) { | ||
440 | psb_intel_output = to_psb_intel_output(connector); | ||
441 | |||
442 | switch (psb_intel_output->type) { | ||
443 | case INTEL_OUTPUT_LVDS: | ||
444 | case INTEL_OUTPUT_MIPI: | ||
445 | ret = gma_backlight_init(dev); | ||
446 | break; | ||
447 | } | ||
448 | } | ||
449 | |||
450 | if (ret) | ||
451 | return ret; | ||
452 | |||
453 | /* Enable runtime pm at last */ | ||
454 | pm_runtime_set_active(&dev->pdev->dev); | ||
455 | return 0; | ||
456 | out_err: | ||
457 | psb_driver_unload(dev); | ||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | int psb_driver_device_is_agp(struct drm_device *dev) | ||
462 | { | ||
463 | return 0; | ||
464 | } | ||
465 | |||
466 | |||
467 | static int psb_sizes_ioctl(struct drm_device *dev, void *data, | ||
468 | struct drm_file *file_priv) | ||
469 | { | ||
470 | struct drm_psb_private *dev_priv = psb_priv(dev); | ||
471 | struct drm_psb_sizes_arg *arg = data; | ||
472 | |||
473 | *arg = dev_priv->sizes; | ||
474 | return 0; | ||
475 | } | ||
476 | |||
477 | static int psb_dc_state_ioctl(struct drm_device *dev, void *data, | ||
478 | struct drm_file *file_priv) | ||
479 | { | ||
480 | uint32_t flags; | ||
481 | uint32_t obj_id; | ||
482 | struct drm_mode_object *obj; | ||
483 | struct drm_connector *connector; | ||
484 | struct drm_crtc *crtc; | ||
485 | struct drm_psb_dc_state_arg *arg = data; | ||
486 | |||
487 | |||
488 | /* Double check MRST case */ | ||
489 | if (IS_MRST(dev) || IS_MFLD(dev)) | ||
490 | return -EOPNOTSUPP; | ||
491 | |||
492 | flags = arg->flags; | ||
493 | obj_id = arg->obj_id; | ||
494 | |||
495 | if (flags & PSB_DC_CRTC_MASK) { | ||
496 | obj = drm_mode_object_find(dev, obj_id, | ||
497 | DRM_MODE_OBJECT_CRTC); | ||
498 | if (!obj) { | ||
499 | dev_dbg(dev->dev, "Invalid CRTC object.\n"); | ||
500 | return -EINVAL; | ||
501 | } | ||
502 | |||
503 | crtc = obj_to_crtc(obj); | ||
504 | |||
505 | mutex_lock(&dev->mode_config.mutex); | ||
506 | if (drm_helper_crtc_in_use(crtc)) { | ||
507 | if (flags & PSB_DC_CRTC_SAVE) | ||
508 | crtc->funcs->save(crtc); | ||
509 | else | ||
510 | crtc->funcs->restore(crtc); | ||
511 | } | ||
512 | mutex_unlock(&dev->mode_config.mutex); | ||
513 | |||
514 | return 0; | ||
515 | } else if (flags & PSB_DC_OUTPUT_MASK) { | ||
516 | obj = drm_mode_object_find(dev, obj_id, | ||
517 | DRM_MODE_OBJECT_CONNECTOR); | ||
518 | if (!obj) { | ||
519 | dev_dbg(dev->dev, "Invalid connector id.\n"); | ||
520 | return -EINVAL; | ||
521 | } | ||
522 | |||
523 | connector = obj_to_connector(obj); | ||
524 | if (flags & PSB_DC_OUTPUT_SAVE) | ||
525 | connector->funcs->save(connector); | ||
526 | else | ||
527 | connector->funcs->restore(connector); | ||
528 | |||
529 | return 0; | ||
530 | } | ||
531 | return -EINVAL; | ||
532 | } | ||
533 | |||
534 | static inline void get_brightness(struct backlight_device *bd) | ||
535 | { | ||
536 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
537 | if (bd) { | ||
538 | bd->props.brightness = bd->ops->get_brightness(bd); | ||
539 | backlight_update_status(bd); | ||
540 | } | ||
541 | #endif | ||
542 | } | ||
543 | |||
544 | static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data, | ||
545 | struct drm_file *file_priv) | ||
546 | { | ||
547 | struct drm_psb_private *dev_priv = psb_priv(dev); | ||
548 | uint32_t *arg = data; | ||
549 | |||
550 | dev_priv->blc_adj2 = *arg; | ||
551 | get_brightness(dev_priv->backlight_device); | ||
552 | return 0; | ||
553 | } | ||
554 | |||
555 | static int psb_adb_ioctl(struct drm_device *dev, void *data, | ||
556 | struct drm_file *file_priv) | ||
557 | { | ||
558 | struct drm_psb_private *dev_priv = psb_priv(dev); | ||
559 | uint32_t *arg = data; | ||
560 | |||
561 | dev_priv->blc_adj1 = *arg; | ||
562 | get_brightness(dev_priv->backlight_device); | ||
563 | return 0; | ||
564 | } | ||
565 | |||
566 | /* return the current mode to the dpst module */ | ||
567 | static int psb_dpst_ioctl(struct drm_device *dev, void *data, | ||
568 | struct drm_file *file_priv) | ||
569 | { | ||
570 | struct drm_psb_private *dev_priv = psb_priv(dev); | ||
571 | uint32_t *arg = data; | ||
572 | uint32_t x; | ||
573 | uint32_t y; | ||
574 | uint32_t reg; | ||
575 | |||
576 | if (!gma_power_begin(dev, 0)) | ||
577 | return -EIO; | ||
578 | |||
579 | reg = PSB_RVDC32(PIPEASRC); | ||
580 | |||
581 | gma_power_end(dev); | ||
582 | |||
583 | /* horizontal is the left 16 bits */ | ||
584 | x = reg >> 16; | ||
585 | /* vertical is the right 16 bits */ | ||
586 | y = reg & 0x0000ffff; | ||
587 | |||
588 | /* the values are the image size minus one */ | ||
589 | x++; | ||
590 | y++; | ||
591 | |||
592 | *arg = (x << 16) | y; | ||
593 | |||
594 | return 0; | ||
595 | } | ||
596 | static int psb_gamma_ioctl(struct drm_device *dev, void *data, | ||
597 | struct drm_file *file_priv) | ||
598 | { | ||
599 | struct drm_psb_dpst_lut_arg *lut_arg = data; | ||
600 | struct drm_mode_object *obj; | ||
601 | struct drm_crtc *crtc; | ||
602 | struct drm_connector *connector; | ||
603 | struct psb_intel_crtc *psb_intel_crtc; | ||
604 | int i = 0; | ||
605 | int32_t obj_id; | ||
606 | |||
607 | obj_id = lut_arg->output_id; | ||
608 | obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_CONNECTOR); | ||
609 | if (!obj) { | ||
610 | dev_dbg(dev->dev, "Invalid Connector object.\n"); | ||
611 | return -EINVAL; | ||
612 | } | ||
613 | |||
614 | connector = obj_to_connector(obj); | ||
615 | crtc = connector->encoder->crtc; | ||
616 | psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
617 | |||
618 | for (i = 0; i < 256; i++) | ||
619 | psb_intel_crtc->lut_adj[i] = lut_arg->lut[i]; | ||
620 | |||
621 | psb_intel_crtc_load_lut(crtc); | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | static int psb_mode_operation_ioctl(struct drm_device *dev, void *data, | ||
627 | struct drm_file *file_priv) | ||
628 | { | ||
629 | uint32_t obj_id; | ||
630 | uint16_t op; | ||
631 | struct drm_mode_modeinfo *umode; | ||
632 | struct drm_display_mode *mode = NULL; | ||
633 | struct drm_psb_mode_operation_arg *arg; | ||
634 | struct drm_mode_object *obj; | ||
635 | struct drm_connector *connector; | ||
636 | struct drm_framebuffer *drm_fb; | ||
637 | struct psb_framebuffer *psb_fb; | ||
638 | struct drm_connector_helper_funcs *connector_funcs; | ||
639 | int ret = 0; | ||
640 | int resp = MODE_OK; | ||
641 | struct drm_psb_private *dev_priv = psb_priv(dev); | ||
642 | |||
643 | arg = (struct drm_psb_mode_operation_arg *)data; | ||
644 | obj_id = arg->obj_id; | ||
645 | op = arg->operation; | ||
646 | |||
647 | switch (op) { | ||
648 | case PSB_MODE_OPERATION_SET_DC_BASE: | ||
649 | obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_FB); | ||
650 | if (!obj) { | ||
651 | dev_dbg(dev->dev, "Invalid FB id %d\n", obj_id); | ||
652 | return -EINVAL; | ||
653 | } | ||
654 | |||
655 | drm_fb = obj_to_fb(obj); | ||
656 | psb_fb = to_psb_fb(drm_fb); | ||
657 | |||
658 | if (gma_power_begin(dev, 0)) { | ||
659 | REG_WRITE(DSPASURF, psb_fb->gtt->offset); | ||
660 | REG_READ(DSPASURF); | ||
661 | gma_power_end(dev); | ||
662 | } else { | ||
663 | dev_priv->saveDSPASURF = psb_fb->gtt->offset; | ||
664 | } | ||
665 | |||
666 | return 0; | ||
667 | case PSB_MODE_OPERATION_MODE_VALID: | ||
668 | umode = &arg->mode; | ||
669 | |||
670 | mutex_lock(&dev->mode_config.mutex); | ||
671 | |||
672 | obj = drm_mode_object_find(dev, obj_id, | ||
673 | DRM_MODE_OBJECT_CONNECTOR); | ||
674 | if (!obj) { | ||
675 | ret = -EINVAL; | ||
676 | goto mode_op_out; | ||
677 | } | ||
678 | |||
679 | connector = obj_to_connector(obj); | ||
680 | |||
681 | mode = drm_mode_create(dev); | ||
682 | if (!mode) { | ||
683 | ret = -ENOMEM; | ||
684 | goto mode_op_out; | ||
685 | } | ||
686 | |||
687 | /* drm_crtc_convert_umode(mode, umode); */ | ||
688 | { | ||
689 | mode->clock = umode->clock; | ||
690 | mode->hdisplay = umode->hdisplay; | ||
691 | mode->hsync_start = umode->hsync_start; | ||
692 | mode->hsync_end = umode->hsync_end; | ||
693 | mode->htotal = umode->htotal; | ||
694 | mode->hskew = umode->hskew; | ||
695 | mode->vdisplay = umode->vdisplay; | ||
696 | mode->vsync_start = umode->vsync_start; | ||
697 | mode->vsync_end = umode->vsync_end; | ||
698 | mode->vtotal = umode->vtotal; | ||
699 | mode->vscan = umode->vscan; | ||
700 | mode->vrefresh = umode->vrefresh; | ||
701 | mode->flags = umode->flags; | ||
702 | mode->type = umode->type; | ||
703 | strncpy(mode->name, umode->name, DRM_DISPLAY_MODE_LEN); | ||
704 | mode->name[DRM_DISPLAY_MODE_LEN-1] = 0; | ||
705 | } | ||
706 | |||
707 | connector_funcs = (struct drm_connector_helper_funcs *) | ||
708 | connector->helper_private; | ||
709 | |||
710 | if (connector_funcs->mode_valid) { | ||
711 | resp = connector_funcs->mode_valid(connector, mode); | ||
712 | arg->data = (void *)resp; | ||
713 | } | ||
714 | |||
715 | /*do some clean up work*/ | ||
716 | if (mode) | ||
717 | drm_mode_destroy(dev, mode); | ||
718 | mode_op_out: | ||
719 | mutex_unlock(&dev->mode_config.mutex); | ||
720 | return ret; | ||
721 | |||
722 | default: | ||
723 | dev_dbg(dev->dev, "Unsupported psb mode operation\n"); | ||
724 | return -EOPNOTSUPP; | ||
725 | } | ||
726 | |||
727 | return 0; | ||
728 | } | ||
729 | |||
730 | static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data, | ||
731 | struct drm_file *file_priv) | ||
732 | { | ||
733 | struct drm_psb_private *dev_priv = psb_priv(dev); | ||
734 | struct drm_psb_stolen_memory_arg *arg = data; | ||
735 | |||
736 | arg->base = dev_priv->stolen_base; | ||
737 | arg->size = dev_priv->vram_stolen_size; | ||
738 | |||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | /* FIXME: needs Medfield changes */ | ||
743 | static int psb_register_rw_ioctl(struct drm_device *dev, void *data, | ||
744 | struct drm_file *file_priv) | ||
745 | { | ||
746 | struct drm_psb_private *dev_priv = psb_priv(dev); | ||
747 | struct drm_psb_register_rw_arg *arg = data; | ||
748 | bool usage = arg->b_force_hw_on ? true : false; | ||
749 | |||
750 | if (arg->display_write_mask != 0) { | ||
751 | if (gma_power_begin(dev, usage)) { | ||
752 | if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS) | ||
753 | PSB_WVDC32(arg->display.pfit_controls, | ||
754 | PFIT_CONTROL); | ||
755 | if (arg->display_write_mask & | ||
756 | REGRWBITS_PFIT_AUTOSCALE_RATIOS) | ||
757 | PSB_WVDC32(arg->display.pfit_autoscale_ratios, | ||
758 | PFIT_AUTO_RATIOS); | ||
759 | if (arg->display_write_mask & | ||
760 | REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) | ||
761 | PSB_WVDC32( | ||
762 | arg->display.pfit_programmed_scale_ratios, | ||
763 | PFIT_PGM_RATIOS); | ||
764 | if (arg->display_write_mask & REGRWBITS_PIPEASRC) | ||
765 | PSB_WVDC32(arg->display.pipeasrc, | ||
766 | PIPEASRC); | ||
767 | if (arg->display_write_mask & REGRWBITS_PIPEBSRC) | ||
768 | PSB_WVDC32(arg->display.pipebsrc, | ||
769 | PIPEBSRC); | ||
770 | if (arg->display_write_mask & REGRWBITS_VTOTAL_A) | ||
771 | PSB_WVDC32(arg->display.vtotal_a, | ||
772 | VTOTAL_A); | ||
773 | if (arg->display_write_mask & REGRWBITS_VTOTAL_B) | ||
774 | PSB_WVDC32(arg->display.vtotal_b, | ||
775 | VTOTAL_B); | ||
776 | gma_power_end(dev); | ||
777 | } else { | ||
778 | if (arg->display_write_mask & REGRWBITS_PFIT_CONTROLS) | ||
779 | dev_priv->savePFIT_CONTROL = | ||
780 | arg->display.pfit_controls; | ||
781 | if (arg->display_write_mask & | ||
782 | REGRWBITS_PFIT_AUTOSCALE_RATIOS) | ||
783 | dev_priv->savePFIT_AUTO_RATIOS = | ||
784 | arg->display.pfit_autoscale_ratios; | ||
785 | if (arg->display_write_mask & | ||
786 | REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) | ||
787 | dev_priv->savePFIT_PGM_RATIOS = | ||
788 | arg->display.pfit_programmed_scale_ratios; | ||
789 | if (arg->display_write_mask & REGRWBITS_PIPEASRC) | ||
790 | dev_priv->savePIPEASRC = arg->display.pipeasrc; | ||
791 | if (arg->display_write_mask & REGRWBITS_PIPEBSRC) | ||
792 | dev_priv->savePIPEBSRC = arg->display.pipebsrc; | ||
793 | if (arg->display_write_mask & REGRWBITS_VTOTAL_A) | ||
794 | dev_priv->saveVTOTAL_A = arg->display.vtotal_a; | ||
795 | if (arg->display_write_mask & REGRWBITS_VTOTAL_B) | ||
796 | dev_priv->saveVTOTAL_B = arg->display.vtotal_b; | ||
797 | } | ||
798 | } | ||
799 | |||
800 | if (arg->display_read_mask != 0) { | ||
801 | if (gma_power_begin(dev, usage)) { | ||
802 | if (arg->display_read_mask & | ||
803 | REGRWBITS_PFIT_CONTROLS) | ||
804 | arg->display.pfit_controls = | ||
805 | PSB_RVDC32(PFIT_CONTROL); | ||
806 | if (arg->display_read_mask & | ||
807 | REGRWBITS_PFIT_AUTOSCALE_RATIOS) | ||
808 | arg->display.pfit_autoscale_ratios = | ||
809 | PSB_RVDC32(PFIT_AUTO_RATIOS); | ||
810 | if (arg->display_read_mask & | ||
811 | REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) | ||
812 | arg->display.pfit_programmed_scale_ratios = | ||
813 | PSB_RVDC32(PFIT_PGM_RATIOS); | ||
814 | if (arg->display_read_mask & REGRWBITS_PIPEASRC) | ||
815 | arg->display.pipeasrc = PSB_RVDC32(PIPEASRC); | ||
816 | if (arg->display_read_mask & REGRWBITS_PIPEBSRC) | ||
817 | arg->display.pipebsrc = PSB_RVDC32(PIPEBSRC); | ||
818 | if (arg->display_read_mask & REGRWBITS_VTOTAL_A) | ||
819 | arg->display.vtotal_a = PSB_RVDC32(VTOTAL_A); | ||
820 | if (arg->display_read_mask & REGRWBITS_VTOTAL_B) | ||
821 | arg->display.vtotal_b = PSB_RVDC32(VTOTAL_B); | ||
822 | gma_power_end(dev); | ||
823 | } else { | ||
824 | if (arg->display_read_mask & | ||
825 | REGRWBITS_PFIT_CONTROLS) | ||
826 | arg->display.pfit_controls = | ||
827 | dev_priv->savePFIT_CONTROL; | ||
828 | if (arg->display_read_mask & | ||
829 | REGRWBITS_PFIT_AUTOSCALE_RATIOS) | ||
830 | arg->display.pfit_autoscale_ratios = | ||
831 | dev_priv->savePFIT_AUTO_RATIOS; | ||
832 | if (arg->display_read_mask & | ||
833 | REGRWBITS_PFIT_PROGRAMMED_SCALE_RATIOS) | ||
834 | arg->display.pfit_programmed_scale_ratios = | ||
835 | dev_priv->savePFIT_PGM_RATIOS; | ||
836 | if (arg->display_read_mask & REGRWBITS_PIPEASRC) | ||
837 | arg->display.pipeasrc = dev_priv->savePIPEASRC; | ||
838 | if (arg->display_read_mask & REGRWBITS_PIPEBSRC) | ||
839 | arg->display.pipebsrc = dev_priv->savePIPEBSRC; | ||
840 | if (arg->display_read_mask & REGRWBITS_VTOTAL_A) | ||
841 | arg->display.vtotal_a = dev_priv->saveVTOTAL_A; | ||
842 | if (arg->display_read_mask & REGRWBITS_VTOTAL_B) | ||
843 | arg->display.vtotal_b = dev_priv->saveVTOTAL_B; | ||
844 | } | ||
845 | } | ||
846 | |||
847 | if (arg->overlay_write_mask != 0) { | ||
848 | if (gma_power_begin(dev, usage)) { | ||
849 | if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) { | ||
850 | PSB_WVDC32(arg->overlay.OGAMC5, OV_OGAMC5); | ||
851 | PSB_WVDC32(arg->overlay.OGAMC4, OV_OGAMC4); | ||
852 | PSB_WVDC32(arg->overlay.OGAMC3, OV_OGAMC3); | ||
853 | PSB_WVDC32(arg->overlay.OGAMC2, OV_OGAMC2); | ||
854 | PSB_WVDC32(arg->overlay.OGAMC1, OV_OGAMC1); | ||
855 | PSB_WVDC32(arg->overlay.OGAMC0, OV_OGAMC0); | ||
856 | } | ||
857 | if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) { | ||
858 | PSB_WVDC32(arg->overlay.OGAMC5, OVC_OGAMC5); | ||
859 | PSB_WVDC32(arg->overlay.OGAMC4, OVC_OGAMC4); | ||
860 | PSB_WVDC32(arg->overlay.OGAMC3, OVC_OGAMC3); | ||
861 | PSB_WVDC32(arg->overlay.OGAMC2, OVC_OGAMC2); | ||
862 | PSB_WVDC32(arg->overlay.OGAMC1, OVC_OGAMC1); | ||
863 | PSB_WVDC32(arg->overlay.OGAMC0, OVC_OGAMC0); | ||
864 | } | ||
865 | |||
866 | if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) { | ||
867 | PSB_WVDC32(arg->overlay.OVADD, OV_OVADD); | ||
868 | |||
869 | if (arg->overlay.b_wait_vblank) { | ||
870 | /* Wait for 20ms.*/ | ||
871 | unsigned long vblank_timeout = jiffies | ||
872 | + HZ/50; | ||
873 | uint32_t temp; | ||
874 | while (time_before_eq(jiffies, | ||
875 | vblank_timeout)) { | ||
876 | temp = PSB_RVDC32(OV_DOVASTA); | ||
877 | if ((temp & (0x1 << 31)) != 0) | ||
878 | break; | ||
879 | cpu_relax(); | ||
880 | } | ||
881 | } | ||
882 | } | ||
883 | if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) { | ||
884 | PSB_WVDC32(arg->overlay.OVADD, OVC_OVADD); | ||
885 | if (arg->overlay.b_wait_vblank) { | ||
886 | /* Wait for 20ms.*/ | ||
887 | unsigned long vblank_timeout = | ||
888 | jiffies + HZ/50; | ||
889 | uint32_t temp; | ||
890 | while (time_before_eq(jiffies, | ||
891 | vblank_timeout)) { | ||
892 | temp = PSB_RVDC32(OVC_DOVCSTA); | ||
893 | if ((temp & (0x1 << 31)) != 0) | ||
894 | break; | ||
895 | cpu_relax(); | ||
896 | } | ||
897 | } | ||
898 | } | ||
899 | gma_power_end(dev); | ||
900 | } else { | ||
901 | if (arg->overlay_write_mask & OV_REGRWBITS_OGAM_ALL) { | ||
902 | dev_priv->saveOV_OGAMC5 = arg->overlay.OGAMC5; | ||
903 | dev_priv->saveOV_OGAMC4 = arg->overlay.OGAMC4; | ||
904 | dev_priv->saveOV_OGAMC3 = arg->overlay.OGAMC3; | ||
905 | dev_priv->saveOV_OGAMC2 = arg->overlay.OGAMC2; | ||
906 | dev_priv->saveOV_OGAMC1 = arg->overlay.OGAMC1; | ||
907 | dev_priv->saveOV_OGAMC0 = arg->overlay.OGAMC0; | ||
908 | } | ||
909 | if (arg->overlay_write_mask & OVC_REGRWBITS_OGAM_ALL) { | ||
910 | dev_priv->saveOVC_OGAMC5 = arg->overlay.OGAMC5; | ||
911 | dev_priv->saveOVC_OGAMC4 = arg->overlay.OGAMC4; | ||
912 | dev_priv->saveOVC_OGAMC3 = arg->overlay.OGAMC3; | ||
913 | dev_priv->saveOVC_OGAMC2 = arg->overlay.OGAMC2; | ||
914 | dev_priv->saveOVC_OGAMC1 = arg->overlay.OGAMC1; | ||
915 | dev_priv->saveOVC_OGAMC0 = arg->overlay.OGAMC0; | ||
916 | } | ||
917 | if (arg->overlay_write_mask & OV_REGRWBITS_OVADD) | ||
918 | dev_priv->saveOV_OVADD = arg->overlay.OVADD; | ||
919 | if (arg->overlay_write_mask & OVC_REGRWBITS_OVADD) | ||
920 | dev_priv->saveOVC_OVADD = arg->overlay.OVADD; | ||
921 | } | ||
922 | } | ||
923 | |||
924 | if (arg->overlay_read_mask != 0) { | ||
925 | if (gma_power_begin(dev, usage)) { | ||
926 | if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) { | ||
927 | arg->overlay.OGAMC5 = PSB_RVDC32(OV_OGAMC5); | ||
928 | arg->overlay.OGAMC4 = PSB_RVDC32(OV_OGAMC4); | ||
929 | arg->overlay.OGAMC3 = PSB_RVDC32(OV_OGAMC3); | ||
930 | arg->overlay.OGAMC2 = PSB_RVDC32(OV_OGAMC2); | ||
931 | arg->overlay.OGAMC1 = PSB_RVDC32(OV_OGAMC1); | ||
932 | arg->overlay.OGAMC0 = PSB_RVDC32(OV_OGAMC0); | ||
933 | } | ||
934 | if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) { | ||
935 | arg->overlay.OGAMC5 = PSB_RVDC32(OVC_OGAMC5); | ||
936 | arg->overlay.OGAMC4 = PSB_RVDC32(OVC_OGAMC4); | ||
937 | arg->overlay.OGAMC3 = PSB_RVDC32(OVC_OGAMC3); | ||
938 | arg->overlay.OGAMC2 = PSB_RVDC32(OVC_OGAMC2); | ||
939 | arg->overlay.OGAMC1 = PSB_RVDC32(OVC_OGAMC1); | ||
940 | arg->overlay.OGAMC0 = PSB_RVDC32(OVC_OGAMC0); | ||
941 | } | ||
942 | if (arg->overlay_read_mask & OV_REGRWBITS_OVADD) | ||
943 | arg->overlay.OVADD = PSB_RVDC32(OV_OVADD); | ||
944 | if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD) | ||
945 | arg->overlay.OVADD = PSB_RVDC32(OVC_OVADD); | ||
946 | gma_power_end(dev); | ||
947 | } else { | ||
948 | if (arg->overlay_read_mask & OV_REGRWBITS_OGAM_ALL) { | ||
949 | arg->overlay.OGAMC5 = dev_priv->saveOV_OGAMC5; | ||
950 | arg->overlay.OGAMC4 = dev_priv->saveOV_OGAMC4; | ||
951 | arg->overlay.OGAMC3 = dev_priv->saveOV_OGAMC3; | ||
952 | arg->overlay.OGAMC2 = dev_priv->saveOV_OGAMC2; | ||
953 | arg->overlay.OGAMC1 = dev_priv->saveOV_OGAMC1; | ||
954 | arg->overlay.OGAMC0 = dev_priv->saveOV_OGAMC0; | ||
955 | } | ||
956 | if (arg->overlay_read_mask & OVC_REGRWBITS_OGAM_ALL) { | ||
957 | arg->overlay.OGAMC5 = dev_priv->saveOVC_OGAMC5; | ||
958 | arg->overlay.OGAMC4 = dev_priv->saveOVC_OGAMC4; | ||
959 | arg->overlay.OGAMC3 = dev_priv->saveOVC_OGAMC3; | ||
960 | arg->overlay.OGAMC2 = dev_priv->saveOVC_OGAMC2; | ||
961 | arg->overlay.OGAMC1 = dev_priv->saveOVC_OGAMC1; | ||
962 | arg->overlay.OGAMC0 = dev_priv->saveOVC_OGAMC0; | ||
963 | } | ||
964 | if (arg->overlay_read_mask & OV_REGRWBITS_OVADD) | ||
965 | arg->overlay.OVADD = dev_priv->saveOV_OVADD; | ||
966 | if (arg->overlay_read_mask & OVC_REGRWBITS_OVADD) | ||
967 | arg->overlay.OVADD = dev_priv->saveOVC_OVADD; | ||
968 | } | ||
969 | } | ||
970 | |||
971 | if (arg->sprite_enable_mask != 0) { | ||
972 | if (gma_power_begin(dev, usage)) { | ||
973 | PSB_WVDC32(0x1F3E, DSPARB); | ||
974 | PSB_WVDC32(arg->sprite.dspa_control | ||
975 | | PSB_RVDC32(DSPACNTR), DSPACNTR); | ||
976 | PSB_WVDC32(arg->sprite.dspa_key_value, DSPAKEYVAL); | ||
977 | PSB_WVDC32(arg->sprite.dspa_key_mask, DSPAKEYMASK); | ||
978 | PSB_WVDC32(PSB_RVDC32(DSPASURF), DSPASURF); | ||
979 | PSB_RVDC32(DSPASURF); | ||
980 | PSB_WVDC32(arg->sprite.dspc_control, DSPCCNTR); | ||
981 | PSB_WVDC32(arg->sprite.dspc_stride, DSPCSTRIDE); | ||
982 | PSB_WVDC32(arg->sprite.dspc_position, DSPCPOS); | ||
983 | PSB_WVDC32(arg->sprite.dspc_linear_offset, DSPCLINOFF); | ||
984 | PSB_WVDC32(arg->sprite.dspc_size, DSPCSIZE); | ||
985 | PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF); | ||
986 | PSB_RVDC32(DSPCSURF); | ||
987 | gma_power_end(dev); | ||
988 | } | ||
989 | } | ||
990 | |||
991 | if (arg->sprite_disable_mask != 0) { | ||
992 | if (gma_power_begin(dev, usage)) { | ||
993 | PSB_WVDC32(0x3F3E, DSPARB); | ||
994 | PSB_WVDC32(0x0, DSPCCNTR); | ||
995 | PSB_WVDC32(arg->sprite.dspc_surface, DSPCSURF); | ||
996 | PSB_RVDC32(DSPCSURF); | ||
997 | gma_power_end(dev); | ||
998 | } | ||
999 | } | ||
1000 | |||
1001 | if (arg->subpicture_enable_mask != 0) { | ||
1002 | if (gma_power_begin(dev, usage)) { | ||
1003 | uint32_t temp; | ||
1004 | if (arg->subpicture_enable_mask & REGRWBITS_DSPACNTR) { | ||
1005 | temp = PSB_RVDC32(DSPACNTR); | ||
1006 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | ||
1007 | temp &= ~DISPPLANE_BOTTOM; | ||
1008 | temp |= DISPPLANE_32BPP; | ||
1009 | PSB_WVDC32(temp, DSPACNTR); | ||
1010 | |||
1011 | temp = PSB_RVDC32(DSPABASE); | ||
1012 | PSB_WVDC32(temp, DSPABASE); | ||
1013 | PSB_RVDC32(DSPABASE); | ||
1014 | temp = PSB_RVDC32(DSPASURF); | ||
1015 | PSB_WVDC32(temp, DSPASURF); | ||
1016 | PSB_RVDC32(DSPASURF); | ||
1017 | } | ||
1018 | if (arg->subpicture_enable_mask & REGRWBITS_DSPBCNTR) { | ||
1019 | temp = PSB_RVDC32(DSPBCNTR); | ||
1020 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | ||
1021 | temp &= ~DISPPLANE_BOTTOM; | ||
1022 | temp |= DISPPLANE_32BPP; | ||
1023 | PSB_WVDC32(temp, DSPBCNTR); | ||
1024 | |||
1025 | temp = PSB_RVDC32(DSPBBASE); | ||
1026 | PSB_WVDC32(temp, DSPBBASE); | ||
1027 | PSB_RVDC32(DSPBBASE); | ||
1028 | temp = PSB_RVDC32(DSPBSURF); | ||
1029 | PSB_WVDC32(temp, DSPBSURF); | ||
1030 | PSB_RVDC32(DSPBSURF); | ||
1031 | } | ||
1032 | if (arg->subpicture_enable_mask & REGRWBITS_DSPCCNTR) { | ||
1033 | temp = PSB_RVDC32(DSPCCNTR); | ||
1034 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | ||
1035 | temp &= ~DISPPLANE_BOTTOM; | ||
1036 | temp |= DISPPLANE_32BPP; | ||
1037 | PSB_WVDC32(temp, DSPCCNTR); | ||
1038 | |||
1039 | temp = PSB_RVDC32(DSPCBASE); | ||
1040 | PSB_WVDC32(temp, DSPCBASE); | ||
1041 | PSB_RVDC32(DSPCBASE); | ||
1042 | temp = PSB_RVDC32(DSPCSURF); | ||
1043 | PSB_WVDC32(temp, DSPCSURF); | ||
1044 | PSB_RVDC32(DSPCSURF); | ||
1045 | } | ||
1046 | gma_power_end(dev); | ||
1047 | } | ||
1048 | } | ||
1049 | |||
1050 | if (arg->subpicture_disable_mask != 0) { | ||
1051 | if (gma_power_begin(dev, usage)) { | ||
1052 | uint32_t temp; | ||
1053 | if (arg->subpicture_disable_mask & REGRWBITS_DSPACNTR) { | ||
1054 | temp = PSB_RVDC32(DSPACNTR); | ||
1055 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | ||
1056 | temp |= DISPPLANE_32BPP_NO_ALPHA; | ||
1057 | PSB_WVDC32(temp, DSPACNTR); | ||
1058 | |||
1059 | temp = PSB_RVDC32(DSPABASE); | ||
1060 | PSB_WVDC32(temp, DSPABASE); | ||
1061 | PSB_RVDC32(DSPABASE); | ||
1062 | temp = PSB_RVDC32(DSPASURF); | ||
1063 | PSB_WVDC32(temp, DSPASURF); | ||
1064 | PSB_RVDC32(DSPASURF); | ||
1065 | } | ||
1066 | if (arg->subpicture_disable_mask & REGRWBITS_DSPBCNTR) { | ||
1067 | temp = PSB_RVDC32(DSPBCNTR); | ||
1068 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | ||
1069 | temp |= DISPPLANE_32BPP_NO_ALPHA; | ||
1070 | PSB_WVDC32(temp, DSPBCNTR); | ||
1071 | |||
1072 | temp = PSB_RVDC32(DSPBBASE); | ||
1073 | PSB_WVDC32(temp, DSPBBASE); | ||
1074 | PSB_RVDC32(DSPBBASE); | ||
1075 | temp = PSB_RVDC32(DSPBSURF); | ||
1076 | PSB_WVDC32(temp, DSPBSURF); | ||
1077 | PSB_RVDC32(DSPBSURF); | ||
1078 | } | ||
1079 | if (arg->subpicture_disable_mask & REGRWBITS_DSPCCNTR) { | ||
1080 | temp = PSB_RVDC32(DSPCCNTR); | ||
1081 | temp &= ~DISPPLANE_PIXFORMAT_MASK; | ||
1082 | temp |= DISPPLANE_32BPP_NO_ALPHA; | ||
1083 | PSB_WVDC32(temp, DSPCCNTR); | ||
1084 | |||
1085 | temp = PSB_RVDC32(DSPCBASE); | ||
1086 | PSB_WVDC32(temp, DSPCBASE); | ||
1087 | PSB_RVDC32(DSPCBASE); | ||
1088 | temp = PSB_RVDC32(DSPCSURF); | ||
1089 | PSB_WVDC32(temp, DSPCSURF); | ||
1090 | PSB_RVDC32(DSPCSURF); | ||
1091 | } | ||
1092 | gma_power_end(dev); | ||
1093 | } | ||
1094 | } | ||
1095 | |||
1096 | return 0; | ||
1097 | } | ||
1098 | |||
1099 | static int psb_driver_open(struct drm_device *dev, struct drm_file *priv) | ||
1100 | { | ||
1101 | return 0; | ||
1102 | } | ||
1103 | |||
1104 | static void psb_driver_close(struct drm_device *dev, struct drm_file *priv) | ||
1105 | { | ||
1106 | } | ||
1107 | |||
1108 | static long psb_unlocked_ioctl(struct file *filp, unsigned int cmd, | ||
1109 | unsigned long arg) | ||
1110 | { | ||
1111 | struct drm_file *file_priv = filp->private_data; | ||
1112 | struct drm_device *dev = file_priv->minor->dev; | ||
1113 | int ret; | ||
1114 | |||
1115 | pm_runtime_forbid(dev->dev); | ||
1116 | ret = drm_ioctl(filp, cmd, arg); | ||
1117 | pm_runtime_allow(dev->dev); | ||
1118 | return ret; | ||
1119 | /* FIXME: do we need to wrap the other side of this */ | ||
1120 | } | ||
1121 | |||
1122 | |||
1123 | /* When a client dies: | ||
1124 | * - Check for and clean up flipped page state | ||
1125 | */ | ||
1126 | void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv) | ||
1127 | { | ||
1128 | } | ||
1129 | |||
1130 | static void psb_remove(struct pci_dev *pdev) | ||
1131 | { | ||
1132 | struct drm_device *dev = pci_get_drvdata(pdev); | ||
1133 | drm_put_dev(dev); | ||
1134 | } | ||
1135 | |||
1136 | static const struct dev_pm_ops psb_pm_ops = { | ||
1137 | .suspend = gma_power_suspend, | ||
1138 | .resume = gma_power_resume, | ||
1139 | .freeze = gma_power_suspend, | ||
1140 | .thaw = gma_power_resume, | ||
1141 | .poweroff = gma_power_suspend, | ||
1142 | .restore = gma_power_resume, | ||
1143 | .runtime_suspend = psb_runtime_suspend, | ||
1144 | .runtime_resume = psb_runtime_resume, | ||
1145 | .runtime_idle = psb_runtime_idle, | ||
1146 | }; | ||
1147 | |||
1148 | static struct vm_operations_struct psb_gem_vm_ops = { | ||
1149 | .fault = psb_gem_fault, | ||
1150 | .open = drm_gem_vm_open, | ||
1151 | .close = drm_gem_vm_close, | ||
1152 | }; | ||
1153 | |||
1154 | static const struct file_operations gma500_driver_fops = { | ||
1155 | .owner = THIS_MODULE, | ||
1156 | .open = drm_open, | ||
1157 | .release = drm_release, | ||
1158 | .unlocked_ioctl = psb_unlocked_ioctl, | ||
1159 | .mmap = drm_gem_mmap, | ||
1160 | .poll = drm_poll, | ||
1161 | .fasync = drm_fasync, | ||
1162 | .read = drm_read, | ||
1163 | }; | ||
1164 | |||
1165 | static struct drm_driver driver = { | ||
1166 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \ | ||
1167 | DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM , | ||
1168 | .load = psb_driver_load, | ||
1169 | .unload = psb_driver_unload, | ||
1170 | |||
1171 | .ioctls = psb_ioctls, | ||
1172 | .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls), | ||
1173 | .device_is_agp = psb_driver_device_is_agp, | ||
1174 | .irq_preinstall = psb_irq_preinstall, | ||
1175 | .irq_postinstall = psb_irq_postinstall, | ||
1176 | .irq_uninstall = psb_irq_uninstall, | ||
1177 | .irq_handler = psb_irq_handler, | ||
1178 | .enable_vblank = psb_enable_vblank, | ||
1179 | .disable_vblank = psb_disable_vblank, | ||
1180 | .get_vblank_counter = psb_get_vblank_counter, | ||
1181 | .lastclose = psb_lastclose, | ||
1182 | .open = psb_driver_open, | ||
1183 | .preclose = psb_driver_preclose, | ||
1184 | .postclose = psb_driver_close, | ||
1185 | .reclaim_buffers = drm_core_reclaim_buffers, | ||
1186 | |||
1187 | .gem_init_object = psb_gem_init_object, | ||
1188 | .gem_free_object = psb_gem_free_object, | ||
1189 | .gem_vm_ops = &psb_gem_vm_ops, | ||
1190 | .dumb_create = psb_gem_dumb_create, | ||
1191 | .dumb_map_offset = psb_gem_dumb_map_gtt, | ||
1192 | .dumb_destroy = psb_gem_dumb_destroy, | ||
1193 | .fops = &gma500_driver_fops, | ||
1194 | .name = DRIVER_NAME, | ||
1195 | .desc = DRIVER_DESC, | ||
1196 | .date = PSB_DRM_DRIVER_DATE, | ||
1197 | .major = PSB_DRM_DRIVER_MAJOR, | ||
1198 | .minor = PSB_DRM_DRIVER_MINOR, | ||
1199 | .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL | ||
1200 | }; | ||
1201 | |||
1202 | static struct pci_driver psb_pci_driver = { | ||
1203 | .name = DRIVER_NAME, | ||
1204 | .id_table = pciidlist, | ||
1205 | .probe = psb_probe, | ||
1206 | .remove = psb_remove, | ||
1207 | .driver.pm = &psb_pm_ops, | ||
1208 | }; | ||
1209 | |||
1210 | static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) | ||
1211 | { | ||
1212 | return drm_get_pci_dev(pdev, ent, &driver); | ||
1213 | } | ||
1214 | |||
1215 | static int __init psb_init(void) | ||
1216 | { | ||
1217 | return drm_pci_init(&driver, &psb_pci_driver); | ||
1218 | } | ||
1219 | |||
1220 | static void __exit psb_exit(void) | ||
1221 | { | ||
1222 | drm_pci_exit(&driver, &psb_pci_driver); | ||
1223 | } | ||
1224 | |||
1225 | late_initcall(psb_init); | ||
1226 | module_exit(psb_exit); | ||
1227 | |||
1228 | MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others"); | ||
1229 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
1230 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h deleted file mode 100644 index 11d963a055be..000000000000 --- a/drivers/staging/gma500/psb_drv.h +++ /dev/null | |||
@@ -1,952 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2007-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 | #ifndef _PSB_DRV_H_ | ||
21 | #define _PSB_DRV_H_ | ||
22 | |||
23 | #include <linux/kref.h> | ||
24 | |||
25 | #include <drm/drmP.h> | ||
26 | #include "drm_global.h" | ||
27 | #include "gem_glue.h" | ||
28 | #include "psb_drm.h" | ||
29 | #include "psb_reg.h" | ||
30 | #include "psb_intel_drv.h" | ||
31 | #include "gtt.h" | ||
32 | #include "power.h" | ||
33 | #include "mrst.h" | ||
34 | #include "medfield.h" | ||
35 | |||
36 | /* Append new drm mode definition here, align with libdrm definition */ | ||
37 | #define DRM_MODE_SCALE_NO_SCALE 2 | ||
38 | |||
39 | enum { | ||
40 | CHIP_PSB_8108 = 0, /* Poulsbo */ | ||
41 | CHIP_PSB_8109 = 1, /* Poulsbo */ | ||
42 | CHIP_MRST_4100 = 2, /* Moorestown/Oaktrail */ | ||
43 | CHIP_MFLD_0130 = 3, /* Medfield */ | ||
44 | }; | ||
45 | |||
46 | #define IS_PSB(dev) (((dev)->pci_device & 0xfffe) == 0x8108) | ||
47 | #define IS_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100) | ||
48 | #define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130) | ||
49 | |||
50 | /* | ||
51 | * Driver definitions | ||
52 | */ | ||
53 | |||
54 | #define DRIVER_NAME "gma500" | ||
55 | #define DRIVER_DESC "DRM driver for the Intel GMA500" | ||
56 | |||
57 | #define PSB_DRM_DRIVER_DATE "2011-06-06" | ||
58 | #define PSB_DRM_DRIVER_MAJOR 1 | ||
59 | #define PSB_DRM_DRIVER_MINOR 0 | ||
60 | #define PSB_DRM_DRIVER_PATCHLEVEL 0 | ||
61 | |||
62 | /* | ||
63 | * Hardware offsets | ||
64 | */ | ||
65 | #define PSB_VDC_OFFSET 0x00000000 | ||
66 | #define PSB_VDC_SIZE 0x000080000 | ||
67 | #define MRST_MMIO_SIZE 0x0000C0000 | ||
68 | #define MDFLD_MMIO_SIZE 0x000100000 | ||
69 | #define PSB_SGX_SIZE 0x8000 | ||
70 | #define PSB_SGX_OFFSET 0x00040000 | ||
71 | #define MRST_SGX_OFFSET 0x00080000 | ||
72 | /* | ||
73 | * PCI resource identifiers | ||
74 | */ | ||
75 | #define PSB_MMIO_RESOURCE 0 | ||
76 | #define PSB_GATT_RESOURCE 2 | ||
77 | #define PSB_GTT_RESOURCE 3 | ||
78 | /* | ||
79 | * PCI configuration | ||
80 | */ | ||
81 | #define PSB_GMCH_CTRL 0x52 | ||
82 | #define PSB_BSM 0x5C | ||
83 | #define _PSB_GMCH_ENABLED 0x4 | ||
84 | #define PSB_PGETBL_CTL 0x2020 | ||
85 | #define _PSB_PGETBL_ENABLED 0x00000001 | ||
86 | #define PSB_SGX_2D_SLAVE_PORT 0x4000 | ||
87 | |||
88 | /* To get rid of */ | ||
89 | #define PSB_TT_PRIV0_LIMIT (256*1024*1024) | ||
90 | #define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT) | ||
91 | |||
92 | /* | ||
93 | * SGX side MMU definitions (these can probably go) | ||
94 | */ | ||
95 | |||
96 | /* | ||
97 | * Flags for external memory type field. | ||
98 | */ | ||
99 | #define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */ | ||
100 | #define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */ | ||
101 | #define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */ | ||
102 | /* | ||
103 | * PTE's and PDE's | ||
104 | */ | ||
105 | #define PSB_PDE_MASK 0x003FFFFF | ||
106 | #define PSB_PDE_SHIFT 22 | ||
107 | #define PSB_PTE_SHIFT 12 | ||
108 | /* | ||
109 | * Cache control | ||
110 | */ | ||
111 | #define PSB_PTE_VALID 0x0001 /* PTE / PDE valid */ | ||
112 | #define PSB_PTE_WO 0x0002 /* Write only */ | ||
113 | #define PSB_PTE_RO 0x0004 /* Read only */ | ||
114 | #define PSB_PTE_CACHED 0x0008 /* CPU cache coherent */ | ||
115 | |||
116 | /* | ||
117 | * VDC registers and bits | ||
118 | */ | ||
119 | #define PSB_MSVDX_CLOCKGATING 0x2064 | ||
120 | #define PSB_TOPAZ_CLOCKGATING 0x2068 | ||
121 | #define PSB_HWSTAM 0x2098 | ||
122 | #define PSB_INSTPM 0x20C0 | ||
123 | #define PSB_INT_IDENTITY_R 0x20A4 | ||
124 | #define _MDFLD_PIPEC_EVENT_FLAG (1<<2) | ||
125 | #define _MDFLD_PIPEC_VBLANK_FLAG (1<<3) | ||
126 | #define _PSB_DPST_PIPEB_FLAG (1<<4) | ||
127 | #define _MDFLD_PIPEB_EVENT_FLAG (1<<4) | ||
128 | #define _PSB_VSYNC_PIPEB_FLAG (1<<5) | ||
129 | #define _PSB_DPST_PIPEA_FLAG (1<<6) | ||
130 | #define _PSB_PIPEA_EVENT_FLAG (1<<6) | ||
131 | #define _PSB_VSYNC_PIPEA_FLAG (1<<7) | ||
132 | #define _MDFLD_MIPIA_FLAG (1<<16) | ||
133 | #define _MDFLD_MIPIC_FLAG (1<<17) | ||
134 | #define _PSB_IRQ_SGX_FLAG (1<<18) | ||
135 | #define _PSB_IRQ_MSVDX_FLAG (1<<19) | ||
136 | #define _LNC_IRQ_TOPAZ_FLAG (1<<20) | ||
137 | |||
138 | #define _PSB_PIPE_EVENT_FLAG (_PSB_VSYNC_PIPEA_FLAG | \ | ||
139 | _PSB_VSYNC_PIPEB_FLAG) | ||
140 | |||
141 | /* This flag includes all the display IRQ bits excepts the vblank irqs. */ | ||
142 | #define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \ | ||
143 | _MDFLD_PIPEB_EVENT_FLAG | \ | ||
144 | _PSB_PIPEA_EVENT_FLAG | \ | ||
145 | _PSB_VSYNC_PIPEA_FLAG | \ | ||
146 | _MDFLD_MIPIA_FLAG | \ | ||
147 | _MDFLD_MIPIC_FLAG) | ||
148 | #define PSB_INT_IDENTITY_R 0x20A4 | ||
149 | #define PSB_INT_MASK_R 0x20A8 | ||
150 | #define PSB_INT_ENABLE_R 0x20A0 | ||
151 | |||
152 | #define _PSB_MMU_ER_MASK 0x0001FF00 | ||
153 | #define _PSB_MMU_ER_HOST (1 << 16) | ||
154 | #define GPIOA 0x5010 | ||
155 | #define GPIOB 0x5014 | ||
156 | #define GPIOC 0x5018 | ||
157 | #define GPIOD 0x501c | ||
158 | #define GPIOE 0x5020 | ||
159 | #define GPIOF 0x5024 | ||
160 | #define GPIOG 0x5028 | ||
161 | #define GPIOH 0x502c | ||
162 | #define GPIO_CLOCK_DIR_MASK (1 << 0) | ||
163 | #define GPIO_CLOCK_DIR_IN (0 << 1) | ||
164 | #define GPIO_CLOCK_DIR_OUT (1 << 1) | ||
165 | #define GPIO_CLOCK_VAL_MASK (1 << 2) | ||
166 | #define GPIO_CLOCK_VAL_OUT (1 << 3) | ||
167 | #define GPIO_CLOCK_VAL_IN (1 << 4) | ||
168 | #define GPIO_CLOCK_PULLUP_DISABLE (1 << 5) | ||
169 | #define GPIO_DATA_DIR_MASK (1 << 8) | ||
170 | #define GPIO_DATA_DIR_IN (0 << 9) | ||
171 | #define GPIO_DATA_DIR_OUT (1 << 9) | ||
172 | #define GPIO_DATA_VAL_MASK (1 << 10) | ||
173 | #define GPIO_DATA_VAL_OUT (1 << 11) | ||
174 | #define GPIO_DATA_VAL_IN (1 << 12) | ||
175 | #define GPIO_DATA_PULLUP_DISABLE (1 << 13) | ||
176 | |||
177 | #define VCLK_DIVISOR_VGA0 0x6000 | ||
178 | #define VCLK_DIVISOR_VGA1 0x6004 | ||
179 | #define VCLK_POST_DIV 0x6010 | ||
180 | |||
181 | #define PSB_COMM_2D (PSB_ENGINE_2D << 4) | ||
182 | #define PSB_COMM_3D (PSB_ENGINE_3D << 4) | ||
183 | #define PSB_COMM_TA (PSB_ENGINE_TA << 4) | ||
184 | #define PSB_COMM_HP (PSB_ENGINE_HP << 4) | ||
185 | #define PSB_COMM_USER_IRQ (1024 >> 2) | ||
186 | #define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1) | ||
187 | #define PSB_COMM_FW (2048 >> 2) | ||
188 | |||
189 | #define PSB_UIRQ_VISTEST 1 | ||
190 | #define PSB_UIRQ_OOM_REPLY 2 | ||
191 | #define PSB_UIRQ_FIRE_TA_REPLY 3 | ||
192 | #define PSB_UIRQ_FIRE_RASTER_REPLY 4 | ||
193 | |||
194 | #define PSB_2D_SIZE (256*1024*1024) | ||
195 | #define PSB_MAX_RELOC_PAGES 1024 | ||
196 | |||
197 | #define PSB_LOW_REG_OFFS 0x0204 | ||
198 | #define PSB_HIGH_REG_OFFS 0x0600 | ||
199 | |||
200 | #define PSB_NUM_VBLANKS 2 | ||
201 | |||
202 | |||
203 | #define PSB_2D_SIZE (256*1024*1024) | ||
204 | #define PSB_MAX_RELOC_PAGES 1024 | ||
205 | |||
206 | #define PSB_LOW_REG_OFFS 0x0204 | ||
207 | #define PSB_HIGH_REG_OFFS 0x0600 | ||
208 | |||
209 | #define PSB_NUM_VBLANKS 2 | ||
210 | #define PSB_WATCHDOG_DELAY (DRM_HZ * 2) | ||
211 | #define PSB_LID_DELAY (DRM_HZ / 10) | ||
212 | |||
213 | #define MDFLD_PNW_B0 0x04 | ||
214 | #define MDFLD_PNW_C0 0x08 | ||
215 | |||
216 | #define MDFLD_DSR_2D_3D_0 (1 << 0) | ||
217 | #define MDFLD_DSR_2D_3D_2 (1 << 1) | ||
218 | #define MDFLD_DSR_CURSOR_0 (1 << 2) | ||
219 | #define MDFLD_DSR_CURSOR_2 (1 << 3) | ||
220 | #define MDFLD_DSR_OVERLAY_0 (1 << 4) | ||
221 | #define MDFLD_DSR_OVERLAY_2 (1 << 5) | ||
222 | #define MDFLD_DSR_MIPI_CONTROL (1 << 6) | ||
223 | #define MDFLD_DSR_DAMAGE_MASK_0 ((1 << 0) | (1 << 2) | (1 << 4)) | ||
224 | #define MDFLD_DSR_DAMAGE_MASK_2 ((1 << 1) | (1 << 3) | (1 << 5)) | ||
225 | #define MDFLD_DSR_2D_3D (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2) | ||
226 | |||
227 | #define MDFLD_DSR_RR 45 | ||
228 | #define MDFLD_DPU_ENABLE (1 << 31) | ||
229 | #define MDFLD_DSR_FULLSCREEN (1 << 30) | ||
230 | #define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR) | ||
231 | |||
232 | #define PSB_PWR_STATE_ON 1 | ||
233 | #define PSB_PWR_STATE_OFF 2 | ||
234 | |||
235 | #define PSB_PMPOLICY_NOPM 0 | ||
236 | #define PSB_PMPOLICY_CLOCKGATING 1 | ||
237 | #define PSB_PMPOLICY_POWERDOWN 2 | ||
238 | |||
239 | #define PSB_PMSTATE_POWERUP 0 | ||
240 | #define PSB_PMSTATE_CLOCKGATED 1 | ||
241 | #define PSB_PMSTATE_POWERDOWN 2 | ||
242 | #define PSB_PCIx_MSI_ADDR_LOC 0x94 | ||
243 | #define PSB_PCIx_MSI_DATA_LOC 0x98 | ||
244 | |||
245 | /* Medfield crystal settings */ | ||
246 | #define KSEL_CRYSTAL_19 1 | ||
247 | #define KSEL_BYPASS_19 5 | ||
248 | #define KSEL_BYPASS_25 6 | ||
249 | #define KSEL_BYPASS_83_100 7 | ||
250 | |||
251 | struct opregion_header; | ||
252 | struct opregion_acpi; | ||
253 | struct opregion_swsci; | ||
254 | struct opregion_asle; | ||
255 | |||
256 | struct psb_intel_opregion { | ||
257 | struct opregion_header *header; | ||
258 | struct opregion_acpi *acpi; | ||
259 | struct opregion_swsci *swsci; | ||
260 | struct opregion_asle *asle; | ||
261 | int enabled; | ||
262 | }; | ||
263 | |||
264 | struct psb_ops; | ||
265 | |||
266 | struct drm_psb_private { | ||
267 | struct drm_device *dev; | ||
268 | const struct psb_ops *ops; | ||
269 | |||
270 | struct psb_gtt gtt; | ||
271 | |||
272 | /* GTT Memory manager */ | ||
273 | struct psb_gtt_mm *gtt_mm; | ||
274 | struct page *scratch_page; | ||
275 | u32 *gtt_map; | ||
276 | uint32_t stolen_base; | ||
277 | void *vram_addr; | ||
278 | unsigned long vram_stolen_size; | ||
279 | int gtt_initialized; | ||
280 | u16 gmch_ctrl; /* Saved GTT setup */ | ||
281 | u32 pge_ctl; | ||
282 | |||
283 | struct mutex gtt_mutex; | ||
284 | struct resource *gtt_mem; /* Our PCI resource */ | ||
285 | |||
286 | struct psb_mmu_driver *mmu; | ||
287 | struct psb_mmu_pd *pf_pd; | ||
288 | |||
289 | /* | ||
290 | * Register base | ||
291 | */ | ||
292 | |||
293 | uint8_t *sgx_reg; | ||
294 | uint8_t *vdc_reg; | ||
295 | uint32_t gatt_free_offset; | ||
296 | |||
297 | /* | ||
298 | * Fencing / irq. | ||
299 | */ | ||
300 | |||
301 | uint32_t vdc_irq_mask; | ||
302 | uint32_t pipestat[PSB_NUM_PIPE]; | ||
303 | |||
304 | spinlock_t irqmask_lock; | ||
305 | |||
306 | /* | ||
307 | * Power | ||
308 | */ | ||
309 | |||
310 | bool suspended; | ||
311 | bool display_power; | ||
312 | int display_count; | ||
313 | |||
314 | /* | ||
315 | * Modesetting | ||
316 | */ | ||
317 | struct psb_intel_mode_device mode_dev; | ||
318 | |||
319 | struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE]; | ||
320 | struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE]; | ||
321 | uint32_t num_pipe; | ||
322 | |||
323 | /* | ||
324 | * OSPM info (Power management base) (can go ?) | ||
325 | */ | ||
326 | uint32_t ospm_base; | ||
327 | |||
328 | /* | ||
329 | * Sizes info | ||
330 | */ | ||
331 | |||
332 | struct drm_psb_sizes_arg sizes; | ||
333 | |||
334 | u32 fuse_reg_value; | ||
335 | u32 video_device_fuse; | ||
336 | |||
337 | /* PCI revision ID for B0:D2:F0 */ | ||
338 | uint8_t platform_rev_id; | ||
339 | |||
340 | /* | ||
341 | * LVDS info | ||
342 | */ | ||
343 | int backlight_duty_cycle; /* restore backlight to this value */ | ||
344 | bool panel_wants_dither; | ||
345 | struct drm_display_mode *panel_fixed_mode; | ||
346 | struct drm_display_mode *lfp_lvds_vbt_mode; | ||
347 | struct drm_display_mode *sdvo_lvds_vbt_mode; | ||
348 | |||
349 | struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */ | ||
350 | struct psb_intel_i2c_chan *lvds_i2c_bus; | ||
351 | |||
352 | /* Feature bits from the VBIOS */ | ||
353 | unsigned int int_tv_support:1; | ||
354 | unsigned int lvds_dither:1; | ||
355 | unsigned int lvds_vbt:1; | ||
356 | unsigned int int_crt_support:1; | ||
357 | unsigned int lvds_use_ssc:1; | ||
358 | int lvds_ssc_freq; | ||
359 | bool is_lvds_on; | ||
360 | bool is_mipi_on; | ||
361 | u32 mipi_ctrl_display; | ||
362 | |||
363 | unsigned int core_freq; | ||
364 | uint32_t iLVDS_enable; | ||
365 | |||
366 | /* Runtime PM state */ | ||
367 | int rpm_enabled; | ||
368 | |||
369 | /* MID specific */ | ||
370 | struct mrst_vbt vbt_data; | ||
371 | struct mrst_gct_data gct_data; | ||
372 | |||
373 | /* MIPI Panel type etc */ | ||
374 | int panel_id; | ||
375 | bool dual_mipi; /* dual display - DPI & DBI */ | ||
376 | bool dpi_panel_on; /* The DPI panel power is on */ | ||
377 | bool dpi_panel_on2; /* The DPI panel power is on */ | ||
378 | bool dbi_panel_on; /* The DBI panel power is on */ | ||
379 | bool dbi_panel_on2; /* The DBI panel power is on */ | ||
380 | u32 dsr_fb_update; /* DSR FB update counter */ | ||
381 | |||
382 | /* Moorestown HDMI state */ | ||
383 | struct mrst_hdmi_dev *hdmi_priv; | ||
384 | |||
385 | /* Moorestown pipe config register value cache */ | ||
386 | uint32_t pipeconf; | ||
387 | uint32_t pipeconf1; | ||
388 | uint32_t pipeconf2; | ||
389 | |||
390 | /* Moorestown plane control register value cache */ | ||
391 | uint32_t dspcntr; | ||
392 | uint32_t dspcntr1; | ||
393 | uint32_t dspcntr2; | ||
394 | |||
395 | /* Moorestown MM backlight cache */ | ||
396 | uint8_t saveBKLTCNT; | ||
397 | uint8_t saveBKLTREQ; | ||
398 | uint8_t saveBKLTBRTL; | ||
399 | |||
400 | /* | ||
401 | * Register state | ||
402 | */ | ||
403 | uint32_t saveDSPACNTR; | ||
404 | uint32_t saveDSPBCNTR; | ||
405 | uint32_t savePIPEACONF; | ||
406 | uint32_t savePIPEBCONF; | ||
407 | uint32_t savePIPEASRC; | ||
408 | uint32_t savePIPEBSRC; | ||
409 | uint32_t saveFPA0; | ||
410 | uint32_t saveFPA1; | ||
411 | uint32_t saveDPLL_A; | ||
412 | uint32_t saveDPLL_A_MD; | ||
413 | uint32_t saveHTOTAL_A; | ||
414 | uint32_t saveHBLANK_A; | ||
415 | uint32_t saveHSYNC_A; | ||
416 | uint32_t saveVTOTAL_A; | ||
417 | uint32_t saveVBLANK_A; | ||
418 | uint32_t saveVSYNC_A; | ||
419 | uint32_t saveDSPASTRIDE; | ||
420 | uint32_t saveDSPASIZE; | ||
421 | uint32_t saveDSPAPOS; | ||
422 | uint32_t saveDSPABASE; | ||
423 | uint32_t saveDSPASURF; | ||
424 | uint32_t saveDSPASTATUS; | ||
425 | uint32_t saveFPB0; | ||
426 | uint32_t saveFPB1; | ||
427 | uint32_t saveDPLL_B; | ||
428 | uint32_t saveDPLL_B_MD; | ||
429 | uint32_t saveHTOTAL_B; | ||
430 | uint32_t saveHBLANK_B; | ||
431 | uint32_t saveHSYNC_B; | ||
432 | uint32_t saveVTOTAL_B; | ||
433 | uint32_t saveVBLANK_B; | ||
434 | uint32_t saveVSYNC_B; | ||
435 | uint32_t saveDSPBSTRIDE; | ||
436 | uint32_t saveDSPBSIZE; | ||
437 | uint32_t saveDSPBPOS; | ||
438 | uint32_t saveDSPBBASE; | ||
439 | uint32_t saveDSPBSURF; | ||
440 | uint32_t saveDSPBSTATUS; | ||
441 | uint32_t saveVCLK_DIVISOR_VGA0; | ||
442 | uint32_t saveVCLK_DIVISOR_VGA1; | ||
443 | uint32_t saveVCLK_POST_DIV; | ||
444 | uint32_t saveVGACNTRL; | ||
445 | uint32_t saveADPA; | ||
446 | uint32_t saveLVDS; | ||
447 | uint32_t saveDVOA; | ||
448 | uint32_t saveDVOB; | ||
449 | uint32_t saveDVOC; | ||
450 | uint32_t savePP_ON; | ||
451 | uint32_t savePP_OFF; | ||
452 | uint32_t savePP_CONTROL; | ||
453 | uint32_t savePP_CYCLE; | ||
454 | uint32_t savePFIT_CONTROL; | ||
455 | uint32_t savePaletteA[256]; | ||
456 | uint32_t savePaletteB[256]; | ||
457 | uint32_t saveBLC_PWM_CTL2; | ||
458 | uint32_t saveBLC_PWM_CTL; | ||
459 | uint32_t saveCLOCKGATING; | ||
460 | uint32_t saveDSPARB; | ||
461 | uint32_t saveDSPATILEOFF; | ||
462 | uint32_t saveDSPBTILEOFF; | ||
463 | uint32_t saveDSPAADDR; | ||
464 | uint32_t saveDSPBADDR; | ||
465 | uint32_t savePFIT_AUTO_RATIOS; | ||
466 | uint32_t savePFIT_PGM_RATIOS; | ||
467 | uint32_t savePP_ON_DELAYS; | ||
468 | uint32_t savePP_OFF_DELAYS; | ||
469 | uint32_t savePP_DIVISOR; | ||
470 | uint32_t saveBSM; | ||
471 | uint32_t saveVBT; | ||
472 | uint32_t saveBCLRPAT_A; | ||
473 | uint32_t saveBCLRPAT_B; | ||
474 | uint32_t saveDSPALINOFF; | ||
475 | uint32_t saveDSPBLINOFF; | ||
476 | uint32_t savePERF_MODE; | ||
477 | uint32_t saveDSPFW1; | ||
478 | uint32_t saveDSPFW2; | ||
479 | uint32_t saveDSPFW3; | ||
480 | uint32_t saveDSPFW4; | ||
481 | uint32_t saveDSPFW5; | ||
482 | uint32_t saveDSPFW6; | ||
483 | uint32_t saveCHICKENBIT; | ||
484 | uint32_t saveDSPACURSOR_CTRL; | ||
485 | uint32_t saveDSPBCURSOR_CTRL; | ||
486 | uint32_t saveDSPACURSOR_BASE; | ||
487 | uint32_t saveDSPBCURSOR_BASE; | ||
488 | uint32_t saveDSPACURSOR_POS; | ||
489 | uint32_t saveDSPBCURSOR_POS; | ||
490 | uint32_t save_palette_a[256]; | ||
491 | uint32_t save_palette_b[256]; | ||
492 | uint32_t saveOV_OVADD; | ||
493 | uint32_t saveOV_OGAMC0; | ||
494 | uint32_t saveOV_OGAMC1; | ||
495 | uint32_t saveOV_OGAMC2; | ||
496 | uint32_t saveOV_OGAMC3; | ||
497 | uint32_t saveOV_OGAMC4; | ||
498 | uint32_t saveOV_OGAMC5; | ||
499 | uint32_t saveOVC_OVADD; | ||
500 | uint32_t saveOVC_OGAMC0; | ||
501 | uint32_t saveOVC_OGAMC1; | ||
502 | uint32_t saveOVC_OGAMC2; | ||
503 | uint32_t saveOVC_OGAMC3; | ||
504 | uint32_t saveOVC_OGAMC4; | ||
505 | uint32_t saveOVC_OGAMC5; | ||
506 | |||
507 | /* MSI reg save */ | ||
508 | uint32_t msi_addr; | ||
509 | uint32_t msi_data; | ||
510 | |||
511 | /* Medfield specific register save state */ | ||
512 | uint32_t saveHDMIPHYMISCCTL; | ||
513 | uint32_t saveHDMIB_CONTROL; | ||
514 | uint32_t saveDSPCCNTR; | ||
515 | uint32_t savePIPECCONF; | ||
516 | uint32_t savePIPECSRC; | ||
517 | uint32_t saveHTOTAL_C; | ||
518 | uint32_t saveHBLANK_C; | ||
519 | uint32_t saveHSYNC_C; | ||
520 | uint32_t saveVTOTAL_C; | ||
521 | uint32_t saveVBLANK_C; | ||
522 | uint32_t saveVSYNC_C; | ||
523 | uint32_t saveDSPCSTRIDE; | ||
524 | uint32_t saveDSPCSIZE; | ||
525 | uint32_t saveDSPCPOS; | ||
526 | uint32_t saveDSPCSURF; | ||
527 | uint32_t saveDSPCSTATUS; | ||
528 | uint32_t saveDSPCLINOFF; | ||
529 | uint32_t saveDSPCTILEOFF; | ||
530 | uint32_t saveDSPCCURSOR_CTRL; | ||
531 | uint32_t saveDSPCCURSOR_BASE; | ||
532 | uint32_t saveDSPCCURSOR_POS; | ||
533 | uint32_t save_palette_c[256]; | ||
534 | uint32_t saveOV_OVADD_C; | ||
535 | uint32_t saveOV_OGAMC0_C; | ||
536 | uint32_t saveOV_OGAMC1_C; | ||
537 | uint32_t saveOV_OGAMC2_C; | ||
538 | uint32_t saveOV_OGAMC3_C; | ||
539 | uint32_t saveOV_OGAMC4_C; | ||
540 | uint32_t saveOV_OGAMC5_C; | ||
541 | |||
542 | /* DSI register save */ | ||
543 | uint32_t saveDEVICE_READY_REG; | ||
544 | uint32_t saveINTR_EN_REG; | ||
545 | uint32_t saveDSI_FUNC_PRG_REG; | ||
546 | uint32_t saveHS_TX_TIMEOUT_REG; | ||
547 | uint32_t saveLP_RX_TIMEOUT_REG; | ||
548 | uint32_t saveTURN_AROUND_TIMEOUT_REG; | ||
549 | uint32_t saveDEVICE_RESET_REG; | ||
550 | uint32_t saveDPI_RESOLUTION_REG; | ||
551 | uint32_t saveHORIZ_SYNC_PAD_COUNT_REG; | ||
552 | uint32_t saveHORIZ_BACK_PORCH_COUNT_REG; | ||
553 | uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG; | ||
554 | uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG; | ||
555 | uint32_t saveVERT_SYNC_PAD_COUNT_REG; | ||
556 | uint32_t saveVERT_BACK_PORCH_COUNT_REG; | ||
557 | uint32_t saveVERT_FRONT_PORCH_COUNT_REG; | ||
558 | uint32_t saveHIGH_LOW_SWITCH_COUNT_REG; | ||
559 | uint32_t saveINIT_COUNT_REG; | ||
560 | uint32_t saveMAX_RET_PAK_REG; | ||
561 | uint32_t saveVIDEO_FMT_REG; | ||
562 | uint32_t saveEOT_DISABLE_REG; | ||
563 | uint32_t saveLP_BYTECLK_REG; | ||
564 | uint32_t saveHS_LS_DBI_ENABLE_REG; | ||
565 | uint32_t saveTXCLKESC_REG; | ||
566 | uint32_t saveDPHY_PARAM_REG; | ||
567 | uint32_t saveMIPI_CONTROL_REG; | ||
568 | uint32_t saveMIPI; | ||
569 | uint32_t saveMIPI_C; | ||
570 | |||
571 | /* DPST register save */ | ||
572 | uint32_t saveHISTOGRAM_INT_CONTROL_REG; | ||
573 | uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG; | ||
574 | uint32_t savePWM_CONTROL_LOGIC; | ||
575 | |||
576 | /* | ||
577 | * DSI info. | ||
578 | */ | ||
579 | void * dbi_dsr_info; | ||
580 | void * dbi_dpu_info; | ||
581 | void * dsi_configs[2]; | ||
582 | /* | ||
583 | * LID-Switch | ||
584 | */ | ||
585 | spinlock_t lid_lock; | ||
586 | struct timer_list lid_timer; | ||
587 | struct psb_intel_opregion opregion; | ||
588 | u32 *lid_state; | ||
589 | u32 lid_last_state; | ||
590 | |||
591 | /* | ||
592 | * Watchdog | ||
593 | */ | ||
594 | |||
595 | uint32_t apm_reg; | ||
596 | uint16_t apm_base; | ||
597 | |||
598 | /* | ||
599 | * Used for modifying backlight from | ||
600 | * xrandr -- consider removing and using HAL instead | ||
601 | */ | ||
602 | struct backlight_device *backlight_device; | ||
603 | struct drm_property *backlight_property; | ||
604 | uint32_t blc_adj1; | ||
605 | uint32_t blc_adj2; | ||
606 | |||
607 | void *fbdev; | ||
608 | /* DPST state */ | ||
609 | uint32_t dsr_idle_count; | ||
610 | bool is_in_idle; | ||
611 | bool dsr_enable; | ||
612 | void (*exit_idle)(struct drm_device *dev, u32 update_src); | ||
613 | |||
614 | /* 2D acceleration */ | ||
615 | spinlock_t lock_2d; | ||
616 | |||
617 | /* FIXME: Arrays anyone ? */ | ||
618 | struct mdfld_dsi_encoder *encoder0; | ||
619 | struct mdfld_dsi_encoder *encoder2; | ||
620 | struct mdfld_dsi_dbi_output * dbi_output; | ||
621 | struct mdfld_dsi_dbi_output * dbi_output2; | ||
622 | u32 bpp; | ||
623 | u32 bpp2; | ||
624 | |||
625 | bool dispstatus; | ||
626 | }; | ||
627 | |||
628 | |||
629 | /* | ||
630 | * Operations for each board type | ||
631 | */ | ||
632 | |||
633 | struct psb_ops { | ||
634 | const char *name; | ||
635 | unsigned int accel_2d:1; | ||
636 | int pipes; /* Number of output pipes */ | ||
637 | int crtcs; /* Number of CRTCs */ | ||
638 | int sgx_offset; /* Base offset of SGX device */ | ||
639 | |||
640 | /* Sub functions */ | ||
641 | struct drm_crtc_helper_funcs const *crtc_helper; | ||
642 | struct drm_crtc_funcs const *crtc_funcs; | ||
643 | |||
644 | /* Setup hooks */ | ||
645 | int (*chip_setup)(struct drm_device *dev); | ||
646 | void (*chip_teardown)(struct drm_device *dev); | ||
647 | |||
648 | /* Display management hooks */ | ||
649 | int (*output_init)(struct drm_device *dev); | ||
650 | /* Power management hooks */ | ||
651 | void (*init_pm)(struct drm_device *dev); | ||
652 | int (*save_regs)(struct drm_device *dev); | ||
653 | int (*restore_regs)(struct drm_device *dev); | ||
654 | int (*power_up)(struct drm_device *dev); | ||
655 | int (*power_down)(struct drm_device *dev); | ||
656 | |||
657 | void (*lvds_bl_power)(struct drm_device *dev, bool on); | ||
658 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
659 | /* Backlight */ | ||
660 | int (*backlight_init)(struct drm_device *dev); | ||
661 | #endif | ||
662 | int i2c_bus; /* I2C bus identifier for Moorestown */ | ||
663 | }; | ||
664 | |||
665 | |||
666 | |||
667 | struct psb_mmu_driver; | ||
668 | |||
669 | extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int); | ||
670 | extern int drm_pick_crtcs(struct drm_device *dev); | ||
671 | |||
672 | static inline struct drm_psb_private *psb_priv(struct drm_device *dev) | ||
673 | { | ||
674 | return (struct drm_psb_private *) dev->dev_private; | ||
675 | } | ||
676 | |||
677 | /* | ||
678 | * MMU stuff. | ||
679 | */ | ||
680 | |||
681 | extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers, | ||
682 | int trap_pagefaults, | ||
683 | int invalid_type, | ||
684 | struct drm_psb_private *dev_priv); | ||
685 | extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver); | ||
686 | extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver | ||
687 | *driver); | ||
688 | extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset, | ||
689 | uint32_t gtt_start, uint32_t gtt_pages); | ||
690 | extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver, | ||
691 | int trap_pagefaults, | ||
692 | int invalid_type); | ||
693 | extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd); | ||
694 | extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot); | ||
695 | extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd, | ||
696 | unsigned long address, | ||
697 | uint32_t num_pages); | ||
698 | extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd, | ||
699 | uint32_t start_pfn, | ||
700 | unsigned long address, | ||
701 | uint32_t num_pages, int type); | ||
702 | extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual, | ||
703 | unsigned long *pfn); | ||
704 | |||
705 | /* | ||
706 | * Enable / disable MMU for different requestors. | ||
707 | */ | ||
708 | |||
709 | |||
710 | extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context); | ||
711 | extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages, | ||
712 | unsigned long address, uint32_t num_pages, | ||
713 | uint32_t desired_tile_stride, | ||
714 | uint32_t hw_tile_stride, int type); | ||
715 | extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd, | ||
716 | unsigned long address, uint32_t num_pages, | ||
717 | uint32_t desired_tile_stride, | ||
718 | uint32_t hw_tile_stride); | ||
719 | /* | ||
720 | *psb_irq.c | ||
721 | */ | ||
722 | |||
723 | extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); | ||
724 | extern int psb_irq_enable_dpst(struct drm_device *dev); | ||
725 | extern int psb_irq_disable_dpst(struct drm_device *dev); | ||
726 | extern void psb_irq_preinstall(struct drm_device *dev); | ||
727 | extern int psb_irq_postinstall(struct drm_device *dev); | ||
728 | extern void psb_irq_uninstall(struct drm_device *dev); | ||
729 | extern void psb_irq_turn_on_dpst(struct drm_device *dev); | ||
730 | extern void psb_irq_turn_off_dpst(struct drm_device *dev); | ||
731 | |||
732 | extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands); | ||
733 | extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence); | ||
734 | extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence); | ||
735 | extern int psb_enable_vblank(struct drm_device *dev, int crtc); | ||
736 | extern void psb_disable_vblank(struct drm_device *dev, int crtc); | ||
737 | void | ||
738 | psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); | ||
739 | |||
740 | void | ||
741 | psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask); | ||
742 | |||
743 | extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc); | ||
744 | |||
745 | extern int mdfld_enable_te(struct drm_device *dev, int pipe); | ||
746 | extern void mdfld_disable_te(struct drm_device *dev, int pipe); | ||
747 | |||
748 | /* | ||
749 | * intel_opregion.c | ||
750 | */ | ||
751 | extern int gma_intel_opregion_init(struct drm_device *dev); | ||
752 | extern int gma_intel_opregion_exit(struct drm_device *dev); | ||
753 | |||
754 | /* | ||
755 | * framebuffer.c | ||
756 | */ | ||
757 | extern int psbfb_probed(struct drm_device *dev); | ||
758 | extern int psbfb_remove(struct drm_device *dev, | ||
759 | struct drm_framebuffer *fb); | ||
760 | /* | ||
761 | * accel_2d.c | ||
762 | */ | ||
763 | extern void psbfb_copyarea(struct fb_info *info, | ||
764 | const struct fb_copyarea *region); | ||
765 | extern int psbfb_sync(struct fb_info *info); | ||
766 | extern void psb_spank(struct drm_psb_private *dev_priv); | ||
767 | extern int psb_accel_ioctl(struct drm_device *dev, void *data, | ||
768 | struct drm_file *file); | ||
769 | |||
770 | /* | ||
771 | * psb_reset.c | ||
772 | */ | ||
773 | |||
774 | extern void psb_lid_timer_init(struct drm_psb_private *dev_priv); | ||
775 | extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv); | ||
776 | extern void psb_print_pagefault(struct drm_psb_private *dev_priv); | ||
777 | |||
778 | /* modesetting */ | ||
779 | extern void psb_modeset_init(struct drm_device *dev); | ||
780 | extern void psb_modeset_cleanup(struct drm_device *dev); | ||
781 | extern int psb_fbdev_init(struct drm_device *dev); | ||
782 | |||
783 | /* backlight.c */ | ||
784 | int gma_backlight_init(struct drm_device *dev); | ||
785 | void gma_backlight_exit(struct drm_device *dev); | ||
786 | |||
787 | /* mrst_crtc.c */ | ||
788 | extern const struct drm_crtc_helper_funcs mrst_helper_funcs; | ||
789 | |||
790 | /* mrst_lvds.c */ | ||
791 | extern void mrst_lvds_init(struct drm_device *dev, | ||
792 | struct psb_intel_mode_device *mode_dev); | ||
793 | |||
794 | /* psb_intel_display.c */ | ||
795 | extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs; | ||
796 | extern const struct drm_crtc_funcs psb_intel_crtc_funcs; | ||
797 | |||
798 | /* psb_intel_lvds.c */ | ||
799 | extern const struct drm_connector_helper_funcs | ||
800 | psb_intel_lvds_connector_helper_funcs; | ||
801 | extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs; | ||
802 | |||
803 | /* gem.c */ | ||
804 | extern int psb_gem_init_object(struct drm_gem_object *obj); | ||
805 | extern void psb_gem_free_object(struct drm_gem_object *obj); | ||
806 | extern int psb_gem_get_aperture(struct drm_device *dev, void *data, | ||
807 | struct drm_file *file); | ||
808 | extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev, | ||
809 | struct drm_mode_create_dumb *args); | ||
810 | extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev, | ||
811 | uint32_t handle); | ||
812 | extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev, | ||
813 | uint32_t handle, uint64_t *offset); | ||
814 | extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf); | ||
815 | extern int psb_gem_create_ioctl(struct drm_device *dev, void *data, | ||
816 | struct drm_file *file); | ||
817 | extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data, | ||
818 | struct drm_file *file); | ||
819 | |||
820 | /* psb_device.c */ | ||
821 | extern const struct psb_ops psb_chip_ops; | ||
822 | |||
823 | /* mrst_device.c */ | ||
824 | extern const struct psb_ops mrst_chip_ops; | ||
825 | |||
826 | /* mdfld_device.c */ | ||
827 | extern const struct psb_ops mdfld_chip_ops; | ||
828 | |||
829 | /* cdv_device.c */ | ||
830 | extern const struct psb_ops cdv_chip_ops; | ||
831 | |||
832 | /* | ||
833 | * Debug print bits setting | ||
834 | */ | ||
835 | #define PSB_D_GENERAL (1 << 0) | ||
836 | #define PSB_D_INIT (1 << 1) | ||
837 | #define PSB_D_IRQ (1 << 2) | ||
838 | #define PSB_D_ENTRY (1 << 3) | ||
839 | /* debug the get H/V BP/FP count */ | ||
840 | #define PSB_D_HV (1 << 4) | ||
841 | #define PSB_D_DBI_BF (1 << 5) | ||
842 | #define PSB_D_PM (1 << 6) | ||
843 | #define PSB_D_RENDER (1 << 7) | ||
844 | #define PSB_D_REG (1 << 8) | ||
845 | #define PSB_D_MSVDX (1 << 9) | ||
846 | #define PSB_D_TOPAZ (1 << 10) | ||
847 | |||
848 | extern int drm_psb_no_fb; | ||
849 | extern int drm_idle_check_interval; | ||
850 | |||
851 | /* | ||
852 | * Utilities | ||
853 | */ | ||
854 | |||
855 | static inline u32 MRST_MSG_READ32(uint port, uint offset) | ||
856 | { | ||
857 | int mcr = (0xD0<<24) | (port << 16) | (offset << 8); | ||
858 | uint32_t ret_val = 0; | ||
859 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | ||
860 | pci_write_config_dword(pci_root, 0xD0, mcr); | ||
861 | pci_read_config_dword(pci_root, 0xD4, &ret_val); | ||
862 | pci_dev_put(pci_root); | ||
863 | return ret_val; | ||
864 | } | ||
865 | static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value) | ||
866 | { | ||
867 | int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0; | ||
868 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | ||
869 | pci_write_config_dword(pci_root, 0xD4, value); | ||
870 | pci_write_config_dword(pci_root, 0xD0, mcr); | ||
871 | pci_dev_put(pci_root); | ||
872 | } | ||
873 | static inline u32 MDFLD_MSG_READ32(uint port, uint offset) | ||
874 | { | ||
875 | int mcr = (0x10<<24) | (port << 16) | (offset << 8); | ||
876 | uint32_t ret_val = 0; | ||
877 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | ||
878 | pci_write_config_dword(pci_root, 0xD0, mcr); | ||
879 | pci_read_config_dword(pci_root, 0xD4, &ret_val); | ||
880 | pci_dev_put(pci_root); | ||
881 | return ret_val; | ||
882 | } | ||
883 | static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value) | ||
884 | { | ||
885 | int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0; | ||
886 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | ||
887 | pci_write_config_dword(pci_root, 0xD4, value); | ||
888 | pci_write_config_dword(pci_root, 0xD0, mcr); | ||
889 | pci_dev_put(pci_root); | ||
890 | } | ||
891 | |||
892 | static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg) | ||
893 | { | ||
894 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
895 | return ioread32(dev_priv->vdc_reg + reg); | ||
896 | } | ||
897 | |||
898 | #define REG_READ(reg) REGISTER_READ(dev, (reg)) | ||
899 | |||
900 | static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg, | ||
901 | uint32_t val) | ||
902 | { | ||
903 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
904 | iowrite32((val), dev_priv->vdc_reg + (reg)); | ||
905 | } | ||
906 | |||
907 | #define REG_WRITE(reg, val) REGISTER_WRITE(dev, (reg), (val)) | ||
908 | |||
909 | static inline void REGISTER_WRITE16(struct drm_device *dev, | ||
910 | uint32_t reg, uint32_t val) | ||
911 | { | ||
912 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
913 | iowrite16((val), dev_priv->vdc_reg + (reg)); | ||
914 | } | ||
915 | |||
916 | #define REG_WRITE16(reg, val) REGISTER_WRITE16(dev, (reg), (val)) | ||
917 | |||
918 | static inline void REGISTER_WRITE8(struct drm_device *dev, | ||
919 | uint32_t reg, uint32_t val) | ||
920 | { | ||
921 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
922 | iowrite8((val), dev_priv->vdc_reg + (reg)); | ||
923 | } | ||
924 | |||
925 | #define REG_WRITE8(reg, val) REGISTER_WRITE8(dev, (reg), (val)) | ||
926 | |||
927 | #define PSB_WVDC32(_val, _offs) iowrite32(_val, dev_priv->vdc_reg + (_offs)) | ||
928 | #define PSB_RVDC32(_offs) ioread32(dev_priv->vdc_reg + (_offs)) | ||
929 | |||
930 | /* #define TRAP_SGX_PM_FAULT 1 */ | ||
931 | #ifdef TRAP_SGX_PM_FAULT | ||
932 | #define PSB_RSGX32(_offs) \ | ||
933 | ({ \ | ||
934 | if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) { \ | ||
935 | printk(KERN_ERR \ | ||
936 | "access sgx when it's off!! (READ) %s, %d\n", \ | ||
937 | __FILE__, __LINE__); \ | ||
938 | melay(1000); \ | ||
939 | } \ | ||
940 | ioread32(dev_priv->sgx_reg + (_offs)); \ | ||
941 | }) | ||
942 | #else | ||
943 | #define PSB_RSGX32(_offs) ioread32(dev_priv->sgx_reg + (_offs)) | ||
944 | #endif | ||
945 | #define PSB_WSGX32(_val, _offs) iowrite32(_val, dev_priv->sgx_reg + (_offs)) | ||
946 | |||
947 | #define MSVDX_REG_DUMP 0 | ||
948 | |||
949 | #define PSB_WMSVDX32(_val, _offs) iowrite32(_val, dev_priv->msvdx_reg + (_offs)) | ||
950 | #define PSB_RMSVDX32(_offs) ioread32(dev_priv->msvdx_reg + (_offs)) | ||
951 | |||
952 | #endif | ||
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c deleted file mode 100644 index 85659613ae62..000000000000 --- a/drivers/staging/gma500/psb_intel_display.c +++ /dev/null | |||
@@ -1,1429 +0,0 @@ | |||
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 | |||
32 | #include "mdfld_output.h" | ||
33 | |||
34 | struct psb_intel_clock_t { | ||
35 | /* given values */ | ||
36 | int n; | ||
37 | int m1, m2; | ||
38 | int p1, p2; | ||
39 | /* derived values */ | ||
40 | int dot; | ||
41 | int vco; | ||
42 | int m; | ||
43 | int p; | ||
44 | }; | ||
45 | |||
46 | struct psb_intel_range_t { | ||
47 | int min, max; | ||
48 | }; | ||
49 | |||
50 | struct psb_intel_p2_t { | ||
51 | int dot_limit; | ||
52 | int p2_slow, p2_fast; | ||
53 | }; | ||
54 | |||
55 | #define INTEL_P2_NUM 2 | ||
56 | |||
57 | struct psb_intel_limit_t { | ||
58 | struct psb_intel_range_t dot, vco, n, m, m1, m2, p, p1; | ||
59 | struct psb_intel_p2_t p2; | ||
60 | }; | ||
61 | |||
62 | #define I8XX_DOT_MIN 25000 | ||
63 | #define I8XX_DOT_MAX 350000 | ||
64 | #define I8XX_VCO_MIN 930000 | ||
65 | #define I8XX_VCO_MAX 1400000 | ||
66 | #define I8XX_N_MIN 3 | ||
67 | #define I8XX_N_MAX 16 | ||
68 | #define I8XX_M_MIN 96 | ||
69 | #define I8XX_M_MAX 140 | ||
70 | #define I8XX_M1_MIN 18 | ||
71 | #define I8XX_M1_MAX 26 | ||
72 | #define I8XX_M2_MIN 6 | ||
73 | #define I8XX_M2_MAX 16 | ||
74 | #define I8XX_P_MIN 4 | ||
75 | #define I8XX_P_MAX 128 | ||
76 | #define I8XX_P1_MIN 2 | ||
77 | #define I8XX_P1_MAX 33 | ||
78 | #define I8XX_P1_LVDS_MIN 1 | ||
79 | #define I8XX_P1_LVDS_MAX 6 | ||
80 | #define I8XX_P2_SLOW 4 | ||
81 | #define I8XX_P2_FAST 2 | ||
82 | #define I8XX_P2_LVDS_SLOW 14 | ||
83 | #define I8XX_P2_LVDS_FAST 14 /* No fast option */ | ||
84 | #define I8XX_P2_SLOW_LIMIT 165000 | ||
85 | |||
86 | #define I9XX_DOT_MIN 20000 | ||
87 | #define I9XX_DOT_MAX 400000 | ||
88 | #define I9XX_VCO_MIN 1400000 | ||
89 | #define I9XX_VCO_MAX 2800000 | ||
90 | #define I9XX_N_MIN 3 | ||
91 | #define I9XX_N_MAX 8 | ||
92 | #define I9XX_M_MIN 70 | ||
93 | #define I9XX_M_MAX 120 | ||
94 | #define I9XX_M1_MIN 10 | ||
95 | #define I9XX_M1_MAX 20 | ||
96 | #define I9XX_M2_MIN 5 | ||
97 | #define I9XX_M2_MAX 9 | ||
98 | #define I9XX_P_SDVO_DAC_MIN 5 | ||
99 | #define I9XX_P_SDVO_DAC_MAX 80 | ||
100 | #define I9XX_P_LVDS_MIN 7 | ||
101 | #define I9XX_P_LVDS_MAX 98 | ||
102 | #define I9XX_P1_MIN 1 | ||
103 | #define I9XX_P1_MAX 8 | ||
104 | #define I9XX_P2_SDVO_DAC_SLOW 10 | ||
105 | #define I9XX_P2_SDVO_DAC_FAST 5 | ||
106 | #define I9XX_P2_SDVO_DAC_SLOW_LIMIT 200000 | ||
107 | #define I9XX_P2_LVDS_SLOW 14 | ||
108 | #define I9XX_P2_LVDS_FAST 7 | ||
109 | #define I9XX_P2_LVDS_SLOW_LIMIT 112000 | ||
110 | |||
111 | #define INTEL_LIMIT_I8XX_DVO_DAC 0 | ||
112 | #define INTEL_LIMIT_I8XX_LVDS 1 | ||
113 | #define INTEL_LIMIT_I9XX_SDVO_DAC 2 | ||
114 | #define INTEL_LIMIT_I9XX_LVDS 3 | ||
115 | |||
116 | static const struct psb_intel_limit_t psb_intel_limits[] = { | ||
117 | { /* INTEL_LIMIT_I8XX_DVO_DAC */ | ||
118 | .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, | ||
119 | .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, | ||
120 | .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, | ||
121 | .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, | ||
122 | .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, | ||
123 | .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, | ||
124 | .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, | ||
125 | .p1 = {.min = I8XX_P1_MIN, .max = I8XX_P1_MAX}, | ||
126 | .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, | ||
127 | .p2_slow = I8XX_P2_SLOW, .p2_fast = I8XX_P2_FAST}, | ||
128 | }, | ||
129 | { /* INTEL_LIMIT_I8XX_LVDS */ | ||
130 | .dot = {.min = I8XX_DOT_MIN, .max = I8XX_DOT_MAX}, | ||
131 | .vco = {.min = I8XX_VCO_MIN, .max = I8XX_VCO_MAX}, | ||
132 | .n = {.min = I8XX_N_MIN, .max = I8XX_N_MAX}, | ||
133 | .m = {.min = I8XX_M_MIN, .max = I8XX_M_MAX}, | ||
134 | .m1 = {.min = I8XX_M1_MIN, .max = I8XX_M1_MAX}, | ||
135 | .m2 = {.min = I8XX_M2_MIN, .max = I8XX_M2_MAX}, | ||
136 | .p = {.min = I8XX_P_MIN, .max = I8XX_P_MAX}, | ||
137 | .p1 = {.min = I8XX_P1_LVDS_MIN, .max = I8XX_P1_LVDS_MAX}, | ||
138 | .p2 = {.dot_limit = I8XX_P2_SLOW_LIMIT, | ||
139 | .p2_slow = I8XX_P2_LVDS_SLOW, .p2_fast = I8XX_P2_LVDS_FAST}, | ||
140 | }, | ||
141 | { /* INTEL_LIMIT_I9XX_SDVO_DAC */ | ||
142 | .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, | ||
143 | .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, | ||
144 | .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, | ||
145 | .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, | ||
146 | .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, | ||
147 | .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, | ||
148 | .p = {.min = I9XX_P_SDVO_DAC_MIN, .max = I9XX_P_SDVO_DAC_MAX}, | ||
149 | .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, | ||
150 | .p2 = {.dot_limit = I9XX_P2_SDVO_DAC_SLOW_LIMIT, | ||
151 | .p2_slow = I9XX_P2_SDVO_DAC_SLOW, .p2_fast = | ||
152 | I9XX_P2_SDVO_DAC_FAST}, | ||
153 | }, | ||
154 | { /* INTEL_LIMIT_I9XX_LVDS */ | ||
155 | .dot = {.min = I9XX_DOT_MIN, .max = I9XX_DOT_MAX}, | ||
156 | .vco = {.min = I9XX_VCO_MIN, .max = I9XX_VCO_MAX}, | ||
157 | .n = {.min = I9XX_N_MIN, .max = I9XX_N_MAX}, | ||
158 | .m = {.min = I9XX_M_MIN, .max = I9XX_M_MAX}, | ||
159 | .m1 = {.min = I9XX_M1_MIN, .max = I9XX_M1_MAX}, | ||
160 | .m2 = {.min = I9XX_M2_MIN, .max = I9XX_M2_MAX}, | ||
161 | .p = {.min = I9XX_P_LVDS_MIN, .max = I9XX_P_LVDS_MAX}, | ||
162 | .p1 = {.min = I9XX_P1_MIN, .max = I9XX_P1_MAX}, | ||
163 | /* The single-channel range is 25-112Mhz, and dual-channel | ||
164 | * is 80-224Mhz. Prefer single channel as much as possible. | ||
165 | */ | ||
166 | .p2 = {.dot_limit = I9XX_P2_LVDS_SLOW_LIMIT, | ||
167 | .p2_slow = I9XX_P2_LVDS_SLOW, .p2_fast = I9XX_P2_LVDS_FAST}, | ||
168 | }, | ||
169 | }; | ||
170 | |||
171 | static const struct psb_intel_limit_t *psb_intel_limit(struct drm_crtc *crtc) | ||
172 | { | ||
173 | const struct psb_intel_limit_t *limit; | ||
174 | |||
175 | if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) | ||
176 | limit = &psb_intel_limits[INTEL_LIMIT_I9XX_LVDS]; | ||
177 | else | ||
178 | limit = &psb_intel_limits[INTEL_LIMIT_I9XX_SDVO_DAC]; | ||
179 | return limit; | ||
180 | } | ||
181 | |||
182 | /** Derive the pixel clock for the given refclk and divisors for 8xx chips. */ | ||
183 | |||
184 | static void i8xx_clock(int refclk, struct psb_intel_clock_t *clock) | ||
185 | { | ||
186 | clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); | ||
187 | clock->p = clock->p1 * clock->p2; | ||
188 | clock->vco = refclk * clock->m / (clock->n + 2); | ||
189 | clock->dot = clock->vco / clock->p; | ||
190 | } | ||
191 | |||
192 | /** Derive the pixel clock for the given refclk and divisors for 9xx chips. */ | ||
193 | |||
194 | static void i9xx_clock(int refclk, struct psb_intel_clock_t *clock) | ||
195 | { | ||
196 | clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2); | ||
197 | clock->p = clock->p1 * clock->p2; | ||
198 | clock->vco = refclk * clock->m / (clock->n + 2); | ||
199 | clock->dot = clock->vco / clock->p; | ||
200 | } | ||
201 | |||
202 | static void psb_intel_clock(struct drm_device *dev, int refclk, | ||
203 | struct psb_intel_clock_t *clock) | ||
204 | { | ||
205 | return i9xx_clock(refclk, clock); | ||
206 | } | ||
207 | |||
208 | /** | ||
209 | * Returns whether any output on the specified pipe is of the specified type | ||
210 | */ | ||
211 | bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type) | ||
212 | { | ||
213 | struct drm_device *dev = crtc->dev; | ||
214 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
215 | struct drm_connector *l_entry; | ||
216 | |||
217 | list_for_each_entry(l_entry, &mode_config->connector_list, head) { | ||
218 | if (l_entry->encoder && l_entry->encoder->crtc == crtc) { | ||
219 | struct psb_intel_output *psb_intel_output = | ||
220 | to_psb_intel_output(l_entry); | ||
221 | if (psb_intel_output->type == type) | ||
222 | return true; | ||
223 | } | ||
224 | } | ||
225 | return false; | ||
226 | } | ||
227 | |||
228 | #define INTELPllInvalid(s) { /* ErrorF (s) */; return false; } | ||
229 | /** | ||
230 | * Returns whether the given set of divisors are valid for a given refclk with | ||
231 | * the given connectors. | ||
232 | */ | ||
233 | |||
234 | static bool psb_intel_PLL_is_valid(struct drm_crtc *crtc, | ||
235 | struct psb_intel_clock_t *clock) | ||
236 | { | ||
237 | const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); | ||
238 | |||
239 | if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1) | ||
240 | INTELPllInvalid("p1 out of range\n"); | ||
241 | if (clock->p < limit->p.min || limit->p.max < clock->p) | ||
242 | INTELPllInvalid("p out of range\n"); | ||
243 | if (clock->m2 < limit->m2.min || limit->m2.max < clock->m2) | ||
244 | INTELPllInvalid("m2 out of range\n"); | ||
245 | if (clock->m1 < limit->m1.min || limit->m1.max < clock->m1) | ||
246 | INTELPllInvalid("m1 out of range\n"); | ||
247 | if (clock->m1 <= clock->m2) | ||
248 | INTELPllInvalid("m1 <= m2\n"); | ||
249 | if (clock->m < limit->m.min || limit->m.max < clock->m) | ||
250 | INTELPllInvalid("m out of range\n"); | ||
251 | if (clock->n < limit->n.min || limit->n.max < clock->n) | ||
252 | INTELPllInvalid("n out of range\n"); | ||
253 | if (clock->vco < limit->vco.min || limit->vco.max < clock->vco) | ||
254 | INTELPllInvalid("vco out of range\n"); | ||
255 | /* XXX: We may need to be checking "Dot clock" | ||
256 | * depending on the multiplier, connector, etc., | ||
257 | * rather than just a single range. | ||
258 | */ | ||
259 | if (clock->dot < limit->dot.min || limit->dot.max < clock->dot) | ||
260 | INTELPllInvalid("dot out of range\n"); | ||
261 | |||
262 | return true; | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * Returns a set of divisors for the desired target clock with the given | ||
267 | * refclk, or FALSE. The returned values represent the clock equation: | ||
268 | * reflck * (5 * (m1 + 2) + (m2 + 2)) / (n + 2) / p1 / p2. | ||
269 | */ | ||
270 | static bool psb_intel_find_best_PLL(struct drm_crtc *crtc, int target, | ||
271 | int refclk, | ||
272 | struct psb_intel_clock_t *best_clock) | ||
273 | { | ||
274 | struct drm_device *dev = crtc->dev; | ||
275 | struct psb_intel_clock_t clock; | ||
276 | const struct psb_intel_limit_t *limit = psb_intel_limit(crtc); | ||
277 | int err = target; | ||
278 | |||
279 | if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) && | ||
280 | (REG_READ(LVDS) & LVDS_PORT_EN) != 0) { | ||
281 | /* | ||
282 | * For LVDS, if the panel is on, just rely on its current | ||
283 | * settings for dual-channel. We haven't figured out how to | ||
284 | * reliably set up different single/dual channel state, if we | ||
285 | * even can. | ||
286 | */ | ||
287 | if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) == | ||
288 | LVDS_CLKB_POWER_UP) | ||
289 | clock.p2 = limit->p2.p2_fast; | ||
290 | else | ||
291 | clock.p2 = limit->p2.p2_slow; | ||
292 | } else { | ||
293 | if (target < limit->p2.dot_limit) | ||
294 | clock.p2 = limit->p2.p2_slow; | ||
295 | else | ||
296 | clock.p2 = limit->p2.p2_fast; | ||
297 | } | ||
298 | |||
299 | memset(best_clock, 0, sizeof(*best_clock)); | ||
300 | |||
301 | for (clock.m1 = limit->m1.min; clock.m1 <= limit->m1.max; | ||
302 | clock.m1++) { | ||
303 | for (clock.m2 = limit->m2.min; | ||
304 | clock.m2 < clock.m1 && clock.m2 <= limit->m2.max; | ||
305 | clock.m2++) { | ||
306 | for (clock.n = limit->n.min; | ||
307 | clock.n <= limit->n.max; clock.n++) { | ||
308 | for (clock.p1 = limit->p1.min; | ||
309 | clock.p1 <= limit->p1.max; | ||
310 | clock.p1++) { | ||
311 | int this_err; | ||
312 | |||
313 | psb_intel_clock(dev, refclk, &clock); | ||
314 | |||
315 | if (!psb_intel_PLL_is_valid | ||
316 | (crtc, &clock)) | ||
317 | continue; | ||
318 | |||
319 | this_err = abs(clock.dot - target); | ||
320 | if (this_err < err) { | ||
321 | *best_clock = clock; | ||
322 | err = this_err; | ||
323 | } | ||
324 | } | ||
325 | } | ||
326 | } | ||
327 | } | ||
328 | |||
329 | return err != target; | ||
330 | } | ||
331 | |||
332 | void psb_intel_wait_for_vblank(struct drm_device *dev) | ||
333 | { | ||
334 | /* Wait for 20ms, i.e. one cycle at 50hz. */ | ||
335 | mdelay(20); | ||
336 | } | ||
337 | |||
338 | int psb_intel_pipe_set_base(struct drm_crtc *crtc, | ||
339 | int x, int y, struct drm_framebuffer *old_fb) | ||
340 | { | ||
341 | struct drm_device *dev = crtc->dev; | ||
342 | /* struct drm_i915_master_private *master_priv; */ | ||
343 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
344 | struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb); | ||
345 | int pipe = psb_intel_crtc->pipe; | ||
346 | unsigned long start, offset; | ||
347 | int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE); | ||
348 | int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF); | ||
349 | int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE; | ||
350 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
351 | u32 dspcntr; | ||
352 | int ret = 0; | ||
353 | |||
354 | if (!gma_power_begin(dev, true)) | ||
355 | return 0; | ||
356 | |||
357 | /* no fb bound */ | ||
358 | if (!crtc->fb) { | ||
359 | dev_dbg(dev->dev, "No FB bound\n"); | ||
360 | goto psb_intel_pipe_cleaner; | ||
361 | } | ||
362 | |||
363 | /* We are displaying this buffer, make sure it is actually loaded | ||
364 | into the GTT */ | ||
365 | ret = psb_gtt_pin(psbfb->gtt); | ||
366 | if (ret < 0) | ||
367 | goto psb_intel_pipe_set_base_exit; | ||
368 | start = psbfb->gtt->offset; | ||
369 | |||
370 | offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8); | ||
371 | |||
372 | REG_WRITE(dspstride, crtc->fb->pitches[0]); | ||
373 | |||
374 | dspcntr = REG_READ(dspcntr_reg); | ||
375 | dspcntr &= ~DISPPLANE_PIXFORMAT_MASK; | ||
376 | |||
377 | switch (crtc->fb->bits_per_pixel) { | ||
378 | case 8: | ||
379 | dspcntr |= DISPPLANE_8BPP; | ||
380 | break; | ||
381 | case 16: | ||
382 | if (crtc->fb->depth == 15) | ||
383 | dspcntr |= DISPPLANE_15_16BPP; | ||
384 | else | ||
385 | dspcntr |= DISPPLANE_16BPP; | ||
386 | break; | ||
387 | case 24: | ||
388 | case 32: | ||
389 | dspcntr |= DISPPLANE_32BPP_NO_ALPHA; | ||
390 | break; | ||
391 | default: | ||
392 | dev_err(dev->dev, "Unknown color depth\n"); | ||
393 | ret = -EINVAL; | ||
394 | psb_gtt_unpin(psbfb->gtt); | ||
395 | goto psb_intel_pipe_set_base_exit; | ||
396 | } | ||
397 | REG_WRITE(dspcntr_reg, dspcntr); | ||
398 | |||
399 | |||
400 | if (0 /* FIXMEAC - check what PSB needs */) { | ||
401 | REG_WRITE(dspbase, offset); | ||
402 | REG_READ(dspbase); | ||
403 | REG_WRITE(dspsurf, start); | ||
404 | REG_READ(dspsurf); | ||
405 | } else { | ||
406 | REG_WRITE(dspbase, start + offset); | ||
407 | REG_READ(dspbase); | ||
408 | } | ||
409 | |||
410 | psb_intel_pipe_cleaner: | ||
411 | /* If there was a previous display we can now unpin it */ | ||
412 | if (old_fb) | ||
413 | psb_gtt_unpin(to_psb_fb(old_fb)->gtt); | ||
414 | |||
415 | psb_intel_pipe_set_base_exit: | ||
416 | gma_power_end(dev); | ||
417 | return ret; | ||
418 | } | ||
419 | |||
420 | /** | ||
421 | * Sets the power management mode of the pipe and plane. | ||
422 | * | ||
423 | * This code should probably grow support for turning the cursor off and back | ||
424 | * on appropriately at the same time as we're turning the pipe off/on. | ||
425 | */ | ||
426 | static void psb_intel_crtc_dpms(struct drm_crtc *crtc, int mode) | ||
427 | { | ||
428 | struct drm_device *dev = crtc->dev; | ||
429 | /* struct drm_i915_master_private *master_priv; */ | ||
430 | /* struct drm_i915_private *dev_priv = dev->dev_private; */ | ||
431 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
432 | int pipe = psb_intel_crtc->pipe; | ||
433 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
434 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
435 | int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE; | ||
436 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
437 | u32 temp; | ||
438 | bool enabled; | ||
439 | |||
440 | /* XXX: When our outputs are all unaware of DPMS modes other than off | ||
441 | * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC. | ||
442 | */ | ||
443 | switch (mode) { | ||
444 | case DRM_MODE_DPMS_ON: | ||
445 | case DRM_MODE_DPMS_STANDBY: | ||
446 | case DRM_MODE_DPMS_SUSPEND: | ||
447 | /* Enable the DPLL */ | ||
448 | temp = REG_READ(dpll_reg); | ||
449 | if ((temp & DPLL_VCO_ENABLE) == 0) { | ||
450 | REG_WRITE(dpll_reg, temp); | ||
451 | REG_READ(dpll_reg); | ||
452 | /* Wait for the clocks to stabilize. */ | ||
453 | udelay(150); | ||
454 | REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | ||
455 | REG_READ(dpll_reg); | ||
456 | /* Wait for the clocks to stabilize. */ | ||
457 | udelay(150); | ||
458 | REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE); | ||
459 | REG_READ(dpll_reg); | ||
460 | /* Wait for the clocks to stabilize. */ | ||
461 | udelay(150); | ||
462 | } | ||
463 | |||
464 | /* Enable the pipe */ | ||
465 | temp = REG_READ(pipeconf_reg); | ||
466 | if ((temp & PIPEACONF_ENABLE) == 0) | ||
467 | REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE); | ||
468 | |||
469 | /* Enable the plane */ | ||
470 | temp = REG_READ(dspcntr_reg); | ||
471 | if ((temp & DISPLAY_PLANE_ENABLE) == 0) { | ||
472 | REG_WRITE(dspcntr_reg, | ||
473 | temp | DISPLAY_PLANE_ENABLE); | ||
474 | /* Flush the plane changes */ | ||
475 | REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); | ||
476 | } | ||
477 | |||
478 | psb_intel_crtc_load_lut(crtc); | ||
479 | |||
480 | /* Give the overlay scaler a chance to enable | ||
481 | * if it's on this pipe */ | ||
482 | /* psb_intel_crtc_dpms_video(crtc, true); TODO */ | ||
483 | break; | ||
484 | case DRM_MODE_DPMS_OFF: | ||
485 | /* Give the overlay scaler a chance to disable | ||
486 | * if it's on this pipe */ | ||
487 | /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */ | ||
488 | |||
489 | /* Disable the VGA plane that we never use */ | ||
490 | REG_WRITE(VGACNTRL, VGA_DISP_DISABLE); | ||
491 | |||
492 | /* Disable display plane */ | ||
493 | temp = REG_READ(dspcntr_reg); | ||
494 | if ((temp & DISPLAY_PLANE_ENABLE) != 0) { | ||
495 | REG_WRITE(dspcntr_reg, | ||
496 | temp & ~DISPLAY_PLANE_ENABLE); | ||
497 | /* Flush the plane changes */ | ||
498 | REG_WRITE(dspbase_reg, REG_READ(dspbase_reg)); | ||
499 | REG_READ(dspbase_reg); | ||
500 | } | ||
501 | |||
502 | /* Next, disable display pipes */ | ||
503 | temp = REG_READ(pipeconf_reg); | ||
504 | if ((temp & PIPEACONF_ENABLE) != 0) { | ||
505 | REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE); | ||
506 | REG_READ(pipeconf_reg); | ||
507 | } | ||
508 | |||
509 | /* Wait for vblank for the disable to take effect. */ | ||
510 | psb_intel_wait_for_vblank(dev); | ||
511 | |||
512 | temp = REG_READ(dpll_reg); | ||
513 | if ((temp & DPLL_VCO_ENABLE) != 0) { | ||
514 | REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE); | ||
515 | REG_READ(dpll_reg); | ||
516 | } | ||
517 | |||
518 | /* Wait for the clocks to turn off. */ | ||
519 | udelay(150); | ||
520 | break; | ||
521 | } | ||
522 | |||
523 | enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF; | ||
524 | |||
525 | /*Set FIFO Watermarks*/ | ||
526 | REG_WRITE(DSPARB, 0x3F3E); | ||
527 | } | ||
528 | |||
529 | static void psb_intel_crtc_prepare(struct drm_crtc *crtc) | ||
530 | { | ||
531 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
532 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF); | ||
533 | } | ||
534 | |||
535 | static void psb_intel_crtc_commit(struct drm_crtc *crtc) | ||
536 | { | ||
537 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
538 | crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON); | ||
539 | } | ||
540 | |||
541 | void psb_intel_encoder_prepare(struct drm_encoder *encoder) | ||
542 | { | ||
543 | struct drm_encoder_helper_funcs *encoder_funcs = | ||
544 | encoder->helper_private; | ||
545 | /* lvds has its own version of prepare see psb_intel_lvds_prepare */ | ||
546 | encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF); | ||
547 | } | ||
548 | |||
549 | void psb_intel_encoder_commit(struct drm_encoder *encoder) | ||
550 | { | ||
551 | struct drm_encoder_helper_funcs *encoder_funcs = | ||
552 | encoder->helper_private; | ||
553 | /* lvds has its own version of commit see psb_intel_lvds_commit */ | ||
554 | encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON); | ||
555 | } | ||
556 | |||
557 | static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc, | ||
558 | struct drm_display_mode *mode, | ||
559 | struct drm_display_mode *adjusted_mode) | ||
560 | { | ||
561 | return true; | ||
562 | } | ||
563 | |||
564 | |||
565 | /** | ||
566 | * Return the pipe currently connected to the panel fitter, | ||
567 | * or -1 if the panel fitter is not present or not in use | ||
568 | */ | ||
569 | static int psb_intel_panel_fitter_pipe(struct drm_device *dev) | ||
570 | { | ||
571 | u32 pfit_control; | ||
572 | |||
573 | pfit_control = REG_READ(PFIT_CONTROL); | ||
574 | |||
575 | /* See if the panel fitter is in use */ | ||
576 | if ((pfit_control & PFIT_ENABLE) == 0) | ||
577 | return -1; | ||
578 | /* Must be on PIPE 1 for PSB */ | ||
579 | return 1; | ||
580 | } | ||
581 | |||
582 | static int psb_intel_crtc_mode_set(struct drm_crtc *crtc, | ||
583 | struct drm_display_mode *mode, | ||
584 | struct drm_display_mode *adjusted_mode, | ||
585 | int x, int y, | ||
586 | struct drm_framebuffer *old_fb) | ||
587 | { | ||
588 | struct drm_device *dev = crtc->dev; | ||
589 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
590 | struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private; | ||
591 | int pipe = psb_intel_crtc->pipe; | ||
592 | int fp_reg = (pipe == 0) ? FPA0 : FPB0; | ||
593 | int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B; | ||
594 | int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR; | ||
595 | int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF; | ||
596 | int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B; | ||
597 | int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B; | ||
598 | int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B; | ||
599 | int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B; | ||
600 | int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B; | ||
601 | int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B; | ||
602 | int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE; | ||
603 | int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS; | ||
604 | int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC; | ||
605 | int refclk; | ||
606 | struct psb_intel_clock_t clock; | ||
607 | u32 dpll = 0, fp = 0, dspcntr, pipeconf; | ||
608 | bool ok, is_sdvo = false, is_dvo = false; | ||
609 | bool is_crt = false, is_lvds = false, is_tv = false; | ||
610 | struct drm_mode_config *mode_config = &dev->mode_config; | ||
611 | struct drm_connector *connector; | ||
612 | |||
613 | /* No scan out no play */ | ||
614 | if (crtc->fb == NULL) { | ||
615 | crtc_funcs->mode_set_base(crtc, x, y, old_fb); | ||
616 | return 0; | ||
617 | } | ||
618 | |||
619 | list_for_each_entry(connector, &mode_config->connector_list, head) { | ||
620 | struct psb_intel_output *psb_intel_output = | ||
621 | to_psb_intel_output(connector); | ||
622 | |||
623 | if (!connector->encoder | ||
624 | || connector->encoder->crtc != crtc) | ||
625 | continue; | ||
626 | |||
627 | switch (psb_intel_output->type) { | ||
628 | case INTEL_OUTPUT_LVDS: | ||
629 | is_lvds = true; | ||
630 | break; | ||
631 | case INTEL_OUTPUT_SDVO: | ||
632 | is_sdvo = true; | ||
633 | break; | ||
634 | case INTEL_OUTPUT_DVO: | ||
635 | is_dvo = true; | ||
636 | break; | ||
637 | case INTEL_OUTPUT_TVOUT: | ||
638 | is_tv = true; | ||
639 | break; | ||
640 | case INTEL_OUTPUT_ANALOG: | ||
641 | is_crt = true; | ||
642 | break; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | refclk = 96000; | ||
647 | |||
648 | ok = psb_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk, | ||
649 | &clock); | ||
650 | if (!ok) { | ||
651 | dev_err(dev->dev, "Couldn't find PLL settings for mode!\n"); | ||
652 | return 0; | ||
653 | } | ||
654 | |||
655 | fp = clock.n << 16 | clock.m1 << 8 | clock.m2; | ||
656 | |||
657 | dpll = DPLL_VGA_MODE_DIS; | ||
658 | if (is_lvds) { | ||
659 | dpll |= DPLLB_MODE_LVDS; | ||
660 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
661 | } else | ||
662 | dpll |= DPLLB_MODE_DAC_SERIAL; | ||
663 | if (is_sdvo) { | ||
664 | int sdvo_pixel_multiply = | ||
665 | adjusted_mode->clock / mode->clock; | ||
666 | dpll |= DPLL_DVO_HIGH_SPEED; | ||
667 | dpll |= | ||
668 | (sdvo_pixel_multiply - 1) << SDVO_MULTIPLIER_SHIFT_HIRES; | ||
669 | } | ||
670 | |||
671 | /* compute bitmask from p1 value */ | ||
672 | dpll |= (1 << (clock.p1 - 1)) << 16; | ||
673 | switch (clock.p2) { | ||
674 | case 5: | ||
675 | dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_5; | ||
676 | break; | ||
677 | case 7: | ||
678 | dpll |= DPLLB_LVDS_P2_CLOCK_DIV_7; | ||
679 | break; | ||
680 | case 10: | ||
681 | dpll |= DPLL_DAC_SERIAL_P2_CLOCK_DIV_10; | ||
682 | break; | ||
683 | case 14: | ||
684 | dpll |= DPLLB_LVDS_P2_CLOCK_DIV_14; | ||
685 | break; | ||
686 | } | ||
687 | |||
688 | if (is_tv) { | ||
689 | /* XXX: just matching BIOS for now */ | ||
690 | /* dpll |= PLL_REF_INPUT_TVCLKINBC; */ | ||
691 | dpll |= 3; | ||
692 | } | ||
693 | dpll |= PLL_REF_INPUT_DREFCLK; | ||
694 | |||
695 | /* setup pipeconf */ | ||
696 | pipeconf = REG_READ(pipeconf_reg); | ||
697 | |||
698 | /* Set up the display plane register */ | ||
699 | dspcntr = DISPPLANE_GAMMA_ENABLE; | ||
700 | |||
701 | if (pipe == 0) | ||
702 | dspcntr |= DISPPLANE_SEL_PIPE_A; | ||
703 | else | ||
704 | dspcntr |= DISPPLANE_SEL_PIPE_B; | ||
705 | |||
706 | dspcntr |= DISPLAY_PLANE_ENABLE; | ||
707 | pipeconf |= PIPEACONF_ENABLE; | ||
708 | dpll |= DPLL_VCO_ENABLE; | ||
709 | |||
710 | |||
711 | /* Disable the panel fitter if it was on our pipe */ | ||
712 | if (psb_intel_panel_fitter_pipe(dev) == pipe) | ||
713 | REG_WRITE(PFIT_CONTROL, 0); | ||
714 | |||
715 | drm_mode_debug_printmodeline(mode); | ||
716 | |||
717 | if (dpll & DPLL_VCO_ENABLE) { | ||
718 | REG_WRITE(fp_reg, fp); | ||
719 | REG_WRITE(dpll_reg, dpll & ~DPLL_VCO_ENABLE); | ||
720 | REG_READ(dpll_reg); | ||
721 | udelay(150); | ||
722 | } | ||
723 | |||
724 | /* The LVDS pin pair needs to be on before the DPLLs are enabled. | ||
725 | * This is an exception to the general rule that mode_set doesn't turn | ||
726 | * things on. | ||
727 | */ | ||
728 | if (is_lvds) { | ||
729 | u32 lvds = REG_READ(LVDS); | ||
730 | |||
731 | lvds &= ~LVDS_PIPEB_SELECT; | ||
732 | if (pipe == 1) | ||
733 | lvds |= LVDS_PIPEB_SELECT; | ||
734 | |||
735 | lvds |= LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP; | ||
736 | /* Set the B0-B3 data pairs corresponding to | ||
737 | * whether we're going to | ||
738 | * set the DPLLs for dual-channel mode or not. | ||
739 | */ | ||
740 | lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP); | ||
741 | if (clock.p2 == 7) | ||
742 | lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP; | ||
743 | |||
744 | /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP) | ||
745 | * appropriately here, but we need to look more | ||
746 | * thoroughly into how panels behave in the two modes. | ||
747 | */ | ||
748 | |||
749 | REG_WRITE(LVDS, lvds); | ||
750 | REG_READ(LVDS); | ||
751 | } | ||
752 | |||
753 | REG_WRITE(fp_reg, fp); | ||
754 | REG_WRITE(dpll_reg, dpll); | ||
755 | REG_READ(dpll_reg); | ||
756 | /* Wait for the clocks to stabilize. */ | ||
757 | udelay(150); | ||
758 | |||
759 | /* write it again -- the BIOS does, after all */ | ||
760 | REG_WRITE(dpll_reg, dpll); | ||
761 | |||
762 | REG_READ(dpll_reg); | ||
763 | /* Wait for the clocks to stabilize. */ | ||
764 | udelay(150); | ||
765 | |||
766 | REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) | | ||
767 | ((adjusted_mode->crtc_htotal - 1) << 16)); | ||
768 | REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | | ||
769 | ((adjusted_mode->crtc_hblank_end - 1) << 16)); | ||
770 | REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | | ||
771 | ((adjusted_mode->crtc_hsync_end - 1) << 16)); | ||
772 | REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | | ||
773 | ((adjusted_mode->crtc_vtotal - 1) << 16)); | ||
774 | REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | | ||
775 | ((adjusted_mode->crtc_vblank_end - 1) << 16)); | ||
776 | REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | | ||
777 | ((adjusted_mode->crtc_vsync_end - 1) << 16)); | ||
778 | /* pipesrc and dspsize control the size that is scaled from, | ||
779 | * which should always be the user's requested size. | ||
780 | */ | ||
781 | REG_WRITE(dspsize_reg, | ||
782 | ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1)); | ||
783 | REG_WRITE(dsppos_reg, 0); | ||
784 | REG_WRITE(pipesrc_reg, | ||
785 | ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1)); | ||
786 | REG_WRITE(pipeconf_reg, pipeconf); | ||
787 | REG_READ(pipeconf_reg); | ||
788 | |||
789 | psb_intel_wait_for_vblank(dev); | ||
790 | |||
791 | REG_WRITE(dspcntr_reg, dspcntr); | ||
792 | |||
793 | /* Flush the plane changes */ | ||
794 | crtc_funcs->mode_set_base(crtc, x, y, old_fb); | ||
795 | |||
796 | psb_intel_wait_for_vblank(dev); | ||
797 | |||
798 | return 0; | ||
799 | } | ||
800 | |||
801 | /** Loads the palette/gamma unit for the CRTC with the prepared values */ | ||
802 | void psb_intel_crtc_load_lut(struct drm_crtc *crtc) | ||
803 | { | ||
804 | struct drm_device *dev = crtc->dev; | ||
805 | struct drm_psb_private *dev_priv = | ||
806 | (struct drm_psb_private *)dev->dev_private; | ||
807 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
808 | int palreg = PALETTE_A; | ||
809 | int i; | ||
810 | |||
811 | /* The clocks have to be on to load the palette. */ | ||
812 | if (!crtc->enabled) | ||
813 | return; | ||
814 | |||
815 | switch (psb_intel_crtc->pipe) { | ||
816 | case 0: | ||
817 | break; | ||
818 | case 1: | ||
819 | palreg = PALETTE_B; | ||
820 | break; | ||
821 | case 2: | ||
822 | palreg = PALETTE_C; | ||
823 | break; | ||
824 | default: | ||
825 | dev_err(dev->dev, "Illegal Pipe Number.\n"); | ||
826 | return; | ||
827 | } | ||
828 | |||
829 | if (gma_power_begin(dev, false)) { | ||
830 | for (i = 0; i < 256; i++) { | ||
831 | REG_WRITE(palreg + 4 * i, | ||
832 | ((psb_intel_crtc->lut_r[i] + | ||
833 | psb_intel_crtc->lut_adj[i]) << 16) | | ||
834 | ((psb_intel_crtc->lut_g[i] + | ||
835 | psb_intel_crtc->lut_adj[i]) << 8) | | ||
836 | (psb_intel_crtc->lut_b[i] + | ||
837 | psb_intel_crtc->lut_adj[i])); | ||
838 | } | ||
839 | gma_power_end(dev); | ||
840 | } else { | ||
841 | for (i = 0; i < 256; i++) { | ||
842 | dev_priv->save_palette_a[i] = | ||
843 | ((psb_intel_crtc->lut_r[i] + | ||
844 | psb_intel_crtc->lut_adj[i]) << 16) | | ||
845 | ((psb_intel_crtc->lut_g[i] + | ||
846 | psb_intel_crtc->lut_adj[i]) << 8) | | ||
847 | (psb_intel_crtc->lut_b[i] + | ||
848 | psb_intel_crtc->lut_adj[i]); | ||
849 | } | ||
850 | |||
851 | } | ||
852 | } | ||
853 | |||
854 | /** | ||
855 | * Save HW states of giving crtc | ||
856 | */ | ||
857 | static void psb_intel_crtc_save(struct drm_crtc *crtc) | ||
858 | { | ||
859 | struct drm_device *dev = crtc->dev; | ||
860 | /* struct drm_psb_private *dev_priv = | ||
861 | (struct drm_psb_private *)dev->dev_private; */ | ||
862 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
863 | struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; | ||
864 | int pipeA = (psb_intel_crtc->pipe == 0); | ||
865 | uint32_t paletteReg; | ||
866 | int i; | ||
867 | |||
868 | if (!crtc_state) { | ||
869 | dev_err(dev->dev, "No CRTC state found\n"); | ||
870 | return; | ||
871 | } | ||
872 | |||
873 | crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR); | ||
874 | crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF); | ||
875 | crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC); | ||
876 | crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0); | ||
877 | crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1); | ||
878 | crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B); | ||
879 | crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B); | ||
880 | crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B); | ||
881 | crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B); | ||
882 | crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B); | ||
883 | crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B); | ||
884 | crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B); | ||
885 | crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE); | ||
886 | |||
887 | /*NOTE: DSPSIZE DSPPOS only for psb*/ | ||
888 | crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE); | ||
889 | crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS); | ||
890 | |||
891 | crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE); | ||
892 | |||
893 | paletteReg = pipeA ? PALETTE_A : PALETTE_B; | ||
894 | for (i = 0; i < 256; ++i) | ||
895 | crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2)); | ||
896 | } | ||
897 | |||
898 | /** | ||
899 | * Restore HW states of giving crtc | ||
900 | */ | ||
901 | static void psb_intel_crtc_restore(struct drm_crtc *crtc) | ||
902 | { | ||
903 | struct drm_device *dev = crtc->dev; | ||
904 | /* struct drm_psb_private * dev_priv = | ||
905 | (struct drm_psb_private *)dev->dev_private; */ | ||
906 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
907 | struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state; | ||
908 | /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */ | ||
909 | int pipeA = (psb_intel_crtc->pipe == 0); | ||
910 | uint32_t paletteReg; | ||
911 | int i; | ||
912 | |||
913 | if (!crtc_state) { | ||
914 | dev_err(dev->dev, "No crtc state\n"); | ||
915 | return; | ||
916 | } | ||
917 | |||
918 | if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) { | ||
919 | REG_WRITE(pipeA ? DPLL_A : DPLL_B, | ||
920 | crtc_state->saveDPLL & ~DPLL_VCO_ENABLE); | ||
921 | REG_READ(pipeA ? DPLL_A : DPLL_B); | ||
922 | udelay(150); | ||
923 | } | ||
924 | |||
925 | REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0); | ||
926 | REG_READ(pipeA ? FPA0 : FPB0); | ||
927 | |||
928 | REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1); | ||
929 | REG_READ(pipeA ? FPA1 : FPB1); | ||
930 | |||
931 | REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL); | ||
932 | REG_READ(pipeA ? DPLL_A : DPLL_B); | ||
933 | udelay(150); | ||
934 | |||
935 | REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL); | ||
936 | REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK); | ||
937 | REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC); | ||
938 | REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL); | ||
939 | REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK); | ||
940 | REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC); | ||
941 | REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE); | ||
942 | |||
943 | REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE); | ||
944 | REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS); | ||
945 | |||
946 | REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC); | ||
947 | REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); | ||
948 | REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF); | ||
949 | |||
950 | psb_intel_wait_for_vblank(dev); | ||
951 | |||
952 | REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR); | ||
953 | REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE); | ||
954 | |||
955 | psb_intel_wait_for_vblank(dev); | ||
956 | |||
957 | paletteReg = pipeA ? PALETTE_A : PALETTE_B; | ||
958 | for (i = 0; i < 256; ++i) | ||
959 | REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]); | ||
960 | } | ||
961 | |||
962 | static int psb_intel_crtc_cursor_set(struct drm_crtc *crtc, | ||
963 | struct drm_file *file_priv, | ||
964 | uint32_t handle, | ||
965 | uint32_t width, uint32_t height) | ||
966 | { | ||
967 | struct drm_device *dev = crtc->dev; | ||
968 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
969 | int pipe = psb_intel_crtc->pipe; | ||
970 | uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR; | ||
971 | uint32_t base = (pipe == 0) ? CURABASE : CURBBASE; | ||
972 | uint32_t temp; | ||
973 | size_t addr = 0; | ||
974 | struct gtt_range *gt; | ||
975 | struct drm_gem_object *obj; | ||
976 | int ret; | ||
977 | |||
978 | /* if we want to turn of the cursor ignore width and height */ | ||
979 | if (!handle) { | ||
980 | /* turn off the cursor */ | ||
981 | temp = CURSOR_MODE_DISABLE; | ||
982 | |||
983 | if (gma_power_begin(dev, false)) { | ||
984 | REG_WRITE(control, temp); | ||
985 | REG_WRITE(base, 0); | ||
986 | gma_power_end(dev); | ||
987 | } | ||
988 | |||
989 | /* Unpin the old GEM object */ | ||
990 | if (psb_intel_crtc->cursor_obj) { | ||
991 | gt = container_of(psb_intel_crtc->cursor_obj, | ||
992 | struct gtt_range, gem); | ||
993 | psb_gtt_unpin(gt); | ||
994 | drm_gem_object_unreference(psb_intel_crtc->cursor_obj); | ||
995 | psb_intel_crtc->cursor_obj = NULL; | ||
996 | } | ||
997 | |||
998 | return 0; | ||
999 | } | ||
1000 | |||
1001 | /* Currently we only support 64x64 cursors */ | ||
1002 | if (width != 64 || height != 64) { | ||
1003 | dev_dbg(dev->dev, "we currently only support 64x64 cursors\n"); | ||
1004 | return -EINVAL; | ||
1005 | } | ||
1006 | |||
1007 | obj = drm_gem_object_lookup(dev, file_priv, handle); | ||
1008 | if (!obj) | ||
1009 | return -ENOENT; | ||
1010 | |||
1011 | if (obj->size < width * height * 4) { | ||
1012 | dev_dbg(dev->dev, "buffer is to small\n"); | ||
1013 | return -ENOMEM; | ||
1014 | } | ||
1015 | |||
1016 | gt = container_of(obj, struct gtt_range, gem); | ||
1017 | |||
1018 | /* Pin the memory into the GTT */ | ||
1019 | ret = psb_gtt_pin(gt); | ||
1020 | if (ret) { | ||
1021 | dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle); | ||
1022 | return ret; | ||
1023 | } | ||
1024 | |||
1025 | |||
1026 | addr = gt->offset; /* Or resource.start ??? */ | ||
1027 | |||
1028 | psb_intel_crtc->cursor_addr = addr; | ||
1029 | |||
1030 | temp = 0; | ||
1031 | /* set the pipe for the cursor */ | ||
1032 | temp |= (pipe << 28); | ||
1033 | temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE; | ||
1034 | |||
1035 | if (gma_power_begin(dev, false)) { | ||
1036 | REG_WRITE(control, temp); | ||
1037 | REG_WRITE(base, addr); | ||
1038 | gma_power_end(dev); | ||
1039 | } | ||
1040 | |||
1041 | /* unpin the old bo */ | ||
1042 | if (psb_intel_crtc->cursor_obj) { | ||
1043 | gt = container_of(psb_intel_crtc->cursor_obj, | ||
1044 | struct gtt_range, gem); | ||
1045 | psb_gtt_unpin(gt); | ||
1046 | drm_gem_object_unreference(psb_intel_crtc->cursor_obj); | ||
1047 | psb_intel_crtc->cursor_obj = obj; | ||
1048 | } | ||
1049 | return 0; | ||
1050 | } | ||
1051 | |||
1052 | static int psb_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y) | ||
1053 | { | ||
1054 | struct drm_device *dev = crtc->dev; | ||
1055 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
1056 | int pipe = psb_intel_crtc->pipe; | ||
1057 | uint32_t temp = 0; | ||
1058 | uint32_t addr; | ||
1059 | |||
1060 | |||
1061 | if (x < 0) { | ||
1062 | temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT); | ||
1063 | x = -x; | ||
1064 | } | ||
1065 | if (y < 0) { | ||
1066 | temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT); | ||
1067 | y = -y; | ||
1068 | } | ||
1069 | |||
1070 | temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT); | ||
1071 | temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT); | ||
1072 | |||
1073 | addr = psb_intel_crtc->cursor_addr; | ||
1074 | |||
1075 | if (gma_power_begin(dev, false)) { | ||
1076 | REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp); | ||
1077 | REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, addr); | ||
1078 | gma_power_end(dev); | ||
1079 | } | ||
1080 | return 0; | ||
1081 | } | ||
1082 | |||
1083 | void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, | ||
1084 | u16 *green, u16 *blue, uint32_t type, uint32_t size) | ||
1085 | { | ||
1086 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
1087 | int i; | ||
1088 | |||
1089 | if (size != 256) | ||
1090 | return; | ||
1091 | |||
1092 | for (i = 0; i < 256; i++) { | ||
1093 | psb_intel_crtc->lut_r[i] = red[i] >> 8; | ||
1094 | psb_intel_crtc->lut_g[i] = green[i] >> 8; | ||
1095 | psb_intel_crtc->lut_b[i] = blue[i] >> 8; | ||
1096 | } | ||
1097 | |||
1098 | psb_intel_crtc_load_lut(crtc); | ||
1099 | } | ||
1100 | |||
1101 | static int psb_crtc_set_config(struct drm_mode_set *set) | ||
1102 | { | ||
1103 | int ret; | ||
1104 | struct drm_device *dev = set->crtc->dev; | ||
1105 | |||
1106 | pm_runtime_forbid(&dev->pdev->dev); | ||
1107 | ret = drm_crtc_helper_set_config(set); | ||
1108 | pm_runtime_allow(&dev->pdev->dev); | ||
1109 | return ret; | ||
1110 | } | ||
1111 | |||
1112 | /* Returns the clock of the currently programmed mode of the given pipe. */ | ||
1113 | static int psb_intel_crtc_clock_get(struct drm_device *dev, | ||
1114 | struct drm_crtc *crtc) | ||
1115 | { | ||
1116 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
1117 | int pipe = psb_intel_crtc->pipe; | ||
1118 | u32 dpll; | ||
1119 | u32 fp; | ||
1120 | struct psb_intel_clock_t clock; | ||
1121 | bool is_lvds; | ||
1122 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
1123 | |||
1124 | if (gma_power_begin(dev, false)) { | ||
1125 | dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B); | ||
1126 | if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) | ||
1127 | fp = REG_READ((pipe == 0) ? FPA0 : FPB0); | ||
1128 | else | ||
1129 | fp = REG_READ((pipe == 0) ? FPA1 : FPB1); | ||
1130 | is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN); | ||
1131 | gma_power_end(dev); | ||
1132 | } else { | ||
1133 | dpll = (pipe == 0) ? | ||
1134 | dev_priv->saveDPLL_A : dev_priv->saveDPLL_B; | ||
1135 | |||
1136 | if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0) | ||
1137 | fp = (pipe == 0) ? | ||
1138 | dev_priv->saveFPA0 : | ||
1139 | dev_priv->saveFPB0; | ||
1140 | else | ||
1141 | fp = (pipe == 0) ? | ||
1142 | dev_priv->saveFPA1 : | ||
1143 | dev_priv->saveFPB1; | ||
1144 | |||
1145 | is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN); | ||
1146 | } | ||
1147 | |||
1148 | clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT; | ||
1149 | clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT; | ||
1150 | clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT; | ||
1151 | |||
1152 | if (is_lvds) { | ||
1153 | clock.p1 = | ||
1154 | ffs((dpll & | ||
1155 | DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >> | ||
1156 | DPLL_FPA01_P1_POST_DIV_SHIFT); | ||
1157 | clock.p2 = 14; | ||
1158 | |||
1159 | if ((dpll & PLL_REF_INPUT_MASK) == | ||
1160 | PLLB_REF_INPUT_SPREADSPECTRUMIN) { | ||
1161 | /* XXX: might not be 66MHz */ | ||
1162 | i8xx_clock(66000, &clock); | ||
1163 | } else | ||
1164 | i8xx_clock(48000, &clock); | ||
1165 | } else { | ||
1166 | if (dpll & PLL_P1_DIVIDE_BY_TWO) | ||
1167 | clock.p1 = 2; | ||
1168 | else { | ||
1169 | clock.p1 = | ||
1170 | ((dpll & | ||
1171 | DPLL_FPA01_P1_POST_DIV_MASK_I830) >> | ||
1172 | DPLL_FPA01_P1_POST_DIV_SHIFT) + 2; | ||
1173 | } | ||
1174 | if (dpll & PLL_P2_DIVIDE_BY_4) | ||
1175 | clock.p2 = 4; | ||
1176 | else | ||
1177 | clock.p2 = 2; | ||
1178 | |||
1179 | i8xx_clock(48000, &clock); | ||
1180 | } | ||
1181 | |||
1182 | /* XXX: It would be nice to validate the clocks, but we can't reuse | ||
1183 | * i830PllIsValid() because it relies on the xf86_config connector | ||
1184 | * configuration being accurate, which it isn't necessarily. | ||
1185 | */ | ||
1186 | |||
1187 | return clock.dot; | ||
1188 | } | ||
1189 | |||
1190 | /** Returns the currently programmed mode of the given pipe. */ | ||
1191 | struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, | ||
1192 | struct drm_crtc *crtc) | ||
1193 | { | ||
1194 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
1195 | int pipe = psb_intel_crtc->pipe; | ||
1196 | struct drm_display_mode *mode; | ||
1197 | int htot; | ||
1198 | int hsync; | ||
1199 | int vtot; | ||
1200 | int vsync; | ||
1201 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
1202 | |||
1203 | if (gma_power_begin(dev, false)) { | ||
1204 | htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B); | ||
1205 | hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B); | ||
1206 | vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B); | ||
1207 | vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B); | ||
1208 | gma_power_end(dev); | ||
1209 | } else { | ||
1210 | htot = (pipe == 0) ? | ||
1211 | dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B; | ||
1212 | hsync = (pipe == 0) ? | ||
1213 | dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B; | ||
1214 | vtot = (pipe == 0) ? | ||
1215 | dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B; | ||
1216 | vsync = (pipe == 0) ? | ||
1217 | dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B; | ||
1218 | } | ||
1219 | |||
1220 | mode = kzalloc(sizeof(*mode), GFP_KERNEL); | ||
1221 | if (!mode) | ||
1222 | return NULL; | ||
1223 | |||
1224 | mode->clock = psb_intel_crtc_clock_get(dev, crtc); | ||
1225 | mode->hdisplay = (htot & 0xffff) + 1; | ||
1226 | mode->htotal = ((htot & 0xffff0000) >> 16) + 1; | ||
1227 | mode->hsync_start = (hsync & 0xffff) + 1; | ||
1228 | mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1; | ||
1229 | mode->vdisplay = (vtot & 0xffff) + 1; | ||
1230 | mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1; | ||
1231 | mode->vsync_start = (vsync & 0xffff) + 1; | ||
1232 | mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1; | ||
1233 | |||
1234 | drm_mode_set_name(mode); | ||
1235 | drm_mode_set_crtcinfo(mode, 0); | ||
1236 | |||
1237 | return mode; | ||
1238 | } | ||
1239 | |||
1240 | void psb_intel_crtc_destroy(struct drm_crtc *crtc) | ||
1241 | { | ||
1242 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
1243 | struct gtt_range *gt; | ||
1244 | |||
1245 | /* Unpin the old GEM object */ | ||
1246 | if (psb_intel_crtc->cursor_obj) { | ||
1247 | gt = container_of(psb_intel_crtc->cursor_obj, | ||
1248 | struct gtt_range, gem); | ||
1249 | psb_gtt_unpin(gt); | ||
1250 | drm_gem_object_unreference(psb_intel_crtc->cursor_obj); | ||
1251 | psb_intel_crtc->cursor_obj = NULL; | ||
1252 | } | ||
1253 | kfree(psb_intel_crtc->crtc_state); | ||
1254 | drm_crtc_cleanup(crtc); | ||
1255 | kfree(psb_intel_crtc); | ||
1256 | } | ||
1257 | |||
1258 | const struct drm_crtc_helper_funcs psb_intel_helper_funcs = { | ||
1259 | .dpms = psb_intel_crtc_dpms, | ||
1260 | .mode_fixup = psb_intel_crtc_mode_fixup, | ||
1261 | .mode_set = psb_intel_crtc_mode_set, | ||
1262 | .mode_set_base = psb_intel_pipe_set_base, | ||
1263 | .prepare = psb_intel_crtc_prepare, | ||
1264 | .commit = psb_intel_crtc_commit, | ||
1265 | }; | ||
1266 | |||
1267 | const struct drm_crtc_funcs psb_intel_crtc_funcs = { | ||
1268 | .save = psb_intel_crtc_save, | ||
1269 | .restore = psb_intel_crtc_restore, | ||
1270 | .cursor_set = psb_intel_crtc_cursor_set, | ||
1271 | .cursor_move = psb_intel_crtc_cursor_move, | ||
1272 | .gamma_set = psb_intel_crtc_gamma_set, | ||
1273 | .set_config = psb_crtc_set_config, | ||
1274 | .destroy = psb_intel_crtc_destroy, | ||
1275 | }; | ||
1276 | |||
1277 | /* | ||
1278 | * Set the default value of cursor control and base register | ||
1279 | * to zero. This is a workaround for h/w defect on Oaktrail | ||
1280 | */ | ||
1281 | static void psb_intel_cursor_init(struct drm_device *dev, int pipe) | ||
1282 | { | ||
1283 | u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR }; | ||
1284 | u32 base[3] = { CURABASE, CURBBASE, CURCBASE }; | ||
1285 | |||
1286 | REG_WRITE(control[pipe], 0); | ||
1287 | REG_WRITE(base[pipe], 0); | ||
1288 | } | ||
1289 | |||
1290 | void psb_intel_crtc_init(struct drm_device *dev, int pipe, | ||
1291 | struct psb_intel_mode_device *mode_dev) | ||
1292 | { | ||
1293 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
1294 | struct psb_intel_crtc *psb_intel_crtc; | ||
1295 | int i; | ||
1296 | uint16_t *r_base, *g_base, *b_base; | ||
1297 | |||
1298 | /* We allocate a extra array of drm_connector pointers | ||
1299 | * for fbdev after the crtc */ | ||
1300 | psb_intel_crtc = | ||
1301 | kzalloc(sizeof(struct psb_intel_crtc) + | ||
1302 | (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)), | ||
1303 | GFP_KERNEL); | ||
1304 | if (psb_intel_crtc == NULL) | ||
1305 | return; | ||
1306 | |||
1307 | psb_intel_crtc->crtc_state = | ||
1308 | kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL); | ||
1309 | if (!psb_intel_crtc->crtc_state) { | ||
1310 | dev_err(dev->dev, "Crtc state error: No memory\n"); | ||
1311 | kfree(psb_intel_crtc); | ||
1312 | return; | ||
1313 | } | ||
1314 | |||
1315 | /* Set the CRTC operations from the chip specific data */ | ||
1316 | drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs); | ||
1317 | |||
1318 | drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256); | ||
1319 | psb_intel_crtc->pipe = pipe; | ||
1320 | psb_intel_crtc->plane = pipe; | ||
1321 | |||
1322 | r_base = psb_intel_crtc->base.gamma_store; | ||
1323 | g_base = r_base + 256; | ||
1324 | b_base = g_base + 256; | ||
1325 | for (i = 0; i < 256; i++) { | ||
1326 | psb_intel_crtc->lut_r[i] = i; | ||
1327 | psb_intel_crtc->lut_g[i] = i; | ||
1328 | psb_intel_crtc->lut_b[i] = i; | ||
1329 | r_base[i] = i << 8; | ||
1330 | g_base[i] = i << 8; | ||
1331 | b_base[i] = i << 8; | ||
1332 | |||
1333 | psb_intel_crtc->lut_adj[i] = 0; | ||
1334 | } | ||
1335 | |||
1336 | psb_intel_crtc->mode_dev = mode_dev; | ||
1337 | psb_intel_crtc->cursor_addr = 0; | ||
1338 | |||
1339 | drm_crtc_helper_add(&psb_intel_crtc->base, | ||
1340 | dev_priv->ops->crtc_helper); | ||
1341 | |||
1342 | /* Setup the array of drm_connector pointer array */ | ||
1343 | psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base; | ||
1344 | BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) || | ||
1345 | dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL); | ||
1346 | dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] = | ||
1347 | &psb_intel_crtc->base; | ||
1348 | dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] = | ||
1349 | &psb_intel_crtc->base; | ||
1350 | psb_intel_crtc->mode_set.connectors = | ||
1351 | (struct drm_connector **) (psb_intel_crtc + 1); | ||
1352 | psb_intel_crtc->mode_set.num_connectors = 0; | ||
1353 | psb_intel_cursor_init(dev, pipe); | ||
1354 | } | ||
1355 | |||
1356 | int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, | ||
1357 | struct drm_file *file_priv) | ||
1358 | { | ||
1359 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
1360 | struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data; | ||
1361 | struct drm_mode_object *drmmode_obj; | ||
1362 | struct psb_intel_crtc *crtc; | ||
1363 | |||
1364 | if (!dev_priv) { | ||
1365 | dev_err(dev->dev, "called with no initialization\n"); | ||
1366 | return -EINVAL; | ||
1367 | } | ||
1368 | |||
1369 | drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id, | ||
1370 | DRM_MODE_OBJECT_CRTC); | ||
1371 | |||
1372 | if (!drmmode_obj) { | ||
1373 | dev_err(dev->dev, "no such CRTC id\n"); | ||
1374 | return -EINVAL; | ||
1375 | } | ||
1376 | |||
1377 | crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj)); | ||
1378 | pipe_from_crtc_id->pipe = crtc->pipe; | ||
1379 | |||
1380 | return 0; | ||
1381 | } | ||
1382 | |||
1383 | struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe) | ||
1384 | { | ||
1385 | struct drm_crtc *crtc = NULL; | ||
1386 | |||
1387 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { | ||
1388 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
1389 | if (psb_intel_crtc->pipe == pipe) | ||
1390 | break; | ||
1391 | } | ||
1392 | return crtc; | ||
1393 | } | ||
1394 | |||
1395 | int psb_intel_connector_clones(struct drm_device *dev, int type_mask) | ||
1396 | { | ||
1397 | int index_mask = 0; | ||
1398 | struct drm_connector *connector; | ||
1399 | int entry = 0; | ||
1400 | |||
1401 | list_for_each_entry(connector, &dev->mode_config.connector_list, | ||
1402 | head) { | ||
1403 | struct psb_intel_output *psb_intel_output = | ||
1404 | to_psb_intel_output(connector); | ||
1405 | if (type_mask & (1 << psb_intel_output->type)) | ||
1406 | index_mask |= (1 << entry); | ||
1407 | entry++; | ||
1408 | } | ||
1409 | return index_mask; | ||
1410 | } | ||
1411 | |||
1412 | |||
1413 | void psb_intel_modeset_cleanup(struct drm_device *dev) | ||
1414 | { | ||
1415 | drm_mode_config_cleanup(dev); | ||
1416 | } | ||
1417 | |||
1418 | |||
1419 | /* current intel driver doesn't take advantage of encoders | ||
1420 | always give back the encoder for the connector | ||
1421 | */ | ||
1422 | struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector) | ||
1423 | { | ||
1424 | struct psb_intel_output *psb_intel_output = | ||
1425 | to_psb_intel_output(connector); | ||
1426 | |||
1427 | return &psb_intel_output->enc; | ||
1428 | } | ||
1429 | |||
diff --git a/drivers/staging/gma500/psb_intel_display.h b/drivers/staging/gma500/psb_intel_display.h deleted file mode 100644 index 535b49a5e409..000000000000 --- a/drivers/staging/gma500/psb_intel_display.h +++ /dev/null | |||
@@ -1,28 +0,0 @@ | |||
1 | /* copyright (c) 2008, Intel Corporation | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms and conditions of the GNU General Public License, | ||
5 | * version 2, as published by the Free Software Foundation. | ||
6 | * | ||
7 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
8 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
9 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
10 | * more details. | ||
11 | * | ||
12 | * You should have received a copy of the GNU General Public License along with | ||
13 | * this program; if not, write to the Free Software Foundation, Inc., | ||
14 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
15 | * | ||
16 | * Authors: | ||
17 | * Eric Anholt <eric@anholt.net> | ||
18 | */ | ||
19 | |||
20 | #ifndef _INTEL_DISPLAY_H_ | ||
21 | #define _INTEL_DISPLAY_H_ | ||
22 | |||
23 | bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type); | ||
24 | void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, | ||
25 | u16 *green, u16 *blue, uint32_t type, uint32_t size); | ||
26 | void psb_intel_crtc_destroy(struct drm_crtc *crtc); | ||
27 | |||
28 | #endif | ||
diff --git a/drivers/staging/gma500/psb_intel_drv.h b/drivers/staging/gma500/psb_intel_drv.h deleted file mode 100644 index 36b554b5c335..000000000000 --- a/drivers/staging/gma500/psb_intel_drv.h +++ /dev/null | |||
@@ -1,230 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2009-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 | */ | ||
18 | |||
19 | #ifndef __INTEL_DRV_H__ | ||
20 | #define __INTEL_DRV_H__ | ||
21 | |||
22 | #include <linux/i2c.h> | ||
23 | #include <linux/i2c-algo-bit.h> | ||
24 | #include <drm/drm_crtc.h> | ||
25 | #include <drm/drm_crtc_helper.h> | ||
26 | #include <linux/gpio.h> | ||
27 | |||
28 | /* | ||
29 | * Display related stuff | ||
30 | */ | ||
31 | |||
32 | /* store information about an Ixxx DVO */ | ||
33 | /* The i830->i865 use multiple DVOs with multiple i2cs */ | ||
34 | /* the i915, i945 have a single sDVO i2c bus - which is different */ | ||
35 | #define MAX_OUTPUTS 6 | ||
36 | /* maximum connectors per crtcs in the mode set */ | ||
37 | #define INTELFB_CONN_LIMIT 4 | ||
38 | |||
39 | #define INTEL_I2C_BUS_DVO 1 | ||
40 | #define INTEL_I2C_BUS_SDVO 2 | ||
41 | |||
42 | /* these are outputs from the chip - integrated only | ||
43 | * external chips are via DVO or SDVO output */ | ||
44 | #define INTEL_OUTPUT_UNUSED 0 | ||
45 | #define INTEL_OUTPUT_ANALOG 1 | ||
46 | #define INTEL_OUTPUT_DVO 2 | ||
47 | #define INTEL_OUTPUT_SDVO 3 | ||
48 | #define INTEL_OUTPUT_LVDS 4 | ||
49 | #define INTEL_OUTPUT_TVOUT 5 | ||
50 | #define INTEL_OUTPUT_HDMI 6 | ||
51 | #define INTEL_OUTPUT_MIPI 7 | ||
52 | #define INTEL_OUTPUT_MIPI2 8 | ||
53 | |||
54 | #define INTEL_DVO_CHIP_NONE 0 | ||
55 | #define INTEL_DVO_CHIP_LVDS 1 | ||
56 | #define INTEL_DVO_CHIP_TMDS 2 | ||
57 | #define INTEL_DVO_CHIP_TVOUT 4 | ||
58 | |||
59 | /* | ||
60 | * Hold information useally put on the device driver privates here, | ||
61 | * since it needs to be shared across multiple of devices drivers privates. | ||
62 | */ | ||
63 | struct psb_intel_mode_device { | ||
64 | |||
65 | /* | ||
66 | * Abstracted memory manager operations | ||
67 | */ | ||
68 | size_t(*bo_offset) (struct drm_device *dev, void *bo); | ||
69 | |||
70 | /* | ||
71 | * Cursor (Can go ?) | ||
72 | */ | ||
73 | int cursor_needs_physical; | ||
74 | |||
75 | /* | ||
76 | * LVDS info | ||
77 | */ | ||
78 | int backlight_duty_cycle; /* restore backlight to this value */ | ||
79 | bool panel_wants_dither; | ||
80 | struct drm_display_mode *panel_fixed_mode; | ||
81 | struct drm_display_mode *panel_fixed_mode2; | ||
82 | struct drm_display_mode *vbt_mode; /* if any */ | ||
83 | |||
84 | uint32_t saveBLC_PWM_CTL; | ||
85 | }; | ||
86 | |||
87 | struct psb_intel_i2c_chan { | ||
88 | /* for getting at dev. private (mmio etc.) */ | ||
89 | struct drm_device *drm_dev; | ||
90 | u32 reg; /* GPIO reg */ | ||
91 | struct i2c_adapter adapter; | ||
92 | struct i2c_algo_bit_data algo; | ||
93 | u8 slave_addr; | ||
94 | }; | ||
95 | |||
96 | struct psb_intel_output { | ||
97 | struct drm_connector base; | ||
98 | |||
99 | struct drm_encoder enc; | ||
100 | int type; | ||
101 | |||
102 | struct psb_intel_i2c_chan *i2c_bus; /* for control functions */ | ||
103 | struct psb_intel_i2c_chan *ddc_bus; /* for DDC only stuff */ | ||
104 | bool load_detect_temp; | ||
105 | void *dev_priv; | ||
106 | |||
107 | struct psb_intel_mode_device *mode_dev; | ||
108 | struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */ | ||
109 | }; | ||
110 | |||
111 | struct psb_intel_crtc_state { | ||
112 | uint32_t saveDSPCNTR; | ||
113 | uint32_t savePIPECONF; | ||
114 | uint32_t savePIPESRC; | ||
115 | uint32_t saveDPLL; | ||
116 | uint32_t saveFP0; | ||
117 | uint32_t saveFP1; | ||
118 | uint32_t saveHTOTAL; | ||
119 | uint32_t saveHBLANK; | ||
120 | uint32_t saveHSYNC; | ||
121 | uint32_t saveVTOTAL; | ||
122 | uint32_t saveVBLANK; | ||
123 | uint32_t saveVSYNC; | ||
124 | uint32_t saveDSPSTRIDE; | ||
125 | uint32_t saveDSPSIZE; | ||
126 | uint32_t saveDSPPOS; | ||
127 | uint32_t saveDSPBASE; | ||
128 | uint32_t savePalette[256]; | ||
129 | }; | ||
130 | |||
131 | struct psb_intel_crtc { | ||
132 | struct drm_crtc base; | ||
133 | int pipe; | ||
134 | int plane; | ||
135 | uint32_t cursor_addr; | ||
136 | u8 lut_r[256], lut_g[256], lut_b[256]; | ||
137 | u8 lut_adj[256]; | ||
138 | struct psb_intel_framebuffer *fbdev_fb; | ||
139 | /* a mode_set for fbdev users on this crtc */ | ||
140 | struct drm_mode_set mode_set; | ||
141 | |||
142 | /* GEM object that holds our cursor */ | ||
143 | struct drm_gem_object *cursor_obj; | ||
144 | |||
145 | struct drm_display_mode saved_mode; | ||
146 | struct drm_display_mode saved_adjusted_mode; | ||
147 | |||
148 | struct psb_intel_mode_device *mode_dev; | ||
149 | |||
150 | /*crtc mode setting flags*/ | ||
151 | u32 mode_flags; | ||
152 | |||
153 | /* Saved Crtc HW states */ | ||
154 | struct psb_intel_crtc_state *crtc_state; | ||
155 | }; | ||
156 | |||
157 | #define to_psb_intel_crtc(x) \ | ||
158 | container_of(x, struct psb_intel_crtc, base) | ||
159 | #define to_psb_intel_output(x) \ | ||
160 | container_of(x, struct psb_intel_output, base) | ||
161 | #define enc_to_psb_intel_output(x) \ | ||
162 | container_of(x, struct psb_intel_output, enc) | ||
163 | #define to_psb_intel_framebuffer(x) \ | ||
164 | container_of(x, struct psb_intel_framebuffer, base) | ||
165 | |||
166 | struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev, | ||
167 | const u32 reg, const char *name); | ||
168 | void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan); | ||
169 | int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output); | ||
170 | extern bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output); | ||
171 | |||
172 | extern void psb_intel_crtc_init(struct drm_device *dev, int pipe, | ||
173 | struct psb_intel_mode_device *mode_dev); | ||
174 | extern void psb_intel_crt_init(struct drm_device *dev); | ||
175 | extern void psb_intel_sdvo_init(struct drm_device *dev, int output_device); | ||
176 | extern void psb_intel_dvo_init(struct drm_device *dev); | ||
177 | extern void psb_intel_tv_init(struct drm_device *dev); | ||
178 | extern void psb_intel_lvds_init(struct drm_device *dev, | ||
179 | struct psb_intel_mode_device *mode_dev); | ||
180 | extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level); | ||
181 | extern void mrst_lvds_init(struct drm_device *dev, | ||
182 | struct psb_intel_mode_device *mode_dev); | ||
183 | extern void mrst_wait_for_INTR_PKT_SENT(struct drm_device *dev); | ||
184 | extern void mrst_dsi_init(struct drm_device *dev, | ||
185 | struct psb_intel_mode_device *mode_dev); | ||
186 | extern void mid_dsi_init(struct drm_device *dev, | ||
187 | struct psb_intel_mode_device *mode_dev, int dsi_num); | ||
188 | |||
189 | extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc); | ||
190 | extern void psb_intel_encoder_prepare(struct drm_encoder *encoder); | ||
191 | extern void psb_intel_encoder_commit(struct drm_encoder *encoder); | ||
192 | |||
193 | extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector | ||
194 | *connector); | ||
195 | |||
196 | extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev, | ||
197 | struct drm_crtc *crtc); | ||
198 | extern void psb_intel_wait_for_vblank(struct drm_device *dev); | ||
199 | extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data, | ||
200 | struct drm_file *file_priv); | ||
201 | extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, | ||
202 | int pipe); | ||
203 | extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, | ||
204 | int sdvoB); | ||
205 | extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector); | ||
206 | extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, | ||
207 | int enable); | ||
208 | extern int intelfb_probe(struct drm_device *dev); | ||
209 | extern int intelfb_remove(struct drm_device *dev, | ||
210 | struct drm_framebuffer *fb); | ||
211 | extern struct drm_framebuffer *psb_intel_framebuffer_create(struct drm_device | ||
212 | *dev, struct | ||
213 | drm_mode_fb_cmd | ||
214 | *mode_cmd, | ||
215 | void *mm_private); | ||
216 | extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, | ||
217 | struct drm_display_mode *mode, | ||
218 | struct drm_display_mode *adjusted_mode); | ||
219 | extern int psb_intel_lvds_mode_valid(struct drm_connector *connector, | ||
220 | struct drm_display_mode *mode); | ||
221 | extern int psb_intel_lvds_set_property(struct drm_connector *connector, | ||
222 | struct drm_property *property, | ||
223 | uint64_t value); | ||
224 | extern void psb_intel_lvds_destroy(struct drm_connector *connector); | ||
225 | extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs; | ||
226 | |||
227 | extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe); | ||
228 | extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe); | ||
229 | |||
230 | #endif /* __INTEL_DRV_H__ */ | ||
diff --git a/drivers/staging/gma500/psb_intel_lvds.c b/drivers/staging/gma500/psb_intel_lvds.c deleted file mode 100644 index 21022e1a977a..000000000000 --- a/drivers/staging/gma500/psb_intel_lvds.c +++ /dev/null | |||
@@ -1,854 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright © 2006-2007 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 <drm/drmP.h> | ||
25 | |||
26 | #include "intel_bios.h" | ||
27 | #include "psb_drv.h" | ||
28 | #include "psb_intel_drv.h" | ||
29 | #include "psb_intel_reg.h" | ||
30 | #include "power.h" | ||
31 | #include <linux/pm_runtime.h> | ||
32 | |||
33 | /* | ||
34 | * LVDS I2C backlight control macros | ||
35 | */ | ||
36 | #define BRIGHTNESS_MAX_LEVEL 100 | ||
37 | #define BRIGHTNESS_MASK 0xFF | ||
38 | #define BLC_I2C_TYPE 0x01 | ||
39 | #define BLC_PWM_TYPT 0x02 | ||
40 | |||
41 | #define BLC_POLARITY_NORMAL 0 | ||
42 | #define BLC_POLARITY_INVERSE 1 | ||
43 | |||
44 | #define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE) | ||
45 | #define PSB_BLC_MIN_PWM_REG_FREQ (0x2) | ||
46 | #define PSB_BLC_PWM_PRECISION_FACTOR (10) | ||
47 | #define PSB_BACKLIGHT_PWM_CTL_SHIFT (16) | ||
48 | #define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE) | ||
49 | |||
50 | struct psb_intel_lvds_priv { | ||
51 | /* | ||
52 | * Saved LVDO output states | ||
53 | */ | ||
54 | uint32_t savePP_ON; | ||
55 | uint32_t savePP_OFF; | ||
56 | uint32_t saveLVDS; | ||
57 | uint32_t savePP_CONTROL; | ||
58 | uint32_t savePP_CYCLE; | ||
59 | uint32_t savePFIT_CONTROL; | ||
60 | uint32_t savePFIT_PGM_RATIOS; | ||
61 | uint32_t saveBLC_PWM_CTL; | ||
62 | }; | ||
63 | |||
64 | |||
65 | /* | ||
66 | * Returns the maximum level of the backlight duty cycle field. | ||
67 | */ | ||
68 | static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev) | ||
69 | { | ||
70 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
71 | u32 ret; | ||
72 | |||
73 | if (gma_power_begin(dev, false)) { | ||
74 | ret = REG_READ(BLC_PWM_CTL); | ||
75 | gma_power_end(dev); | ||
76 | } else /* Powered off, use the saved value */ | ||
77 | ret = dev_priv->saveBLC_PWM_CTL; | ||
78 | |||
79 | /* Top 15bits hold the frequency mask */ | ||
80 | ret = (ret & BACKLIGHT_MODULATION_FREQ_MASK) >> | ||
81 | BACKLIGHT_MODULATION_FREQ_SHIFT; | ||
82 | |||
83 | ret *= 2; /* Return a 16bit range as needed for setting */ | ||
84 | if (ret == 0) | ||
85 | dev_err(dev->dev, "BL bug: Reg %08x save %08X\n", | ||
86 | REG_READ(BLC_PWM_CTL), dev_priv->saveBLC_PWM_CTL); | ||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | /* | ||
91 | * Set LVDS backlight level by I2C command | ||
92 | * | ||
93 | * FIXME: at some point we need to both track this for PM and also | ||
94 | * disable runtime pm on MRST if the brightness is nil (ie blanked) | ||
95 | */ | ||
96 | static int psb_lvds_i2c_set_brightness(struct drm_device *dev, | ||
97 | unsigned int level) | ||
98 | { | ||
99 | struct drm_psb_private *dev_priv = | ||
100 | (struct drm_psb_private *)dev->dev_private; | ||
101 | |||
102 | struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus; | ||
103 | u8 out_buf[2]; | ||
104 | unsigned int blc_i2c_brightness; | ||
105 | |||
106 | struct i2c_msg msgs[] = { | ||
107 | { | ||
108 | .addr = lvds_i2c_bus->slave_addr, | ||
109 | .flags = 0, | ||
110 | .len = 2, | ||
111 | .buf = out_buf, | ||
112 | } | ||
113 | }; | ||
114 | |||
115 | blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level * | ||
116 | BRIGHTNESS_MASK / | ||
117 | BRIGHTNESS_MAX_LEVEL); | ||
118 | |||
119 | if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) | ||
120 | blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness; | ||
121 | |||
122 | out_buf[0] = dev_priv->lvds_bl->brightnesscmd; | ||
123 | out_buf[1] = (u8)blc_i2c_brightness; | ||
124 | |||
125 | if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) { | ||
126 | dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n", | ||
127 | dev_priv->lvds_bl->brightnesscmd, | ||
128 | blc_i2c_brightness); | ||
129 | return 0; | ||
130 | } | ||
131 | |||
132 | dev_err(dev->dev, "I2C transfer error\n"); | ||
133 | return -1; | ||
134 | } | ||
135 | |||
136 | |||
137 | static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level) | ||
138 | { | ||
139 | struct drm_psb_private *dev_priv = | ||
140 | (struct drm_psb_private *)dev->dev_private; | ||
141 | |||
142 | u32 max_pwm_blc; | ||
143 | u32 blc_pwm_duty_cycle; | ||
144 | |||
145 | max_pwm_blc = psb_intel_lvds_get_max_backlight(dev); | ||
146 | |||
147 | /*BLC_PWM_CTL Should be initiated while backlight device init*/ | ||
148 | BUG_ON(max_pwm_blc == 0); | ||
149 | |||
150 | blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL; | ||
151 | |||
152 | if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE) | ||
153 | blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle; | ||
154 | |||
155 | blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR; | ||
156 | REG_WRITE(BLC_PWM_CTL, | ||
157 | (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | | ||
158 | (blc_pwm_duty_cycle)); | ||
159 | |||
160 | dev_info(dev->dev, "Backlight lvds set brightness %08x\n", | ||
161 | (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) | | ||
162 | (blc_pwm_duty_cycle)); | ||
163 | |||
164 | return 0; | ||
165 | } | ||
166 | |||
167 | /* | ||
168 | * Set LVDS backlight level either by I2C or PWM | ||
169 | */ | ||
170 | void psb_intel_lvds_set_brightness(struct drm_device *dev, int level) | ||
171 | { | ||
172 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
173 | |||
174 | dev_dbg(dev->dev, "backlight level is %d\n", level); | ||
175 | |||
176 | if (!dev_priv->lvds_bl) { | ||
177 | dev_err(dev->dev, "NO LVDS backlight info\n"); | ||
178 | return; | ||
179 | } | ||
180 | |||
181 | if (dev_priv->lvds_bl->type == BLC_I2C_TYPE) | ||
182 | psb_lvds_i2c_set_brightness(dev, level); | ||
183 | else | ||
184 | psb_lvds_pwm_set_brightness(dev, level); | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * Sets the backlight level. | ||
189 | * | ||
190 | * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight(). | ||
191 | */ | ||
192 | static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level) | ||
193 | { | ||
194 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
195 | u32 blc_pwm_ctl; | ||
196 | |||
197 | if (gma_power_begin(dev, false)) { | ||
198 | blc_pwm_ctl = REG_READ(BLC_PWM_CTL); | ||
199 | blc_pwm_ctl &= ~BACKLIGHT_DUTY_CYCLE_MASK; | ||
200 | REG_WRITE(BLC_PWM_CTL, | ||
201 | (blc_pwm_ctl | | ||
202 | (level << BACKLIGHT_DUTY_CYCLE_SHIFT))); | ||
203 | dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl | | ||
204 | (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); | ||
205 | gma_power_end(dev); | ||
206 | } else { | ||
207 | blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL & | ||
208 | ~BACKLIGHT_DUTY_CYCLE_MASK; | ||
209 | dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl | | ||
210 | (level << BACKLIGHT_DUTY_CYCLE_SHIFT)); | ||
211 | } | ||
212 | } | ||
213 | |||
214 | /* | ||
215 | * Sets the power state for the panel. | ||
216 | */ | ||
217 | static void psb_intel_lvds_set_power(struct drm_device *dev, | ||
218 | struct psb_intel_output *output, bool on) | ||
219 | { | ||
220 | u32 pp_status; | ||
221 | |||
222 | if (!gma_power_begin(dev, true)) { | ||
223 | dev_err(dev->dev, "set power, chip off!\n"); | ||
224 | return; | ||
225 | } | ||
226 | |||
227 | if (on) { | ||
228 | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | | ||
229 | POWER_TARGET_ON); | ||
230 | do { | ||
231 | pp_status = REG_READ(PP_STATUS); | ||
232 | } while ((pp_status & PP_ON) == 0); | ||
233 | |||
234 | psb_intel_lvds_set_backlight(dev, | ||
235 | output-> | ||
236 | mode_dev->backlight_duty_cycle); | ||
237 | } else { | ||
238 | psb_intel_lvds_set_backlight(dev, 0); | ||
239 | |||
240 | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & | ||
241 | ~POWER_TARGET_ON); | ||
242 | do { | ||
243 | pp_status = REG_READ(PP_STATUS); | ||
244 | } while (pp_status & PP_ON); | ||
245 | } | ||
246 | |||
247 | gma_power_end(dev); | ||
248 | } | ||
249 | |||
250 | static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode) | ||
251 | { | ||
252 | struct drm_device *dev = encoder->dev; | ||
253 | struct psb_intel_output *output = enc_to_psb_intel_output(encoder); | ||
254 | |||
255 | if (mode == DRM_MODE_DPMS_ON) | ||
256 | psb_intel_lvds_set_power(dev, output, true); | ||
257 | else | ||
258 | psb_intel_lvds_set_power(dev, output, false); | ||
259 | |||
260 | /* XXX: We never power down the LVDS pairs. */ | ||
261 | } | ||
262 | |||
263 | static void psb_intel_lvds_save(struct drm_connector *connector) | ||
264 | { | ||
265 | struct drm_device *dev = connector->dev; | ||
266 | struct drm_psb_private *dev_priv = | ||
267 | (struct drm_psb_private *)dev->dev_private; | ||
268 | struct psb_intel_output *psb_intel_output = | ||
269 | to_psb_intel_output(connector); | ||
270 | struct psb_intel_lvds_priv *lvds_priv = | ||
271 | (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv; | ||
272 | |||
273 | lvds_priv->savePP_ON = REG_READ(LVDSPP_ON); | ||
274 | lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF); | ||
275 | lvds_priv->saveLVDS = REG_READ(LVDS); | ||
276 | lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL); | ||
277 | lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE); | ||
278 | /*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/ | ||
279 | lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); | ||
280 | lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL); | ||
281 | lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS); | ||
282 | |||
283 | /*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/ | ||
284 | dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & | ||
285 | BACKLIGHT_DUTY_CYCLE_MASK); | ||
286 | |||
287 | /* | ||
288 | * If the light is off at server startup, | ||
289 | * just make it full brightness | ||
290 | */ | ||
291 | if (dev_priv->backlight_duty_cycle == 0) | ||
292 | dev_priv->backlight_duty_cycle = | ||
293 | psb_intel_lvds_get_max_backlight(dev); | ||
294 | |||
295 | dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", | ||
296 | lvds_priv->savePP_ON, | ||
297 | lvds_priv->savePP_OFF, | ||
298 | lvds_priv->saveLVDS, | ||
299 | lvds_priv->savePP_CONTROL, | ||
300 | lvds_priv->savePP_CYCLE, | ||
301 | lvds_priv->saveBLC_PWM_CTL); | ||
302 | } | ||
303 | |||
304 | static void psb_intel_lvds_restore(struct drm_connector *connector) | ||
305 | { | ||
306 | struct drm_device *dev = connector->dev; | ||
307 | u32 pp_status; | ||
308 | struct psb_intel_output *psb_intel_output = | ||
309 | to_psb_intel_output(connector); | ||
310 | struct psb_intel_lvds_priv *lvds_priv = | ||
311 | (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv; | ||
312 | |||
313 | dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n", | ||
314 | lvds_priv->savePP_ON, | ||
315 | lvds_priv->savePP_OFF, | ||
316 | lvds_priv->saveLVDS, | ||
317 | lvds_priv->savePP_CONTROL, | ||
318 | lvds_priv->savePP_CYCLE, | ||
319 | lvds_priv->saveBLC_PWM_CTL); | ||
320 | |||
321 | REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL); | ||
322 | REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL); | ||
323 | REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS); | ||
324 | REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON); | ||
325 | REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF); | ||
326 | /*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/ | ||
327 | REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE); | ||
328 | REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL); | ||
329 | REG_WRITE(LVDS, lvds_priv->saveLVDS); | ||
330 | |||
331 | if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) { | ||
332 | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | | ||
333 | POWER_TARGET_ON); | ||
334 | do { | ||
335 | pp_status = REG_READ(PP_STATUS); | ||
336 | } while ((pp_status & PP_ON) == 0); | ||
337 | } else { | ||
338 | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & | ||
339 | ~POWER_TARGET_ON); | ||
340 | do { | ||
341 | pp_status = REG_READ(PP_STATUS); | ||
342 | } while (pp_status & PP_ON); | ||
343 | } | ||
344 | } | ||
345 | |||
346 | int psb_intel_lvds_mode_valid(struct drm_connector *connector, | ||
347 | struct drm_display_mode *mode) | ||
348 | { | ||
349 | struct psb_intel_output *psb_intel_output = | ||
350 | to_psb_intel_output(connector); | ||
351 | struct drm_display_mode *fixed_mode = | ||
352 | psb_intel_output->mode_dev->panel_fixed_mode; | ||
353 | |||
354 | if (psb_intel_output->type == INTEL_OUTPUT_MIPI2) | ||
355 | fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2; | ||
356 | |||
357 | /* just in case */ | ||
358 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
359 | return MODE_NO_DBLESCAN; | ||
360 | |||
361 | /* just in case */ | ||
362 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) | ||
363 | return MODE_NO_INTERLACE; | ||
364 | |||
365 | if (fixed_mode) { | ||
366 | if (mode->hdisplay > fixed_mode->hdisplay) | ||
367 | return MODE_PANEL; | ||
368 | if (mode->vdisplay > fixed_mode->vdisplay) | ||
369 | return MODE_PANEL; | ||
370 | } | ||
371 | return MODE_OK; | ||
372 | } | ||
373 | |||
374 | bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder, | ||
375 | struct drm_display_mode *mode, | ||
376 | struct drm_display_mode *adjusted_mode) | ||
377 | { | ||
378 | struct psb_intel_mode_device *mode_dev = | ||
379 | enc_to_psb_intel_output(encoder)->mode_dev; | ||
380 | struct drm_device *dev = encoder->dev; | ||
381 | struct psb_intel_crtc *psb_intel_crtc = | ||
382 | to_psb_intel_crtc(encoder->crtc); | ||
383 | struct drm_encoder *tmp_encoder; | ||
384 | struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode; | ||
385 | struct psb_intel_output *psb_intel_output = | ||
386 | enc_to_psb_intel_output(encoder); | ||
387 | |||
388 | if (psb_intel_output->type == INTEL_OUTPUT_MIPI2) | ||
389 | panel_fixed_mode = mode_dev->panel_fixed_mode2; | ||
390 | |||
391 | /* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */ | ||
392 | if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) { | ||
393 | printk(KERN_ERR "Can't support LVDS on pipe A\n"); | ||
394 | return false; | ||
395 | } | ||
396 | if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) { | ||
397 | printk(KERN_ERR "Must use PIPE A\n"); | ||
398 | return false; | ||
399 | } | ||
400 | /* Should never happen!! */ | ||
401 | list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list, | ||
402 | head) { | ||
403 | if (tmp_encoder != encoder | ||
404 | && tmp_encoder->crtc == encoder->crtc) { | ||
405 | printk(KERN_ERR "Can't enable LVDS and another " | ||
406 | "encoder on the same pipe\n"); | ||
407 | return false; | ||
408 | } | ||
409 | } | ||
410 | |||
411 | /* | ||
412 | * If we have timings from the BIOS for the panel, put them in | ||
413 | * to the adjusted mode. The CRTC will be set up for this mode, | ||
414 | * with the panel scaling set up to source from the H/VDisplay | ||
415 | * of the original mode. | ||
416 | */ | ||
417 | if (panel_fixed_mode != NULL) { | ||
418 | adjusted_mode->hdisplay = panel_fixed_mode->hdisplay; | ||
419 | adjusted_mode->hsync_start = panel_fixed_mode->hsync_start; | ||
420 | adjusted_mode->hsync_end = panel_fixed_mode->hsync_end; | ||
421 | adjusted_mode->htotal = panel_fixed_mode->htotal; | ||
422 | adjusted_mode->vdisplay = panel_fixed_mode->vdisplay; | ||
423 | adjusted_mode->vsync_start = panel_fixed_mode->vsync_start; | ||
424 | adjusted_mode->vsync_end = panel_fixed_mode->vsync_end; | ||
425 | adjusted_mode->vtotal = panel_fixed_mode->vtotal; | ||
426 | adjusted_mode->clock = panel_fixed_mode->clock; | ||
427 | drm_mode_set_crtcinfo(adjusted_mode, | ||
428 | CRTC_INTERLACE_HALVE_V); | ||
429 | } | ||
430 | |||
431 | /* | ||
432 | * XXX: It would be nice to support lower refresh rates on the | ||
433 | * panels to reduce power consumption, and perhaps match the | ||
434 | * user's requested refresh rate. | ||
435 | */ | ||
436 | |||
437 | return true; | ||
438 | } | ||
439 | |||
440 | static void psb_intel_lvds_prepare(struct drm_encoder *encoder) | ||
441 | { | ||
442 | struct drm_device *dev = encoder->dev; | ||
443 | struct psb_intel_output *output = enc_to_psb_intel_output(encoder); | ||
444 | struct psb_intel_mode_device *mode_dev = output->mode_dev; | ||
445 | |||
446 | if (!gma_power_begin(dev, true)) | ||
447 | return; | ||
448 | |||
449 | mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL); | ||
450 | mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL & | ||
451 | BACKLIGHT_DUTY_CYCLE_MASK); | ||
452 | |||
453 | psb_intel_lvds_set_power(dev, output, false); | ||
454 | |||
455 | gma_power_end(dev); | ||
456 | } | ||
457 | |||
458 | static void psb_intel_lvds_commit(struct drm_encoder *encoder) | ||
459 | { | ||
460 | struct drm_device *dev = encoder->dev; | ||
461 | struct psb_intel_output *output = enc_to_psb_intel_output(encoder); | ||
462 | struct psb_intel_mode_device *mode_dev = output->mode_dev; | ||
463 | |||
464 | if (mode_dev->backlight_duty_cycle == 0) | ||
465 | mode_dev->backlight_duty_cycle = | ||
466 | psb_intel_lvds_get_max_backlight(dev); | ||
467 | |||
468 | psb_intel_lvds_set_power(dev, output, true); | ||
469 | } | ||
470 | |||
471 | static void psb_intel_lvds_mode_set(struct drm_encoder *encoder, | ||
472 | struct drm_display_mode *mode, | ||
473 | struct drm_display_mode *adjusted_mode) | ||
474 | { | ||
475 | struct drm_device *dev = encoder->dev; | ||
476 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
477 | u32 pfit_control; | ||
478 | |||
479 | /* | ||
480 | * The LVDS pin pair will already have been turned on in the | ||
481 | * psb_intel_crtc_mode_set since it has a large impact on the DPLL | ||
482 | * settings. | ||
483 | */ | ||
484 | |||
485 | /* | ||
486 | * Enable automatic panel scaling so that non-native modes fill the | ||
487 | * screen. Should be enabled before the pipe is enabled, according to | ||
488 | * register description and PRM. | ||
489 | */ | ||
490 | if (mode->hdisplay != adjusted_mode->hdisplay || | ||
491 | mode->vdisplay != adjusted_mode->vdisplay) | ||
492 | pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE | | ||
493 | HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR | | ||
494 | HORIZ_INTERP_BILINEAR); | ||
495 | else | ||
496 | pfit_control = 0; | ||
497 | |||
498 | if (dev_priv->lvds_dither) | ||
499 | pfit_control |= PANEL_8TO6_DITHER_ENABLE; | ||
500 | |||
501 | REG_WRITE(PFIT_CONTROL, pfit_control); | ||
502 | } | ||
503 | |||
504 | /* | ||
505 | * Detect the LVDS connection. | ||
506 | * | ||
507 | * This always returns CONNECTOR_STATUS_CONNECTED. | ||
508 | * This connector should only have | ||
509 | * been set up if the LVDS was actually connected anyway. | ||
510 | */ | ||
511 | static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector | ||
512 | *connector, bool force) | ||
513 | { | ||
514 | return connector_status_connected; | ||
515 | } | ||
516 | |||
517 | /* | ||
518 | * Return the list of DDC modes if available, or the BIOS fixed mode otherwise. | ||
519 | */ | ||
520 | static int psb_intel_lvds_get_modes(struct drm_connector *connector) | ||
521 | { | ||
522 | struct drm_device *dev = connector->dev; | ||
523 | struct psb_intel_output *psb_intel_output = | ||
524 | to_psb_intel_output(connector); | ||
525 | struct psb_intel_mode_device *mode_dev = | ||
526 | psb_intel_output->mode_dev; | ||
527 | int ret = 0; | ||
528 | |||
529 | if (!IS_MRST(dev)) | ||
530 | ret = psb_intel_ddc_get_modes(psb_intel_output); | ||
531 | |||
532 | if (ret) | ||
533 | return ret; | ||
534 | |||
535 | /* Didn't get an EDID, so | ||
536 | * Set wide sync ranges so we get all modes | ||
537 | * handed to valid_mode for checking | ||
538 | */ | ||
539 | connector->display_info.min_vfreq = 0; | ||
540 | connector->display_info.max_vfreq = 200; | ||
541 | connector->display_info.min_hfreq = 0; | ||
542 | connector->display_info.max_hfreq = 200; | ||
543 | |||
544 | if (mode_dev->panel_fixed_mode != NULL) { | ||
545 | struct drm_display_mode *mode = | ||
546 | drm_mode_duplicate(dev, mode_dev->panel_fixed_mode); | ||
547 | drm_mode_probed_add(connector, mode); | ||
548 | return 1; | ||
549 | } | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | /** | ||
555 | * psb_intel_lvds_destroy - unregister and free LVDS structures | ||
556 | * @connector: connector to free | ||
557 | * | ||
558 | * Unregister the DDC bus for this connector then free the driver private | ||
559 | * structure. | ||
560 | */ | ||
561 | void psb_intel_lvds_destroy(struct drm_connector *connector) | ||
562 | { | ||
563 | struct psb_intel_output *psb_intel_output = | ||
564 | to_psb_intel_output(connector); | ||
565 | |||
566 | if (psb_intel_output->ddc_bus) | ||
567 | psb_intel_i2c_destroy(psb_intel_output->ddc_bus); | ||
568 | drm_sysfs_connector_remove(connector); | ||
569 | drm_connector_cleanup(connector); | ||
570 | kfree(connector); | ||
571 | } | ||
572 | |||
573 | int psb_intel_lvds_set_property(struct drm_connector *connector, | ||
574 | struct drm_property *property, | ||
575 | uint64_t value) | ||
576 | { | ||
577 | struct drm_encoder *encoder = connector->encoder; | ||
578 | |||
579 | if (!encoder) | ||
580 | return -1; | ||
581 | |||
582 | if (!strcmp(property->name, "scaling mode")) { | ||
583 | struct psb_intel_crtc *crtc = | ||
584 | to_psb_intel_crtc(encoder->crtc); | ||
585 | uint64_t curval; | ||
586 | |||
587 | if (!crtc) | ||
588 | goto set_prop_error; | ||
589 | |||
590 | switch (value) { | ||
591 | case DRM_MODE_SCALE_FULLSCREEN: | ||
592 | break; | ||
593 | case DRM_MODE_SCALE_NO_SCALE: | ||
594 | break; | ||
595 | case DRM_MODE_SCALE_ASPECT: | ||
596 | break; | ||
597 | default: | ||
598 | goto set_prop_error; | ||
599 | } | ||
600 | |||
601 | if (drm_connector_property_get_value(connector, | ||
602 | property, | ||
603 | &curval)) | ||
604 | goto set_prop_error; | ||
605 | |||
606 | if (curval == value) | ||
607 | goto set_prop_done; | ||
608 | |||
609 | if (drm_connector_property_set_value(connector, | ||
610 | property, | ||
611 | value)) | ||
612 | goto set_prop_error; | ||
613 | |||
614 | if (crtc->saved_mode.hdisplay != 0 && | ||
615 | crtc->saved_mode.vdisplay != 0) { | ||
616 | if (!drm_crtc_helper_set_mode(encoder->crtc, | ||
617 | &crtc->saved_mode, | ||
618 | encoder->crtc->x, | ||
619 | encoder->crtc->y, | ||
620 | encoder->crtc->fb)) | ||
621 | goto set_prop_error; | ||
622 | } | ||
623 | } else if (!strcmp(property->name, "backlight")) { | ||
624 | if (drm_connector_property_set_value(connector, | ||
625 | property, | ||
626 | value)) | ||
627 | goto set_prop_error; | ||
628 | else { | ||
629 | #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE | ||
630 | struct drm_psb_private *devp = | ||
631 | encoder->dev->dev_private; | ||
632 | struct backlight_device *bd = devp->backlight_device; | ||
633 | if (bd) { | ||
634 | bd->props.brightness = value; | ||
635 | backlight_update_status(bd); | ||
636 | } | ||
637 | #endif | ||
638 | } | ||
639 | } else if (!strcmp(property->name, "DPMS")) { | ||
640 | struct drm_encoder_helper_funcs *hfuncs | ||
641 | = encoder->helper_private; | ||
642 | hfuncs->dpms(encoder, value); | ||
643 | } | ||
644 | |||
645 | set_prop_done: | ||
646 | return 0; | ||
647 | set_prop_error: | ||
648 | return -1; | ||
649 | } | ||
650 | |||
651 | static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = { | ||
652 | .dpms = psb_intel_lvds_encoder_dpms, | ||
653 | .mode_fixup = psb_intel_lvds_mode_fixup, | ||
654 | .prepare = psb_intel_lvds_prepare, | ||
655 | .mode_set = psb_intel_lvds_mode_set, | ||
656 | .commit = psb_intel_lvds_commit, | ||
657 | }; | ||
658 | |||
659 | const struct drm_connector_helper_funcs | ||
660 | psb_intel_lvds_connector_helper_funcs = { | ||
661 | .get_modes = psb_intel_lvds_get_modes, | ||
662 | .mode_valid = psb_intel_lvds_mode_valid, | ||
663 | .best_encoder = psb_intel_best_encoder, | ||
664 | }; | ||
665 | |||
666 | const struct drm_connector_funcs psb_intel_lvds_connector_funcs = { | ||
667 | .dpms = drm_helper_connector_dpms, | ||
668 | .save = psb_intel_lvds_save, | ||
669 | .restore = psb_intel_lvds_restore, | ||
670 | .detect = psb_intel_lvds_detect, | ||
671 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
672 | .set_property = psb_intel_lvds_set_property, | ||
673 | .destroy = psb_intel_lvds_destroy, | ||
674 | }; | ||
675 | |||
676 | |||
677 | static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder) | ||
678 | { | ||
679 | drm_encoder_cleanup(encoder); | ||
680 | } | ||
681 | |||
682 | const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = { | ||
683 | .destroy = psb_intel_lvds_enc_destroy, | ||
684 | }; | ||
685 | |||
686 | |||
687 | |||
688 | /** | ||
689 | * psb_intel_lvds_init - setup LVDS connectors on this device | ||
690 | * @dev: drm device | ||
691 | * | ||
692 | * Create the connector, register the LVDS DDC bus, and try to figure out what | ||
693 | * modes we can display on the LVDS panel (if present). | ||
694 | */ | ||
695 | void psb_intel_lvds_init(struct drm_device *dev, | ||
696 | struct psb_intel_mode_device *mode_dev) | ||
697 | { | ||
698 | struct psb_intel_output *psb_intel_output; | ||
699 | struct psb_intel_lvds_priv *lvds_priv; | ||
700 | struct drm_connector *connector; | ||
701 | struct drm_encoder *encoder; | ||
702 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | ||
703 | struct drm_crtc *crtc; | ||
704 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
705 | u32 lvds; | ||
706 | int pipe; | ||
707 | |||
708 | psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL); | ||
709 | if (!psb_intel_output) | ||
710 | return; | ||
711 | |||
712 | lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL); | ||
713 | if (!lvds_priv) { | ||
714 | kfree(psb_intel_output); | ||
715 | dev_err(dev->dev, "LVDS private allocation error\n"); | ||
716 | return; | ||
717 | } | ||
718 | |||
719 | psb_intel_output->dev_priv = lvds_priv; | ||
720 | psb_intel_output->mode_dev = mode_dev; | ||
721 | |||
722 | connector = &psb_intel_output->base; | ||
723 | encoder = &psb_intel_output->enc; | ||
724 | drm_connector_init(dev, &psb_intel_output->base, | ||
725 | &psb_intel_lvds_connector_funcs, | ||
726 | DRM_MODE_CONNECTOR_LVDS); | ||
727 | |||
728 | drm_encoder_init(dev, &psb_intel_output->enc, | ||
729 | &psb_intel_lvds_enc_funcs, | ||
730 | DRM_MODE_ENCODER_LVDS); | ||
731 | |||
732 | drm_mode_connector_attach_encoder(&psb_intel_output->base, | ||
733 | &psb_intel_output->enc); | ||
734 | psb_intel_output->type = INTEL_OUTPUT_LVDS; | ||
735 | |||
736 | drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs); | ||
737 | drm_connector_helper_add(connector, | ||
738 | &psb_intel_lvds_connector_helper_funcs); | ||
739 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | ||
740 | connector->interlace_allowed = false; | ||
741 | connector->doublescan_allowed = false; | ||
742 | |||
743 | /*Attach connector properties*/ | ||
744 | drm_connector_attach_property(connector, | ||
745 | dev->mode_config.scaling_mode_property, | ||
746 | DRM_MODE_SCALE_FULLSCREEN); | ||
747 | drm_connector_attach_property(connector, | ||
748 | dev_priv->backlight_property, | ||
749 | BRIGHTNESS_MAX_LEVEL); | ||
750 | |||
751 | /* | ||
752 | * Set up I2C bus | ||
753 | * FIXME: distroy i2c_bus when exit | ||
754 | */ | ||
755 | psb_intel_output->i2c_bus = psb_intel_i2c_create(dev, | ||
756 | GPIOB, | ||
757 | "LVDSBLC_B"); | ||
758 | if (!psb_intel_output->i2c_bus) { | ||
759 | dev_printk(KERN_ERR, | ||
760 | &dev->pdev->dev, "I2C bus registration failed.\n"); | ||
761 | goto failed_blc_i2c; | ||
762 | } | ||
763 | psb_intel_output->i2c_bus->slave_addr = 0x2C; | ||
764 | dev_priv->lvds_i2c_bus = psb_intel_output->i2c_bus; | ||
765 | |||
766 | /* | ||
767 | * LVDS discovery: | ||
768 | * 1) check for EDID on DDC | ||
769 | * 2) check for VBT data | ||
770 | * 3) check to see if LVDS is already on | ||
771 | * if none of the above, no panel | ||
772 | * 4) make sure lid is open | ||
773 | * if closed, act like it's not there for now | ||
774 | */ | ||
775 | |||
776 | /* Set up the DDC bus. */ | ||
777 | psb_intel_output->ddc_bus = psb_intel_i2c_create(dev, | ||
778 | GPIOC, | ||
779 | "LVDSDDC_C"); | ||
780 | if (!psb_intel_output->ddc_bus) { | ||
781 | dev_printk(KERN_ERR, &dev->pdev->dev, | ||
782 | "DDC bus registration " "failed.\n"); | ||
783 | goto failed_ddc; | ||
784 | } | ||
785 | |||
786 | /* | ||
787 | * Attempt to get the fixed panel mode from DDC. Assume that the | ||
788 | * preferred mode is the right one. | ||
789 | */ | ||
790 | psb_intel_ddc_get_modes(psb_intel_output); | ||
791 | list_for_each_entry(scan, &connector->probed_modes, head) { | ||
792 | if (scan->type & DRM_MODE_TYPE_PREFERRED) { | ||
793 | mode_dev->panel_fixed_mode = | ||
794 | drm_mode_duplicate(dev, scan); | ||
795 | goto out; /* FIXME: check for quirks */ | ||
796 | } | ||
797 | } | ||
798 | |||
799 | /* Failed to get EDID, what about VBT? do we need this? */ | ||
800 | if (mode_dev->vbt_mode) | ||
801 | mode_dev->panel_fixed_mode = | ||
802 | drm_mode_duplicate(dev, mode_dev->vbt_mode); | ||
803 | |||
804 | if (!mode_dev->panel_fixed_mode) | ||
805 | if (dev_priv->lfp_lvds_vbt_mode) | ||
806 | mode_dev->panel_fixed_mode = | ||
807 | drm_mode_duplicate(dev, | ||
808 | dev_priv->lfp_lvds_vbt_mode); | ||
809 | |||
810 | /* | ||
811 | * If we didn't get EDID, try checking if the panel is already turned | ||
812 | * on. If so, assume that whatever is currently programmed is the | ||
813 | * correct mode. | ||
814 | */ | ||
815 | lvds = REG_READ(LVDS); | ||
816 | pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0; | ||
817 | crtc = psb_intel_get_crtc_from_pipe(dev, pipe); | ||
818 | |||
819 | if (crtc && (lvds & LVDS_PORT_EN)) { | ||
820 | mode_dev->panel_fixed_mode = | ||
821 | psb_intel_crtc_mode_get(dev, crtc); | ||
822 | if (mode_dev->panel_fixed_mode) { | ||
823 | mode_dev->panel_fixed_mode->type |= | ||
824 | DRM_MODE_TYPE_PREFERRED; | ||
825 | goto out; /* FIXME: check for quirks */ | ||
826 | } | ||
827 | } | ||
828 | |||
829 | /* If we still don't have a mode after all that, give up. */ | ||
830 | if (!mode_dev->panel_fixed_mode) { | ||
831 | dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n"); | ||
832 | goto failed_find; | ||
833 | } | ||
834 | |||
835 | /* | ||
836 | * Blacklist machines with BIOSes that list an LVDS panel without | ||
837 | * actually having one. | ||
838 | */ | ||
839 | out: | ||
840 | drm_sysfs_connector_add(connector); | ||
841 | return; | ||
842 | |||
843 | failed_find: | ||
844 | if (psb_intel_output->ddc_bus) | ||
845 | psb_intel_i2c_destroy(psb_intel_output->ddc_bus); | ||
846 | failed_ddc: | ||
847 | if (psb_intel_output->i2c_bus) | ||
848 | psb_intel_i2c_destroy(psb_intel_output->i2c_bus); | ||
849 | failed_blc_i2c: | ||
850 | drm_encoder_cleanup(encoder); | ||
851 | drm_connector_cleanup(connector); | ||
852 | kfree(connector); | ||
853 | } | ||
854 | |||
diff --git a/drivers/staging/gma500/psb_intel_modes.c b/drivers/staging/gma500/psb_intel_modes.c deleted file mode 100644 index bde1aff96190..000000000000 --- a/drivers/staging/gma500/psb_intel_modes.c +++ /dev/null | |||
@@ -1,77 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2007 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 | * Authers: Jesse Barnes <jesse.barnes@intel.com> | ||
18 | */ | ||
19 | |||
20 | #include <linux/i2c.h> | ||
21 | #include <linux/fb.h> | ||
22 | #include <drm/drmP.h> | ||
23 | #include "psb_intel_drv.h" | ||
24 | |||
25 | /** | ||
26 | * psb_intel_ddc_probe | ||
27 | * | ||
28 | */ | ||
29 | bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output) | ||
30 | { | ||
31 | u8 out_buf[] = { 0x0, 0x0 }; | ||
32 | u8 buf[2]; | ||
33 | int ret; | ||
34 | struct i2c_msg msgs[] = { | ||
35 | { | ||
36 | .addr = 0x50, | ||
37 | .flags = 0, | ||
38 | .len = 1, | ||
39 | .buf = out_buf, | ||
40 | }, | ||
41 | { | ||
42 | .addr = 0x50, | ||
43 | .flags = I2C_M_RD, | ||
44 | .len = 1, | ||
45 | .buf = buf, | ||
46 | } | ||
47 | }; | ||
48 | |||
49 | ret = i2c_transfer(&psb_intel_output->ddc_bus->adapter, msgs, 2); | ||
50 | if (ret == 2) | ||
51 | return true; | ||
52 | |||
53 | return false; | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * psb_intel_ddc_get_modes - get modelist from monitor | ||
58 | * @connector: DRM connector device to use | ||
59 | * | ||
60 | * Fetch the EDID information from @connector using the DDC bus. | ||
61 | */ | ||
62 | int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output) | ||
63 | { | ||
64 | struct edid *edid; | ||
65 | int ret = 0; | ||
66 | |||
67 | edid = | ||
68 | drm_get_edid(&psb_intel_output->base, | ||
69 | &psb_intel_output->ddc_bus->adapter); | ||
70 | if (edid) { | ||
71 | drm_mode_connector_update_edid_property(&psb_intel_output-> | ||
72 | base, edid); | ||
73 | ret = drm_add_edid_modes(&psb_intel_output->base, edid); | ||
74 | kfree(edid); | ||
75 | } | ||
76 | return ret; | ||
77 | } | ||
diff --git a/drivers/staging/gma500/psb_intel_reg.h b/drivers/staging/gma500/psb_intel_reg.h deleted file mode 100644 index 1ac16aa791c9..000000000000 --- a/drivers/staging/gma500/psb_intel_reg.h +++ /dev/null | |||
@@ -1,1235 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2009, 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 | #ifndef __PSB_INTEL_REG_H__ | ||
18 | #define __PSB_INTEL_REG_H__ | ||
19 | |||
20 | #define BLC_PWM_CTL 0x61254 | ||
21 | #define BLC_PWM_CTL2 0x61250 | ||
22 | #define BLC_PWM_CTL_C 0x62254 | ||
23 | #define BLC_PWM_CTL2_C 0x62250 | ||
24 | #define BACKLIGHT_MODULATION_FREQ_SHIFT (17) | ||
25 | /* | ||
26 | * This is the most significant 15 bits of the number of backlight cycles in a | ||
27 | * complete cycle of the modulated backlight control. | ||
28 | * | ||
29 | * The actual value is this field multiplied by two. | ||
30 | */ | ||
31 | #define BACKLIGHT_MODULATION_FREQ_MASK (0x7fff << 17) | ||
32 | #define BLM_LEGACY_MODE (1 << 16) | ||
33 | /* | ||
34 | * This is the number of cycles out of the backlight modulation cycle for which | ||
35 | * the backlight is on. | ||
36 | * | ||
37 | * This field must be no greater than the number of cycles in the complete | ||
38 | * backlight modulation cycle. | ||
39 | */ | ||
40 | #define BACKLIGHT_DUTY_CYCLE_SHIFT (0) | ||
41 | #define BACKLIGHT_DUTY_CYCLE_MASK (0xffff) | ||
42 | |||
43 | #define I915_GCFGC 0xf0 | ||
44 | #define I915_LOW_FREQUENCY_ENABLE (1 << 7) | ||
45 | #define I915_DISPLAY_CLOCK_190_200_MHZ (0 << 4) | ||
46 | #define I915_DISPLAY_CLOCK_333_MHZ (4 << 4) | ||
47 | #define I915_DISPLAY_CLOCK_MASK (7 << 4) | ||
48 | |||
49 | #define I855_HPLLCC 0xc0 | ||
50 | #define I855_CLOCK_CONTROL_MASK (3 << 0) | ||
51 | #define I855_CLOCK_133_200 (0 << 0) | ||
52 | #define I855_CLOCK_100_200 (1 << 0) | ||
53 | #define I855_CLOCK_100_133 (2 << 0) | ||
54 | #define I855_CLOCK_166_250 (3 << 0) | ||
55 | |||
56 | /* I830 CRTC registers */ | ||
57 | #define HTOTAL_A 0x60000 | ||
58 | #define HBLANK_A 0x60004 | ||
59 | #define HSYNC_A 0x60008 | ||
60 | #define VTOTAL_A 0x6000c | ||
61 | #define VBLANK_A 0x60010 | ||
62 | #define VSYNC_A 0x60014 | ||
63 | #define PIPEASRC 0x6001c | ||
64 | #define BCLRPAT_A 0x60020 | ||
65 | #define VSYNCSHIFT_A 0x60028 | ||
66 | |||
67 | #define HTOTAL_B 0x61000 | ||
68 | #define HBLANK_B 0x61004 | ||
69 | #define HSYNC_B 0x61008 | ||
70 | #define VTOTAL_B 0x6100c | ||
71 | #define VBLANK_B 0x61010 | ||
72 | #define VSYNC_B 0x61014 | ||
73 | #define PIPEBSRC 0x6101c | ||
74 | #define BCLRPAT_B 0x61020 | ||
75 | #define VSYNCSHIFT_B 0x61028 | ||
76 | |||
77 | #define HTOTAL_C 0x62000 | ||
78 | #define HBLANK_C 0x62004 | ||
79 | #define HSYNC_C 0x62008 | ||
80 | #define VTOTAL_C 0x6200c | ||
81 | #define VBLANK_C 0x62010 | ||
82 | #define VSYNC_C 0x62014 | ||
83 | #define PIPECSRC 0x6201c | ||
84 | #define BCLRPAT_C 0x62020 | ||
85 | #define VSYNCSHIFT_C 0x62028 | ||
86 | |||
87 | #define PP_STATUS 0x61200 | ||
88 | # define PP_ON (1 << 31) | ||
89 | /* | ||
90 | * Indicates that all dependencies of the panel are on: | ||
91 | * | ||
92 | * - PLL enabled | ||
93 | * - pipe enabled | ||
94 | * - LVDS/DVOB/DVOC on | ||
95 | */ | ||
96 | #define PP_READY (1 << 30) | ||
97 | #define PP_SEQUENCE_NONE (0 << 28) | ||
98 | #define PP_SEQUENCE_ON (1 << 28) | ||
99 | #define PP_SEQUENCE_OFF (2 << 28) | ||
100 | #define PP_SEQUENCE_MASK 0x30000000 | ||
101 | #define PP_CONTROL 0x61204 | ||
102 | #define POWER_TARGET_ON (1 << 0) | ||
103 | |||
104 | #define LVDSPP_ON 0x61208 | ||
105 | #define LVDSPP_OFF 0x6120c | ||
106 | #define PP_CYCLE 0x61210 | ||
107 | |||
108 | #define PFIT_CONTROL 0x61230 | ||
109 | #define PFIT_ENABLE (1 << 31) | ||
110 | #define PFIT_PIPE_MASK (3 << 29) | ||
111 | #define PFIT_PIPE_SHIFT 29 | ||
112 | #define PFIT_SCALING_MODE_PILLARBOX (1 << 27) | ||
113 | #define PFIT_SCALING_MODE_LETTERBOX (3 << 26) | ||
114 | #define VERT_INTERP_DISABLE (0 << 10) | ||
115 | #define VERT_INTERP_BILINEAR (1 << 10) | ||
116 | #define VERT_INTERP_MASK (3 << 10) | ||
117 | #define VERT_AUTO_SCALE (1 << 9) | ||
118 | #define HORIZ_INTERP_DISABLE (0 << 6) | ||
119 | #define HORIZ_INTERP_BILINEAR (1 << 6) | ||
120 | #define HORIZ_INTERP_MASK (3 << 6) | ||
121 | #define HORIZ_AUTO_SCALE (1 << 5) | ||
122 | #define PANEL_8TO6_DITHER_ENABLE (1 << 3) | ||
123 | |||
124 | #define PFIT_PGM_RATIOS 0x61234 | ||
125 | #define PFIT_VERT_SCALE_MASK 0xfff00000 | ||
126 | #define PFIT_HORIZ_SCALE_MASK 0x0000fff0 | ||
127 | |||
128 | #define PFIT_AUTO_RATIOS 0x61238 | ||
129 | |||
130 | #define DPLL_A 0x06014 | ||
131 | #define DPLL_B 0x06018 | ||
132 | #define DPLL_VCO_ENABLE (1 << 31) | ||
133 | #define DPLL_DVO_HIGH_SPEED (1 << 30) | ||
134 | #define DPLL_SYNCLOCK_ENABLE (1 << 29) | ||
135 | #define DPLL_VGA_MODE_DIS (1 << 28) | ||
136 | #define DPLLB_MODE_DAC_SERIAL (1 << 26) /* i915 */ | ||
137 | #define DPLLB_MODE_LVDS (2 << 26) /* i915 */ | ||
138 | #define DPLL_MODE_MASK (3 << 26) | ||
139 | #define DPLL_DAC_SERIAL_P2_CLOCK_DIV_10 (0 << 24) /* i915 */ | ||
140 | #define DPLL_DAC_SERIAL_P2_CLOCK_DIV_5 (1 << 24) /* i915 */ | ||
141 | #define DPLLB_LVDS_P2_CLOCK_DIV_14 (0 << 24) /* i915 */ | ||
142 | #define DPLLB_LVDS_P2_CLOCK_DIV_7 (1 << 24) /* i915 */ | ||
143 | #define DPLL_P2_CLOCK_DIV_MASK 0x03000000 /* i915 */ | ||
144 | #define DPLL_FPA01_P1_POST_DIV_MASK 0x00ff0000 /* i915 */ | ||
145 | #define DPLL_LOCK (1 << 15) /* CDV */ | ||
146 | |||
147 | /* | ||
148 | * The i830 generation, in DAC/serial mode, defines p1 as two plus this | ||
149 | * bitfield, or just 2 if PLL_P1_DIVIDE_BY_TWO is set. | ||
150 | */ | ||
151 | # define DPLL_FPA01_P1_POST_DIV_MASK_I830 0x001f0000 | ||
152 | /* | ||
153 | * The i830 generation, in LVDS mode, defines P1 as the bit number set within | ||
154 | * this field (only one bit may be set). | ||
155 | */ | ||
156 | #define DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS 0x003f0000 | ||
157 | #define DPLL_FPA01_P1_POST_DIV_SHIFT 16 | ||
158 | #define PLL_P2_DIVIDE_BY_4 (1 << 23) /* i830, required | ||
159 | * in DVO non-gang */ | ||
160 | # define PLL_P1_DIVIDE_BY_TWO (1 << 21) /* i830 */ | ||
161 | #define PLL_REF_INPUT_DREFCLK (0 << 13) | ||
162 | #define PLL_REF_INPUT_TVCLKINA (1 << 13) /* i830 */ | ||
163 | #define PLL_REF_INPUT_TVCLKINBC (2 << 13) /* SDVO | ||
164 | * TVCLKIN */ | ||
165 | #define PLLB_REF_INPUT_SPREADSPECTRUMIN (3 << 13) | ||
166 | #define PLL_REF_INPUT_MASK (3 << 13) | ||
167 | #define PLL_LOAD_PULSE_PHASE_SHIFT 9 | ||
168 | /* | ||
169 | * Parallel to Serial Load Pulse phase selection. | ||
170 | * Selects the phase for the 10X DPLL clock for the PCIe | ||
171 | * digital display port. The range is 4 to 13; 10 or more | ||
172 | * is just a flip delay. The default is 6 | ||
173 | */ | ||
174 | #define PLL_LOAD_PULSE_PHASE_MASK (0xf << PLL_LOAD_PULSE_PHASE_SHIFT) | ||
175 | #define DISPLAY_RATE_SELECT_FPA1 (1 << 8) | ||
176 | |||
177 | /* | ||
178 | * SDVO multiplier for 945G/GM. Not used on 965. | ||
179 | * | ||
180 | * DPLL_MD_UDI_MULTIPLIER_MASK | ||
181 | */ | ||
182 | #define SDVO_MULTIPLIER_MASK 0x000000ff | ||
183 | #define SDVO_MULTIPLIER_SHIFT_HIRES 4 | ||
184 | #define SDVO_MULTIPLIER_SHIFT_VGA 0 | ||
185 | |||
186 | /* | ||
187 | * PLL_MD | ||
188 | */ | ||
189 | /* Pipe A SDVO/UDI clock multiplier/divider register for G965. */ | ||
190 | #define DPLL_A_MD 0x0601c | ||
191 | /* Pipe B SDVO/UDI clock multiplier/divider register for G965. */ | ||
192 | #define DPLL_B_MD 0x06020 | ||
193 | /* | ||
194 | * UDI pixel divider, controlling how many pixels are stuffed into a packet. | ||
195 | * | ||
196 | * Value is pixels minus 1. Must be set to 1 pixel for SDVO. | ||
197 | */ | ||
198 | #define DPLL_MD_UDI_DIVIDER_MASK 0x3f000000 | ||
199 | #define DPLL_MD_UDI_DIVIDER_SHIFT 24 | ||
200 | /* UDI pixel divider for VGA, same as DPLL_MD_UDI_DIVIDER_MASK. */ | ||
201 | #define DPLL_MD_VGA_UDI_DIVIDER_MASK 0x003f0000 | ||
202 | #define DPLL_MD_VGA_UDI_DIVIDER_SHIFT 16 | ||
203 | /* | ||
204 | * SDVO/UDI pixel multiplier. | ||
205 | * | ||
206 | * SDVO requires that the bus clock rate be between 1 and 2 Ghz, and the bus | ||
207 | * clock rate is 10 times the DPLL clock. At low resolution/refresh rate | ||
208 | * modes, the bus rate would be below the limits, so SDVO allows for stuffing | ||
209 | * dummy bytes in the datastream at an increased clock rate, with both sides of | ||
210 | * the link knowing how many bytes are fill. | ||
211 | * | ||
212 | * So, for a mode with a dotclock of 65Mhz, we would want to double the clock | ||
213 | * rate to 130Mhz to get a bus rate of 1.30Ghz. The DPLL clock rate would be | ||
214 | * set to 130Mhz, and the SDVO multiplier set to 2x in this register and | ||
215 | * through an SDVO command. | ||
216 | * | ||
217 | * This register field has values of multiplication factor minus 1, with | ||
218 | * a maximum multiplier of 5 for SDVO. | ||
219 | */ | ||
220 | #define DPLL_MD_UDI_MULTIPLIER_MASK 0x00003f00 | ||
221 | #define DPLL_MD_UDI_MULTIPLIER_SHIFT 8 | ||
222 | /* | ||
223 | * SDVO/UDI pixel multiplier for VGA, same as DPLL_MD_UDI_MULTIPLIER_MASK. | ||
224 | * This best be set to the default value (3) or the CRT won't work. No, | ||
225 | * I don't entirely understand what this does... | ||
226 | */ | ||
227 | #define DPLL_MD_VGA_UDI_MULTIPLIER_MASK 0x0000003f | ||
228 | #define DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT 0 | ||
229 | |||
230 | #define DPLL_TEST 0x606c | ||
231 | #define DPLLB_TEST_SDVO_DIV_1 (0 << 22) | ||
232 | #define DPLLB_TEST_SDVO_DIV_2 (1 << 22) | ||
233 | #define DPLLB_TEST_SDVO_DIV_4 (2 << 22) | ||
234 | #define DPLLB_TEST_SDVO_DIV_MASK (3 << 22) | ||
235 | #define DPLLB_TEST_N_BYPASS (1 << 19) | ||
236 | #define DPLLB_TEST_M_BYPASS (1 << 18) | ||
237 | #define DPLLB_INPUT_BUFFER_ENABLE (1 << 16) | ||
238 | #define DPLLA_TEST_N_BYPASS (1 << 3) | ||
239 | #define DPLLA_TEST_M_BYPASS (1 << 2) | ||
240 | #define DPLLA_INPUT_BUFFER_ENABLE (1 << 0) | ||
241 | |||
242 | #define ADPA 0x61100 | ||
243 | #define ADPA_DAC_ENABLE (1 << 31) | ||
244 | #define ADPA_DAC_DISABLE 0 | ||
245 | #define ADPA_PIPE_SELECT_MASK (1 << 30) | ||
246 | #define ADPA_PIPE_A_SELECT 0 | ||
247 | #define ADPA_PIPE_B_SELECT (1 << 30) | ||
248 | #define ADPA_USE_VGA_HVPOLARITY (1 << 15) | ||
249 | #define ADPA_SETS_HVPOLARITY 0 | ||
250 | #define ADPA_VSYNC_CNTL_DISABLE (1 << 11) | ||
251 | #define ADPA_VSYNC_CNTL_ENABLE 0 | ||
252 | #define ADPA_HSYNC_CNTL_DISABLE (1 << 10) | ||
253 | #define ADPA_HSYNC_CNTL_ENABLE 0 | ||
254 | #define ADPA_VSYNC_ACTIVE_HIGH (1 << 4) | ||
255 | #define ADPA_VSYNC_ACTIVE_LOW 0 | ||
256 | #define ADPA_HSYNC_ACTIVE_HIGH (1 << 3) | ||
257 | #define ADPA_HSYNC_ACTIVE_LOW 0 | ||
258 | |||
259 | #define FPA0 0x06040 | ||
260 | #define FPA1 0x06044 | ||
261 | #define FPB0 0x06048 | ||
262 | #define FPB1 0x0604c | ||
263 | #define FP_N_DIV_MASK 0x003f0000 | ||
264 | #define FP_N_DIV_SHIFT 16 | ||
265 | #define FP_M1_DIV_MASK 0x00003f00 | ||
266 | #define FP_M1_DIV_SHIFT 8 | ||
267 | #define FP_M2_DIV_MASK 0x0000003f | ||
268 | #define FP_M2_DIV_SHIFT 0 | ||
269 | |||
270 | #define PORT_HOTPLUG_EN 0x61110 | ||
271 | #define SDVOB_HOTPLUG_INT_EN (1 << 26) | ||
272 | #define SDVOC_HOTPLUG_INT_EN (1 << 25) | ||
273 | #define TV_HOTPLUG_INT_EN (1 << 18) | ||
274 | #define CRT_HOTPLUG_INT_EN (1 << 9) | ||
275 | #define CRT_HOTPLUG_FORCE_DETECT (1 << 3) | ||
276 | /* CDV.. */ | ||
277 | #define CRT_HOTPLUG_ACTIVATION_PERIOD_64 (1 << 8) | ||
278 | #define CRT_HOTPLUG_DAC_ON_TIME_2M (0 << 7) | ||
279 | #define CRT_HOTPLUG_DAC_ON_TIME_4M (1 << 7) | ||
280 | #define CRT_HOTPLUG_VOLTAGE_COMPARE_40 (0 << 5) | ||
281 | #define CRT_HOTPLUG_VOLTAGE_COMPARE_50 (1 << 5) | ||
282 | #define CRT_HOTPLUG_VOLTAGE_COMPARE_60 (2 << 5) | ||
283 | #define CRT_HOTPLUG_VOLTAGE_COMPARE_70 (3 << 5) | ||
284 | #define CRT_HOTPLUG_VOLTAGE_COMPARE_MASK (3 << 5) | ||
285 | #define CRT_HOTPLUG_DETECT_DELAY_1G (0 << 4) | ||
286 | #define CRT_HOTPLUG_DETECT_DELAY_2G (1 << 4) | ||
287 | #define CRT_HOTPLUG_DETECT_VOLTAGE_325MV (0 << 2) | ||
288 | #define CRT_HOTPLUG_DETECT_VOLTAGE_475MV (1 << 2) | ||
289 | #define CRT_HOTPLUG_DETECT_MASK 0x000000F8 | ||
290 | |||
291 | #define PORT_HOTPLUG_STAT 0x61114 | ||
292 | #define CRT_HOTPLUG_INT_STATUS (1 << 11) | ||
293 | #define TV_HOTPLUG_INT_STATUS (1 << 10) | ||
294 | #define CRT_HOTPLUG_MONITOR_MASK (3 << 8) | ||
295 | #define CRT_HOTPLUG_MONITOR_COLOR (3 << 8) | ||
296 | #define CRT_HOTPLUG_MONITOR_MONO (2 << 8) | ||
297 | #define CRT_HOTPLUG_MONITOR_NONE (0 << 8) | ||
298 | #define SDVOC_HOTPLUG_INT_STATUS (1 << 7) | ||
299 | #define SDVOB_HOTPLUG_INT_STATUS (1 << 6) | ||
300 | |||
301 | #define SDVOB 0x61140 | ||
302 | #define SDVOC 0x61160 | ||
303 | #define SDVO_ENABLE (1 << 31) | ||
304 | #define SDVO_PIPE_B_SELECT (1 << 30) | ||
305 | #define SDVO_STALL_SELECT (1 << 29) | ||
306 | #define SDVO_INTERRUPT_ENABLE (1 << 26) | ||
307 | |||
308 | /** | ||
309 | * 915G/GM SDVO pixel multiplier. | ||
310 | * | ||
311 | * Programmed value is multiplier - 1, up to 5x. | ||
312 | * | ||
313 | * DPLL_MD_UDI_MULTIPLIER_MASK | ||
314 | */ | ||
315 | #define SDVO_PORT_MULTIPLY_MASK (7 << 23) | ||
316 | #define SDVO_PORT_MULTIPLY_SHIFT 23 | ||
317 | #define SDVO_PHASE_SELECT_MASK (15 << 19) | ||
318 | #define SDVO_PHASE_SELECT_DEFAULT (6 << 19) | ||
319 | #define SDVO_CLOCK_OUTPUT_INVERT (1 << 18) | ||
320 | #define SDVOC_GANG_MODE (1 << 16) | ||
321 | #define SDVO_BORDER_ENABLE (1 << 7) | ||
322 | #define SDVOB_PCIE_CONCURRENCY (1 << 3) | ||
323 | #define SDVO_DETECTED (1 << 2) | ||
324 | /* Bits to be preserved when writing */ | ||
325 | #define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) | ||
326 | #define SDVOC_PRESERVE_MASK (1 << 17) | ||
327 | |||
328 | /* | ||
329 | * This register controls the LVDS output enable, pipe selection, and data | ||
330 | * format selection. | ||
331 | * | ||
332 | * All of the clock/data pairs are force powered down by power sequencing. | ||
333 | */ | ||
334 | #define LVDS 0x61180 | ||
335 | /* | ||
336 | * Enables the LVDS port. This bit must be set before DPLLs are enabled, as | ||
337 | * the DPLL semantics change when the LVDS is assigned to that pipe. | ||
338 | */ | ||
339 | #define LVDS_PORT_EN (1 << 31) | ||
340 | /* Selects pipe B for LVDS data. Must be set on pre-965. */ | ||
341 | #define LVDS_PIPEB_SELECT (1 << 30) | ||
342 | |||
343 | /* Turns on border drawing to allow centered display. */ | ||
344 | #define LVDS_BORDER_EN (1 << 15) | ||
345 | |||
346 | /* | ||
347 | * Enables the A0-A2 data pairs and CLKA, containing 18 bits of color data per | ||
348 | * pixel. | ||
349 | */ | ||
350 | #define LVDS_A0A2_CLKA_POWER_MASK (3 << 8) | ||
351 | #define LVDS_A0A2_CLKA_POWER_DOWN (0 << 8) | ||
352 | #define LVDS_A0A2_CLKA_POWER_UP (3 << 8) | ||
353 | /* | ||
354 | * Controls the A3 data pair, which contains the additional LSBs for 24 bit | ||
355 | * mode. Only enabled if LVDS_A0A2_CLKA_POWER_UP also indicates it should be | ||
356 | * on. | ||
357 | */ | ||
358 | #define LVDS_A3_POWER_MASK (3 << 6) | ||
359 | #define LVDS_A3_POWER_DOWN (0 << 6) | ||
360 | #define LVDS_A3_POWER_UP (3 << 6) | ||
361 | /* | ||
362 | * Controls the CLKB pair. This should only be set when LVDS_B0B3_POWER_UP | ||
363 | * is set. | ||
364 | */ | ||
365 | #define LVDS_CLKB_POWER_MASK (3 << 4) | ||
366 | #define LVDS_CLKB_POWER_DOWN (0 << 4) | ||
367 | #define LVDS_CLKB_POWER_UP (3 << 4) | ||
368 | /* | ||
369 | * Controls the B0-B3 data pairs. This must be set to match the DPLL p2 | ||
370 | * setting for whether we are in dual-channel mode. The B3 pair will | ||
371 | * additionally only be powered up when LVDS_A3_POWER_UP is set. | ||
372 | */ | ||
373 | #define LVDS_B0B3_POWER_MASK (3 << 2) | ||
374 | #define LVDS_B0B3_POWER_DOWN (0 << 2) | ||
375 | #define LVDS_B0B3_POWER_UP (3 << 2) | ||
376 | |||
377 | #define PIPEACONF 0x70008 | ||
378 | #define PIPEACONF_ENABLE (1 << 31) | ||
379 | #define PIPEACONF_DISABLE 0 | ||
380 | #define PIPEACONF_DOUBLE_WIDE (1 << 30) | ||
381 | #define PIPECONF_ACTIVE (1 << 30) | ||
382 | #define I965_PIPECONF_ACTIVE (1 << 30) | ||
383 | #define PIPECONF_DSIPLL_LOCK (1 << 29) | ||
384 | #define PIPEACONF_SINGLE_WIDE 0 | ||
385 | #define PIPEACONF_PIPE_UNLOCKED 0 | ||
386 | #define PIPEACONF_DSR (1 << 26) | ||
387 | #define PIPEACONF_PIPE_LOCKED (1 << 25) | ||
388 | #define PIPEACONF_PALETTE 0 | ||
389 | #define PIPECONF_FORCE_BORDER (1 << 25) | ||
390 | #define PIPEACONF_GAMMA (1 << 24) | ||
391 | #define PIPECONF_PROGRESSIVE (0 << 21) | ||
392 | #define PIPECONF_INTERLACE_W_FIELD_INDICATION (6 << 21) | ||
393 | #define PIPECONF_INTERLACE_FIELD_0_ONLY (7 << 21) | ||
394 | #define PIPECONF_PLANE_OFF (1 << 19) | ||
395 | #define PIPECONF_CURSOR_OFF (1 << 18) | ||
396 | |||
397 | #define PIPEBCONF 0x71008 | ||
398 | #define PIPEBCONF_ENABLE (1 << 31) | ||
399 | #define PIPEBCONF_DISABLE 0 | ||
400 | #define PIPEBCONF_DOUBLE_WIDE (1 << 30) | ||
401 | #define PIPEBCONF_DISABLE 0 | ||
402 | #define PIPEBCONF_GAMMA (1 << 24) | ||
403 | #define PIPEBCONF_PALETTE 0 | ||
404 | |||
405 | #define PIPECCONF 0x72008 | ||
406 | |||
407 | #define PIPEBGCMAXRED 0x71010 | ||
408 | #define PIPEBGCMAXGREEN 0x71014 | ||
409 | #define PIPEBGCMAXBLUE 0x71018 | ||
410 | |||
411 | #define PIPEASTAT 0x70024 | ||
412 | #define PIPEBSTAT 0x71024 | ||
413 | #define PIPECSTAT 0x72024 | ||
414 | #define PIPE_VBLANK_INTERRUPT_STATUS (1UL << 1) | ||
415 | #define PIPE_START_VBLANK_INTERRUPT_STATUS (1UL << 2) | ||
416 | #define PIPE_VBLANK_CLEAR (1 << 1) | ||
417 | #define PIPE_VBLANK_STATUS (1 << 1) | ||
418 | #define PIPE_TE_STATUS (1UL << 6) | ||
419 | #define PIPE_DPST_EVENT_STATUS (1UL << 7) | ||
420 | #define PIPE_VSYNC_CLEAR (1UL << 9) | ||
421 | #define PIPE_VSYNC_STATUS (1UL << 9) | ||
422 | #define PIPE_HDMI_AUDIO_UNDERRUN_STATUS (1UL << 10) | ||
423 | #define PIPE_HDMI_AUDIO_BUFFER_DONE_STATUS (1UL << 11) | ||
424 | #define PIPE_VBLANK_INTERRUPT_ENABLE (1UL << 17) | ||
425 | #define PIPE_START_VBLANK_INTERRUPT_ENABLE (1UL << 18) | ||
426 | #define PIPE_TE_ENABLE (1UL << 22) | ||
427 | #define PIPE_DPST_EVENT_ENABLE (1UL << 23) | ||
428 | #define PIPE_VSYNC_ENABL (1UL << 25) | ||
429 | #define PIPE_HDMI_AUDIO_UNDERRUN (1UL << 26) | ||
430 | #define PIPE_HDMI_AUDIO_BUFFER_DONE (1UL << 27) | ||
431 | #define PIPE_HDMI_AUDIO_INT_MASK (PIPE_HDMI_AUDIO_UNDERRUN | \ | ||
432 | PIPE_HDMI_AUDIO_BUFFER_DONE) | ||
433 | #define PIPE_EVENT_MASK ((1 << 29)|(1 << 28)|(1 << 27)|(1 << 26)|(1 << 24)|(1 << 23)|(1 << 22)|(1 << 21)|(1 << 20)|(1 << 16)) | ||
434 | #define PIPE_VBLANK_MASK ((1 << 25)|(1 << 24)|(1 << 18)|(1 << 17)) | ||
435 | #define HISTOGRAM_INT_CONTROL 0x61268 | ||
436 | #define HISTOGRAM_BIN_DATA 0X61264 | ||
437 | #define HISTOGRAM_LOGIC_CONTROL 0x61260 | ||
438 | #define PWM_CONTROL_LOGIC 0x61250 | ||
439 | #define PIPE_HOTPLUG_INTERRUPT_STATUS (1UL << 10) | ||
440 | #define HISTOGRAM_INTERRUPT_ENABLE (1UL << 31) | ||
441 | #define HISTOGRAM_LOGIC_ENABLE (1UL << 31) | ||
442 | #define PWM_LOGIC_ENABLE (1UL << 31) | ||
443 | #define PWM_PHASEIN_ENABLE (1UL << 25) | ||
444 | #define PWM_PHASEIN_INT_ENABLE (1UL << 24) | ||
445 | #define PWM_PHASEIN_VB_COUNT 0x00001f00 | ||
446 | #define PWM_PHASEIN_INC 0x0000001f | ||
447 | #define HISTOGRAM_INT_CTRL_CLEAR (1UL << 30) | ||
448 | #define DPST_YUV_LUMA_MODE 0 | ||
449 | |||
450 | struct dpst_ie_histogram_control { | ||
451 | union { | ||
452 | uint32_t data; | ||
453 | struct { | ||
454 | uint32_t bin_reg_index:7; | ||
455 | uint32_t reserved:4; | ||
456 | uint32_t bin_reg_func_select:1; | ||
457 | uint32_t sync_to_phase_in:1; | ||
458 | uint32_t alt_enhancement_mode:2; | ||
459 | uint32_t reserved1:1; | ||
460 | uint32_t sync_to_phase_in_count:8; | ||
461 | uint32_t histogram_mode_select:1; | ||
462 | uint32_t reserved2:4; | ||
463 | uint32_t ie_pipe_assignment:1; | ||
464 | uint32_t ie_mode_table_enabled:1; | ||
465 | uint32_t ie_histogram_enable:1; | ||
466 | }; | ||
467 | }; | ||
468 | }; | ||
469 | |||
470 | struct dpst_guardband { | ||
471 | union { | ||
472 | uint32_t data; | ||
473 | struct { | ||
474 | uint32_t guardband:22; | ||
475 | uint32_t guardband_interrupt_delay:8; | ||
476 | uint32_t interrupt_status:1; | ||
477 | uint32_t interrupt_enable:1; | ||
478 | }; | ||
479 | }; | ||
480 | }; | ||
481 | |||
482 | #define PIPEAFRAMEHIGH 0x70040 | ||
483 | #define PIPEAFRAMEPIXEL 0x70044 | ||
484 | #define PIPEBFRAMEHIGH 0x71040 | ||
485 | #define PIPEBFRAMEPIXEL 0x71044 | ||
486 | #define PIPECFRAMEHIGH 0x72040 | ||
487 | #define PIPECFRAMEPIXEL 0x72044 | ||
488 | #define PIPE_FRAME_HIGH_MASK 0x0000ffff | ||
489 | #define PIPE_FRAME_HIGH_SHIFT 0 | ||
490 | #define PIPE_FRAME_LOW_MASK 0xff000000 | ||
491 | #define PIPE_FRAME_LOW_SHIFT 24 | ||
492 | #define PIPE_PIXEL_MASK 0x00ffffff | ||
493 | #define PIPE_PIXEL_SHIFT 0 | ||
494 | |||
495 | #define DSPARB 0x70030 | ||
496 | #define DSPFW1 0x70034 | ||
497 | #define DSPFW2 0x70038 | ||
498 | #define DSPFW3 0x7003c | ||
499 | #define DSPFW4 0x70050 | ||
500 | #define DSPFW5 0x70054 | ||
501 | #define DSPFW6 0x70058 | ||
502 | #define DSPCHICKENBIT 0x70400 | ||
503 | #define DSPACNTR 0x70180 | ||
504 | #define DSPBCNTR 0x71180 | ||
505 | #define DSPCCNTR 0x72180 | ||
506 | #define DISPLAY_PLANE_ENABLE (1 << 31) | ||
507 | #define DISPLAY_PLANE_DISABLE 0 | ||
508 | #define DISPPLANE_GAMMA_ENABLE (1 << 30) | ||
509 | #define DISPPLANE_GAMMA_DISABLE 0 | ||
510 | #define DISPPLANE_PIXFORMAT_MASK (0xf << 26) | ||
511 | #define DISPPLANE_8BPP (0x2 << 26) | ||
512 | #define DISPPLANE_15_16BPP (0x4 << 26) | ||
513 | #define DISPPLANE_16BPP (0x5 << 26) | ||
514 | #define DISPPLANE_32BPP_NO_ALPHA (0x6 << 26) | ||
515 | #define DISPPLANE_32BPP (0x7 << 26) | ||
516 | #define DISPPLANE_STEREO_ENABLE (1 << 25) | ||
517 | #define DISPPLANE_STEREO_DISABLE 0 | ||
518 | #define DISPPLANE_SEL_PIPE_MASK (1 << 24) | ||
519 | #define DISPPLANE_SEL_PIPE_POS 24 | ||
520 | #define DISPPLANE_SEL_PIPE_A 0 | ||
521 | #define DISPPLANE_SEL_PIPE_B (1 << 24) | ||
522 | #define DISPPLANE_SRC_KEY_ENABLE (1 << 22) | ||
523 | #define DISPPLANE_SRC_KEY_DISABLE 0 | ||
524 | #define DISPPLANE_LINE_DOUBLE (1 << 20) | ||
525 | #define DISPPLANE_NO_LINE_DOUBLE 0 | ||
526 | #define DISPPLANE_STEREO_POLARITY_FIRST 0 | ||
527 | #define DISPPLANE_STEREO_POLARITY_SECOND (1 << 18) | ||
528 | /* plane B only */ | ||
529 | #define DISPPLANE_ALPHA_TRANS_ENABLE (1 << 15) | ||
530 | #define DISPPLANE_ALPHA_TRANS_DISABLE 0 | ||
531 | #define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0 | ||
532 | #define DISPPLANE_SPRITE_ABOVE_OVERLAY (1) | ||
533 | #define DISPPLANE_BOTTOM (4) | ||
534 | |||
535 | #define DSPABASE 0x70184 | ||
536 | #define DSPALINOFF 0x70184 | ||
537 | #define DSPASTRIDE 0x70188 | ||
538 | |||
539 | #define DSPBBASE 0x71184 | ||
540 | #define DSPBLINOFF 0X71184 | ||
541 | #define DSPBADDR DSPBBASE | ||
542 | #define DSPBSTRIDE 0x71188 | ||
543 | |||
544 | #define DSPCBASE 0x72184 | ||
545 | #define DSPCLINOFF 0x72184 | ||
546 | #define DSPCSTRIDE 0x72188 | ||
547 | |||
548 | #define DSPAKEYVAL 0x70194 | ||
549 | #define DSPAKEYMASK 0x70198 | ||
550 | |||
551 | #define DSPAPOS 0x7018C /* reserved */ | ||
552 | #define DSPASIZE 0x70190 | ||
553 | #define DSPBPOS 0x7118C | ||
554 | #define DSPBSIZE 0x71190 | ||
555 | #define DSPCPOS 0x7218C | ||
556 | #define DSPCSIZE 0x72190 | ||
557 | |||
558 | #define DSPASURF 0x7019C | ||
559 | #define DSPATILEOFF 0x701A4 | ||
560 | |||
561 | #define DSPBSURF 0x7119C | ||
562 | #define DSPBTILEOFF 0x711A4 | ||
563 | |||
564 | #define DSPCSURF 0x7219C | ||
565 | #define DSPCTILEOFF 0x721A4 | ||
566 | #define DSPCKEYMAXVAL 0x721A0 | ||
567 | #define DSPCKEYMINVAL 0x72194 | ||
568 | #define DSPCKEYMSK 0x72198 | ||
569 | |||
570 | #define VGACNTRL 0x71400 | ||
571 | #define VGA_DISP_DISABLE (1 << 31) | ||
572 | #define VGA_2X_MODE (1 << 30) | ||
573 | #define VGA_PIPE_B_SELECT (1 << 29) | ||
574 | |||
575 | /* | ||
576 | * Overlay registers | ||
577 | */ | ||
578 | #define OV_C_OFFSET 0x08000 | ||
579 | #define OV_OVADD 0x30000 | ||
580 | #define OV_DOVASTA 0x30008 | ||
581 | # define OV_PIPE_SELECT ((1 << 6)|(1 << 7)) | ||
582 | # define OV_PIPE_SELECT_POS 6 | ||
583 | # define OV_PIPE_A 0 | ||
584 | # define OV_PIPE_C 1 | ||
585 | #define OV_OGAMC5 0x30010 | ||
586 | #define OV_OGAMC4 0x30014 | ||
587 | #define OV_OGAMC3 0x30018 | ||
588 | #define OV_OGAMC2 0x3001C | ||
589 | #define OV_OGAMC1 0x30020 | ||
590 | #define OV_OGAMC0 0x30024 | ||
591 | #define OVC_OVADD 0x38000 | ||
592 | #define OVC_DOVCSTA 0x38008 | ||
593 | #define OVC_OGAMC5 0x38010 | ||
594 | #define OVC_OGAMC4 0x38014 | ||
595 | #define OVC_OGAMC3 0x38018 | ||
596 | #define OVC_OGAMC2 0x3801C | ||
597 | #define OVC_OGAMC1 0x38020 | ||
598 | #define OVC_OGAMC0 0x38024 | ||
599 | |||
600 | /* | ||
601 | * Some BIOS scratch area registers. The 845 (and 830?) store the amount | ||
602 | * of video memory available to the BIOS in SWF1. | ||
603 | */ | ||
604 | #define SWF0 0x71410 | ||
605 | #define SWF1 0x71414 | ||
606 | #define SWF2 0x71418 | ||
607 | #define SWF3 0x7141c | ||
608 | #define SWF4 0x71420 | ||
609 | #define SWF5 0x71424 | ||
610 | #define SWF6 0x71428 | ||
611 | |||
612 | /* | ||
613 | * 855 scratch registers. | ||
614 | */ | ||
615 | #define SWF00 0x70410 | ||
616 | #define SWF01 0x70414 | ||
617 | #define SWF02 0x70418 | ||
618 | #define SWF03 0x7041c | ||
619 | #define SWF04 0x70420 | ||
620 | #define SWF05 0x70424 | ||
621 | #define SWF06 0x70428 | ||
622 | |||
623 | #define SWF10 SWF0 | ||
624 | #define SWF11 SWF1 | ||
625 | #define SWF12 SWF2 | ||
626 | #define SWF13 SWF3 | ||
627 | #define SWF14 SWF4 | ||
628 | #define SWF15 SWF5 | ||
629 | #define SWF16 SWF6 | ||
630 | |||
631 | #define SWF30 0x72414 | ||
632 | #define SWF31 0x72418 | ||
633 | #define SWF32 0x7241c | ||
634 | |||
635 | |||
636 | /* | ||
637 | * Palette registers | ||
638 | */ | ||
639 | #define PALETTE_A 0x0a000 | ||
640 | #define PALETTE_B 0x0a800 | ||
641 | #define PALETTE_C 0x0ac00 | ||
642 | |||
643 | /* Cursor A & B regs */ | ||
644 | #define CURACNTR 0x70080 | ||
645 | #define CURSOR_MODE_DISABLE 0x00 | ||
646 | #define CURSOR_MODE_64_32B_AX 0x07 | ||
647 | #define CURSOR_MODE_64_ARGB_AX ((1 << 5) | CURSOR_MODE_64_32B_AX) | ||
648 | #define MCURSOR_GAMMA_ENABLE (1 << 26) | ||
649 | #define CURABASE 0x70084 | ||
650 | #define CURAPOS 0x70088 | ||
651 | #define CURSOR_POS_MASK 0x007FF | ||
652 | #define CURSOR_POS_SIGN 0x8000 | ||
653 | #define CURSOR_X_SHIFT 0 | ||
654 | #define CURSOR_Y_SHIFT 16 | ||
655 | #define CURBCNTR 0x700c0 | ||
656 | #define CURBBASE 0x700c4 | ||
657 | #define CURBPOS 0x700c8 | ||
658 | #define CURCCNTR 0x700e0 | ||
659 | #define CURCBASE 0x700e4 | ||
660 | #define CURCPOS 0x700e8 | ||
661 | |||
662 | /* | ||
663 | * Interrupt Registers | ||
664 | */ | ||
665 | #define IER 0x020a0 | ||
666 | #define IIR 0x020a4 | ||
667 | #define IMR 0x020a8 | ||
668 | #define ISR 0x020ac | ||
669 | |||
670 | /* | ||
671 | * MOORESTOWN delta registers | ||
672 | */ | ||
673 | #define MRST_DPLL_A 0x0f014 | ||
674 | #define MDFLD_DPLL_B 0x0f018 | ||
675 | #define MDFLD_INPUT_REF_SEL (1 << 14) | ||
676 | #define MDFLD_VCO_SEL (1 << 16) | ||
677 | #define DPLLA_MODE_LVDS (2 << 26) /* mrst */ | ||
678 | #define MDFLD_PLL_LATCHEN (1 << 28) | ||
679 | #define MDFLD_PWR_GATE_EN (1 << 30) | ||
680 | #define MDFLD_P1_MASK (0x1FF << 17) | ||
681 | #define MRST_FPA0 0x0f040 | ||
682 | #define MRST_FPA1 0x0f044 | ||
683 | #define MDFLD_DPLL_DIV0 0x0f048 | ||
684 | #define MDFLD_DPLL_DIV1 0x0f04c | ||
685 | #define MRST_PERF_MODE 0x020f4 | ||
686 | |||
687 | /* | ||
688 | * MEDFIELD HDMI registers | ||
689 | */ | ||
690 | #define HDMIPHYMISCCTL 0x61134 | ||
691 | #define HDMI_PHY_POWER_DOWN 0x7f | ||
692 | #define HDMIB_CONTROL 0x61140 | ||
693 | #define HDMIB_PORT_EN (1 << 31) | ||
694 | #define HDMIB_PIPE_B_SELECT (1 << 30) | ||
695 | #define HDMIB_NULL_PACKET (1 << 9) | ||
696 | #define HDMIB_HDCP_PORT (1 << 5) | ||
697 | |||
698 | /* #define LVDS 0x61180 */ | ||
699 | #define MRST_PANEL_8TO6_DITHER_ENABLE (1 << 25) | ||
700 | #define MRST_PANEL_24_DOT_1_FORMAT (1 << 24) | ||
701 | #define LVDS_A3_POWER_UP_0_OUTPUT (1 << 6) | ||
702 | |||
703 | #define MIPI 0x61190 | ||
704 | #define MIPI_C 0x62190 | ||
705 | #define MIPI_PORT_EN (1 << 31) | ||
706 | /* Turns on border drawing to allow centered display. */ | ||
707 | #define SEL_FLOPPED_HSTX (1 << 23) | ||
708 | #define PASS_FROM_SPHY_TO_AFE (1 << 16) | ||
709 | #define MIPI_BORDER_EN (1 << 15) | ||
710 | #define MIPIA_3LANE_MIPIC_1LANE 0x1 | ||
711 | #define MIPIA_2LANE_MIPIC_2LANE 0x2 | ||
712 | #define TE_TRIGGER_DSI_PROTOCOL (1 << 2) | ||
713 | #define TE_TRIGGER_GPIO_PIN (1 << 3) | ||
714 | #define MIPI_TE_COUNT 0x61194 | ||
715 | |||
716 | /* #define PP_CONTROL 0x61204 */ | ||
717 | #define POWER_DOWN_ON_RESET (1 << 1) | ||
718 | |||
719 | /* #define PFIT_CONTROL 0x61230 */ | ||
720 | #define PFIT_PIPE_SELECT (3 << 29) | ||
721 | #define PFIT_PIPE_SELECT_SHIFT (29) | ||
722 | |||
723 | /* #define BLC_PWM_CTL 0x61254 */ | ||
724 | #define MRST_BACKLIGHT_MODULATION_FREQ_SHIFT (16) | ||
725 | #define MRST_BACKLIGHT_MODULATION_FREQ_MASK (0xffff << 16) | ||
726 | |||
727 | /* #define PIPEACONF 0x70008 */ | ||
728 | #define PIPEACONF_PIPE_STATE (1 << 30) | ||
729 | /* #define DSPACNTR 0x70180 */ | ||
730 | |||
731 | #define MRST_DSPABASE 0x7019c | ||
732 | #define MRST_DSPBBASE 0x7119c | ||
733 | #define MDFLD_DSPCBASE 0x7219c | ||
734 | |||
735 | /* | ||
736 | * Moorestown registers. | ||
737 | */ | ||
738 | |||
739 | /* | ||
740 | * MIPI IP registers | ||
741 | */ | ||
742 | #define MIPIC_REG_OFFSET 0x800 | ||
743 | |||
744 | #define DEVICE_READY_REG 0xb000 | ||
745 | #define LP_OUTPUT_HOLD (1 << 16) | ||
746 | #define EXIT_ULPS_DEV_READY 0x3 | ||
747 | #define LP_OUTPUT_HOLD_RELEASE 0x810000 | ||
748 | # define ENTERING_ULPS (2 << 1) | ||
749 | # define EXITING_ULPS (1 << 1) | ||
750 | # define ULPS_MASK (3 << 1) | ||
751 | # define BUS_POSSESSION (1 << 3) | ||
752 | #define INTR_STAT_REG 0xb004 | ||
753 | #define RX_SOT_ERROR (1 << 0) | ||
754 | #define RX_SOT_SYNC_ERROR (1 << 1) | ||
755 | #define RX_ESCAPE_MODE_ENTRY_ERROR (1 << 3) | ||
756 | #define RX_LP_TX_SYNC_ERROR (1 << 4) | ||
757 | #define RX_HS_RECEIVE_TIMEOUT_ERROR (1 << 5) | ||
758 | #define RX_FALSE_CONTROL_ERROR (1 << 6) | ||
759 | #define RX_ECC_SINGLE_BIT_ERROR (1 << 7) | ||
760 | #define RX_ECC_MULTI_BIT_ERROR (1 << 8) | ||
761 | #define RX_CHECKSUM_ERROR (1 << 9) | ||
762 | #define RX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 10) | ||
763 | #define RX_DSI_VC_ID_INVALID (1 << 11) | ||
764 | #define TX_FALSE_CONTROL_ERROR (1 << 12) | ||
765 | #define TX_ECC_SINGLE_BIT_ERROR (1 << 13) | ||
766 | #define TX_ECC_MULTI_BIT_ERROR (1 << 14) | ||
767 | #define TX_CHECKSUM_ERROR (1 << 15) | ||
768 | #define TX_DSI_DATA_TYPE_NOT_RECOGNIZED (1 << 16) | ||
769 | #define TX_DSI_VC_ID_INVALID (1 << 17) | ||
770 | #define HIGH_CONTENTION (1 << 18) | ||
771 | #define LOW_CONTENTION (1 << 19) | ||
772 | #define DPI_FIFO_UNDER_RUN (1 << 20) | ||
773 | #define HS_TX_TIMEOUT (1 << 21) | ||
774 | #define LP_RX_TIMEOUT (1 << 22) | ||
775 | #define TURN_AROUND_ACK_TIMEOUT (1 << 23) | ||
776 | #define ACK_WITH_NO_ERROR (1 << 24) | ||
777 | #define HS_GENERIC_WR_FIFO_FULL (1 << 27) | ||
778 | #define LP_GENERIC_WR_FIFO_FULL (1 << 28) | ||
779 | #define SPL_PKT_SENT (1 << 30) | ||
780 | #define INTR_EN_REG 0xb008 | ||
781 | #define DSI_FUNC_PRG_REG 0xb00c | ||
782 | #define DPI_CHANNEL_NUMBER_POS 0x03 | ||
783 | #define DBI_CHANNEL_NUMBER_POS 0x05 | ||
784 | #define FMT_DPI_POS 0x07 | ||
785 | #define FMT_DBI_POS 0x0A | ||
786 | #define DBI_DATA_WIDTH_POS 0x0D | ||
787 | |||
788 | /* DPI PIXEL FORMATS */ | ||
789 | #define RGB_565_FMT 0x01 /* RGB 565 FORMAT */ | ||
790 | #define RGB_666_FMT 0x02 /* RGB 666 FORMAT */ | ||
791 | #define LRGB_666_FMT 0x03 /* RGB LOOSELY PACKED | ||
792 | * 666 FORMAT | ||
793 | */ | ||
794 | #define RGB_888_FMT 0x04 /* RGB 888 FORMAT */ | ||
795 | #define VIRTUAL_CHANNEL_NUMBER_0 0x00 /* Virtual channel 0 */ | ||
796 | #define VIRTUAL_CHANNEL_NUMBER_1 0x01 /* Virtual channel 1 */ | ||
797 | #define VIRTUAL_CHANNEL_NUMBER_2 0x02 /* Virtual channel 2 */ | ||
798 | #define VIRTUAL_CHANNEL_NUMBER_3 0x03 /* Virtual channel 3 */ | ||
799 | |||
800 | #define DBI_NOT_SUPPORTED 0x00 /* command mode | ||
801 | * is not supported | ||
802 | */ | ||
803 | #define DBI_DATA_WIDTH_16BIT 0x01 /* 16 bit data */ | ||
804 | #define DBI_DATA_WIDTH_9BIT 0x02 /* 9 bit data */ | ||
805 | #define DBI_DATA_WIDTH_8BIT 0x03 /* 8 bit data */ | ||
806 | #define DBI_DATA_WIDTH_OPT1 0x04 /* option 1 */ | ||
807 | #define DBI_DATA_WIDTH_OPT2 0x05 /* option 2 */ | ||
808 | |||
809 | #define HS_TX_TIMEOUT_REG 0xb010 | ||
810 | #define LP_RX_TIMEOUT_REG 0xb014 | ||
811 | #define TURN_AROUND_TIMEOUT_REG 0xb018 | ||
812 | #define DEVICE_RESET_REG 0xb01C | ||
813 | #define DPI_RESOLUTION_REG 0xb020 | ||
814 | #define RES_V_POS 0x10 | ||
815 | #define DBI_RESOLUTION_REG 0xb024 /* Reserved for MDFLD */ | ||
816 | #define HORIZ_SYNC_PAD_COUNT_REG 0xb028 | ||
817 | #define HORIZ_BACK_PORCH_COUNT_REG 0xb02C | ||
818 | #define HORIZ_FRONT_PORCH_COUNT_REG 0xb030 | ||
819 | #define HORIZ_ACTIVE_AREA_COUNT_REG 0xb034 | ||
820 | #define VERT_SYNC_PAD_COUNT_REG 0xb038 | ||
821 | #define VERT_BACK_PORCH_COUNT_REG 0xb03c | ||
822 | #define VERT_FRONT_PORCH_COUNT_REG 0xb040 | ||
823 | #define HIGH_LOW_SWITCH_COUNT_REG 0xb044 | ||
824 | #define DPI_CONTROL_REG 0xb048 | ||
825 | #define DPI_SHUT_DOWN (1 << 0) | ||
826 | #define DPI_TURN_ON (1 << 1) | ||
827 | #define DPI_COLOR_MODE_ON (1 << 2) | ||
828 | #define DPI_COLOR_MODE_OFF (1 << 3) | ||
829 | #define DPI_BACK_LIGHT_ON (1 << 4) | ||
830 | #define DPI_BACK_LIGHT_OFF (1 << 5) | ||
831 | #define DPI_LP (1 << 6) | ||
832 | #define DPI_DATA_REG 0xb04c | ||
833 | #define DPI_BACK_LIGHT_ON_DATA 0x07 | ||
834 | #define DPI_BACK_LIGHT_OFF_DATA 0x17 | ||
835 | #define INIT_COUNT_REG 0xb050 | ||
836 | #define MAX_RET_PAK_REG 0xb054 | ||
837 | #define VIDEO_FMT_REG 0xb058 | ||
838 | #define COMPLETE_LAST_PCKT (1 << 2) | ||
839 | #define EOT_DISABLE_REG 0xb05c | ||
840 | #define ENABLE_CLOCK_STOPPING (1 << 1) | ||
841 | #define LP_BYTECLK_REG 0xb060 | ||
842 | #define LP_GEN_DATA_REG 0xb064 | ||
843 | #define HS_GEN_DATA_REG 0xb068 | ||
844 | #define LP_GEN_CTRL_REG 0xb06C | ||
845 | #define HS_GEN_CTRL_REG 0xb070 | ||
846 | #define DCS_CHANNEL_NUMBER_POS 0x6 | ||
847 | #define MCS_COMMANDS_POS 0x8 | ||
848 | #define WORD_COUNTS_POS 0x8 | ||
849 | #define MCS_PARAMETER_POS 0x10 | ||
850 | #define GEN_FIFO_STAT_REG 0xb074 | ||
851 | #define HS_DATA_FIFO_FULL (1 << 0) | ||
852 | #define HS_DATA_FIFO_HALF_EMPTY (1 << 1) | ||
853 | #define HS_DATA_FIFO_EMPTY (1 << 2) | ||
854 | #define LP_DATA_FIFO_FULL (1 << 8) | ||
855 | #define LP_DATA_FIFO_HALF_EMPTY (1 << 9) | ||
856 | #define LP_DATA_FIFO_EMPTY (1 << 10) | ||
857 | #define HS_CTRL_FIFO_FULL (1 << 16) | ||
858 | #define HS_CTRL_FIFO_HALF_EMPTY (1 << 17) | ||
859 | #define HS_CTRL_FIFO_EMPTY (1 << 18) | ||
860 | #define LP_CTRL_FIFO_FULL (1 << 24) | ||
861 | #define LP_CTRL_FIFO_HALF_EMPTY (1 << 25) | ||
862 | #define LP_CTRL_FIFO_EMPTY (1 << 26) | ||
863 | #define DBI_FIFO_EMPTY (1 << 27) | ||
864 | #define DPI_FIFO_EMPTY (1 << 28) | ||
865 | #define HS_LS_DBI_ENABLE_REG 0xb078 | ||
866 | #define TXCLKESC_REG 0xb07c | ||
867 | #define DPHY_PARAM_REG 0xb080 | ||
868 | #define DBI_BW_CTRL_REG 0xb084 | ||
869 | #define CLK_LANE_SWT_REG 0xb088 | ||
870 | |||
871 | /* | ||
872 | * MIPI Adapter registers | ||
873 | */ | ||
874 | #define MIPI_CONTROL_REG 0xb104 | ||
875 | #define MIPI_2X_CLOCK_BITS ((1 << 0) | (1 << 1)) | ||
876 | #define MIPI_DATA_ADDRESS_REG 0xb108 | ||
877 | #define MIPI_DATA_LENGTH_REG 0xb10C | ||
878 | #define MIPI_COMMAND_ADDRESS_REG 0xb110 | ||
879 | #define MIPI_COMMAND_LENGTH_REG 0xb114 | ||
880 | #define MIPI_READ_DATA_RETURN_REG0 0xb118 | ||
881 | #define MIPI_READ_DATA_RETURN_REG1 0xb11C | ||
882 | #define MIPI_READ_DATA_RETURN_REG2 0xb120 | ||
883 | #define MIPI_READ_DATA_RETURN_REG3 0xb124 | ||
884 | #define MIPI_READ_DATA_RETURN_REG4 0xb128 | ||
885 | #define MIPI_READ_DATA_RETURN_REG5 0xb12C | ||
886 | #define MIPI_READ_DATA_RETURN_REG6 0xb130 | ||
887 | #define MIPI_READ_DATA_RETURN_REG7 0xb134 | ||
888 | #define MIPI_READ_DATA_VALID_REG 0xb138 | ||
889 | |||
890 | /* DBI COMMANDS */ | ||
891 | #define soft_reset 0x01 | ||
892 | /* | ||
893 | * The display module performs a software reset. | ||
894 | * Registers are written with their SW Reset default values. | ||
895 | */ | ||
896 | #define get_power_mode 0x0a | ||
897 | /* | ||
898 | * The display module returns the current power mode | ||
899 | */ | ||
900 | #define get_address_mode 0x0b | ||
901 | /* | ||
902 | * The display module returns the current status. | ||
903 | */ | ||
904 | #define get_pixel_format 0x0c | ||
905 | /* | ||
906 | * This command gets the pixel format for the RGB image data | ||
907 | * used by the interface. | ||
908 | */ | ||
909 | #define get_display_mode 0x0d | ||
910 | /* | ||
911 | * The display module returns the Display Image Mode status. | ||
912 | */ | ||
913 | #define get_signal_mode 0x0e | ||
914 | /* | ||
915 | * The display module returns the Display Signal Mode. | ||
916 | */ | ||
917 | #define get_diagnostic_result 0x0f | ||
918 | /* | ||
919 | * The display module returns the self-diagnostic results following | ||
920 | * a Sleep Out command. | ||
921 | */ | ||
922 | #define enter_sleep_mode 0x10 | ||
923 | /* | ||
924 | * This command causes the display module to enter the Sleep mode. | ||
925 | * In this mode, all unnecessary blocks inside the display module are | ||
926 | * disabled except interface communication. This is the lowest power | ||
927 | * mode the display module supports. | ||
928 | */ | ||
929 | #define exit_sleep_mode 0x11 | ||
930 | /* | ||
931 | * This command causes the display module to exit Sleep mode. | ||
932 | * All blocks inside the display module are enabled. | ||
933 | */ | ||
934 | #define enter_partial_mode 0x12 | ||
935 | /* | ||
936 | * This command causes the display module to enter the Partial Display | ||
937 | * Mode. The Partial Display Mode window is described by the | ||
938 | * set_partial_area command. | ||
939 | */ | ||
940 | #define enter_normal_mode 0x13 | ||
941 | /* | ||
942 | * This command causes the display module to enter the Normal mode. | ||
943 | * Normal Mode is defined as Partial Display mode and Scroll mode are off | ||
944 | */ | ||
945 | #define exit_invert_mode 0x20 | ||
946 | /* | ||
947 | * This command causes the display module to stop inverting the image | ||
948 | * data on the display device. The frame memory contents remain unchanged. | ||
949 | * No status bits are changed. | ||
950 | */ | ||
951 | #define enter_invert_mode 0x21 | ||
952 | /* | ||
953 | * This command causes the display module to invert the image data only on | ||
954 | * the display device. The frame memory contents remain unchanged. | ||
955 | * No status bits are changed. | ||
956 | */ | ||
957 | #define set_gamma_curve 0x26 | ||
958 | /* | ||
959 | * This command selects the desired gamma curve for the display device. | ||
960 | * Four fixed gamma curves are defined in section DCS spec. | ||
961 | */ | ||
962 | #define set_display_off 0x28 | ||
963 | /* ************************************************************************* *\ | ||
964 | This command causes the display module to stop displaying the image data | ||
965 | on the display device. The frame memory contents remain unchanged. | ||
966 | No status bits are changed. | ||
967 | \* ************************************************************************* */ | ||
968 | #define set_display_on 0x29 | ||
969 | /* ************************************************************************* *\ | ||
970 | This command causes the display module to start displaying the image data | ||
971 | on the display device. The frame memory contents remain unchanged. | ||
972 | No status bits are changed. | ||
973 | \* ************************************************************************* */ | ||
974 | #define set_column_address 0x2a | ||
975 | /* | ||
976 | * This command defines the column extent of the frame memory accessed by | ||
977 | * the hostprocessor with the read_memory_continue and | ||
978 | * write_memory_continue commands. | ||
979 | * No status bits are changed. | ||
980 | */ | ||
981 | #define set_page_addr 0x2b | ||
982 | /* | ||
983 | * This command defines the page extent of the frame memory accessed by | ||
984 | * the host processor with the write_memory_continue and | ||
985 | * read_memory_continue command. | ||
986 | * No status bits are changed. | ||
987 | */ | ||
988 | #define write_mem_start 0x2c | ||
989 | /* | ||
990 | * This command transfers image data from the host processor to the | ||
991 | * display modules frame memory starting at the pixel location specified | ||
992 | * by preceding set_column_address and set_page_address commands. | ||
993 | */ | ||
994 | #define set_partial_area 0x30 | ||
995 | /* | ||
996 | * This command defines the Partial Display mode s display area. | ||
997 | * There are two parameters associated with this command, the first | ||
998 | * defines the Start Row (SR) and the second the End Row (ER). SR and ER | ||
999 | * refer to the Frame Memory Line Pointer. | ||
1000 | */ | ||
1001 | #define set_scroll_area 0x33 | ||
1002 | /* | ||
1003 | * This command defines the display modules Vertical Scrolling Area. | ||
1004 | */ | ||
1005 | #define set_tear_off 0x34 | ||
1006 | /* | ||
1007 | * This command turns off the display modules Tearing Effect output | ||
1008 | * signal on the TE signal line. | ||
1009 | */ | ||
1010 | #define set_tear_on 0x35 | ||
1011 | /* | ||
1012 | * This command turns on the display modules Tearing Effect output signal | ||
1013 | * on the TE signal line. | ||
1014 | */ | ||
1015 | #define set_address_mode 0x36 | ||
1016 | /* | ||
1017 | * This command sets the data order for transfers from the host processor | ||
1018 | * to display modules frame memory,bits B[7:5] and B3, and from the | ||
1019 | * display modules frame memory to the display device, bits B[2:0] and B4. | ||
1020 | */ | ||
1021 | #define set_scroll_start 0x37 | ||
1022 | /* | ||
1023 | * This command sets the start of the vertical scrolling area in the frame | ||
1024 | * memory. The vertical scrolling area is fully defined when this command | ||
1025 | * is used with the set_scroll_area command The set_scroll_start command | ||
1026 | * has one parameter, the Vertical Scroll Pointer. The VSP defines the | ||
1027 | * line in the frame memory that is written to the display device as the | ||
1028 | * first line of the vertical scroll area. | ||
1029 | */ | ||
1030 | #define exit_idle_mode 0x38 | ||
1031 | /* | ||
1032 | * This command causes the display module to exit Idle mode. | ||
1033 | */ | ||
1034 | #define enter_idle_mode 0x39 | ||
1035 | /* | ||
1036 | * This command causes the display module to enter Idle Mode. | ||
1037 | * In Idle Mode, color expression is reduced. Colors are shown on the | ||
1038 | * display device using the MSB of each of the R, G and B color | ||
1039 | * components in the frame memory | ||
1040 | */ | ||
1041 | #define set_pixel_format 0x3a | ||
1042 | /* | ||
1043 | * This command sets the pixel format for the RGB image data used by the | ||
1044 | * interface. | ||
1045 | * Bits D[6:4] DPI Pixel Format Definition | ||
1046 | * Bits D[2:0] DBI Pixel Format Definition | ||
1047 | * Bits D7 and D3 are not used. | ||
1048 | */ | ||
1049 | #define DCS_PIXEL_FORMAT_3bpp 0x1 | ||
1050 | #define DCS_PIXEL_FORMAT_8bpp 0x2 | ||
1051 | #define DCS_PIXEL_FORMAT_12bpp 0x3 | ||
1052 | #define DCS_PIXEL_FORMAT_16bpp 0x5 | ||
1053 | #define DCS_PIXEL_FORMAT_18bpp 0x6 | ||
1054 | #define DCS_PIXEL_FORMAT_24bpp 0x7 | ||
1055 | |||
1056 | #define write_mem_cont 0x3c | ||
1057 | |||
1058 | /* | ||
1059 | * This command transfers image data from the host processor to the | ||
1060 | * display module's frame memory continuing from the pixel location | ||
1061 | * following the previous write_memory_continue or write_memory_start | ||
1062 | * command. | ||
1063 | */ | ||
1064 | #define set_tear_scanline 0x44 | ||
1065 | /* | ||
1066 | * This command turns on the display modules Tearing Effect output signal | ||
1067 | * on the TE signal line when the display module reaches line N. | ||
1068 | */ | ||
1069 | #define get_scanline 0x45 | ||
1070 | /* | ||
1071 | * The display module returns the current scanline, N, used to update the | ||
1072 | * display device. The total number of scanlines on a display device is | ||
1073 | * defined as VSYNC + VBP + VACT + VFP.The first scanline is defined as | ||
1074 | * the first line of V Sync and is denoted as Line 0. | ||
1075 | * When in Sleep Mode, the value returned by get_scanline is undefined. | ||
1076 | */ | ||
1077 | |||
1078 | /* MCS or Generic COMMANDS */ | ||
1079 | /* MCS/generic data type */ | ||
1080 | #define GEN_SHORT_WRITE_0 0x03 /* generic short write, no parameters */ | ||
1081 | #define GEN_SHORT_WRITE_1 0x13 /* generic short write, 1 parameters */ | ||
1082 | #define GEN_SHORT_WRITE_2 0x23 /* generic short write, 2 parameters */ | ||
1083 | #define GEN_READ_0 0x04 /* generic read, no parameters */ | ||
1084 | #define GEN_READ_1 0x14 /* generic read, 1 parameters */ | ||
1085 | #define GEN_READ_2 0x24 /* generic read, 2 parameters */ | ||
1086 | #define GEN_LONG_WRITE 0x29 /* generic long write */ | ||
1087 | #define MCS_SHORT_WRITE_0 0x05 /* MCS short write, no parameters */ | ||
1088 | #define MCS_SHORT_WRITE_1 0x15 /* MCS short write, 1 parameters */ | ||
1089 | #define MCS_READ 0x06 /* MCS read, no parameters */ | ||
1090 | #define MCS_LONG_WRITE 0x39 /* MCS long write */ | ||
1091 | /* MCS/generic commands */ | ||
1092 | /* TPO MCS */ | ||
1093 | #define write_display_profile 0x50 | ||
1094 | #define write_display_brightness 0x51 | ||
1095 | #define write_ctrl_display 0x53 | ||
1096 | #define write_ctrl_cabc 0x55 | ||
1097 | #define UI_IMAGE 0x01 | ||
1098 | #define STILL_IMAGE 0x02 | ||
1099 | #define MOVING_IMAGE 0x03 | ||
1100 | #define write_hysteresis 0x57 | ||
1101 | #define write_gamma_setting 0x58 | ||
1102 | #define write_cabc_min_bright 0x5e | ||
1103 | #define write_kbbc_profile 0x60 | ||
1104 | /* TMD MCS */ | ||
1105 | #define tmd_write_display_brightness 0x8c | ||
1106 | |||
1107 | /* | ||
1108 | * This command is used to control ambient light, panel backlight | ||
1109 | * brightness and gamma settings. | ||
1110 | */ | ||
1111 | #define BRIGHT_CNTL_BLOCK_ON (1 << 5) | ||
1112 | #define AMBIENT_LIGHT_SENSE_ON (1 << 4) | ||
1113 | #define DISPLAY_DIMMING_ON (1 << 3) | ||
1114 | #define BACKLIGHT_ON (1 << 2) | ||
1115 | #define DISPLAY_BRIGHTNESS_AUTO (1 << 1) | ||
1116 | #define GAMMA_AUTO (1 << 0) | ||
1117 | |||
1118 | /* DCS Interface Pixel Formats */ | ||
1119 | #define DCS_PIXEL_FORMAT_3BPP 0x1 | ||
1120 | #define DCS_PIXEL_FORMAT_8BPP 0x2 | ||
1121 | #define DCS_PIXEL_FORMAT_12BPP 0x3 | ||
1122 | #define DCS_PIXEL_FORMAT_16BPP 0x5 | ||
1123 | #define DCS_PIXEL_FORMAT_18BPP 0x6 | ||
1124 | #define DCS_PIXEL_FORMAT_24BPP 0x7 | ||
1125 | /* ONE PARAMETER READ DATA */ | ||
1126 | #define addr_mode_data 0xfc | ||
1127 | #define diag_res_data 0x00 | ||
1128 | #define disp_mode_data 0x23 | ||
1129 | #define pxl_fmt_data 0x77 | ||
1130 | #define pwr_mode_data 0x74 | ||
1131 | #define sig_mode_data 0x00 | ||
1132 | /* TWO PARAMETERS READ DATA */ | ||
1133 | #define scanline_data1 0xff | ||
1134 | #define scanline_data2 0xff | ||
1135 | #define NON_BURST_MODE_SYNC_PULSE 0x01 /* Non Burst Mode | ||
1136 | * with Sync Pulse | ||
1137 | */ | ||
1138 | #define NON_BURST_MODE_SYNC_EVENTS 0x02 /* Non Burst Mode | ||
1139 | * with Sync events | ||
1140 | */ | ||
1141 | #define BURST_MODE 0x03 /* Burst Mode */ | ||
1142 | #define DBI_COMMAND_BUFFER_SIZE 0x240 /* 0x32 */ /* 0x120 */ | ||
1143 | /* Allocate at least | ||
1144 | * 0x100 Byte with 32 | ||
1145 | * byte alignment | ||
1146 | */ | ||
1147 | #define DBI_DATA_BUFFER_SIZE 0x120 /* Allocate at least | ||
1148 | * 0x100 Byte with 32 | ||
1149 | * byte alignment | ||
1150 | */ | ||
1151 | #define DBI_CB_TIME_OUT 0xFFFF | ||
1152 | |||
1153 | #define GEN_FB_TIME_OUT 2000 | ||
1154 | |||
1155 | #define SKU_83 0x01 | ||
1156 | #define SKU_100 0x02 | ||
1157 | #define SKU_100L 0x04 | ||
1158 | #define SKU_BYPASS 0x08 | ||
1159 | |||
1160 | /* Some handy macros for playing with bitfields. */ | ||
1161 | #define PSB_MASK(high, low) (((1<<((high)-(low)+1))-1)<<(low)) | ||
1162 | #define SET_FIELD(value, field) (((value) << field ## _SHIFT) & field ## _MASK) | ||
1163 | #define GET_FIELD(word, field) (((word) & field ## _MASK) >> field ## _SHIFT) | ||
1164 | |||
1165 | #define _PIPE(pipe, a, b) ((a) + (pipe)*((b)-(a))) | ||
1166 | |||
1167 | /* PCI config space */ | ||
1168 | |||
1169 | #define SB_PCKT 0x02100 /* cedarview */ | ||
1170 | # define SB_OPCODE_MASK PSB_MASK(31, 16) | ||
1171 | # define SB_OPCODE_SHIFT 16 | ||
1172 | # define SB_OPCODE_READ 0 | ||
1173 | # define SB_OPCODE_WRITE 1 | ||
1174 | # define SB_DEST_MASK PSB_MASK(15, 8) | ||
1175 | # define SB_DEST_SHIFT 8 | ||
1176 | # define SB_DEST_DPLL 0x88 | ||
1177 | # define SB_BYTE_ENABLE_MASK PSB_MASK(7, 4) | ||
1178 | # define SB_BYTE_ENABLE_SHIFT 4 | ||
1179 | # define SB_BUSY (1 << 0) | ||
1180 | |||
1181 | |||
1182 | /* 32-bit value read/written from the DPIO reg. */ | ||
1183 | #define SB_DATA 0x02104 /* cedarview */ | ||
1184 | /* 32-bit address of the DPIO reg to be read/written. */ | ||
1185 | #define SB_ADDR 0x02108 /* cedarview */ | ||
1186 | #define DPIO_CFG 0x02110 /* cedarview */ | ||
1187 | # define DPIO_MODE_SELECT_1 (1 << 3) | ||
1188 | # define DPIO_MODE_SELECT_0 (1 << 2) | ||
1189 | # define DPIO_SFR_BYPASS (1 << 1) | ||
1190 | /* reset is active low */ | ||
1191 | # define DPIO_CMN_RESET_N (1 << 0) | ||
1192 | |||
1193 | /* Cedarview sideband registers */ | ||
1194 | #define _SB_M_A 0x8008 | ||
1195 | #define _SB_M_B 0x8028 | ||
1196 | #define SB_M(pipe) _PIPE(pipe, _SB_M_A, _SB_M_B) | ||
1197 | # define SB_M_DIVIDER_MASK (0xFF << 24) | ||
1198 | # define SB_M_DIVIDER_SHIFT 24 | ||
1199 | |||
1200 | #define _SB_N_VCO_A 0x8014 | ||
1201 | #define _SB_N_VCO_B 0x8034 | ||
1202 | #define SB_N_VCO(pipe) _PIPE(pipe, _SB_N_VCO_A, _SB_N_VCO_B) | ||
1203 | #define SB_N_VCO_SEL_MASK PSB_MASK(31, 30) | ||
1204 | #define SB_N_VCO_SEL_SHIFT 30 | ||
1205 | #define SB_N_DIVIDER_MASK PSB_MASK(29, 26) | ||
1206 | #define SB_N_DIVIDER_SHIFT 26 | ||
1207 | #define SB_N_CB_TUNE_MASK PSB_MASK(25, 24) | ||
1208 | #define SB_N_CB_TUNE_SHIFT 24 | ||
1209 | |||
1210 | #define _SB_REF_A 0x8018 | ||
1211 | #define _SB_REF_B 0x8038 | ||
1212 | #define SB_REF_SFR(pipe) _PIPE(pipe, _SB_REF_A, _SB_REF_B) | ||
1213 | |||
1214 | #define _SB_P_A 0x801c | ||
1215 | #define _SB_P_B 0x803c | ||
1216 | #define SB_P(pipe) _PIPE(pipe, _SB_P_A, _SB_P_B) | ||
1217 | #define SB_P2_DIVIDER_MASK PSB_MASK(31, 30) | ||
1218 | #define SB_P2_DIVIDER_SHIFT 30 | ||
1219 | #define SB_P2_10 0 /* HDMI, DP, DAC */ | ||
1220 | #define SB_P2_5 1 /* DAC */ | ||
1221 | #define SB_P2_14 2 /* LVDS single */ | ||
1222 | #define SB_P2_7 3 /* LVDS double */ | ||
1223 | #define SB_P1_DIVIDER_MASK PSB_MASK(15, 12) | ||
1224 | #define SB_P1_DIVIDER_SHIFT 12 | ||
1225 | |||
1226 | #define PSB_LANE0 0x120 | ||
1227 | #define PSB_LANE1 0x220 | ||
1228 | #define PSB_LANE2 0x2320 | ||
1229 | #define PSB_LANE3 0x2420 | ||
1230 | |||
1231 | #define LANE_PLL_MASK (0x7 << 20) | ||
1232 | #define LANE_PLL_ENABLE (0x3 << 20) | ||
1233 | |||
1234 | |||
1235 | #endif | ||
diff --git a/drivers/staging/gma500/psb_intel_sdvo.c b/drivers/staging/gma500/psb_intel_sdvo.c deleted file mode 100644 index a4bad1af4b7c..000000000000 --- a/drivers/staging/gma500/psb_intel_sdvo.c +++ /dev/null | |||
@@ -1,1293 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006-2007 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/delay.h> | ||
23 | /* #include <drm/drm_crtc.h> */ | ||
24 | #include <drm/drmP.h> | ||
25 | #include "psb_drv.h" | ||
26 | #include "psb_intel_drv.h" | ||
27 | #include "psb_intel_reg.h" | ||
28 | #include "psb_intel_sdvo_regs.h" | ||
29 | |||
30 | struct psb_intel_sdvo_priv { | ||
31 | struct psb_intel_i2c_chan *i2c_bus; | ||
32 | int slaveaddr; | ||
33 | int output_device; | ||
34 | |||
35 | u16 active_outputs; | ||
36 | |||
37 | struct psb_intel_sdvo_caps caps; | ||
38 | int pixel_clock_min, pixel_clock_max; | ||
39 | |||
40 | int save_sdvo_mult; | ||
41 | u16 save_active_outputs; | ||
42 | struct psb_intel_sdvo_dtd save_input_dtd_1, save_input_dtd_2; | ||
43 | struct psb_intel_sdvo_dtd save_output_dtd[16]; | ||
44 | u32 save_SDVOX; | ||
45 | u8 in_out_map[4]; | ||
46 | |||
47 | u8 by_input_wiring; | ||
48 | u32 active_device; | ||
49 | }; | ||
50 | |||
51 | /** | ||
52 | * Writes the SDVOB or SDVOC with the given value, but always writes both | ||
53 | * SDVOB and SDVOC to work around apparent hardware issues (according to | ||
54 | * comments in the BIOS). | ||
55 | */ | ||
56 | void psb_intel_sdvo_write_sdvox(struct psb_intel_output *psb_intel_output, | ||
57 | u32 val) | ||
58 | { | ||
59 | struct drm_device *dev = psb_intel_output->base.dev; | ||
60 | struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; | ||
61 | u32 bval = val, cval = val; | ||
62 | int i; | ||
63 | |||
64 | if (sdvo_priv->output_device == SDVOB) | ||
65 | cval = REG_READ(SDVOC); | ||
66 | else | ||
67 | bval = REG_READ(SDVOB); | ||
68 | /* | ||
69 | * Write the registers twice for luck. Sometimes, | ||
70 | * writing them only once doesn't appear to 'stick'. | ||
71 | * The BIOS does this too. Yay, magic | ||
72 | */ | ||
73 | for (i = 0; i < 2; i++) { | ||
74 | REG_WRITE(SDVOB, bval); | ||
75 | REG_READ(SDVOB); | ||
76 | REG_WRITE(SDVOC, cval); | ||
77 | REG_READ(SDVOC); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | static bool psb_intel_sdvo_read_byte( | ||
82 | struct psb_intel_output *psb_intel_output, | ||
83 | u8 addr, u8 *ch) | ||
84 | { | ||
85 | struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; | ||
86 | u8 out_buf[2]; | ||
87 | u8 buf[2]; | ||
88 | int ret; | ||
89 | |||
90 | struct i2c_msg msgs[] = { | ||
91 | { | ||
92 | .addr = sdvo_priv->i2c_bus->slave_addr, | ||
93 | .flags = 0, | ||
94 | .len = 1, | ||
95 | .buf = out_buf, | ||
96 | }, | ||
97 | { | ||
98 | .addr = sdvo_priv->i2c_bus->slave_addr, | ||
99 | .flags = I2C_M_RD, | ||
100 | .len = 1, | ||
101 | .buf = buf, | ||
102 | } | ||
103 | }; | ||
104 | |||
105 | out_buf[0] = addr; | ||
106 | out_buf[1] = 0; | ||
107 | |||
108 | ret = i2c_transfer(&sdvo_priv->i2c_bus->adapter, msgs, 2); | ||
109 | if (ret == 2) { | ||
110 | *ch = buf[0]; | ||
111 | return true; | ||
112 | } | ||
113 | |||
114 | return false; | ||
115 | } | ||
116 | |||
117 | static bool psb_intel_sdvo_write_byte( | ||
118 | struct psb_intel_output *psb_intel_output, | ||
119 | int addr, u8 ch) | ||
120 | { | ||
121 | u8 out_buf[2]; | ||
122 | struct i2c_msg msgs[] = { | ||
123 | { | ||
124 | .addr = psb_intel_output->i2c_bus->slave_addr, | ||
125 | .flags = 0, | ||
126 | .len = 2, | ||
127 | .buf = out_buf, | ||
128 | } | ||
129 | }; | ||
130 | |||
131 | out_buf[0] = addr; | ||
132 | out_buf[1] = ch; | ||
133 | |||
134 | if (i2c_transfer(&psb_intel_output->i2c_bus->adapter, msgs, 1) == 1) | ||
135 | return true; | ||
136 | return false; | ||
137 | } | ||
138 | |||
139 | #define SDVO_CMD_NAME_ENTRY(cmd) {cmd, #cmd} | ||
140 | /** Mapping of command numbers to names, for debug output */ | ||
141 | static const struct _sdvo_cmd_name { | ||
142 | u8 cmd; | ||
143 | char *name; | ||
144 | } sdvo_cmd_names[] = { | ||
145 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_RESET), | ||
146 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_DEVICE_CAPS), | ||
147 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_FIRMWARE_REV), | ||
148 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TRAINED_INPUTS), | ||
149 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_OUTPUTS), | ||
150 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_OUTPUTS), | ||
151 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_IN_OUT_MAP), | ||
152 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_IN_OUT_MAP), | ||
153 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ATTACHED_DISPLAYS), | ||
154 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_HOT_PLUG_SUPPORT), | ||
155 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_ACTIVE_HOT_PLUG), | ||
156 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_ACTIVE_HOT_PLUG), | ||
157 | SDVO_CMD_NAME_ENTRY | ||
158 | (SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE), | ||
159 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_INPUT), | ||
160 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TARGET_OUTPUT), | ||
161 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART1), | ||
162 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_INPUT_TIMINGS_PART2), | ||
163 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), | ||
164 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART2), | ||
165 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_INPUT_TIMINGS_PART1), | ||
166 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART1), | ||
167 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_OUTPUT_TIMINGS_PART2), | ||
168 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART1), | ||
169 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_OUTPUT_TIMINGS_PART2), | ||
170 | SDVO_CMD_NAME_ENTRY | ||
171 | (SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING), | ||
172 | SDVO_CMD_NAME_ENTRY | ||
173 | (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1), | ||
174 | SDVO_CMD_NAME_ENTRY | ||
175 | (SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2), | ||
176 | SDVO_CMD_NAME_ENTRY | ||
177 | (SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE), | ||
178 | SDVO_CMD_NAME_ENTRY | ||
179 | (SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE), | ||
180 | SDVO_CMD_NAME_ENTRY | ||
181 | (SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS), | ||
182 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_CLOCK_RATE_MULT), | ||
183 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CLOCK_RATE_MULT), | ||
184 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_SUPPORTED_TV_FORMATS), | ||
185 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_GET_TV_FORMAT), | ||
186 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_TV_FORMAT), | ||
187 | SDVO_CMD_NAME_ENTRY | ||
188 | (SDVO_CMD_SET_TV_RESOLUTION_SUPPORT), | ||
189 | SDVO_CMD_NAME_ENTRY(SDVO_CMD_SET_CONTROL_BUS_SWITCH),}; | ||
190 | |||
191 | #define SDVO_NAME(dev_priv) \ | ||
192 | ((dev_priv)->output_device == SDVOB ? "SDVOB" : "SDVOC") | ||
193 | #define SDVO_PRIV(output) ((struct psb_intel_sdvo_priv *) (output)->dev_priv) | ||
194 | |||
195 | static void psb_intel_sdvo_write_cmd(struct psb_intel_output *psb_intel_output, | ||
196 | u8 cmd, | ||
197 | void *args, | ||
198 | int args_len) | ||
199 | { | ||
200 | struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; | ||
201 | int i; | ||
202 | |||
203 | if (0) { | ||
204 | printk(KERN_DEBUG "%s: W: %02X ", SDVO_NAME(sdvo_priv), cmd); | ||
205 | for (i = 0; i < args_len; i++) | ||
206 | printk(KERN_CONT "%02X ", ((u8 *) args)[i]); | ||
207 | for (; i < 8; i++) | ||
208 | printk(KERN_CONT " "); | ||
209 | for (i = 0; | ||
210 | i < | ||
211 | sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0]); | ||
212 | i++) { | ||
213 | if (cmd == sdvo_cmd_names[i].cmd) { | ||
214 | printk(KERN_CONT | ||
215 | "(%s)", sdvo_cmd_names[i].name); | ||
216 | break; | ||
217 | } | ||
218 | } | ||
219 | if (i == | ||
220 | sizeof(sdvo_cmd_names) / sizeof(sdvo_cmd_names[0])) | ||
221 | printk(KERN_CONT "(%02X)", cmd); | ||
222 | printk(KERN_CONT "\n"); | ||
223 | } | ||
224 | |||
225 | for (i = 0; i < args_len; i++) { | ||
226 | psb_intel_sdvo_write_byte(psb_intel_output, | ||
227 | SDVO_I2C_ARG_0 - i, | ||
228 | ((u8 *) args)[i]); | ||
229 | } | ||
230 | |||
231 | psb_intel_sdvo_write_byte(psb_intel_output, SDVO_I2C_OPCODE, cmd); | ||
232 | } | ||
233 | |||
234 | static const char *const cmd_status_names[] = { | ||
235 | "Power on", | ||
236 | "Success", | ||
237 | "Not supported", | ||
238 | "Invalid arg", | ||
239 | "Pending", | ||
240 | "Target not specified", | ||
241 | "Scaling not supported" | ||
242 | }; | ||
243 | |||
244 | static u8 psb_intel_sdvo_read_response( | ||
245 | struct psb_intel_output *psb_intel_output, | ||
246 | void *response, int response_len) | ||
247 | { | ||
248 | struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; | ||
249 | int i; | ||
250 | u8 status; | ||
251 | u8 retry = 50; | ||
252 | |||
253 | while (retry--) { | ||
254 | /* Read the command response */ | ||
255 | for (i = 0; i < response_len; i++) { | ||
256 | psb_intel_sdvo_read_byte(psb_intel_output, | ||
257 | SDVO_I2C_RETURN_0 + i, | ||
258 | &((u8 *) response)[i]); | ||
259 | } | ||
260 | |||
261 | /* read the return status */ | ||
262 | psb_intel_sdvo_read_byte(psb_intel_output, | ||
263 | SDVO_I2C_CMD_STATUS, | ||
264 | &status); | ||
265 | |||
266 | if (0) { | ||
267 | pr_debug("%s: R: ", SDVO_NAME(sdvo_priv)); | ||
268 | for (i = 0; i < response_len; i++) | ||
269 | printk(KERN_CONT "%02X ", ((u8 *) response)[i]); | ||
270 | for (; i < 8; i++) | ||
271 | printk(" "); | ||
272 | if (status <= SDVO_CMD_STATUS_SCALING_NOT_SUPP) | ||
273 | printk(KERN_CONT "(%s)", | ||
274 | cmd_status_names[status]); | ||
275 | else | ||
276 | printk(KERN_CONT "(??? %d)", status); | ||
277 | printk(KERN_CONT "\n"); | ||
278 | } | ||
279 | |||
280 | if (status != SDVO_CMD_STATUS_PENDING) | ||
281 | return status; | ||
282 | |||
283 | mdelay(50); | ||
284 | } | ||
285 | |||
286 | return status; | ||
287 | } | ||
288 | |||
289 | int psb_intel_sdvo_get_pixel_multiplier(struct drm_display_mode *mode) | ||
290 | { | ||
291 | if (mode->clock >= 100000) | ||
292 | return 1; | ||
293 | else if (mode->clock >= 50000) | ||
294 | return 2; | ||
295 | else | ||
296 | return 4; | ||
297 | } | ||
298 | |||
299 | /** | ||
300 | * Don't check status code from this as it switches the bus back to the | ||
301 | * SDVO chips which defeats the purpose of doing a bus switch in the first | ||
302 | * place. | ||
303 | */ | ||
304 | void psb_intel_sdvo_set_control_bus_switch( | ||
305 | struct psb_intel_output *psb_intel_output, | ||
306 | u8 target) | ||
307 | { | ||
308 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
309 | SDVO_CMD_SET_CONTROL_BUS_SWITCH, | ||
310 | &target, | ||
311 | 1); | ||
312 | } | ||
313 | |||
314 | static bool psb_intel_sdvo_set_target_input( | ||
315 | struct psb_intel_output *psb_intel_output, | ||
316 | bool target_0, bool target_1) | ||
317 | { | ||
318 | struct psb_intel_sdvo_set_target_input_args targets = { 0 }; | ||
319 | u8 status; | ||
320 | |||
321 | if (target_0 && target_1) | ||
322 | return SDVO_CMD_STATUS_NOTSUPP; | ||
323 | |||
324 | if (target_1) | ||
325 | targets.target_1 = 1; | ||
326 | |||
327 | psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_INPUT, | ||
328 | &targets, sizeof(targets)); | ||
329 | |||
330 | status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); | ||
331 | |||
332 | return status == SDVO_CMD_STATUS_SUCCESS; | ||
333 | } | ||
334 | |||
335 | /** | ||
336 | * Return whether each input is trained. | ||
337 | * | ||
338 | * This function is making an assumption about the layout of the response, | ||
339 | * which should be checked against the docs. | ||
340 | */ | ||
341 | static bool psb_intel_sdvo_get_trained_inputs(struct psb_intel_output | ||
342 | *psb_intel_output, bool *input_1, | ||
343 | bool *input_2) | ||
344 | { | ||
345 | struct psb_intel_sdvo_get_trained_inputs_response response; | ||
346 | u8 status; | ||
347 | |||
348 | psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_TRAINED_INPUTS, | ||
349 | NULL, 0); | ||
350 | status = | ||
351 | psb_intel_sdvo_read_response(psb_intel_output, &response, | ||
352 | sizeof(response)); | ||
353 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
354 | return false; | ||
355 | |||
356 | *input_1 = response.input0_trained; | ||
357 | *input_2 = response.input1_trained; | ||
358 | return true; | ||
359 | } | ||
360 | |||
361 | static bool psb_intel_sdvo_get_active_outputs(struct psb_intel_output | ||
362 | *psb_intel_output, u16 *outputs) | ||
363 | { | ||
364 | u8 status; | ||
365 | |||
366 | psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_GET_ACTIVE_OUTPUTS, | ||
367 | NULL, 0); | ||
368 | status = | ||
369 | psb_intel_sdvo_read_response(psb_intel_output, outputs, | ||
370 | sizeof(*outputs)); | ||
371 | |||
372 | return status == SDVO_CMD_STATUS_SUCCESS; | ||
373 | } | ||
374 | |||
375 | static bool psb_intel_sdvo_set_active_outputs(struct psb_intel_output | ||
376 | *psb_intel_output, u16 outputs) | ||
377 | { | ||
378 | u8 status; | ||
379 | |||
380 | psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_ACTIVE_OUTPUTS, | ||
381 | &outputs, sizeof(outputs)); | ||
382 | status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); | ||
383 | return status == SDVO_CMD_STATUS_SUCCESS; | ||
384 | } | ||
385 | |||
386 | static bool psb_intel_sdvo_set_encoder_power_state(struct psb_intel_output | ||
387 | *psb_intel_output, int mode) | ||
388 | { | ||
389 | u8 status, state = SDVO_ENCODER_STATE_ON; | ||
390 | |||
391 | switch (mode) { | ||
392 | case DRM_MODE_DPMS_ON: | ||
393 | state = SDVO_ENCODER_STATE_ON; | ||
394 | break; | ||
395 | case DRM_MODE_DPMS_STANDBY: | ||
396 | state = SDVO_ENCODER_STATE_STANDBY; | ||
397 | break; | ||
398 | case DRM_MODE_DPMS_SUSPEND: | ||
399 | state = SDVO_ENCODER_STATE_SUSPEND; | ||
400 | break; | ||
401 | case DRM_MODE_DPMS_OFF: | ||
402 | state = SDVO_ENCODER_STATE_OFF; | ||
403 | break; | ||
404 | } | ||
405 | |||
406 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
407 | SDVO_CMD_SET_ENCODER_POWER_STATE, &state, | ||
408 | sizeof(state)); | ||
409 | status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); | ||
410 | |||
411 | return status == SDVO_CMD_STATUS_SUCCESS; | ||
412 | } | ||
413 | |||
414 | static bool psb_intel_sdvo_get_input_pixel_clock_range(struct psb_intel_output | ||
415 | *psb_intel_output, | ||
416 | int *clock_min, | ||
417 | int *clock_max) | ||
418 | { | ||
419 | struct psb_intel_sdvo_pixel_clock_range clocks; | ||
420 | u8 status; | ||
421 | |||
422 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
423 | SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE, NULL, | ||
424 | 0); | ||
425 | |||
426 | status = | ||
427 | psb_intel_sdvo_read_response(psb_intel_output, &clocks, | ||
428 | sizeof(clocks)); | ||
429 | |||
430 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
431 | return false; | ||
432 | |||
433 | /* Convert the values from units of 10 kHz to kHz. */ | ||
434 | *clock_min = clocks.min * 10; | ||
435 | *clock_max = clocks.max * 10; | ||
436 | |||
437 | return true; | ||
438 | } | ||
439 | |||
440 | static bool psb_intel_sdvo_set_target_output( | ||
441 | struct psb_intel_output *psb_intel_output, | ||
442 | u16 outputs) | ||
443 | { | ||
444 | u8 status; | ||
445 | |||
446 | psb_intel_sdvo_write_cmd(psb_intel_output, SDVO_CMD_SET_TARGET_OUTPUT, | ||
447 | &outputs, sizeof(outputs)); | ||
448 | |||
449 | status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); | ||
450 | return status == SDVO_CMD_STATUS_SUCCESS; | ||
451 | } | ||
452 | |||
453 | static bool psb_intel_sdvo_get_timing(struct psb_intel_output *psb_intel_output, | ||
454 | u8 cmd, struct psb_intel_sdvo_dtd *dtd) | ||
455 | { | ||
456 | u8 status; | ||
457 | |||
458 | psb_intel_sdvo_write_cmd(psb_intel_output, cmd, NULL, 0); | ||
459 | status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part1, | ||
460 | sizeof(dtd->part1)); | ||
461 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
462 | return false; | ||
463 | |||
464 | psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, NULL, 0); | ||
465 | status = psb_intel_sdvo_read_response(psb_intel_output, &dtd->part2, | ||
466 | sizeof(dtd->part2)); | ||
467 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
468 | return false; | ||
469 | |||
470 | return true; | ||
471 | } | ||
472 | |||
473 | static bool psb_intel_sdvo_get_input_timing( | ||
474 | struct psb_intel_output *psb_intel_output, | ||
475 | struct psb_intel_sdvo_dtd *dtd) | ||
476 | { | ||
477 | return psb_intel_sdvo_get_timing(psb_intel_output, | ||
478 | SDVO_CMD_GET_INPUT_TIMINGS_PART1, | ||
479 | dtd); | ||
480 | } | ||
481 | |||
482 | static bool psb_intel_sdvo_set_timing( | ||
483 | struct psb_intel_output *psb_intel_output, | ||
484 | u8 cmd, | ||
485 | struct psb_intel_sdvo_dtd *dtd) | ||
486 | { | ||
487 | u8 status; | ||
488 | |||
489 | psb_intel_sdvo_write_cmd(psb_intel_output, cmd, &dtd->part1, | ||
490 | sizeof(dtd->part1)); | ||
491 | status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); | ||
492 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
493 | return false; | ||
494 | |||
495 | psb_intel_sdvo_write_cmd(psb_intel_output, cmd + 1, &dtd->part2, | ||
496 | sizeof(dtd->part2)); | ||
497 | status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); | ||
498 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
499 | return false; | ||
500 | |||
501 | return true; | ||
502 | } | ||
503 | |||
504 | static bool psb_intel_sdvo_set_input_timing( | ||
505 | struct psb_intel_output *psb_intel_output, | ||
506 | struct psb_intel_sdvo_dtd *dtd) | ||
507 | { | ||
508 | return psb_intel_sdvo_set_timing(psb_intel_output, | ||
509 | SDVO_CMD_SET_INPUT_TIMINGS_PART1, | ||
510 | dtd); | ||
511 | } | ||
512 | |||
513 | static bool psb_intel_sdvo_set_output_timing( | ||
514 | struct psb_intel_output *psb_intel_output, | ||
515 | struct psb_intel_sdvo_dtd *dtd) | ||
516 | { | ||
517 | return psb_intel_sdvo_set_timing(psb_intel_output, | ||
518 | SDVO_CMD_SET_OUTPUT_TIMINGS_PART1, | ||
519 | dtd); | ||
520 | } | ||
521 | |||
522 | static int psb_intel_sdvo_get_clock_rate_mult(struct psb_intel_output | ||
523 | *psb_intel_output) | ||
524 | { | ||
525 | u8 response, status; | ||
526 | |||
527 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
528 | SDVO_CMD_GET_CLOCK_RATE_MULT, | ||
529 | NULL, | ||
530 | 0); | ||
531 | |||
532 | status = psb_intel_sdvo_read_response(psb_intel_output, &response, 1); | ||
533 | |||
534 | if (status != SDVO_CMD_STATUS_SUCCESS) { | ||
535 | DRM_DEBUG("Couldn't get SDVO clock rate multiplier\n"); | ||
536 | return SDVO_CLOCK_RATE_MULT_1X; | ||
537 | } else { | ||
538 | DRM_DEBUG("Current clock rate multiplier: %d\n", response); | ||
539 | } | ||
540 | |||
541 | return response; | ||
542 | } | ||
543 | |||
544 | static bool psb_intel_sdvo_set_clock_rate_mult(struct psb_intel_output | ||
545 | *psb_intel_output, u8 val) | ||
546 | { | ||
547 | u8 status; | ||
548 | |||
549 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
550 | SDVO_CMD_SET_CLOCK_RATE_MULT, | ||
551 | &val, | ||
552 | 1); | ||
553 | |||
554 | status = psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); | ||
555 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
556 | return false; | ||
557 | |||
558 | return true; | ||
559 | } | ||
560 | |||
561 | static bool psb_sdvo_set_current_inoutmap(struct psb_intel_output *output, | ||
562 | u32 in0outputmask, | ||
563 | u32 in1outputmask) | ||
564 | { | ||
565 | u8 byArgs[4]; | ||
566 | u8 status; | ||
567 | int i; | ||
568 | struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv; | ||
569 | |||
570 | /* Make all fields of the args/ret to zero */ | ||
571 | memset(byArgs, 0, sizeof(byArgs)); | ||
572 | |||
573 | /* Fill up the argument values; */ | ||
574 | byArgs[0] = (u8) (in0outputmask & 0xFF); | ||
575 | byArgs[1] = (u8) ((in0outputmask >> 8) & 0xFF); | ||
576 | byArgs[2] = (u8) (in1outputmask & 0xFF); | ||
577 | byArgs[3] = (u8) ((in1outputmask >> 8) & 0xFF); | ||
578 | |||
579 | |||
580 | /*save inoutmap arg here*/ | ||
581 | for (i = 0; i < 4; i++) | ||
582 | sdvo_priv->in_out_map[i] = byArgs[0]; | ||
583 | |||
584 | psb_intel_sdvo_write_cmd(output, SDVO_CMD_SET_IN_OUT_MAP, byArgs, 4); | ||
585 | status = psb_intel_sdvo_read_response(output, NULL, 0); | ||
586 | |||
587 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
588 | return false; | ||
589 | return true; | ||
590 | } | ||
591 | |||
592 | |||
593 | static void psb_intel_sdvo_set_iomap(struct psb_intel_output *output) | ||
594 | { | ||
595 | u32 dwCurrentSDVOIn0 = 0; | ||
596 | u32 dwCurrentSDVOIn1 = 0; | ||
597 | u32 dwDevMask = 0; | ||
598 | |||
599 | |||
600 | struct psb_intel_sdvo_priv *sdvo_priv = output->dev_priv; | ||
601 | |||
602 | /* Please DO NOT change the following code. */ | ||
603 | /* SDVOB_IN0 or SDVOB_IN1 ==> sdvo_in0 */ | ||
604 | /* SDVOC_IN0 or SDVOC_IN1 ==> sdvo_in1 */ | ||
605 | if (sdvo_priv->by_input_wiring & (SDVOB_IN0 | SDVOC_IN0)) { | ||
606 | switch (sdvo_priv->active_device) { | ||
607 | case SDVO_DEVICE_LVDS: | ||
608 | dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1; | ||
609 | break; | ||
610 | case SDVO_DEVICE_TMDS: | ||
611 | dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1; | ||
612 | break; | ||
613 | case SDVO_DEVICE_TV: | ||
614 | dwDevMask = | ||
615 | SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 | | ||
616 | SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 | | ||
617 | SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 | | ||
618 | SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1; | ||
619 | break; | ||
620 | case SDVO_DEVICE_CRT: | ||
621 | dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1; | ||
622 | break; | ||
623 | } | ||
624 | dwCurrentSDVOIn0 = (sdvo_priv->active_outputs & dwDevMask); | ||
625 | } else if (sdvo_priv->by_input_wiring & (SDVOB_IN1 | SDVOC_IN1)) { | ||
626 | switch (sdvo_priv->active_device) { | ||
627 | case SDVO_DEVICE_LVDS: | ||
628 | dwDevMask = SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1; | ||
629 | break; | ||
630 | case SDVO_DEVICE_TMDS: | ||
631 | dwDevMask = SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1; | ||
632 | break; | ||
633 | case SDVO_DEVICE_TV: | ||
634 | dwDevMask = | ||
635 | SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_SVID0 | | ||
636 | SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_YPRPB1 | | ||
637 | SDVO_OUTPUT_SVID1 | SDVO_OUTPUT_CVBS1 | | ||
638 | SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1; | ||
639 | break; | ||
640 | case SDVO_DEVICE_CRT: | ||
641 | dwDevMask = SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1; | ||
642 | break; | ||
643 | } | ||
644 | dwCurrentSDVOIn1 = (sdvo_priv->active_outputs & dwDevMask); | ||
645 | } | ||
646 | |||
647 | psb_sdvo_set_current_inoutmap(output, dwCurrentSDVOIn0, | ||
648 | dwCurrentSDVOIn1); | ||
649 | } | ||
650 | |||
651 | |||
652 | static bool psb_intel_sdvo_mode_fixup(struct drm_encoder *encoder, | ||
653 | struct drm_display_mode *mode, | ||
654 | struct drm_display_mode *adjusted_mode) | ||
655 | { | ||
656 | /* Make the CRTC code factor in the SDVO pixel multiplier. The SDVO | ||
657 | * device will be told of the multiplier during mode_set. | ||
658 | */ | ||
659 | adjusted_mode->clock *= psb_intel_sdvo_get_pixel_multiplier(mode); | ||
660 | return true; | ||
661 | } | ||
662 | |||
663 | static void psb_intel_sdvo_mode_set(struct drm_encoder *encoder, | ||
664 | struct drm_display_mode *mode, | ||
665 | struct drm_display_mode *adjusted_mode) | ||
666 | { | ||
667 | struct drm_device *dev = encoder->dev; | ||
668 | struct drm_crtc *crtc = encoder->crtc; | ||
669 | struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc); | ||
670 | struct psb_intel_output *psb_intel_output = | ||
671 | enc_to_psb_intel_output(encoder); | ||
672 | struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; | ||
673 | u16 width, height; | ||
674 | u16 h_blank_len, h_sync_len, v_blank_len, v_sync_len; | ||
675 | u16 h_sync_offset, v_sync_offset; | ||
676 | u32 sdvox; | ||
677 | struct psb_intel_sdvo_dtd output_dtd; | ||
678 | int sdvo_pixel_multiply; | ||
679 | |||
680 | if (!mode) | ||
681 | return; | ||
682 | |||
683 | psb_intel_sdvo_set_target_output(psb_intel_output, 0); | ||
684 | |||
685 | width = mode->crtc_hdisplay; | ||
686 | height = mode->crtc_vdisplay; | ||
687 | |||
688 | /* do some mode translations */ | ||
689 | h_blank_len = mode->crtc_hblank_end - mode->crtc_hblank_start; | ||
690 | h_sync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; | ||
691 | |||
692 | v_blank_len = mode->crtc_vblank_end - mode->crtc_vblank_start; | ||
693 | v_sync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; | ||
694 | |||
695 | h_sync_offset = mode->crtc_hsync_start - mode->crtc_hblank_start; | ||
696 | v_sync_offset = mode->crtc_vsync_start - mode->crtc_vblank_start; | ||
697 | |||
698 | output_dtd.part1.clock = mode->clock / 10; | ||
699 | output_dtd.part1.h_active = width & 0xff; | ||
700 | output_dtd.part1.h_blank = h_blank_len & 0xff; | ||
701 | output_dtd.part1.h_high = (((width >> 8) & 0xf) << 4) | | ||
702 | ((h_blank_len >> 8) & 0xf); | ||
703 | output_dtd.part1.v_active = height & 0xff; | ||
704 | output_dtd.part1.v_blank = v_blank_len & 0xff; | ||
705 | output_dtd.part1.v_high = (((height >> 8) & 0xf) << 4) | | ||
706 | ((v_blank_len >> 8) & 0xf); | ||
707 | |||
708 | output_dtd.part2.h_sync_off = h_sync_offset; | ||
709 | output_dtd.part2.h_sync_width = h_sync_len & 0xff; | ||
710 | output_dtd.part2.v_sync_off_width = (v_sync_offset & 0xf) << 4 | | ||
711 | (v_sync_len & 0xf); | ||
712 | output_dtd.part2.sync_off_width_high = | ||
713 | ((h_sync_offset & 0x300) >> 2) | ((h_sync_len & 0x300) >> 4) | | ||
714 | ((v_sync_offset & 0x30) >> 2) | ((v_sync_len & 0x30) >> 4); | ||
715 | |||
716 | output_dtd.part2.dtd_flags = 0x18; | ||
717 | if (mode->flags & DRM_MODE_FLAG_PHSYNC) | ||
718 | output_dtd.part2.dtd_flags |= 0x2; | ||
719 | if (mode->flags & DRM_MODE_FLAG_PVSYNC) | ||
720 | output_dtd.part2.dtd_flags |= 0x4; | ||
721 | |||
722 | output_dtd.part2.sdvo_flags = 0; | ||
723 | output_dtd.part2.v_sync_off_high = v_sync_offset & 0xc0; | ||
724 | output_dtd.part2.reserved = 0; | ||
725 | |||
726 | /* Set the output timing to the screen */ | ||
727 | psb_intel_sdvo_set_target_output(psb_intel_output, | ||
728 | sdvo_priv->active_outputs); | ||
729 | |||
730 | /* Set the input timing to the screen. Assume always input 0. */ | ||
731 | psb_intel_sdvo_set_target_input(psb_intel_output, true, false); | ||
732 | |||
733 | psb_intel_sdvo_set_output_timing(psb_intel_output, &output_dtd); | ||
734 | |||
735 | /* We would like to use i830_sdvo_create_preferred_input_timing() to | ||
736 | * provide the device with a timing it can support, if it supports that | ||
737 | * feature. However, presumably we would need to adjust the CRTC to | ||
738 | * output the preferred timing, and we don't support that currently. | ||
739 | */ | ||
740 | psb_intel_sdvo_set_input_timing(psb_intel_output, &output_dtd); | ||
741 | |||
742 | switch (psb_intel_sdvo_get_pixel_multiplier(mode)) { | ||
743 | case 1: | ||
744 | psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, | ||
745 | SDVO_CLOCK_RATE_MULT_1X); | ||
746 | break; | ||
747 | case 2: | ||
748 | psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, | ||
749 | SDVO_CLOCK_RATE_MULT_2X); | ||
750 | break; | ||
751 | case 4: | ||
752 | psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, | ||
753 | SDVO_CLOCK_RATE_MULT_4X); | ||
754 | break; | ||
755 | } | ||
756 | |||
757 | /* Set the SDVO control regs. */ | ||
758 | sdvox = REG_READ(sdvo_priv->output_device); | ||
759 | switch (sdvo_priv->output_device) { | ||
760 | case SDVOB: | ||
761 | sdvox &= SDVOB_PRESERVE_MASK; | ||
762 | break; | ||
763 | case SDVOC: | ||
764 | sdvox &= SDVOC_PRESERVE_MASK; | ||
765 | break; | ||
766 | } | ||
767 | sdvox |= (9 << 19) | SDVO_BORDER_ENABLE; | ||
768 | if (psb_intel_crtc->pipe == 1) | ||
769 | sdvox |= SDVO_PIPE_B_SELECT; | ||
770 | |||
771 | sdvo_pixel_multiply = psb_intel_sdvo_get_pixel_multiplier(mode); | ||
772 | |||
773 | psb_intel_sdvo_write_sdvox(psb_intel_output, sdvox); | ||
774 | |||
775 | psb_intel_sdvo_set_iomap(psb_intel_output); | ||
776 | } | ||
777 | |||
778 | static void psb_intel_sdvo_dpms(struct drm_encoder *encoder, int mode) | ||
779 | { | ||
780 | struct drm_device *dev = encoder->dev; | ||
781 | struct psb_intel_output *psb_intel_output = | ||
782 | enc_to_psb_intel_output(encoder); | ||
783 | struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; | ||
784 | u32 temp; | ||
785 | |||
786 | if (mode != DRM_MODE_DPMS_ON) { | ||
787 | psb_intel_sdvo_set_active_outputs(psb_intel_output, 0); | ||
788 | if (0) | ||
789 | psb_intel_sdvo_set_encoder_power_state( | ||
790 | psb_intel_output, | ||
791 | mode); | ||
792 | |||
793 | if (mode == DRM_MODE_DPMS_OFF) { | ||
794 | temp = REG_READ(sdvo_priv->output_device); | ||
795 | if ((temp & SDVO_ENABLE) != 0) { | ||
796 | psb_intel_sdvo_write_sdvox(psb_intel_output, | ||
797 | temp & | ||
798 | ~SDVO_ENABLE); | ||
799 | } | ||
800 | } | ||
801 | } else { | ||
802 | bool input1, input2; | ||
803 | int i; | ||
804 | u8 status; | ||
805 | |||
806 | temp = REG_READ(sdvo_priv->output_device); | ||
807 | if ((temp & SDVO_ENABLE) == 0) | ||
808 | psb_intel_sdvo_write_sdvox(psb_intel_output, | ||
809 | temp | SDVO_ENABLE); | ||
810 | for (i = 0; i < 2; i++) | ||
811 | psb_intel_wait_for_vblank(dev); | ||
812 | |||
813 | status = | ||
814 | psb_intel_sdvo_get_trained_inputs(psb_intel_output, | ||
815 | &input1, | ||
816 | &input2); | ||
817 | |||
818 | |||
819 | /* Warn if the device reported failure to sync. | ||
820 | * A lot of SDVO devices fail to notify of sync, but it's | ||
821 | * a given it the status is a success, we succeeded. | ||
822 | */ | ||
823 | if (status == SDVO_CMD_STATUS_SUCCESS && !input1) { | ||
824 | DRM_DEBUG | ||
825 | ("First %s output reported failure to sync\n", | ||
826 | SDVO_NAME(sdvo_priv)); | ||
827 | } | ||
828 | |||
829 | if (0) | ||
830 | psb_intel_sdvo_set_encoder_power_state( | ||
831 | psb_intel_output, | ||
832 | mode); | ||
833 | psb_intel_sdvo_set_active_outputs(psb_intel_output, | ||
834 | sdvo_priv->active_outputs); | ||
835 | } | ||
836 | return; | ||
837 | } | ||
838 | |||
839 | static void psb_intel_sdvo_save(struct drm_connector *connector) | ||
840 | { | ||
841 | struct drm_device *dev = connector->dev; | ||
842 | struct psb_intel_output *psb_intel_output = | ||
843 | to_psb_intel_output(connector); | ||
844 | struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; | ||
845 | /*int o;*/ | ||
846 | |||
847 | sdvo_priv->save_sdvo_mult = | ||
848 | psb_intel_sdvo_get_clock_rate_mult(psb_intel_output); | ||
849 | psb_intel_sdvo_get_active_outputs(psb_intel_output, | ||
850 | &sdvo_priv->save_active_outputs); | ||
851 | |||
852 | if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { | ||
853 | psb_intel_sdvo_set_target_input(psb_intel_output, | ||
854 | true, | ||
855 | false); | ||
856 | psb_intel_sdvo_get_input_timing(psb_intel_output, | ||
857 | &sdvo_priv->save_input_dtd_1); | ||
858 | } | ||
859 | |||
860 | if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) { | ||
861 | psb_intel_sdvo_set_target_input(psb_intel_output, | ||
862 | false, | ||
863 | true); | ||
864 | psb_intel_sdvo_get_input_timing(psb_intel_output, | ||
865 | &sdvo_priv->save_input_dtd_2); | ||
866 | } | ||
867 | sdvo_priv->save_SDVOX = REG_READ(sdvo_priv->output_device); | ||
868 | |||
869 | /*TODO: save the in_out_map state*/ | ||
870 | } | ||
871 | |||
872 | static void psb_intel_sdvo_restore(struct drm_connector *connector) | ||
873 | { | ||
874 | struct drm_device *dev = connector->dev; | ||
875 | struct psb_intel_output *psb_intel_output = | ||
876 | to_psb_intel_output(connector); | ||
877 | struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; | ||
878 | /*int o;*/ | ||
879 | int i; | ||
880 | bool input1, input2; | ||
881 | u8 status; | ||
882 | |||
883 | psb_intel_sdvo_set_active_outputs(psb_intel_output, 0); | ||
884 | |||
885 | if (sdvo_priv->caps.sdvo_inputs_mask & 0x1) { | ||
886 | psb_intel_sdvo_set_target_input(psb_intel_output, true, false); | ||
887 | psb_intel_sdvo_set_input_timing(psb_intel_output, | ||
888 | &sdvo_priv->save_input_dtd_1); | ||
889 | } | ||
890 | |||
891 | if (sdvo_priv->caps.sdvo_inputs_mask & 0x2) { | ||
892 | psb_intel_sdvo_set_target_input(psb_intel_output, false, true); | ||
893 | psb_intel_sdvo_set_input_timing(psb_intel_output, | ||
894 | &sdvo_priv->save_input_dtd_2); | ||
895 | } | ||
896 | |||
897 | psb_intel_sdvo_set_clock_rate_mult(psb_intel_output, | ||
898 | sdvo_priv->save_sdvo_mult); | ||
899 | |||
900 | REG_WRITE(sdvo_priv->output_device, sdvo_priv->save_SDVOX); | ||
901 | |||
902 | if (sdvo_priv->save_SDVOX & SDVO_ENABLE) { | ||
903 | for (i = 0; i < 2; i++) | ||
904 | psb_intel_wait_for_vblank(dev); | ||
905 | status = | ||
906 | psb_intel_sdvo_get_trained_inputs(psb_intel_output, | ||
907 | &input1, | ||
908 | &input2); | ||
909 | if (status == SDVO_CMD_STATUS_SUCCESS && !input1) | ||
910 | DRM_DEBUG | ||
911 | ("First %s output reported failure to sync\n", | ||
912 | SDVO_NAME(sdvo_priv)); | ||
913 | } | ||
914 | |||
915 | psb_intel_sdvo_set_active_outputs(psb_intel_output, | ||
916 | sdvo_priv->save_active_outputs); | ||
917 | |||
918 | /*TODO: restore in_out_map*/ | ||
919 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
920 | SDVO_CMD_SET_IN_OUT_MAP, | ||
921 | sdvo_priv->in_out_map, | ||
922 | 4); | ||
923 | |||
924 | psb_intel_sdvo_read_response(psb_intel_output, NULL, 0); | ||
925 | } | ||
926 | |||
927 | static int psb_intel_sdvo_mode_valid(struct drm_connector *connector, | ||
928 | struct drm_display_mode *mode) | ||
929 | { | ||
930 | struct psb_intel_output *psb_intel_output = | ||
931 | to_psb_intel_output(connector); | ||
932 | struct psb_intel_sdvo_priv *sdvo_priv = psb_intel_output->dev_priv; | ||
933 | |||
934 | if (mode->flags & DRM_MODE_FLAG_DBLSCAN) | ||
935 | return MODE_NO_DBLESCAN; | ||
936 | |||
937 | if (sdvo_priv->pixel_clock_min > mode->clock) | ||
938 | return MODE_CLOCK_LOW; | ||
939 | |||
940 | if (sdvo_priv->pixel_clock_max < mode->clock) | ||
941 | return MODE_CLOCK_HIGH; | ||
942 | |||
943 | return MODE_OK; | ||
944 | } | ||
945 | |||
946 | static bool psb_intel_sdvo_get_capabilities( | ||
947 | struct psb_intel_output *psb_intel_output, | ||
948 | struct psb_intel_sdvo_caps *caps) | ||
949 | { | ||
950 | u8 status; | ||
951 | |||
952 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
953 | SDVO_CMD_GET_DEVICE_CAPS, | ||
954 | NULL, | ||
955 | 0); | ||
956 | status = psb_intel_sdvo_read_response(psb_intel_output, | ||
957 | caps, | ||
958 | sizeof(*caps)); | ||
959 | if (status != SDVO_CMD_STATUS_SUCCESS) | ||
960 | return false; | ||
961 | |||
962 | return true; | ||
963 | } | ||
964 | |||
965 | struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev, int sdvoB) | ||
966 | { | ||
967 | struct drm_connector *connector = NULL; | ||
968 | struct psb_intel_output *iout = NULL; | ||
969 | struct psb_intel_sdvo_priv *sdvo; | ||
970 | |||
971 | /* find the sdvo connector */ | ||
972 | list_for_each_entry(connector, &dev->mode_config.connector_list, | ||
973 | head) { | ||
974 | iout = to_psb_intel_output(connector); | ||
975 | |||
976 | if (iout->type != INTEL_OUTPUT_SDVO) | ||
977 | continue; | ||
978 | |||
979 | sdvo = iout->dev_priv; | ||
980 | |||
981 | if (sdvo->output_device == SDVOB && sdvoB) | ||
982 | return connector; | ||
983 | |||
984 | if (sdvo->output_device == SDVOC && !sdvoB) | ||
985 | return connector; | ||
986 | |||
987 | } | ||
988 | |||
989 | return NULL; | ||
990 | } | ||
991 | |||
992 | int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector) | ||
993 | { | ||
994 | u8 response[2]; | ||
995 | u8 status; | ||
996 | struct psb_intel_output *psb_intel_output; | ||
997 | |||
998 | if (!connector) | ||
999 | return 0; | ||
1000 | |||
1001 | psb_intel_output = to_psb_intel_output(connector); | ||
1002 | |||
1003 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
1004 | SDVO_CMD_GET_HOT_PLUG_SUPPORT, | ||
1005 | NULL, | ||
1006 | 0); | ||
1007 | status = psb_intel_sdvo_read_response(psb_intel_output, | ||
1008 | &response, | ||
1009 | 2); | ||
1010 | |||
1011 | if (response[0] != 0) | ||
1012 | return 1; | ||
1013 | |||
1014 | return 0; | ||
1015 | } | ||
1016 | |||
1017 | void psb_intel_sdvo_set_hotplug(struct drm_connector *connector, int on) | ||
1018 | { | ||
1019 | u8 response[2]; | ||
1020 | u8 status; | ||
1021 | struct psb_intel_output *psb_intel_output = | ||
1022 | to_psb_intel_output(connector); | ||
1023 | |||
1024 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
1025 | SDVO_CMD_GET_ACTIVE_HOT_PLUG, | ||
1026 | NULL, | ||
1027 | 0); | ||
1028 | psb_intel_sdvo_read_response(psb_intel_output, &response, 2); | ||
1029 | |||
1030 | if (on) { | ||
1031 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
1032 | SDVO_CMD_GET_HOT_PLUG_SUPPORT, NULL, | ||
1033 | 0); | ||
1034 | status = psb_intel_sdvo_read_response(psb_intel_output, | ||
1035 | &response, | ||
1036 | 2); | ||
1037 | |||
1038 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
1039 | SDVO_CMD_SET_ACTIVE_HOT_PLUG, | ||
1040 | &response, 2); | ||
1041 | } else { | ||
1042 | response[0] = 0; | ||
1043 | response[1] = 0; | ||
1044 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
1045 | SDVO_CMD_SET_ACTIVE_HOT_PLUG, | ||
1046 | &response, 2); | ||
1047 | } | ||
1048 | |||
1049 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
1050 | SDVO_CMD_GET_ACTIVE_HOT_PLUG, | ||
1051 | NULL, | ||
1052 | 0); | ||
1053 | psb_intel_sdvo_read_response(psb_intel_output, &response, 2); | ||
1054 | } | ||
1055 | |||
1056 | static enum drm_connector_status psb_intel_sdvo_detect(struct drm_connector | ||
1057 | *connector, bool force) | ||
1058 | { | ||
1059 | u8 response[2]; | ||
1060 | u8 status; | ||
1061 | struct psb_intel_output *psb_intel_output = | ||
1062 | to_psb_intel_output(connector); | ||
1063 | |||
1064 | psb_intel_sdvo_write_cmd(psb_intel_output, | ||
1065 | SDVO_CMD_GET_ATTACHED_DISPLAYS, | ||
1066 | NULL, | ||
1067 | 0); | ||
1068 | status = psb_intel_sdvo_read_response(psb_intel_output, &response, 2); | ||
1069 | |||
1070 | DRM_DEBUG("SDVO response %d %d\n", response[0], response[1]); | ||
1071 | if ((response[0] != 0) || (response[1] != 0)) | ||
1072 | return connector_status_connected; | ||
1073 | else | ||
1074 | return connector_status_disconnected; | ||
1075 | } | ||
1076 | |||
1077 | static int psb_intel_sdvo_get_modes(struct drm_connector *connector) | ||
1078 | { | ||
1079 | struct psb_intel_output *psb_intel_output = | ||
1080 | to_psb_intel_output(connector); | ||
1081 | |||
1082 | /* set the bus switch and get the modes */ | ||
1083 | psb_intel_sdvo_set_control_bus_switch(psb_intel_output, | ||
1084 | SDVO_CONTROL_BUS_DDC2); | ||
1085 | psb_intel_ddc_get_modes(psb_intel_output); | ||
1086 | |||
1087 | if (list_empty(&connector->probed_modes)) | ||
1088 | return 0; | ||
1089 | return 1; | ||
1090 | } | ||
1091 | |||
1092 | static void psb_intel_sdvo_destroy(struct drm_connector *connector) | ||
1093 | { | ||
1094 | struct psb_intel_output *psb_intel_output = | ||
1095 | to_psb_intel_output(connector); | ||
1096 | |||
1097 | if (psb_intel_output->i2c_bus) | ||
1098 | psb_intel_i2c_destroy(psb_intel_output->i2c_bus); | ||
1099 | drm_sysfs_connector_remove(connector); | ||
1100 | drm_connector_cleanup(connector); | ||
1101 | kfree(psb_intel_output); | ||
1102 | } | ||
1103 | |||
1104 | static const struct drm_encoder_helper_funcs psb_intel_sdvo_helper_funcs = { | ||
1105 | .dpms = psb_intel_sdvo_dpms, | ||
1106 | .mode_fixup = psb_intel_sdvo_mode_fixup, | ||
1107 | .prepare = psb_intel_encoder_prepare, | ||
1108 | .mode_set = psb_intel_sdvo_mode_set, | ||
1109 | .commit = psb_intel_encoder_commit, | ||
1110 | }; | ||
1111 | |||
1112 | static const struct drm_connector_funcs psb_intel_sdvo_connector_funcs = { | ||
1113 | .dpms = drm_helper_connector_dpms, | ||
1114 | .save = psb_intel_sdvo_save, | ||
1115 | .restore = psb_intel_sdvo_restore, | ||
1116 | .detect = psb_intel_sdvo_detect, | ||
1117 | .fill_modes = drm_helper_probe_single_connector_modes, | ||
1118 | .destroy = psb_intel_sdvo_destroy, | ||
1119 | }; | ||
1120 | |||
1121 | static const struct drm_connector_helper_funcs | ||
1122 | psb_intel_sdvo_connector_helper_funcs = { | ||
1123 | .get_modes = psb_intel_sdvo_get_modes, | ||
1124 | .mode_valid = psb_intel_sdvo_mode_valid, | ||
1125 | .best_encoder = psb_intel_best_encoder, | ||
1126 | }; | ||
1127 | |||
1128 | void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder) | ||
1129 | { | ||
1130 | drm_encoder_cleanup(encoder); | ||
1131 | } | ||
1132 | |||
1133 | static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = { | ||
1134 | .destroy = psb_intel_sdvo_enc_destroy, | ||
1135 | }; | ||
1136 | |||
1137 | |||
1138 | void psb_intel_sdvo_init(struct drm_device *dev, int output_device) | ||
1139 | { | ||
1140 | struct drm_connector *connector; | ||
1141 | struct psb_intel_output *psb_intel_output; | ||
1142 | struct psb_intel_sdvo_priv *sdvo_priv; | ||
1143 | struct psb_intel_i2c_chan *i2cbus = NULL; | ||
1144 | int connector_type; | ||
1145 | u8 ch[0x40]; | ||
1146 | int i; | ||
1147 | int encoder_type, output_id; | ||
1148 | |||
1149 | psb_intel_output = | ||
1150 | kcalloc(sizeof(struct psb_intel_output) + | ||
1151 | sizeof(struct psb_intel_sdvo_priv), 1, GFP_KERNEL); | ||
1152 | if (!psb_intel_output) | ||
1153 | return; | ||
1154 | |||
1155 | connector = &psb_intel_output->base; | ||
1156 | |||
1157 | drm_connector_init(dev, connector, &psb_intel_sdvo_connector_funcs, | ||
1158 | DRM_MODE_CONNECTOR_Unknown); | ||
1159 | drm_connector_helper_add(connector, | ||
1160 | &psb_intel_sdvo_connector_helper_funcs); | ||
1161 | sdvo_priv = (struct psb_intel_sdvo_priv *) (psb_intel_output + 1); | ||
1162 | psb_intel_output->type = INTEL_OUTPUT_SDVO; | ||
1163 | |||
1164 | connector->interlace_allowed = 0; | ||
1165 | connector->doublescan_allowed = 0; | ||
1166 | |||
1167 | /* setup the DDC bus. */ | ||
1168 | if (output_device == SDVOB) | ||
1169 | i2cbus = | ||
1170 | psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOB"); | ||
1171 | else | ||
1172 | i2cbus = | ||
1173 | psb_intel_i2c_create(dev, GPIOE, "SDVOCTRL_E for SDVOC"); | ||
1174 | |||
1175 | if (!i2cbus) | ||
1176 | goto err_connector; | ||
1177 | |||
1178 | sdvo_priv->i2c_bus = i2cbus; | ||
1179 | |||
1180 | if (output_device == SDVOB) { | ||
1181 | output_id = 1; | ||
1182 | sdvo_priv->by_input_wiring = SDVOB_IN0; | ||
1183 | sdvo_priv->i2c_bus->slave_addr = 0x38; | ||
1184 | } else { | ||
1185 | output_id = 2; | ||
1186 | sdvo_priv->i2c_bus->slave_addr = 0x39; | ||
1187 | } | ||
1188 | |||
1189 | sdvo_priv->output_device = output_device; | ||
1190 | psb_intel_output->i2c_bus = i2cbus; | ||
1191 | psb_intel_output->dev_priv = sdvo_priv; | ||
1192 | |||
1193 | |||
1194 | /* Read the regs to test if we can talk to the device */ | ||
1195 | for (i = 0; i < 0x40; i++) { | ||
1196 | if (!psb_intel_sdvo_read_byte(psb_intel_output, i, &ch[i])) { | ||
1197 | dev_dbg(dev->dev, "No SDVO device found on SDVO%c\n", | ||
1198 | output_device == SDVOB ? 'B' : 'C'); | ||
1199 | goto err_i2c; | ||
1200 | } | ||
1201 | } | ||
1202 | |||
1203 | psb_intel_sdvo_get_capabilities(psb_intel_output, &sdvo_priv->caps); | ||
1204 | |||
1205 | memset(&sdvo_priv->active_outputs, 0, | ||
1206 | sizeof(sdvo_priv->active_outputs)); | ||
1207 | |||
1208 | /* TODO, CVBS, SVID, YPRPB & SCART outputs. */ | ||
1209 | if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB0) { | ||
1210 | sdvo_priv->active_outputs = SDVO_OUTPUT_RGB0; | ||
1211 | sdvo_priv->active_device = SDVO_DEVICE_CRT; | ||
1212 | connector->display_info.subpixel_order = | ||
1213 | SubPixelHorizontalRGB; | ||
1214 | encoder_type = DRM_MODE_ENCODER_DAC; | ||
1215 | connector_type = DRM_MODE_CONNECTOR_VGA; | ||
1216 | } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_RGB1) { | ||
1217 | sdvo_priv->active_outputs = SDVO_OUTPUT_RGB1; | ||
1218 | sdvo_priv->active_outputs = SDVO_DEVICE_CRT; | ||
1219 | connector->display_info.subpixel_order = | ||
1220 | SubPixelHorizontalRGB; | ||
1221 | encoder_type = DRM_MODE_ENCODER_DAC; | ||
1222 | connector_type = DRM_MODE_CONNECTOR_VGA; | ||
1223 | } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS0) { | ||
1224 | sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS0; | ||
1225 | sdvo_priv->active_device = SDVO_DEVICE_TMDS; | ||
1226 | connector->display_info.subpixel_order = | ||
1227 | SubPixelHorizontalRGB; | ||
1228 | encoder_type = DRM_MODE_ENCODER_TMDS; | ||
1229 | connector_type = DRM_MODE_CONNECTOR_DVID; | ||
1230 | } else if (sdvo_priv->caps.output_flags & SDVO_OUTPUT_TMDS1) { | ||
1231 | sdvo_priv->active_outputs = SDVO_OUTPUT_TMDS1; | ||
1232 | sdvo_priv->active_device = SDVO_DEVICE_TMDS; | ||
1233 | connector->display_info.subpixel_order = | ||
1234 | SubPixelHorizontalRGB; | ||
1235 | encoder_type = DRM_MODE_ENCODER_TMDS; | ||
1236 | connector_type = DRM_MODE_CONNECTOR_DVID; | ||
1237 | } else { | ||
1238 | unsigned char bytes[2]; | ||
1239 | |||
1240 | memcpy(bytes, &sdvo_priv->caps.output_flags, 2); | ||
1241 | dev_dbg(dev->dev, "%s: No active RGB or TMDS outputs (0x%02x%02x)\n", | ||
1242 | SDVO_NAME(sdvo_priv), bytes[0], bytes[1]); | ||
1243 | goto err_i2c; | ||
1244 | } | ||
1245 | |||
1246 | drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_sdvo_enc_funcs, | ||
1247 | encoder_type); | ||
1248 | drm_encoder_helper_add(&psb_intel_output->enc, | ||
1249 | &psb_intel_sdvo_helper_funcs); | ||
1250 | connector->connector_type = connector_type; | ||
1251 | |||
1252 | drm_mode_connector_attach_encoder(&psb_intel_output->base, | ||
1253 | &psb_intel_output->enc); | ||
1254 | drm_sysfs_connector_add(connector); | ||
1255 | |||
1256 | /* Set the input timing to the screen. Assume always input 0. */ | ||
1257 | psb_intel_sdvo_set_target_input(psb_intel_output, true, false); | ||
1258 | |||
1259 | psb_intel_sdvo_get_input_pixel_clock_range(psb_intel_output, | ||
1260 | &sdvo_priv->pixel_clock_min, | ||
1261 | &sdvo_priv-> | ||
1262 | pixel_clock_max); | ||
1263 | |||
1264 | |||
1265 | dev_dbg(dev->dev, "%s device VID/DID: %02X:%02X.%02X, " | ||
1266 | "clock range %dMHz - %dMHz, " | ||
1267 | "input 1: %c, input 2: %c, " | ||
1268 | "output 1: %c, output 2: %c\n", | ||
1269 | SDVO_NAME(sdvo_priv), | ||
1270 | sdvo_priv->caps.vendor_id, sdvo_priv->caps.device_id, | ||
1271 | sdvo_priv->caps.device_rev_id, | ||
1272 | sdvo_priv->pixel_clock_min / 1000, | ||
1273 | sdvo_priv->pixel_clock_max / 1000, | ||
1274 | (sdvo_priv->caps.sdvo_inputs_mask & 0x1) ? 'Y' : 'N', | ||
1275 | (sdvo_priv->caps.sdvo_inputs_mask & 0x2) ? 'Y' : 'N', | ||
1276 | /* check currently supported outputs */ | ||
1277 | sdvo_priv->caps.output_flags & | ||
1278 | (SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_RGB0) ? 'Y' : 'N', | ||
1279 | sdvo_priv->caps.output_flags & | ||
1280 | (SDVO_OUTPUT_TMDS1 | SDVO_OUTPUT_RGB1) ? 'Y' : 'N'); | ||
1281 | |||
1282 | psb_intel_output->ddc_bus = i2cbus; | ||
1283 | |||
1284 | return; | ||
1285 | |||
1286 | err_i2c: | ||
1287 | psb_intel_i2c_destroy(psb_intel_output->i2c_bus); | ||
1288 | err_connector: | ||
1289 | drm_connector_cleanup(connector); | ||
1290 | kfree(psb_intel_output); | ||
1291 | |||
1292 | return; | ||
1293 | } | ||
diff --git a/drivers/staging/gma500/psb_intel_sdvo_regs.h b/drivers/staging/gma500/psb_intel_sdvo_regs.h deleted file mode 100644 index 96862ea65aba..000000000000 --- a/drivers/staging/gma500/psb_intel_sdvo_regs.h +++ /dev/null | |||
@@ -1,338 +0,0 @@ | |||
1 | /* | ||
2 | * SDVO command definitions and structures. | ||
3 | * | ||
4 | * Copyright (c) 2008, Intel Corporation | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License along with | ||
16 | * this program; if not, write to the Free Software Foundation, Inc., | ||
17 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | * | ||
19 | * Authors: | ||
20 | * Eric Anholt <eric@anholt.net> | ||
21 | */ | ||
22 | |||
23 | #define SDVO_OUTPUT_FIRST (0) | ||
24 | #define SDVO_OUTPUT_TMDS0 (1 << 0) | ||
25 | #define SDVO_OUTPUT_RGB0 (1 << 1) | ||
26 | #define SDVO_OUTPUT_CVBS0 (1 << 2) | ||
27 | #define SDVO_OUTPUT_SVID0 (1 << 3) | ||
28 | #define SDVO_OUTPUT_YPRPB0 (1 << 4) | ||
29 | #define SDVO_OUTPUT_SCART0 (1 << 5) | ||
30 | #define SDVO_OUTPUT_LVDS0 (1 << 6) | ||
31 | #define SDVO_OUTPUT_TMDS1 (1 << 8) | ||
32 | #define SDVO_OUTPUT_RGB1 (1 << 9) | ||
33 | #define SDVO_OUTPUT_CVBS1 (1 << 10) | ||
34 | #define SDVO_OUTPUT_SVID1 (1 << 11) | ||
35 | #define SDVO_OUTPUT_YPRPB1 (1 << 12) | ||
36 | #define SDVO_OUTPUT_SCART1 (1 << 13) | ||
37 | #define SDVO_OUTPUT_LVDS1 (1 << 14) | ||
38 | #define SDVO_OUTPUT_LAST (14) | ||
39 | |||
40 | struct psb_intel_sdvo_caps { | ||
41 | u8 vendor_id; | ||
42 | u8 device_id; | ||
43 | u8 device_rev_id; | ||
44 | u8 sdvo_version_major; | ||
45 | u8 sdvo_version_minor; | ||
46 | unsigned int sdvo_inputs_mask:2; | ||
47 | unsigned int smooth_scaling:1; | ||
48 | unsigned int sharp_scaling:1; | ||
49 | unsigned int up_scaling:1; | ||
50 | unsigned int down_scaling:1; | ||
51 | unsigned int stall_support:1; | ||
52 | unsigned int pad:1; | ||
53 | u16 output_flags; | ||
54 | } __packed; | ||
55 | |||
56 | /** This matches the EDID DTD structure, more or less */ | ||
57 | struct psb_intel_sdvo_dtd { | ||
58 | struct { | ||
59 | u16 clock; /**< pixel clock, in 10kHz units */ | ||
60 | u8 h_active; /**< lower 8 bits (pixels) */ | ||
61 | u8 h_blank; /**< lower 8 bits (pixels) */ | ||
62 | u8 h_high; /**< upper 4 bits each h_active, h_blank */ | ||
63 | u8 v_active; /**< lower 8 bits (lines) */ | ||
64 | u8 v_blank; /**< lower 8 bits (lines) */ | ||
65 | u8 v_high; /**< upper 4 bits each v_active, v_blank */ | ||
66 | } part1; | ||
67 | |||
68 | struct { | ||
69 | u8 h_sync_off; | ||
70 | /**< lower 8 bits, from hblank start */ | ||
71 | u8 h_sync_width;/**< lower 8 bits (pixels) */ | ||
72 | /** lower 4 bits each vsync offset, vsync width */ | ||
73 | u8 v_sync_off_width; | ||
74 | /** | ||
75 | * 2 high bits of hsync offset, 2 high bits of hsync width, | ||
76 | * bits 4-5 of vsync offset, and 2 high bits of vsync width. | ||
77 | */ | ||
78 | u8 sync_off_width_high; | ||
79 | u8 dtd_flags; | ||
80 | u8 sdvo_flags; | ||
81 | /** bits 6-7 of vsync offset at bits 6-7 */ | ||
82 | u8 v_sync_off_high; | ||
83 | u8 reserved; | ||
84 | } part2; | ||
85 | } __packed; | ||
86 | |||
87 | struct psb_intel_sdvo_pixel_clock_range { | ||
88 | u16 min; /**< pixel clock, in 10kHz units */ | ||
89 | u16 max; /**< pixel clock, in 10kHz units */ | ||
90 | } __packed; | ||
91 | |||
92 | struct psb_intel_sdvo_preferred_input_timing_args { | ||
93 | u16 clock; | ||
94 | u16 width; | ||
95 | u16 height; | ||
96 | } __packed; | ||
97 | |||
98 | /* I2C registers for SDVO */ | ||
99 | #define SDVO_I2C_ARG_0 0x07 | ||
100 | #define SDVO_I2C_ARG_1 0x06 | ||
101 | #define SDVO_I2C_ARG_2 0x05 | ||
102 | #define SDVO_I2C_ARG_3 0x04 | ||
103 | #define SDVO_I2C_ARG_4 0x03 | ||
104 | #define SDVO_I2C_ARG_5 0x02 | ||
105 | #define SDVO_I2C_ARG_6 0x01 | ||
106 | #define SDVO_I2C_ARG_7 0x00 | ||
107 | #define SDVO_I2C_OPCODE 0x08 | ||
108 | #define SDVO_I2C_CMD_STATUS 0x09 | ||
109 | #define SDVO_I2C_RETURN_0 0x0a | ||
110 | #define SDVO_I2C_RETURN_1 0x0b | ||
111 | #define SDVO_I2C_RETURN_2 0x0c | ||
112 | #define SDVO_I2C_RETURN_3 0x0d | ||
113 | #define SDVO_I2C_RETURN_4 0x0e | ||
114 | #define SDVO_I2C_RETURN_5 0x0f | ||
115 | #define SDVO_I2C_RETURN_6 0x10 | ||
116 | #define SDVO_I2C_RETURN_7 0x11 | ||
117 | #define SDVO_I2C_VENDOR_BEGIN 0x20 | ||
118 | |||
119 | /* Status results */ | ||
120 | #define SDVO_CMD_STATUS_POWER_ON 0x0 | ||
121 | #define SDVO_CMD_STATUS_SUCCESS 0x1 | ||
122 | #define SDVO_CMD_STATUS_NOTSUPP 0x2 | ||
123 | #define SDVO_CMD_STATUS_INVALID_ARG 0x3 | ||
124 | #define SDVO_CMD_STATUS_PENDING 0x4 | ||
125 | #define SDVO_CMD_STATUS_TARGET_NOT_SPECIFIED 0x5 | ||
126 | #define SDVO_CMD_STATUS_SCALING_NOT_SUPP 0x6 | ||
127 | |||
128 | /* SDVO commands, argument/result registers */ | ||
129 | |||
130 | #define SDVO_CMD_RESET 0x01 | ||
131 | |||
132 | /** Returns a struct psb_intel_sdvo_caps */ | ||
133 | #define SDVO_CMD_GET_DEVICE_CAPS 0x02 | ||
134 | |||
135 | #define SDVO_CMD_GET_FIRMWARE_REV 0x86 | ||
136 | # define SDVO_DEVICE_FIRMWARE_MINOR SDVO_I2C_RETURN_0 | ||
137 | # define SDVO_DEVICE_FIRMWARE_MAJOR SDVO_I2C_RETURN_1 | ||
138 | # define SDVO_DEVICE_FIRMWARE_PATCH SDVO_I2C_RETURN_2 | ||
139 | |||
140 | /** | ||
141 | * Reports which inputs are trained (managed to sync). | ||
142 | * | ||
143 | * Devices must have trained within 2 vsyncs of a mode change. | ||
144 | */ | ||
145 | #define SDVO_CMD_GET_TRAINED_INPUTS 0x03 | ||
146 | struct psb_intel_sdvo_get_trained_inputs_response { | ||
147 | unsigned int input0_trained:1; | ||
148 | unsigned int input1_trained:1; | ||
149 | unsigned int pad:6; | ||
150 | } __packed; | ||
151 | |||
152 | /** Returns a struct psb_intel_sdvo_output_flags of active outputs. */ | ||
153 | #define SDVO_CMD_GET_ACTIVE_OUTPUTS 0x04 | ||
154 | |||
155 | /** | ||
156 | * Sets the current set of active outputs. | ||
157 | * | ||
158 | * Takes a struct psb_intel_sdvo_output_flags. | ||
159 | * Must be preceded by a SET_IN_OUT_MAP | ||
160 | * on multi-output devices. | ||
161 | */ | ||
162 | #define SDVO_CMD_SET_ACTIVE_OUTPUTS 0x05 | ||
163 | |||
164 | /** | ||
165 | * Returns the current mapping of SDVO inputs to outputs on the device. | ||
166 | * | ||
167 | * Returns two struct psb_intel_sdvo_output_flags structures. | ||
168 | */ | ||
169 | #define SDVO_CMD_GET_IN_OUT_MAP 0x06 | ||
170 | |||
171 | /** | ||
172 | * Sets the current mapping of SDVO inputs to outputs on the device. | ||
173 | * | ||
174 | * Takes two struct i380_sdvo_output_flags structures. | ||
175 | */ | ||
176 | #define SDVO_CMD_SET_IN_OUT_MAP 0x07 | ||
177 | |||
178 | /** | ||
179 | * Returns a struct psb_intel_sdvo_output_flags of attached displays. | ||
180 | */ | ||
181 | #define SDVO_CMD_GET_ATTACHED_DISPLAYS 0x0b | ||
182 | |||
183 | /** | ||
184 | * Returns a struct psb_intel_sdvo_ouptut_flags of displays supporting hot plugging. | ||
185 | */ | ||
186 | #define SDVO_CMD_GET_HOT_PLUG_SUPPORT 0x0c | ||
187 | |||
188 | /** | ||
189 | * Takes a struct psb_intel_sdvo_output_flags. | ||
190 | */ | ||
191 | #define SDVO_CMD_SET_ACTIVE_HOT_PLUG 0x0d | ||
192 | |||
193 | /** | ||
194 | * Returns a struct psb_intel_sdvo_output_flags of displays with hot plug | ||
195 | * interrupts enabled. | ||
196 | */ | ||
197 | #define SDVO_CMD_GET_ACTIVE_HOT_PLUG 0x0e | ||
198 | |||
199 | #define SDVO_CMD_GET_INTERRUPT_EVENT_SOURCE 0x0f | ||
200 | struct psb_intel_sdvo_get_interrupt_event_source_response { | ||
201 | u16 interrupt_status; | ||
202 | unsigned int ambient_light_interrupt:1; | ||
203 | unsigned int pad:7; | ||
204 | } __packed; | ||
205 | |||
206 | /** | ||
207 | * Selects which input is affected by future input commands. | ||
208 | * | ||
209 | * Commands affected include SET_INPUT_TIMINGS_PART[12], | ||
210 | * GET_INPUT_TIMINGS_PART[12], GET_PREFERRED_INPUT_TIMINGS_PART[12], | ||
211 | * GET_INPUT_PIXEL_CLOCK_RANGE, and CREATE_PREFERRED_INPUT_TIMINGS. | ||
212 | */ | ||
213 | #define SDVO_CMD_SET_TARGET_INPUT 0x10 | ||
214 | struct psb_intel_sdvo_set_target_input_args { | ||
215 | unsigned int target_1:1; | ||
216 | unsigned int pad:7; | ||
217 | } __packed; | ||
218 | |||
219 | /** | ||
220 | * Takes a struct psb_intel_sdvo_output_flags of which outputs are targeted by | ||
221 | * future output commands. | ||
222 | * | ||
223 | * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12], | ||
224 | * GET_OUTPUT_TIMINGS_PART[12], and GET_OUTPUT_PIXEL_CLOCK_RANGE. | ||
225 | */ | ||
226 | #define SDVO_CMD_SET_TARGET_OUTPUT 0x11 | ||
227 | |||
228 | #define SDVO_CMD_GET_INPUT_TIMINGS_PART1 0x12 | ||
229 | #define SDVO_CMD_GET_INPUT_TIMINGS_PART2 0x13 | ||
230 | #define SDVO_CMD_SET_INPUT_TIMINGS_PART1 0x14 | ||
231 | #define SDVO_CMD_SET_INPUT_TIMINGS_PART2 0x15 | ||
232 | #define SDVO_CMD_SET_OUTPUT_TIMINGS_PART1 0x16 | ||
233 | #define SDVO_CMD_SET_OUTPUT_TIMINGS_PART2 0x17 | ||
234 | #define SDVO_CMD_GET_OUTPUT_TIMINGS_PART1 0x18 | ||
235 | #define SDVO_CMD_GET_OUTPUT_TIMINGS_PART2 0x19 | ||
236 | /* Part 1 */ | ||
237 | # define SDVO_DTD_CLOCK_LOW SDVO_I2C_ARG_0 | ||
238 | # define SDVO_DTD_CLOCK_HIGH SDVO_I2C_ARG_1 | ||
239 | # define SDVO_DTD_H_ACTIVE SDVO_I2C_ARG_2 | ||
240 | # define SDVO_DTD_H_BLANK SDVO_I2C_ARG_3 | ||
241 | # define SDVO_DTD_H_HIGH SDVO_I2C_ARG_4 | ||
242 | # define SDVO_DTD_V_ACTIVE SDVO_I2C_ARG_5 | ||
243 | # define SDVO_DTD_V_BLANK SDVO_I2C_ARG_6 | ||
244 | # define SDVO_DTD_V_HIGH SDVO_I2C_ARG_7 | ||
245 | /* Part 2 */ | ||
246 | # define SDVO_DTD_HSYNC_OFF SDVO_I2C_ARG_0 | ||
247 | # define SDVO_DTD_HSYNC_WIDTH SDVO_I2C_ARG_1 | ||
248 | # define SDVO_DTD_VSYNC_OFF_WIDTH SDVO_I2C_ARG_2 | ||
249 | # define SDVO_DTD_SYNC_OFF_WIDTH_HIGH SDVO_I2C_ARG_3 | ||
250 | # define SDVO_DTD_DTD_FLAGS SDVO_I2C_ARG_4 | ||
251 | # define SDVO_DTD_DTD_FLAG_INTERLACED (1 << 7) | ||
252 | # define SDVO_DTD_DTD_FLAG_STEREO_MASK (3 << 5) | ||
253 | # define SDVO_DTD_DTD_FLAG_INPUT_MASK (3 << 3) | ||
254 | # define SDVO_DTD_DTD_FLAG_SYNC_MASK (3 << 1) | ||
255 | # define SDVO_DTD_SDVO_FLAS SDVO_I2C_ARG_5 | ||
256 | # define SDVO_DTD_SDVO_FLAG_STALL (1 << 7) | ||
257 | # define SDVO_DTD_SDVO_FLAG_CENTERED (0 << 6) | ||
258 | # define SDVO_DTD_SDVO_FLAG_UPPER_LEFT (1 << 6) | ||
259 | # define SDVO_DTD_SDVO_FLAG_SCALING_MASK (3 << 4) | ||
260 | # define SDVO_DTD_SDVO_FLAG_SCALING_NONE (0 << 4) | ||
261 | # define SDVO_DTD_SDVO_FLAG_SCALING_SHARP (1 << 4) | ||
262 | # define SDVO_DTD_SDVO_FLAG_SCALING_SMOOTH (2 << 4) | ||
263 | # define SDVO_DTD_VSYNC_OFF_HIGH SDVO_I2C_ARG_6 | ||
264 | |||
265 | /** | ||
266 | * Generates a DTD based on the given width, height, and flags. | ||
267 | * | ||
268 | * This will be supported by any device supporting scaling or interlaced | ||
269 | * modes. | ||
270 | */ | ||
271 | #define SDVO_CMD_CREATE_PREFERRED_INPUT_TIMING 0x1a | ||
272 | # define SDVO_PREFERRED_INPUT_TIMING_CLOCK_LOW SDVO_I2C_ARG_0 | ||
273 | # define SDVO_PREFERRED_INPUT_TIMING_CLOCK_HIGH SDVO_I2C_ARG_1 | ||
274 | # define SDVO_PREFERRED_INPUT_TIMING_WIDTH_LOW SDVO_I2C_ARG_2 | ||
275 | # define SDVO_PREFERRED_INPUT_TIMING_WIDTH_HIGH SDVO_I2C_ARG_3 | ||
276 | # define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_LOW SDVO_I2C_ARG_4 | ||
277 | # define SDVO_PREFERRED_INPUT_TIMING_HEIGHT_HIGH SDVO_I2C_ARG_5 | ||
278 | # define SDVO_PREFERRED_INPUT_TIMING_FLAGS SDVO_I2C_ARG_6 | ||
279 | # define SDVO_PREFERRED_INPUT_TIMING_FLAGS_INTERLACED (1 << 0) | ||
280 | # define SDVO_PREFERRED_INPUT_TIMING_FLAGS_SCALED (1 << 1) | ||
281 | |||
282 | #define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1 0x1b | ||
283 | #define SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2 0x1c | ||
284 | |||
285 | /** Returns a struct psb_intel_sdvo_pixel_clock_range */ | ||
286 | #define SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE 0x1d | ||
287 | /** Returns a struct psb_intel_sdvo_pixel_clock_range */ | ||
288 | #define SDVO_CMD_GET_OUTPUT_PIXEL_CLOCK_RANGE 0x1e | ||
289 | |||
290 | /** Returns a byte bitfield containing SDVO_CLOCK_RATE_MULT_* flags */ | ||
291 | #define SDVO_CMD_GET_SUPPORTED_CLOCK_RATE_MULTS 0x1f | ||
292 | |||
293 | /** Returns a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ | ||
294 | #define SDVO_CMD_GET_CLOCK_RATE_MULT 0x20 | ||
295 | /** Takes a byte containing a SDVO_CLOCK_RATE_MULT_* flag */ | ||
296 | #define SDVO_CMD_SET_CLOCK_RATE_MULT 0x21 | ||
297 | # define SDVO_CLOCK_RATE_MULT_1X (1 << 0) | ||
298 | # define SDVO_CLOCK_RATE_MULT_2X (1 << 1) | ||
299 | # define SDVO_CLOCK_RATE_MULT_4X (1 << 3) | ||
300 | |||
301 | #define SDVO_CMD_GET_SUPPORTED_TV_FORMATS 0x27 | ||
302 | |||
303 | #define SDVO_CMD_GET_TV_FORMAT 0x28 | ||
304 | |||
305 | #define SDVO_CMD_SET_TV_FORMAT 0x29 | ||
306 | |||
307 | #define SDVO_CMD_GET_SUPPORTED_POWER_STATES 0x2a | ||
308 | #define SDVO_CMD_GET_ENCODER_POWER_STATE 0x2b | ||
309 | #define SDVO_CMD_SET_ENCODER_POWER_STATE 0x2c | ||
310 | # define SDVO_ENCODER_STATE_ON (1 << 0) | ||
311 | # define SDVO_ENCODER_STATE_STANDBY (1 << 1) | ||
312 | # define SDVO_ENCODER_STATE_SUSPEND (1 << 2) | ||
313 | # define SDVO_ENCODER_STATE_OFF (1 << 3) | ||
314 | |||
315 | #define SDVO_CMD_SET_TV_RESOLUTION_SUPPORT 0x93 | ||
316 | |||
317 | #define SDVO_CMD_SET_CONTROL_BUS_SWITCH 0x7a | ||
318 | # define SDVO_CONTROL_BUS_PROM 0x0 | ||
319 | # define SDVO_CONTROL_BUS_DDC1 0x1 | ||
320 | # define SDVO_CONTROL_BUS_DDC2 0x2 | ||
321 | # define SDVO_CONTROL_BUS_DDC3 0x3 | ||
322 | |||
323 | /* SDVO Bus & SDVO Inputs wiring details*/ | ||
324 | /* Bit 0: Is SDVOB connected to In0 (1 = yes, 0 = no*/ | ||
325 | /* Bit 1: Is SDVOB connected to In1 (1 = yes, 0 = no*/ | ||
326 | /* Bit 2: Is SDVOC connected to In0 (1 = yes, 0 = no*/ | ||
327 | /* Bit 3: Is SDVOC connected to In1 (1 = yes, 0 = no*/ | ||
328 | #define SDVOB_IN0 0x01 | ||
329 | #define SDVOB_IN1 0x02 | ||
330 | #define SDVOC_IN0 0x04 | ||
331 | #define SDVOC_IN1 0x08 | ||
332 | |||
333 | #define SDVO_DEVICE_NONE 0x00 | ||
334 | #define SDVO_DEVICE_CRT 0x01 | ||
335 | #define SDVO_DEVICE_TV 0x02 | ||
336 | #define SDVO_DEVICE_LVDS 0x04 | ||
337 | #define SDVO_DEVICE_TMDS 0x08 | ||
338 | |||
diff --git a/drivers/staging/gma500/psb_irq.c b/drivers/staging/gma500/psb_irq.c deleted file mode 100644 index 36dd63044b06..000000000000 --- a/drivers/staging/gma500/psb_irq.c +++ /dev/null | |||
@@ -1,627 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2007, 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 | * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to | ||
19 | * develop this driver. | ||
20 | * | ||
21 | **************************************************************************/ | ||
22 | /* | ||
23 | */ | ||
24 | |||
25 | #include <drm/drmP.h> | ||
26 | #include "psb_drv.h" | ||
27 | #include "psb_reg.h" | ||
28 | #include "psb_intel_reg.h" | ||
29 | #include "power.h" | ||
30 | #include "mdfld_output.h" | ||
31 | |||
32 | /* | ||
33 | * inline functions | ||
34 | */ | ||
35 | |||
36 | static inline u32 | ||
37 | psb_pipestat(int pipe) | ||
38 | { | ||
39 | if (pipe == 0) | ||
40 | return PIPEASTAT; | ||
41 | if (pipe == 1) | ||
42 | return PIPEBSTAT; | ||
43 | if (pipe == 2) | ||
44 | return PIPECSTAT; | ||
45 | BUG(); | ||
46 | } | ||
47 | |||
48 | static inline u32 | ||
49 | mid_pipe_event(int pipe) | ||
50 | { | ||
51 | if (pipe == 0) | ||
52 | return _PSB_PIPEA_EVENT_FLAG; | ||
53 | if (pipe == 1) | ||
54 | return _MDFLD_PIPEB_EVENT_FLAG; | ||
55 | if (pipe == 2) | ||
56 | return _MDFLD_PIPEC_EVENT_FLAG; | ||
57 | BUG(); | ||
58 | } | ||
59 | |||
60 | static inline u32 | ||
61 | mid_pipe_vsync(int pipe) | ||
62 | { | ||
63 | if (pipe == 0) | ||
64 | return _PSB_VSYNC_PIPEA_FLAG; | ||
65 | if (pipe == 1) | ||
66 | return _PSB_VSYNC_PIPEB_FLAG; | ||
67 | if (pipe == 2) | ||
68 | return _MDFLD_PIPEC_VBLANK_FLAG; | ||
69 | BUG(); | ||
70 | } | ||
71 | |||
72 | static inline u32 | ||
73 | mid_pipeconf(int pipe) | ||
74 | { | ||
75 | if (pipe == 0) | ||
76 | return PIPEACONF; | ||
77 | if (pipe == 1) | ||
78 | return PIPEBCONF; | ||
79 | if (pipe == 2) | ||
80 | return PIPECCONF; | ||
81 | BUG(); | ||
82 | } | ||
83 | |||
84 | void | ||
85 | psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) | ||
86 | { | ||
87 | if ((dev_priv->pipestat[pipe] & mask) != mask) { | ||
88 | u32 reg = psb_pipestat(pipe); | ||
89 | dev_priv->pipestat[pipe] |= mask; | ||
90 | /* Enable the interrupt, clear any pending status */ | ||
91 | if (gma_power_begin(dev_priv->dev, false)) { | ||
92 | u32 writeVal = PSB_RVDC32(reg); | ||
93 | writeVal |= (mask | (mask >> 16)); | ||
94 | PSB_WVDC32(writeVal, reg); | ||
95 | (void) PSB_RVDC32(reg); | ||
96 | gma_power_end(dev_priv->dev); | ||
97 | } | ||
98 | } | ||
99 | } | ||
100 | |||
101 | void | ||
102 | psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask) | ||
103 | { | ||
104 | if ((dev_priv->pipestat[pipe] & mask) != 0) { | ||
105 | u32 reg = psb_pipestat(pipe); | ||
106 | dev_priv->pipestat[pipe] &= ~mask; | ||
107 | if (gma_power_begin(dev_priv->dev, false)) { | ||
108 | u32 writeVal = PSB_RVDC32(reg); | ||
109 | writeVal &= ~mask; | ||
110 | PSB_WVDC32(writeVal, reg); | ||
111 | (void) PSB_RVDC32(reg); | ||
112 | gma_power_end(dev_priv->dev); | ||
113 | } | ||
114 | } | ||
115 | } | ||
116 | |||
117 | void mid_enable_pipe_event(struct drm_psb_private *dev_priv, int pipe) | ||
118 | { | ||
119 | if (gma_power_begin(dev_priv->dev, false)) { | ||
120 | u32 pipe_event = mid_pipe_event(pipe); | ||
121 | dev_priv->vdc_irq_mask |= pipe_event; | ||
122 | PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); | ||
123 | PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); | ||
124 | gma_power_end(dev_priv->dev); | ||
125 | } | ||
126 | } | ||
127 | |||
128 | void mid_disable_pipe_event(struct drm_psb_private *dev_priv, int pipe) | ||
129 | { | ||
130 | if (dev_priv->pipestat[pipe] == 0) { | ||
131 | if (gma_power_begin(dev_priv->dev, false)) { | ||
132 | u32 pipe_event = mid_pipe_event(pipe); | ||
133 | dev_priv->vdc_irq_mask &= ~pipe_event; | ||
134 | PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); | ||
135 | PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); | ||
136 | gma_power_end(dev_priv->dev); | ||
137 | } | ||
138 | } | ||
139 | } | ||
140 | |||
141 | /** | ||
142 | * Display controller interrupt handler for pipe event. | ||
143 | * | ||
144 | */ | ||
145 | static void mid_pipe_event_handler(struct drm_device *dev, int pipe) | ||
146 | { | ||
147 | struct drm_psb_private *dev_priv = | ||
148 | (struct drm_psb_private *) dev->dev_private; | ||
149 | |||
150 | uint32_t pipe_stat_val = 0; | ||
151 | uint32_t pipe_stat_reg = psb_pipestat(pipe); | ||
152 | uint32_t pipe_enable = dev_priv->pipestat[pipe]; | ||
153 | uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16; | ||
154 | uint32_t pipe_clear; | ||
155 | uint32_t i = 0; | ||
156 | |||
157 | spin_lock(&dev_priv->irqmask_lock); | ||
158 | |||
159 | pipe_stat_val = PSB_RVDC32(pipe_stat_reg); | ||
160 | pipe_stat_val &= pipe_enable | pipe_status; | ||
161 | pipe_stat_val &= pipe_stat_val >> 16; | ||
162 | |||
163 | spin_unlock(&dev_priv->irqmask_lock); | ||
164 | |||
165 | /* Clear the 2nd level interrupt status bits | ||
166 | * Sometimes the bits are very sticky so we repeat until they unstick */ | ||
167 | for (i = 0; i < 0xffff; i++) { | ||
168 | PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg); | ||
169 | pipe_clear = PSB_RVDC32(pipe_stat_reg) & pipe_status; | ||
170 | |||
171 | if (pipe_clear == 0) | ||
172 | break; | ||
173 | } | ||
174 | |||
175 | if (pipe_clear) | ||
176 | dev_err(dev->dev, | ||
177 | "%s, can't clear status bits for pipe %d, its value = 0x%x.\n", | ||
178 | __func__, pipe, PSB_RVDC32(pipe_stat_reg)); | ||
179 | |||
180 | if (pipe_stat_val & PIPE_VBLANK_STATUS) | ||
181 | drm_handle_vblank(dev, pipe); | ||
182 | |||
183 | if (pipe_stat_val & PIPE_TE_STATUS) | ||
184 | drm_handle_vblank(dev, pipe); | ||
185 | } | ||
186 | |||
187 | /* | ||
188 | * Display controller interrupt handler. | ||
189 | */ | ||
190 | static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat) | ||
191 | { | ||
192 | if (vdc_stat & _PSB_VSYNC_PIPEA_FLAG) | ||
193 | mid_pipe_event_handler(dev, 0); | ||
194 | |||
195 | if (vdc_stat & _PSB_VSYNC_PIPEB_FLAG) | ||
196 | mid_pipe_event_handler(dev, 1); | ||
197 | } | ||
198 | |||
199 | irqreturn_t psb_irq_handler(DRM_IRQ_ARGS) | ||
200 | { | ||
201 | struct drm_device *dev = (struct drm_device *) arg; | ||
202 | struct drm_psb_private *dev_priv = | ||
203 | (struct drm_psb_private *) dev->dev_private; | ||
204 | |||
205 | uint32_t vdc_stat, dsp_int = 0, sgx_int = 0; | ||
206 | int handled = 0; | ||
207 | |||
208 | spin_lock(&dev_priv->irqmask_lock); | ||
209 | |||
210 | vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R); | ||
211 | |||
212 | if (vdc_stat & _PSB_PIPE_EVENT_FLAG) | ||
213 | dsp_int = 1; | ||
214 | |||
215 | /* FIXME: Handle Medfield | ||
216 | if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG) | ||
217 | dsp_int = 1; | ||
218 | */ | ||
219 | |||
220 | if (vdc_stat & _PSB_IRQ_SGX_FLAG) | ||
221 | sgx_int = 1; | ||
222 | |||
223 | vdc_stat &= dev_priv->vdc_irq_mask; | ||
224 | spin_unlock(&dev_priv->irqmask_lock); | ||
225 | |||
226 | if (dsp_int && gma_power_is_on(dev)) { | ||
227 | psb_vdc_interrupt(dev, vdc_stat); | ||
228 | handled = 1; | ||
229 | } | ||
230 | |||
231 | if (sgx_int) { | ||
232 | /* Not expected - we have it masked, shut it up */ | ||
233 | u32 s, s2; | ||
234 | s = PSB_RSGX32(PSB_CR_EVENT_STATUS); | ||
235 | s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2); | ||
236 | PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR); | ||
237 | PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2); | ||
238 | /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but | ||
239 | we may as well poll even if we add that ! */ | ||
240 | handled = 1; | ||
241 | } | ||
242 | |||
243 | PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R); | ||
244 | (void) PSB_RVDC32(PSB_INT_IDENTITY_R); | ||
245 | DRM_READMEMORYBARRIER(); | ||
246 | |||
247 | if (!handled) | ||
248 | return IRQ_NONE; | ||
249 | |||
250 | return IRQ_HANDLED; | ||
251 | } | ||
252 | |||
253 | void psb_irq_preinstall(struct drm_device *dev) | ||
254 | { | ||
255 | struct drm_psb_private *dev_priv = | ||
256 | (struct drm_psb_private *) dev->dev_private; | ||
257 | unsigned long irqflags; | ||
258 | |||
259 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | ||
260 | |||
261 | if (gma_power_is_on(dev)) | ||
262 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); | ||
263 | if (dev->vblank_enabled[0]) | ||
264 | dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; | ||
265 | if (dev->vblank_enabled[1]) | ||
266 | dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; | ||
267 | |||
268 | /* FIXME: Handle Medfield irq mask | ||
269 | if (dev->vblank_enabled[1]) | ||
270 | dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG; | ||
271 | if (dev->vblank_enabled[2]) | ||
272 | dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG; | ||
273 | */ | ||
274 | |||
275 | /* This register is safe even if display island is off */ | ||
276 | PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); | ||
277 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | ||
278 | } | ||
279 | |||
280 | int psb_irq_postinstall(struct drm_device *dev) | ||
281 | { | ||
282 | struct drm_psb_private *dev_priv = | ||
283 | (struct drm_psb_private *) dev->dev_private; | ||
284 | unsigned long irqflags; | ||
285 | |||
286 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | ||
287 | |||
288 | /* This register is safe even if display island is off */ | ||
289 | PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); | ||
290 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); | ||
291 | |||
292 | if (dev->vblank_enabled[0]) | ||
293 | psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
294 | else | ||
295 | psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
296 | |||
297 | if (dev->vblank_enabled[1]) | ||
298 | psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
299 | else | ||
300 | psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
301 | |||
302 | if (dev->vblank_enabled[2]) | ||
303 | psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
304 | else | ||
305 | psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
306 | |||
307 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | ||
308 | return 0; | ||
309 | } | ||
310 | |||
311 | void psb_irq_uninstall(struct drm_device *dev) | ||
312 | { | ||
313 | struct drm_psb_private *dev_priv = | ||
314 | (struct drm_psb_private *) dev->dev_private; | ||
315 | unsigned long irqflags; | ||
316 | |||
317 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | ||
318 | |||
319 | PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM); | ||
320 | |||
321 | if (dev->vblank_enabled[0]) | ||
322 | psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
323 | |||
324 | if (dev->vblank_enabled[1]) | ||
325 | psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
326 | |||
327 | if (dev->vblank_enabled[2]) | ||
328 | psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
329 | |||
330 | dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG | | ||
331 | _PSB_IRQ_MSVDX_FLAG | | ||
332 | _LNC_IRQ_TOPAZ_FLAG; | ||
333 | |||
334 | /* These two registers are safe even if display island is off */ | ||
335 | PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); | ||
336 | PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); | ||
337 | |||
338 | wmb(); | ||
339 | |||
340 | /* This register is safe even if display island is off */ | ||
341 | PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R); | ||
342 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | ||
343 | } | ||
344 | |||
345 | void psb_irq_turn_on_dpst(struct drm_device *dev) | ||
346 | { | ||
347 | struct drm_psb_private *dev_priv = | ||
348 | (struct drm_psb_private *) dev->dev_private; | ||
349 | u32 hist_reg; | ||
350 | u32 pwm_reg; | ||
351 | |||
352 | if (gma_power_begin(dev, false)) { | ||
353 | PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL); | ||
354 | hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL); | ||
355 | PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL); | ||
356 | hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); | ||
357 | |||
358 | PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC); | ||
359 | pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); | ||
360 | PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE | ||
361 | | PWM_PHASEIN_INT_ENABLE, | ||
362 | PWM_CONTROL_LOGIC); | ||
363 | pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); | ||
364 | |||
365 | psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); | ||
366 | |||
367 | hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); | ||
368 | PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR, | ||
369 | HISTOGRAM_INT_CONTROL); | ||
370 | pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); | ||
371 | PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE, | ||
372 | PWM_CONTROL_LOGIC); | ||
373 | |||
374 | gma_power_end(dev); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | int psb_irq_enable_dpst(struct drm_device *dev) | ||
379 | { | ||
380 | struct drm_psb_private *dev_priv = | ||
381 | (struct drm_psb_private *) dev->dev_private; | ||
382 | unsigned long irqflags; | ||
383 | |||
384 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | ||
385 | |||
386 | /* enable DPST */ | ||
387 | mid_enable_pipe_event(dev_priv, 0); | ||
388 | psb_irq_turn_on_dpst(dev); | ||
389 | |||
390 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | ||
391 | return 0; | ||
392 | } | ||
393 | |||
394 | void psb_irq_turn_off_dpst(struct drm_device *dev) | ||
395 | { | ||
396 | struct drm_psb_private *dev_priv = | ||
397 | (struct drm_psb_private *) dev->dev_private; | ||
398 | u32 hist_reg; | ||
399 | u32 pwm_reg; | ||
400 | |||
401 | if (gma_power_begin(dev, false)) { | ||
402 | PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL); | ||
403 | hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL); | ||
404 | |||
405 | psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE); | ||
406 | |||
407 | pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); | ||
408 | PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE), | ||
409 | PWM_CONTROL_LOGIC); | ||
410 | pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC); | ||
411 | |||
412 | gma_power_end(dev); | ||
413 | } | ||
414 | } | ||
415 | |||
416 | int psb_irq_disable_dpst(struct drm_device *dev) | ||
417 | { | ||
418 | struct drm_psb_private *dev_priv = | ||
419 | (struct drm_psb_private *) dev->dev_private; | ||
420 | unsigned long irqflags; | ||
421 | |||
422 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | ||
423 | |||
424 | mid_disable_pipe_event(dev_priv, 0); | ||
425 | psb_irq_turn_off_dpst(dev); | ||
426 | |||
427 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | ||
428 | |||
429 | return 0; | ||
430 | } | ||
431 | |||
432 | #ifdef PSB_FIXME | ||
433 | static int psb_vblank_do_wait(struct drm_device *dev, | ||
434 | unsigned int *sequence, atomic_t *counter) | ||
435 | { | ||
436 | unsigned int cur_vblank; | ||
437 | int ret = 0; | ||
438 | DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ, | ||
439 | (((cur_vblank = atomic_read(counter)) | ||
440 | - *sequence) <= (1 << 23))); | ||
441 | *sequence = cur_vblank; | ||
442 | |||
443 | return ret; | ||
444 | } | ||
445 | #endif | ||
446 | |||
447 | /* | ||
448 | * It is used to enable VBLANK interrupt | ||
449 | */ | ||
450 | int psb_enable_vblank(struct drm_device *dev, int pipe) | ||
451 | { | ||
452 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
453 | unsigned long irqflags; | ||
454 | uint32_t reg_val = 0; | ||
455 | uint32_t pipeconf_reg = mid_pipeconf(pipe); | ||
456 | |||
457 | #if defined(CONFIG_DRM_PSB_MFLD) | ||
458 | /* Medfield is different - we should perhaps extract out vblank | ||
459 | and blacklight etc ops */ | ||
460 | if (IS_MFLD(dev) && !mdfld_panel_dpi(dev)) | ||
461 | return mdfld_enable_te(dev, pipe); | ||
462 | #endif | ||
463 | if (gma_power_begin(dev, false)) { | ||
464 | reg_val = REG_READ(pipeconf_reg); | ||
465 | gma_power_end(dev); | ||
466 | } | ||
467 | |||
468 | if (!(reg_val & PIPEACONF_ENABLE)) | ||
469 | return -EINVAL; | ||
470 | |||
471 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | ||
472 | |||
473 | if (pipe == 0) | ||
474 | dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEA_FLAG; | ||
475 | else if (pipe == 1) | ||
476 | dev_priv->vdc_irq_mask |= _PSB_VSYNC_PIPEB_FLAG; | ||
477 | |||
478 | PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); | ||
479 | PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); | ||
480 | psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
481 | |||
482 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | ||
483 | |||
484 | return 0; | ||
485 | } | ||
486 | |||
487 | /* | ||
488 | * It is used to disable VBLANK interrupt | ||
489 | */ | ||
490 | void psb_disable_vblank(struct drm_device *dev, int pipe) | ||
491 | { | ||
492 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
493 | unsigned long irqflags; | ||
494 | |||
495 | #if defined(CONFIG_DRM_PSB_MFLD) | ||
496 | if (IS_MFLD(dev) && !mdfld_panel_dpi(dev)) | ||
497 | mdfld_disable_te(dev, pipe); | ||
498 | #endif | ||
499 | spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); | ||
500 | |||
501 | if (pipe == 0) | ||
502 | dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEA_FLAG; | ||
503 | else if (pipe == 1) | ||
504 | dev_priv->vdc_irq_mask &= ~_PSB_VSYNC_PIPEB_FLAG; | ||
505 | |||
506 | PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R); | ||
507 | PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R); | ||
508 | psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE); | ||
509 | |||
510 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); | ||
511 | } | ||
512 | |||
513 | /** | ||
514 | * mdfld_enable_te - enable TE events | ||
515 | * @dev: our DRM device | ||
516 | * @pipe: which pipe to work on | ||
517 | * | ||
518 | * Enable TE events on a Medfield display pipe. Medfield specific. | ||
519 | */ | ||
520 | int mdfld_enable_te(struct drm_device *dev, int pipe) | ||
521 | { | ||
522 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
523 | unsigned long flags; | ||
524 | uint32_t reg_val = 0; | ||
525 | uint32_t pipeconf_reg = mid_pipeconf(pipe); | ||
526 | |||
527 | if (gma_power_begin(dev, false)) { | ||
528 | reg_val = REG_READ(pipeconf_reg); | ||
529 | gma_power_end(dev); | ||
530 | } | ||
531 | |||
532 | if (!(reg_val & PIPEACONF_ENABLE)) | ||
533 | return -EINVAL; | ||
534 | |||
535 | spin_lock_irqsave(&dev_priv->irqmask_lock, flags); | ||
536 | |||
537 | mid_enable_pipe_event(dev_priv, pipe); | ||
538 | psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE); | ||
539 | |||
540 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags); | ||
541 | |||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * mdfld_disable_te - disable TE events | ||
547 | * @dev: our DRM device | ||
548 | * @pipe: which pipe to work on | ||
549 | * | ||
550 | * Disable TE events on a Medfield display pipe. Medfield specific. | ||
551 | */ | ||
552 | void mdfld_disable_te(struct drm_device *dev, int pipe) | ||
553 | { | ||
554 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
555 | unsigned long flags; | ||
556 | |||
557 | spin_lock_irqsave(&dev_priv->irqmask_lock, flags); | ||
558 | |||
559 | mid_disable_pipe_event(dev_priv, pipe); | ||
560 | psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE); | ||
561 | |||
562 | spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags); | ||
563 | } | ||
564 | |||
565 | /* Called from drm generic code, passed a 'crtc', which | ||
566 | * we use as a pipe index | ||
567 | */ | ||
568 | u32 psb_get_vblank_counter(struct drm_device *dev, int pipe) | ||
569 | { | ||
570 | uint32_t high_frame = PIPEAFRAMEHIGH; | ||
571 | uint32_t low_frame = PIPEAFRAMEPIXEL; | ||
572 | uint32_t pipeconf_reg = PIPEACONF; | ||
573 | uint32_t reg_val = 0; | ||
574 | uint32_t high1 = 0, high2 = 0, low = 0, count = 0; | ||
575 | |||
576 | switch (pipe) { | ||
577 | case 0: | ||
578 | break; | ||
579 | case 1: | ||
580 | high_frame = PIPEBFRAMEHIGH; | ||
581 | low_frame = PIPEBFRAMEPIXEL; | ||
582 | pipeconf_reg = PIPEBCONF; | ||
583 | break; | ||
584 | case 2: | ||
585 | high_frame = PIPECFRAMEHIGH; | ||
586 | low_frame = PIPECFRAMEPIXEL; | ||
587 | pipeconf_reg = PIPECCONF; | ||
588 | break; | ||
589 | default: | ||
590 | dev_err(dev->dev, "%s, invalid pipe.\n", __func__); | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | if (!gma_power_begin(dev, false)) | ||
595 | return 0; | ||
596 | |||
597 | reg_val = REG_READ(pipeconf_reg); | ||
598 | |||
599 | if (!(reg_val & PIPEACONF_ENABLE)) { | ||
600 | dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n", | ||
601 | pipe); | ||
602 | goto psb_get_vblank_counter_exit; | ||
603 | } | ||
604 | |||
605 | /* | ||
606 | * High & low register fields aren't synchronized, so make sure | ||
607 | * we get a low value that's stable across two reads of the high | ||
608 | * register. | ||
609 | */ | ||
610 | do { | ||
611 | high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> | ||
612 | PIPE_FRAME_HIGH_SHIFT); | ||
613 | low = ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >> | ||
614 | PIPE_FRAME_LOW_SHIFT); | ||
615 | high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >> | ||
616 | PIPE_FRAME_HIGH_SHIFT); | ||
617 | } while (high1 != high2); | ||
618 | |||
619 | count = (high1 << 8) | low; | ||
620 | |||
621 | psb_get_vblank_counter_exit: | ||
622 | |||
623 | gma_power_end(dev); | ||
624 | |||
625 | return count; | ||
626 | } | ||
627 | |||
diff --git a/drivers/staging/gma500/psb_irq.h b/drivers/staging/gma500/psb_irq.h deleted file mode 100644 index 216fda38b57d..000000000000 --- a/drivers/staging/gma500/psb_irq.h +++ /dev/null | |||
@@ -1,45 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2009-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 | * Authors: | ||
19 | * Benjamin Defnet <benjamin.r.defnet@intel.com> | ||
20 | * Rajesh Poornachandran <rajesh.poornachandran@intel.com> | ||
21 | * | ||
22 | **************************************************************************/ | ||
23 | |||
24 | #ifndef _SYSIRQ_H_ | ||
25 | #define _SYSIRQ_H_ | ||
26 | |||
27 | #include <drm/drmP.h> | ||
28 | |||
29 | bool sysirq_init(struct drm_device *dev); | ||
30 | void sysirq_uninit(struct drm_device *dev); | ||
31 | |||
32 | void psb_irq_preinstall(struct drm_device *dev); | ||
33 | int psb_irq_postinstall(struct drm_device *dev); | ||
34 | void psb_irq_uninstall(struct drm_device *dev); | ||
35 | irqreturn_t psb_irq_handler(DRM_IRQ_ARGS); | ||
36 | |||
37 | int psb_irq_enable_dpst(struct drm_device *dev); | ||
38 | int psb_irq_disable_dpst(struct drm_device *dev); | ||
39 | void psb_irq_turn_on_dpst(struct drm_device *dev); | ||
40 | void psb_irq_turn_off_dpst(struct drm_device *dev); | ||
41 | int psb_enable_vblank(struct drm_device *dev, int pipe); | ||
42 | void psb_disable_vblank(struct drm_device *dev, int pipe); | ||
43 | u32 psb_get_vblank_counter(struct drm_device *dev, int pipe); | ||
44 | |||
45 | #endif /* _SYSIRQ_H_ */ | ||
diff --git a/drivers/staging/gma500/psb_lid.c b/drivers/staging/gma500/psb_lid.c deleted file mode 100644 index b867aabe6bf3..000000000000 --- a/drivers/staging/gma500/psb_lid.c +++ /dev/null | |||
@@ -1,88 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2007, 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: Thomas Hellstrom <thomas-at-tungstengraphics-dot-com> | ||
18 | **************************************************************************/ | ||
19 | |||
20 | #include <drm/drmP.h> | ||
21 | #include "psb_drv.h" | ||
22 | #include "psb_reg.h" | ||
23 | #include "psb_intel_reg.h" | ||
24 | #include <linux/spinlock.h> | ||
25 | |||
26 | static void psb_lid_timer_func(unsigned long data) | ||
27 | { | ||
28 | struct drm_psb_private * dev_priv = (struct drm_psb_private *)data; | ||
29 | struct drm_device *dev = (struct drm_device *)dev_priv->dev; | ||
30 | struct timer_list *lid_timer = &dev_priv->lid_timer; | ||
31 | unsigned long irq_flags; | ||
32 | u32 *lid_state = dev_priv->lid_state; | ||
33 | u32 pp_status; | ||
34 | |||
35 | if (readl(lid_state) == dev_priv->lid_last_state) | ||
36 | goto lid_timer_schedule; | ||
37 | |||
38 | if ((readl(lid_state)) & 0x01) { | ||
39 | /*lid state is open*/ | ||
40 | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) | POWER_TARGET_ON); | ||
41 | do { | ||
42 | pp_status = REG_READ(PP_STATUS); | ||
43 | } while ((pp_status & PP_ON) == 0); | ||
44 | |||
45 | /*FIXME: should be backlight level before*/ | ||
46 | psb_intel_lvds_set_brightness(dev, 100); | ||
47 | } else { | ||
48 | psb_intel_lvds_set_brightness(dev, 0); | ||
49 | |||
50 | REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) & ~POWER_TARGET_ON); | ||
51 | do { | ||
52 | pp_status = REG_READ(PP_STATUS); | ||
53 | } while ((pp_status & PP_ON) == 0); | ||
54 | } | ||
55 | dev_priv->lid_last_state = readl(lid_state); | ||
56 | |||
57 | lid_timer_schedule: | ||
58 | spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); | ||
59 | if (!timer_pending(lid_timer)) { | ||
60 | lid_timer->expires = jiffies + PSB_LID_DELAY; | ||
61 | add_timer(lid_timer); | ||
62 | } | ||
63 | spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); | ||
64 | } | ||
65 | |||
66 | void psb_lid_timer_init(struct drm_psb_private *dev_priv) | ||
67 | { | ||
68 | struct timer_list *lid_timer = &dev_priv->lid_timer; | ||
69 | unsigned long irq_flags; | ||
70 | |||
71 | spin_lock_init(&dev_priv->lid_lock); | ||
72 | spin_lock_irqsave(&dev_priv->lid_lock, irq_flags); | ||
73 | |||
74 | init_timer(lid_timer); | ||
75 | |||
76 | lid_timer->data = (unsigned long)dev_priv; | ||
77 | lid_timer->function = psb_lid_timer_func; | ||
78 | lid_timer->expires = jiffies + PSB_LID_DELAY; | ||
79 | |||
80 | add_timer(lid_timer); | ||
81 | spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags); | ||
82 | } | ||
83 | |||
84 | void psb_lid_timer_takedown(struct drm_psb_private *dev_priv) | ||
85 | { | ||
86 | del_timer_sync(&dev_priv->lid_timer); | ||
87 | } | ||
88 | |||
diff --git a/drivers/staging/gma500/psb_reg.h b/drivers/staging/gma500/psb_reg.h deleted file mode 100644 index b81c7c1e9c2d..000000000000 --- a/drivers/staging/gma500/psb_reg.h +++ /dev/null | |||
@@ -1,582 +0,0 @@ | |||
1 | /************************************************************************** | ||
2 | * | ||
3 | * Copyright (c) (2005-2007) Imagination Technologies Limited. | ||
4 | * Copyright (c) 2007, Intel Corporation. | ||
5 | * All Rights Reserved. | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify it | ||
8 | * under the terms and conditions of the GNU General Public License, | ||
9 | * version 2, as published by the Free Software Foundation. | ||
10 | * | ||
11 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
14 | * more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along with | ||
17 | * this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.. | ||
19 | * | ||
20 | **************************************************************************/ | ||
21 | |||
22 | #ifndef _PSB_REG_H_ | ||
23 | #define _PSB_REG_H_ | ||
24 | |||
25 | #define PSB_CR_CLKGATECTL 0x0000 | ||
26 | #define _PSB_C_CLKGATECTL_AUTO_MAN_REG (1 << 24) | ||
27 | #define _PSB_C_CLKGATECTL_USE_CLKG_SHIFT (20) | ||
28 | #define _PSB_C_CLKGATECTL_USE_CLKG_MASK (0x3 << 20) | ||
29 | #define _PSB_C_CLKGATECTL_DPM_CLKG_SHIFT (16) | ||
30 | #define _PSB_C_CLKGATECTL_DPM_CLKG_MASK (0x3 << 16) | ||
31 | #define _PSB_C_CLKGATECTL_TA_CLKG_SHIFT (12) | ||
32 | #define _PSB_C_CLKGATECTL_TA_CLKG_MASK (0x3 << 12) | ||
33 | #define _PSB_C_CLKGATECTL_TSP_CLKG_SHIFT (8) | ||
34 | #define _PSB_C_CLKGATECTL_TSP_CLKG_MASK (0x3 << 8) | ||
35 | #define _PSB_C_CLKGATECTL_ISP_CLKG_SHIFT (4) | ||
36 | #define _PSB_C_CLKGATECTL_ISP_CLKG_MASK (0x3 << 4) | ||
37 | #define _PSB_C_CLKGATECTL_2D_CLKG_SHIFT (0) | ||
38 | #define _PSB_C_CLKGATECTL_2D_CLKG_MASK (0x3 << 0) | ||
39 | #define _PSB_C_CLKGATECTL_CLKG_ENABLED (0) | ||
40 | #define _PSB_C_CLKGATECTL_CLKG_DISABLED (1) | ||
41 | #define _PSB_C_CLKGATECTL_CLKG_AUTO (2) | ||
42 | |||
43 | #define PSB_CR_CORE_ID 0x0010 | ||
44 | #define _PSB_CC_ID_ID_SHIFT (16) | ||
45 | #define _PSB_CC_ID_ID_MASK (0xFFFF << 16) | ||
46 | #define _PSB_CC_ID_CONFIG_SHIFT (0) | ||
47 | #define _PSB_CC_ID_CONFIG_MASK (0xFFFF << 0) | ||
48 | |||
49 | #define PSB_CR_CORE_REVISION 0x0014 | ||
50 | #define _PSB_CC_REVISION_DESIGNER_SHIFT (24) | ||
51 | #define _PSB_CC_REVISION_DESIGNER_MASK (0xFF << 24) | ||
52 | #define _PSB_CC_REVISION_MAJOR_SHIFT (16) | ||
53 | #define _PSB_CC_REVISION_MAJOR_MASK (0xFF << 16) | ||
54 | #define _PSB_CC_REVISION_MINOR_SHIFT (8) | ||
55 | #define _PSB_CC_REVISION_MINOR_MASK (0xFF << 8) | ||
56 | #define _PSB_CC_REVISION_MAINTENANCE_SHIFT (0) | ||
57 | #define _PSB_CC_REVISION_MAINTENANCE_MASK (0xFF << 0) | ||
58 | |||
59 | #define PSB_CR_DESIGNER_REV_FIELD1 0x0018 | ||
60 | |||
61 | #define PSB_CR_SOFT_RESET 0x0080 | ||
62 | #define _PSB_CS_RESET_TSP_RESET (1 << 6) | ||
63 | #define _PSB_CS_RESET_ISP_RESET (1 << 5) | ||
64 | #define _PSB_CS_RESET_USE_RESET (1 << 4) | ||
65 | #define _PSB_CS_RESET_TA_RESET (1 << 3) | ||
66 | #define _PSB_CS_RESET_DPM_RESET (1 << 2) | ||
67 | #define _PSB_CS_RESET_TWOD_RESET (1 << 1) | ||
68 | #define _PSB_CS_RESET_BIF_RESET (1 << 0) | ||
69 | |||
70 | #define PSB_CR_DESIGNER_REV_FIELD2 0x001C | ||
71 | |||
72 | #define PSB_CR_EVENT_HOST_ENABLE2 0x0110 | ||
73 | |||
74 | #define PSB_CR_EVENT_STATUS2 0x0118 | ||
75 | |||
76 | #define PSB_CR_EVENT_HOST_CLEAR2 0x0114 | ||
77 | #define _PSB_CE2_BIF_REQUESTER_FAULT (1 << 4) | ||
78 | |||
79 | #define PSB_CR_EVENT_STATUS 0x012C | ||
80 | |||
81 | #define PSB_CR_EVENT_HOST_ENABLE 0x0130 | ||
82 | |||
83 | #define PSB_CR_EVENT_HOST_CLEAR 0x0134 | ||
84 | #define _PSB_CE_MASTER_INTERRUPT (1 << 31) | ||
85 | #define _PSB_CE_TA_DPM_FAULT (1 << 28) | ||
86 | #define _PSB_CE_TWOD_COMPLETE (1 << 27) | ||
87 | #define _PSB_CE_DPM_OUT_OF_MEMORY_ZLS (1 << 25) | ||
88 | #define _PSB_CE_DPM_TA_MEM_FREE (1 << 24) | ||
89 | #define _PSB_CE_PIXELBE_END_RENDER (1 << 18) | ||
90 | #define _PSB_CE_SW_EVENT (1 << 14) | ||
91 | #define _PSB_CE_TA_FINISHED (1 << 13) | ||
92 | #define _PSB_CE_TA_TERMINATE (1 << 12) | ||
93 | #define _PSB_CE_DPM_REACHED_MEM_THRESH (1 << 3) | ||
94 | #define _PSB_CE_DPM_OUT_OF_MEMORY_GBL (1 << 2) | ||
95 | #define _PSB_CE_DPM_OUT_OF_MEMORY_MT (1 << 1) | ||
96 | #define _PSB_CE_DPM_3D_MEM_FREE (1 << 0) | ||
97 | |||
98 | |||
99 | #define PSB_USE_OFFSET_MASK 0x0007FFFF | ||
100 | #define PSB_USE_OFFSET_SIZE (PSB_USE_OFFSET_MASK + 1) | ||
101 | #define PSB_CR_USE_CODE_BASE0 0x0A0C | ||
102 | #define PSB_CR_USE_CODE_BASE1 0x0A10 | ||
103 | #define PSB_CR_USE_CODE_BASE2 0x0A14 | ||
104 | #define PSB_CR_USE_CODE_BASE3 0x0A18 | ||
105 | #define PSB_CR_USE_CODE_BASE4 0x0A1C | ||
106 | #define PSB_CR_USE_CODE_BASE5 0x0A20 | ||
107 | #define PSB_CR_USE_CODE_BASE6 0x0A24 | ||
108 | #define PSB_CR_USE_CODE_BASE7 0x0A28 | ||
109 | #define PSB_CR_USE_CODE_BASE8 0x0A2C | ||
110 | #define PSB_CR_USE_CODE_BASE9 0x0A30 | ||
111 | #define PSB_CR_USE_CODE_BASE10 0x0A34 | ||
112 | #define PSB_CR_USE_CODE_BASE11 0x0A38 | ||
113 | #define PSB_CR_USE_CODE_BASE12 0x0A3C | ||
114 | #define PSB_CR_USE_CODE_BASE13 0x0A40 | ||
115 | #define PSB_CR_USE_CODE_BASE14 0x0A44 | ||
116 | #define PSB_CR_USE_CODE_BASE15 0x0A48 | ||
117 | #define PSB_CR_USE_CODE_BASE(_i) (0x0A0C + ((_i) << 2)) | ||
118 | #define _PSB_CUC_BASE_DM_SHIFT (25) | ||
119 | #define _PSB_CUC_BASE_DM_MASK (0x3 << 25) | ||
120 | #define _PSB_CUC_BASE_ADDR_SHIFT (0) /* 1024-bit aligned address? */ | ||
121 | #define _PSB_CUC_BASE_ADDR_ALIGNSHIFT (7) | ||
122 | #define _PSB_CUC_BASE_ADDR_MASK (0x1FFFFFF << 0) | ||
123 | #define _PSB_CUC_DM_VERTEX (0) | ||
124 | #define _PSB_CUC_DM_PIXEL (1) | ||
125 | #define _PSB_CUC_DM_RESERVED (2) | ||
126 | #define _PSB_CUC_DM_EDM (3) | ||
127 | |||
128 | #define PSB_CR_PDS_EXEC_BASE 0x0AB8 | ||
129 | #define _PSB_CR_PDS_EXEC_BASE_ADDR_SHIFT (20) /* 1MB aligned address */ | ||
130 | #define _PSB_CR_PDS_EXEC_BASE_ADDR_ALIGNSHIFT (20) | ||
131 | |||
132 | #define PSB_CR_EVENT_KICKER 0x0AC4 | ||
133 | #define _PSB_CE_KICKER_ADDRESS_SHIFT (4) /* 128-bit aligned address */ | ||
134 | |||
135 | #define PSB_CR_EVENT_KICK 0x0AC8 | ||
136 | #define _PSB_CE_KICK_NOW (1 << 0) | ||
137 | |||
138 | #define PSB_CR_BIF_DIR_LIST_BASE1 0x0C38 | ||
139 | |||
140 | #define PSB_CR_BIF_CTRL 0x0C00 | ||
141 | #define _PSB_CB_CTRL_CLEAR_FAULT (1 << 4) | ||
142 | #define _PSB_CB_CTRL_INVALDC (1 << 3) | ||
143 | #define _PSB_CB_CTRL_FLUSH (1 << 2) | ||
144 | |||
145 | #define PSB_CR_BIF_INT_STAT 0x0C04 | ||
146 | |||
147 | #define PSB_CR_BIF_FAULT 0x0C08 | ||
148 | #define _PSB_CBI_STAT_PF_N_RW (1 << 14) | ||
149 | #define _PSB_CBI_STAT_FAULT_SHIFT (0) | ||
150 | #define _PSB_CBI_STAT_FAULT_MASK (0x3FFF << 0) | ||
151 | #define _PSB_CBI_STAT_FAULT_CACHE (1 << 1) | ||
152 | #define _PSB_CBI_STAT_FAULT_TA (1 << 2) | ||
153 | #define _PSB_CBI_STAT_FAULT_VDM (1 << 3) | ||
154 | #define _PSB_CBI_STAT_FAULT_2D (1 << 4) | ||
155 | #define _PSB_CBI_STAT_FAULT_PBE (1 << 5) | ||
156 | #define _PSB_CBI_STAT_FAULT_TSP (1 << 6) | ||
157 | #define _PSB_CBI_STAT_FAULT_ISP (1 << 7) | ||
158 | #define _PSB_CBI_STAT_FAULT_USSEPDS (1 << 8) | ||
159 | #define _PSB_CBI_STAT_FAULT_HOST (1 << 9) | ||
160 | |||
161 | #define PSB_CR_BIF_BANK0 0x0C78 | ||
162 | #define PSB_CR_BIF_BANK1 0x0C7C | ||
163 | #define PSB_CR_BIF_DIR_LIST_BASE0 0x0C84 | ||
164 | #define PSB_CR_BIF_TWOD_REQ_BASE 0x0C88 | ||
165 | #define PSB_CR_BIF_3D_REQ_BASE 0x0CAC | ||
166 | |||
167 | #define PSB_CR_2D_SOCIF 0x0E18 | ||
168 | #define _PSB_C2_SOCIF_FREESPACE_SHIFT (0) | ||
169 | #define _PSB_C2_SOCIF_FREESPACE_MASK (0xFF << 0) | ||
170 | #define _PSB_C2_SOCIF_EMPTY (0x80 << 0) | ||
171 | |||
172 | #define PSB_CR_2D_BLIT_STATUS 0x0E04 | ||
173 | #define _PSB_C2B_STATUS_BUSY (1 << 24) | ||
174 | #define _PSB_C2B_STATUS_COMPLETE_SHIFT (0) | ||
175 | #define _PSB_C2B_STATUS_COMPLETE_MASK (0xFFFFFF << 0) | ||
176 | |||
177 | /* | ||
178 | * 2D defs. | ||
179 | */ | ||
180 | |||
181 | /* | ||
182 | * 2D Slave Port Data : Block Header's Object Type | ||
183 | */ | ||
184 | |||
185 | #define PSB_2D_CLIP_BH (0x00000000) | ||
186 | #define PSB_2D_PAT_BH (0x10000000) | ||
187 | #define PSB_2D_CTRL_BH (0x20000000) | ||
188 | #define PSB_2D_SRC_OFF_BH (0x30000000) | ||
189 | #define PSB_2D_MASK_OFF_BH (0x40000000) | ||
190 | #define PSB_2D_RESERVED1_BH (0x50000000) | ||
191 | #define PSB_2D_RESERVED2_BH (0x60000000) | ||
192 | #define PSB_2D_FENCE_BH (0x70000000) | ||
193 | #define PSB_2D_BLIT_BH (0x80000000) | ||
194 | #define PSB_2D_SRC_SURF_BH (0x90000000) | ||
195 | #define PSB_2D_DST_SURF_BH (0xA0000000) | ||
196 | #define PSB_2D_PAT_SURF_BH (0xB0000000) | ||
197 | #define PSB_2D_SRC_PAL_BH (0xC0000000) | ||
198 | #define PSB_2D_PAT_PAL_BH (0xD0000000) | ||
199 | #define PSB_2D_MASK_SURF_BH (0xE0000000) | ||
200 | #define PSB_2D_FLUSH_BH (0xF0000000) | ||
201 | |||
202 | /* | ||
203 | * Clip Definition block (PSB_2D_CLIP_BH) | ||
204 | */ | ||
205 | #define PSB_2D_CLIPCOUNT_MAX (1) | ||
206 | #define PSB_2D_CLIPCOUNT_MASK (0x00000000) | ||
207 | #define PSB_2D_CLIPCOUNT_CLRMASK (0xFFFFFFFF) | ||
208 | #define PSB_2D_CLIPCOUNT_SHIFT (0) | ||
209 | /* clip rectangle min & max */ | ||
210 | #define PSB_2D_CLIP_XMAX_MASK (0x00FFF000) | ||
211 | #define PSB_2D_CLIP_XMAX_CLRMASK (0xFF000FFF) | ||
212 | #define PSB_2D_CLIP_XMAX_SHIFT (12) | ||
213 | #define PSB_2D_CLIP_XMIN_MASK (0x00000FFF) | ||
214 | #define PSB_2D_CLIP_XMIN_CLRMASK (0x00FFF000) | ||
215 | #define PSB_2D_CLIP_XMIN_SHIFT (0) | ||
216 | /* clip rectangle offset */ | ||
217 | #define PSB_2D_CLIP_YMAX_MASK (0x00FFF000) | ||
218 | #define PSB_2D_CLIP_YMAX_CLRMASK (0xFF000FFF) | ||
219 | #define PSB_2D_CLIP_YMAX_SHIFT (12) | ||
220 | #define PSB_2D_CLIP_YMIN_MASK (0x00000FFF) | ||
221 | #define PSB_2D_CLIP_YMIN_CLRMASK (0x00FFF000) | ||
222 | #define PSB_2D_CLIP_YMIN_SHIFT (0) | ||
223 | |||
224 | /* | ||
225 | * Pattern Control (PSB_2D_PAT_BH) | ||
226 | */ | ||
227 | #define PSB_2D_PAT_HEIGHT_MASK (0x0000001F) | ||
228 | #define PSB_2D_PAT_HEIGHT_SHIFT (0) | ||
229 | #define PSB_2D_PAT_WIDTH_MASK (0x000003E0) | ||
230 | #define PSB_2D_PAT_WIDTH_SHIFT (5) | ||
231 | #define PSB_2D_PAT_YSTART_MASK (0x00007C00) | ||
232 | #define PSB_2D_PAT_YSTART_SHIFT (10) | ||
233 | #define PSB_2D_PAT_XSTART_MASK (0x000F8000) | ||
234 | #define PSB_2D_PAT_XSTART_SHIFT (15) | ||
235 | |||
236 | /* | ||
237 | * 2D Control block (PSB_2D_CTRL_BH) | ||
238 | */ | ||
239 | /* Present Flags */ | ||
240 | #define PSB_2D_SRCCK_CTRL (0x00000001) | ||
241 | #define PSB_2D_DSTCK_CTRL (0x00000002) | ||
242 | #define PSB_2D_ALPHA_CTRL (0x00000004) | ||
243 | /* Colour Key Colour (SRC/DST)*/ | ||
244 | #define PSB_2D_CK_COL_MASK (0xFFFFFFFF) | ||
245 | #define PSB_2D_CK_COL_CLRMASK (0x00000000) | ||
246 | #define PSB_2D_CK_COL_SHIFT (0) | ||
247 | /* Colour Key Mask (SRC/DST)*/ | ||
248 | #define PSB_2D_CK_MASK_MASK (0xFFFFFFFF) | ||
249 | #define PSB_2D_CK_MASK_CLRMASK (0x00000000) | ||
250 | #define PSB_2D_CK_MASK_SHIFT (0) | ||
251 | /* Alpha Control (Alpha/RGB)*/ | ||
252 | #define PSB_2D_GBLALPHA_MASK (0x000FF000) | ||
253 | #define PSB_2D_GBLALPHA_CLRMASK (0xFFF00FFF) | ||
254 | #define PSB_2D_GBLALPHA_SHIFT (12) | ||
255 | #define PSB_2D_SRCALPHA_OP_MASK (0x00700000) | ||
256 | #define PSB_2D_SRCALPHA_OP_CLRMASK (0xFF8FFFFF) | ||
257 | #define PSB_2D_SRCALPHA_OP_SHIFT (20) | ||
258 | #define PSB_2D_SRCALPHA_OP_ONE (0x00000000) | ||
259 | #define PSB_2D_SRCALPHA_OP_SRC (0x00100000) | ||
260 | #define PSB_2D_SRCALPHA_OP_DST (0x00200000) | ||
261 | #define PSB_2D_SRCALPHA_OP_SG (0x00300000) | ||
262 | #define PSB_2D_SRCALPHA_OP_DG (0x00400000) | ||
263 | #define PSB_2D_SRCALPHA_OP_GBL (0x00500000) | ||
264 | #define PSB_2D_SRCALPHA_OP_ZERO (0x00600000) | ||
265 | #define PSB_2D_SRCALPHA_INVERT (0x00800000) | ||
266 | #define PSB_2D_SRCALPHA_INVERT_CLR (0xFF7FFFFF) | ||
267 | #define PSB_2D_DSTALPHA_OP_MASK (0x07000000) | ||
268 | #define PSB_2D_DSTALPHA_OP_CLRMASK (0xF8FFFFFF) | ||
269 | #define PSB_2D_DSTALPHA_OP_SHIFT (24) | ||
270 | #define PSB_2D_DSTALPHA_OP_ONE (0x00000000) | ||
271 | #define PSB_2D_DSTALPHA_OP_SRC (0x01000000) | ||
272 | #define PSB_2D_DSTALPHA_OP_DST (0x02000000) | ||
273 | #define PSB_2D_DSTALPHA_OP_SG (0x03000000) | ||
274 | #define PSB_2D_DSTALPHA_OP_DG (0x04000000) | ||
275 | #define PSB_2D_DSTALPHA_OP_GBL (0x05000000) | ||
276 | #define PSB_2D_DSTALPHA_OP_ZERO (0x06000000) | ||
277 | #define PSB_2D_DSTALPHA_INVERT (0x08000000) | ||
278 | #define PSB_2D_DSTALPHA_INVERT_CLR (0xF7FFFFFF) | ||
279 | |||
280 | #define PSB_2D_PRE_MULTIPLICATION_ENABLE (0x10000000) | ||
281 | #define PSB_2D_PRE_MULTIPLICATION_CLRMASK (0xEFFFFFFF) | ||
282 | #define PSB_2D_ZERO_SOURCE_ALPHA_ENABLE (0x20000000) | ||
283 | #define PSB_2D_ZERO_SOURCE_ALPHA_CLRMASK (0xDFFFFFFF) | ||
284 | |||
285 | /* | ||
286 | *Source Offset (PSB_2D_SRC_OFF_BH) | ||
287 | */ | ||
288 | #define PSB_2D_SRCOFF_XSTART_MASK ((0x00000FFF) << 12) | ||
289 | #define PSB_2D_SRCOFF_XSTART_SHIFT (12) | ||
290 | #define PSB_2D_SRCOFF_YSTART_MASK (0x00000FFF) | ||
291 | #define PSB_2D_SRCOFF_YSTART_SHIFT (0) | ||
292 | |||
293 | /* | ||
294 | * Mask Offset (PSB_2D_MASK_OFF_BH) | ||
295 | */ | ||
296 | #define PSB_2D_MASKOFF_XSTART_MASK ((0x00000FFF) << 12) | ||
297 | #define PSB_2D_MASKOFF_XSTART_SHIFT (12) | ||
298 | #define PSB_2D_MASKOFF_YSTART_MASK (0x00000FFF) | ||
299 | #define PSB_2D_MASKOFF_YSTART_SHIFT (0) | ||
300 | |||
301 | /* | ||
302 | * 2D Fence (see PSB_2D_FENCE_BH): bits 0:27 are ignored | ||
303 | */ | ||
304 | |||
305 | /* | ||
306 | *Blit Rectangle (PSB_2D_BLIT_BH) | ||
307 | */ | ||
308 | |||
309 | #define PSB_2D_ROT_MASK (3 << 25) | ||
310 | #define PSB_2D_ROT_CLRMASK (~PSB_2D_ROT_MASK) | ||
311 | #define PSB_2D_ROT_NONE (0 << 25) | ||
312 | #define PSB_2D_ROT_90DEGS (1 << 25) | ||
313 | #define PSB_2D_ROT_180DEGS (2 << 25) | ||
314 | #define PSB_2D_ROT_270DEGS (3 << 25) | ||
315 | |||
316 | #define PSB_2D_COPYORDER_MASK (3 << 23) | ||
317 | #define PSB_2D_COPYORDER_CLRMASK (~PSB_2D_COPYORDER_MASK) | ||
318 | #define PSB_2D_COPYORDER_TL2BR (0 << 23) | ||
319 | #define PSB_2D_COPYORDER_BR2TL (1 << 23) | ||
320 | #define PSB_2D_COPYORDER_TR2BL (2 << 23) | ||
321 | #define PSB_2D_COPYORDER_BL2TR (3 << 23) | ||
322 | |||
323 | #define PSB_2D_DSTCK_CLRMASK (0xFF9FFFFF) | ||
324 | #define PSB_2D_DSTCK_DISABLE (0x00000000) | ||
325 | #define PSB_2D_DSTCK_PASS (0x00200000) | ||
326 | #define PSB_2D_DSTCK_REJECT (0x00400000) | ||
327 | |||
328 | #define PSB_2D_SRCCK_CLRMASK (0xFFE7FFFF) | ||
329 | #define PSB_2D_SRCCK_DISABLE (0x00000000) | ||
330 | #define PSB_2D_SRCCK_PASS (0x00080000) | ||
331 | #define PSB_2D_SRCCK_REJECT (0x00100000) | ||
332 | |||
333 | #define PSB_2D_CLIP_ENABLE (0x00040000) | ||
334 | |||
335 | #define PSB_2D_ALPHA_ENABLE (0x00020000) | ||
336 | |||
337 | #define PSB_2D_PAT_CLRMASK (0xFFFEFFFF) | ||
338 | #define PSB_2D_PAT_MASK (0x00010000) | ||
339 | #define PSB_2D_USE_PAT (0x00010000) | ||
340 | #define PSB_2D_USE_FILL (0x00000000) | ||
341 | /* | ||
342 | * Tungsten Graphics note on rop codes: If rop A and rop B are | ||
343 | * identical, the mask surface will not be read and need not be | ||
344 | * set up. | ||
345 | */ | ||
346 | |||
347 | #define PSB_2D_ROP3B_MASK (0x0000FF00) | ||
348 | #define PSB_2D_ROP3B_CLRMASK (0xFFFF00FF) | ||
349 | #define PSB_2D_ROP3B_SHIFT (8) | ||
350 | /* rop code A */ | ||
351 | #define PSB_2D_ROP3A_MASK (0x000000FF) | ||
352 | #define PSB_2D_ROP3A_CLRMASK (0xFFFFFF00) | ||
353 | #define PSB_2D_ROP3A_SHIFT (0) | ||
354 | |||
355 | #define PSB_2D_ROP4_MASK (0x0000FFFF) | ||
356 | /* | ||
357 | * DWORD0: (Only pass if Pattern control == Use Fill Colour) | ||
358 | * Fill Colour RGBA8888 | ||
359 | */ | ||
360 | #define PSB_2D_FILLCOLOUR_MASK (0xFFFFFFFF) | ||
361 | #define PSB_2D_FILLCOLOUR_SHIFT (0) | ||
362 | /* | ||
363 | * DWORD1: (Always Present) | ||
364 | * X Start (Dest) | ||
365 | * Y Start (Dest) | ||
366 | */ | ||
367 | #define PSB_2D_DST_XSTART_MASK (0x00FFF000) | ||
368 | #define PSB_2D_DST_XSTART_CLRMASK (0xFF000FFF) | ||
369 | #define PSB_2D_DST_XSTART_SHIFT (12) | ||
370 | #define PSB_2D_DST_YSTART_MASK (0x00000FFF) | ||
371 | #define PSB_2D_DST_YSTART_CLRMASK (0xFFFFF000) | ||
372 | #define PSB_2D_DST_YSTART_SHIFT (0) | ||
373 | /* | ||
374 | * DWORD2: (Always Present) | ||
375 | * X Size (Dest) | ||
376 | * Y Size (Dest) | ||
377 | */ | ||
378 | #define PSB_2D_DST_XSIZE_MASK (0x00FFF000) | ||
379 | #define PSB_2D_DST_XSIZE_CLRMASK (0xFF000FFF) | ||
380 | #define PSB_2D_DST_XSIZE_SHIFT (12) | ||
381 | #define PSB_2D_DST_YSIZE_MASK (0x00000FFF) | ||
382 | #define PSB_2D_DST_YSIZE_CLRMASK (0xFFFFF000) | ||
383 | #define PSB_2D_DST_YSIZE_SHIFT (0) | ||
384 | |||
385 | /* | ||
386 | * Source Surface (PSB_2D_SRC_SURF_BH) | ||
387 | */ | ||
388 | /* | ||
389 | * WORD 0 | ||
390 | */ | ||
391 | |||
392 | #define PSB_2D_SRC_FORMAT_MASK (0x00078000) | ||
393 | #define PSB_2D_SRC_1_PAL (0x00000000) | ||
394 | #define PSB_2D_SRC_2_PAL (0x00008000) | ||
395 | #define PSB_2D_SRC_4_PAL (0x00010000) | ||
396 | #define PSB_2D_SRC_8_PAL (0x00018000) | ||
397 | #define PSB_2D_SRC_8_ALPHA (0x00020000) | ||
398 | #define PSB_2D_SRC_4_ALPHA (0x00028000) | ||
399 | #define PSB_2D_SRC_332RGB (0x00030000) | ||
400 | #define PSB_2D_SRC_4444ARGB (0x00038000) | ||
401 | #define PSB_2D_SRC_555RGB (0x00040000) | ||
402 | #define PSB_2D_SRC_1555ARGB (0x00048000) | ||
403 | #define PSB_2D_SRC_565RGB (0x00050000) | ||
404 | #define PSB_2D_SRC_0888ARGB (0x00058000) | ||
405 | #define PSB_2D_SRC_8888ARGB (0x00060000) | ||
406 | #define PSB_2D_SRC_8888UYVY (0x00068000) | ||
407 | #define PSB_2D_SRC_RESERVED (0x00070000) | ||
408 | #define PSB_2D_SRC_1555ARGB_LOOKUP (0x00078000) | ||
409 | |||
410 | |||
411 | #define PSB_2D_SRC_STRIDE_MASK (0x00007FFF) | ||
412 | #define PSB_2D_SRC_STRIDE_CLRMASK (0xFFFF8000) | ||
413 | #define PSB_2D_SRC_STRIDE_SHIFT (0) | ||
414 | /* | ||
415 | * WORD 1 - Base Address | ||
416 | */ | ||
417 | #define PSB_2D_SRC_ADDR_MASK (0x0FFFFFFC) | ||
418 | #define PSB_2D_SRC_ADDR_CLRMASK (0x00000003) | ||
419 | #define PSB_2D_SRC_ADDR_SHIFT (2) | ||
420 | #define PSB_2D_SRC_ADDR_ALIGNSHIFT (2) | ||
421 | |||
422 | /* | ||
423 | * Pattern Surface (PSB_2D_PAT_SURF_BH) | ||
424 | */ | ||
425 | /* | ||
426 | * WORD 0 | ||
427 | */ | ||
428 | |||
429 | #define PSB_2D_PAT_FORMAT_MASK (0x00078000) | ||
430 | #define PSB_2D_PAT_1_PAL (0x00000000) | ||
431 | #define PSB_2D_PAT_2_PAL (0x00008000) | ||
432 | #define PSB_2D_PAT_4_PAL (0x00010000) | ||
433 | #define PSB_2D_PAT_8_PAL (0x00018000) | ||
434 | #define PSB_2D_PAT_8_ALPHA (0x00020000) | ||
435 | #define PSB_2D_PAT_4_ALPHA (0x00028000) | ||
436 | #define PSB_2D_PAT_332RGB (0x00030000) | ||
437 | #define PSB_2D_PAT_4444ARGB (0x00038000) | ||
438 | #define PSB_2D_PAT_555RGB (0x00040000) | ||
439 | #define PSB_2D_PAT_1555ARGB (0x00048000) | ||
440 | #define PSB_2D_PAT_565RGB (0x00050000) | ||
441 | #define PSB_2D_PAT_0888ARGB (0x00058000) | ||
442 | #define PSB_2D_PAT_8888ARGB (0x00060000) | ||
443 | |||
444 | #define PSB_2D_PAT_STRIDE_MASK (0x00007FFF) | ||
445 | #define PSB_2D_PAT_STRIDE_CLRMASK (0xFFFF8000) | ||
446 | #define PSB_2D_PAT_STRIDE_SHIFT (0) | ||
447 | /* | ||
448 | * WORD 1 - Base Address | ||
449 | */ | ||
450 | #define PSB_2D_PAT_ADDR_MASK (0x0FFFFFFC) | ||
451 | #define PSB_2D_PAT_ADDR_CLRMASK (0x00000003) | ||
452 | #define PSB_2D_PAT_ADDR_SHIFT (2) | ||
453 | #define PSB_2D_PAT_ADDR_ALIGNSHIFT (2) | ||
454 | |||
455 | /* | ||
456 | * Destination Surface (PSB_2D_DST_SURF_BH) | ||
457 | */ | ||
458 | /* | ||
459 | * WORD 0 | ||
460 | */ | ||
461 | |||
462 | #define PSB_2D_DST_FORMAT_MASK (0x00078000) | ||
463 | #define PSB_2D_DST_332RGB (0x00030000) | ||
464 | #define PSB_2D_DST_4444ARGB (0x00038000) | ||
465 | #define PSB_2D_DST_555RGB (0x00040000) | ||
466 | #define PSB_2D_DST_1555ARGB (0x00048000) | ||
467 | #define PSB_2D_DST_565RGB (0x00050000) | ||
468 | #define PSB_2D_DST_0888ARGB (0x00058000) | ||
469 | #define PSB_2D_DST_8888ARGB (0x00060000) | ||
470 | #define PSB_2D_DST_8888AYUV (0x00070000) | ||
471 | |||
472 | #define PSB_2D_DST_STRIDE_MASK (0x00007FFF) | ||
473 | #define PSB_2D_DST_STRIDE_CLRMASK (0xFFFF8000) | ||
474 | #define PSB_2D_DST_STRIDE_SHIFT (0) | ||
475 | /* | ||
476 | * WORD 1 - Base Address | ||
477 | */ | ||
478 | #define PSB_2D_DST_ADDR_MASK (0x0FFFFFFC) | ||
479 | #define PSB_2D_DST_ADDR_CLRMASK (0x00000003) | ||
480 | #define PSB_2D_DST_ADDR_SHIFT (2) | ||
481 | #define PSB_2D_DST_ADDR_ALIGNSHIFT (2) | ||
482 | |||
483 | /* | ||
484 | * Mask Surface (PSB_2D_MASK_SURF_BH) | ||
485 | */ | ||
486 | /* | ||
487 | * WORD 0 | ||
488 | */ | ||
489 | #define PSB_2D_MASK_STRIDE_MASK (0x00007FFF) | ||
490 | #define PSB_2D_MASK_STRIDE_CLRMASK (0xFFFF8000) | ||
491 | #define PSB_2D_MASK_STRIDE_SHIFT (0) | ||
492 | /* | ||
493 | * WORD 1 - Base Address | ||
494 | */ | ||
495 | #define PSB_2D_MASK_ADDR_MASK (0x0FFFFFFC) | ||
496 | #define PSB_2D_MASK_ADDR_CLRMASK (0x00000003) | ||
497 | #define PSB_2D_MASK_ADDR_SHIFT (2) | ||
498 | #define PSB_2D_MASK_ADDR_ALIGNSHIFT (2) | ||
499 | |||
500 | /* | ||
501 | * Source Palette (PSB_2D_SRC_PAL_BH) | ||
502 | */ | ||
503 | |||
504 | #define PSB_2D_SRCPAL_ADDR_SHIFT (0) | ||
505 | #define PSB_2D_SRCPAL_ADDR_CLRMASK (0xF0000007) | ||
506 | #define PSB_2D_SRCPAL_ADDR_MASK (0x0FFFFFF8) | ||
507 | #define PSB_2D_SRCPAL_BYTEALIGN (1024) | ||
508 | |||
509 | /* | ||
510 | * Pattern Palette (PSB_2D_PAT_PAL_BH) | ||
511 | */ | ||
512 | |||
513 | #define PSB_2D_PATPAL_ADDR_SHIFT (0) | ||
514 | #define PSB_2D_PATPAL_ADDR_CLRMASK (0xF0000007) | ||
515 | #define PSB_2D_PATPAL_ADDR_MASK (0x0FFFFFF8) | ||
516 | #define PSB_2D_PATPAL_BYTEALIGN (1024) | ||
517 | |||
518 | /* | ||
519 | * Rop3 Codes (2 LS bytes) | ||
520 | */ | ||
521 | |||
522 | #define PSB_2D_ROP3_SRCCOPY (0xCCCC) | ||
523 | #define PSB_2D_ROP3_PATCOPY (0xF0F0) | ||
524 | #define PSB_2D_ROP3_WHITENESS (0xFFFF) | ||
525 | #define PSB_2D_ROP3_BLACKNESS (0x0000) | ||
526 | #define PSB_2D_ROP3_SRC (0xCC) | ||
527 | #define PSB_2D_ROP3_PAT (0xF0) | ||
528 | #define PSB_2D_ROP3_DST (0xAA) | ||
529 | |||
530 | /* | ||
531 | * Sizes. | ||
532 | */ | ||
533 | |||
534 | #define PSB_SCENE_HW_COOKIE_SIZE 16 | ||
535 | #define PSB_TA_MEM_HW_COOKIE_SIZE 16 | ||
536 | |||
537 | /* | ||
538 | * Scene stuff. | ||
539 | */ | ||
540 | |||
541 | #define PSB_NUM_HW_SCENES 2 | ||
542 | |||
543 | /* | ||
544 | * Scheduler completion actions. | ||
545 | */ | ||
546 | |||
547 | #define PSB_RASTER_BLOCK 0 | ||
548 | #define PSB_RASTER 1 | ||
549 | #define PSB_RETURN 2 | ||
550 | #define PSB_TA 3 | ||
551 | |||
552 | /* Power management */ | ||
553 | #define PSB_PUNIT_PORT 0x04 | ||
554 | #define PSB_OSPMBA 0x78 | ||
555 | #define PSB_APMBA 0x7a | ||
556 | #define PSB_APM_CMD 0x0 | ||
557 | #define PSB_APM_STS 0x04 | ||
558 | #define PSB_PWRGT_VID_ENC_MASK 0x30 | ||
559 | #define PSB_PWRGT_VID_DEC_MASK 0xc | ||
560 | #define PSB_PWRGT_GL3_MASK 0xc0 | ||
561 | |||
562 | #define PSB_PM_SSC 0x20 | ||
563 | #define PSB_PM_SSS 0x30 | ||
564 | #define PSB_PWRGT_DISPLAY_MASK 0xc /*on a different BA than video/gfx*/ | ||
565 | #define MDFLD_PWRGT_DISPLAY_A_CNTR 0x0000000c | ||
566 | #define MDFLD_PWRGT_DISPLAY_B_CNTR 0x0000c000 | ||
567 | #define MDFLD_PWRGT_DISPLAY_C_CNTR 0x00030000 | ||
568 | #define MDFLD_PWRGT_DISP_MIPI_CNTR 0x000c0000 | ||
569 | #define MDFLD_PWRGT_DISPLAY_CNTR (MDFLD_PWRGT_DISPLAY_A_CNTR | MDFLD_PWRGT_DISPLAY_B_CNTR | MDFLD_PWRGT_DISPLAY_C_CNTR | MDFLD_PWRGT_DISP_MIPI_CNTR) /* 0x000fc00c */ | ||
570 | /* Display SSS register bits are different in A0 vs. B0 */ | ||
571 | #define PSB_PWRGT_GFX_MASK 0x3 | ||
572 | #define MDFLD_PWRGT_DISPLAY_A_STS 0x000000c0 | ||
573 | #define MDFLD_PWRGT_DISPLAY_B_STS 0x00000300 | ||
574 | #define MDFLD_PWRGT_DISPLAY_C_STS 0x00000c00 | ||
575 | #define PSB_PWRGT_GFX_MASK_B0 0xc3 | ||
576 | #define MDFLD_PWRGT_DISPLAY_A_STS_B0 0x0000000c | ||
577 | #define MDFLD_PWRGT_DISPLAY_B_STS_B0 0x0000c000 | ||
578 | #define MDFLD_PWRGT_DISPLAY_C_STS_B0 0x00030000 | ||
579 | #define MDFLD_PWRGT_DISP_MIPI_STS 0x000c0000 | ||
580 | #define MDFLD_PWRGT_DISPLAY_STS_A0 (MDFLD_PWRGT_DISPLAY_A_STS | MDFLD_PWRGT_DISPLAY_B_STS | MDFLD_PWRGT_DISPLAY_C_STS | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */ | ||
581 | #define MDFLD_PWRGT_DISPLAY_STS_B0 (MDFLD_PWRGT_DISPLAY_A_STS_B0 | MDFLD_PWRGT_DISPLAY_B_STS_B0 | MDFLD_PWRGT_DISPLAY_C_STS_B0 | MDFLD_PWRGT_DISP_MIPI_STS) /* 0x000fc00c */ | ||
582 | #endif | ||