aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/staging/gma500
diff options
context:
space:
mode:
authorJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
committerJonathan Herman <hermanjl@cs.unc.edu>2013-01-22 10:38:37 -0500
commitfcc9d2e5a6c89d22b8b773a64fb4ad21ac318446 (patch)
treea57612d1888735a2ec7972891b68c1ac5ec8faea /drivers/staging/gma500
parent8dea78da5cee153b8af9c07a2745f6c55057fe12 (diff)
Added missing tegra files.HEADmaster
Diffstat (limited to 'drivers/staging/gma500')
-rw-r--r--drivers/staging/gma500/Kconfig33
-rw-r--r--drivers/staging/gma500/Makefile52
-rw-r--r--drivers/staging/gma500/TODO15
-rw-r--r--drivers/staging/gma500/accel_2d.c412
-rw-r--r--drivers/staging/gma500/backlight.c49
-rw-r--r--drivers/staging/gma500/cdv_device.c351
-rw-r--r--drivers/staging/gma500/cdv_device.h36
-rw-r--r--drivers/staging/gma500/cdv_intel_crt.c326
-rw-r--r--drivers/staging/gma500/cdv_intel_display.c1508
-rw-r--r--drivers/staging/gma500/cdv_intel_hdmi.c376
-rw-r--r--drivers/staging/gma500/cdv_intel_lvds.c721
-rw-r--r--drivers/staging/gma500/displays/hdmi.h33
-rw-r--r--drivers/staging/gma500/displays/pyr_cmd.h34
-rw-r--r--drivers/staging/gma500/displays/pyr_vid.h34
-rw-r--r--drivers/staging/gma500/displays/tmd_cmd.h34
-rw-r--r--drivers/staging/gma500/displays/tmd_vid.h34
-rw-r--r--drivers/staging/gma500/displays/tpo_cmd.h35
-rw-r--r--drivers/staging/gma500/displays/tpo_vid.h33
-rw-r--r--drivers/staging/gma500/framebuffer.c787
-rw-r--r--drivers/staging/gma500/framebuffer.h48
-rw-r--r--drivers/staging/gma500/gem.c295
-rw-r--r--drivers/staging/gma500/gem_glue.c89
-rw-r--r--drivers/staging/gma500/gem_glue.h2
-rw-r--r--drivers/staging/gma500/gtt.c500
-rw-r--r--drivers/staging/gma500/gtt.h61
-rw-r--r--drivers/staging/gma500/intel_bios.c303
-rw-r--r--drivers/staging/gma500/intel_bios.h430
-rw-r--r--drivers/staging/gma500/intel_i2c.c169
-rw-r--r--drivers/staging/gma500/intel_opregion.c80
-rw-r--r--drivers/staging/gma500/mdfld_device.c714
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi.c761
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi.h173
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi_dpu.c778
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dbi_dpu.h154
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dpi.c805
-rw-r--r--drivers/staging/gma500/mdfld_dsi_dpi.h78
-rw-r--r--drivers/staging/gma500/mdfld_dsi_output.c1013
-rw-r--r--drivers/staging/gma500/mdfld_dsi_output.h138
-rw-r--r--drivers/staging/gma500/mdfld_dsi_pkg_sender.c1484
-rw-r--r--drivers/staging/gma500/mdfld_dsi_pkg_sender.h184
-rw-r--r--drivers/staging/gma500/mdfld_intel_display.c1402
-rw-r--r--drivers/staging/gma500/mdfld_msic.h31
-rw-r--r--drivers/staging/gma500/mdfld_output.c170
-rw-r--r--drivers/staging/gma500/mdfld_output.h41
-rw-r--r--drivers/staging/gma500/mdfld_pyr_cmd.c558
-rw-r--r--drivers/staging/gma500/mdfld_tmd_vid.c206
-rw-r--r--drivers/staging/gma500/mdfld_tpo_cmd.c509
-rw-r--r--drivers/staging/gma500/mdfld_tpo_vid.c140
-rw-r--r--drivers/staging/gma500/medfield.h268
-rw-r--r--drivers/staging/gma500/mid_bios.c269
-rw-r--r--drivers/staging/gma500/mid_bios.h21
-rw-r--r--drivers/staging/gma500/mmu.c858
-rw-r--r--drivers/staging/gma500/mrst.h252
-rw-r--r--drivers/staging/gma500/mrst_crtc.c610
-rw-r--r--drivers/staging/gma500/mrst_device.c634
-rw-r--r--drivers/staging/gma500/mrst_hdmi.c852
-rw-r--r--drivers/staging/gma500/mrst_hdmi_i2c.c327
-rw-r--r--drivers/staging/gma500/mrst_lvds.c407
-rw-r--r--drivers/staging/gma500/power.c316
-rw-r--r--drivers/staging/gma500/power.h67
-rw-r--r--drivers/staging/gma500/psb_device.c353
-rw-r--r--drivers/staging/gma500/psb_drm.h219
-rw-r--r--drivers/staging/gma500/psb_drv.c1231
-rw-r--r--drivers/staging/gma500/psb_drv.h948
-rw-r--r--drivers/staging/gma500/psb_intel_display.c1433
-rw-r--r--drivers/staging/gma500/psb_intel_display.h28
-rw-r--r--drivers/staging/gma500/psb_intel_drv.h230
-rw-r--r--drivers/staging/gma500/psb_intel_lvds.c849
-rw-r--r--drivers/staging/gma500/psb_intel_modes.c77
-rw-r--r--drivers/staging/gma500/psb_intel_reg.h1235
-rw-r--r--drivers/staging/gma500/psb_intel_sdvo.c1293
-rw-r--r--drivers/staging/gma500/psb_intel_sdvo_regs.h338
-rw-r--r--drivers/staging/gma500/psb_irq.c616
-rw-r--r--drivers/staging/gma500/psb_irq.h45
-rw-r--r--drivers/staging/gma500/psb_lid.c90
-rw-r--r--drivers/staging/gma500/psb_reg.h582
76 files changed, 30667 insertions, 0 deletions
diff --git a/drivers/staging/gma500/Kconfig b/drivers/staging/gma500/Kconfig
new file mode 100644
index 00000000000..bfe2166acda
--- /dev/null
+++ b/drivers/staging/gma500/Kconfig
@@ -0,0 +1,33 @@
1config DRM_PSB
2 tristate "Intel GMA5/600 KMS Framebuffer"
3 depends on DRM && PCI && X86
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
14config 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
22config 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
29config 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
new file mode 100644
index 00000000000..c729868b1b1
--- /dev/null
+++ b/drivers/staging/gma500/Makefile
@@ -0,0 +1,52 @@
1#
2# KMS driver for the GMA500
3#
4ccflags-y += -Iinclude/drm
5
6psb_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
27psb_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
33psb_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
39psb_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
52obj-$(CONFIG_DRM_PSB) += psb_gfx.o
diff --git a/drivers/staging/gma500/TODO b/drivers/staging/gma500/TODO
new file mode 100644
index 00000000000..fc836158e74
--- /dev/null
+++ b/drivers/staging/gma500/TODO
@@ -0,0 +1,15 @@
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
13As per kernel policy and the in the interest of the safety of various
14kittens there is no support or plans to add hooks for the closed user space
15stuff.
diff --git a/drivers/staging/gma500/accel_2d.c b/drivers/staging/gma500/accel_2d.c
new file mode 100644
index 00000000000..14400fcfe8a
--- /dev/null
+++ b/drivers/staging/gma500/accel_2d.c
@@ -0,0 +1,412 @@
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 */
51void 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 */
83static 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 */
108static 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
115 mutex_lock(&dev_priv->mutex_2d);
116 while (size > 0) {
117 submit_size = (size < 0x60) ? size : 0x60;
118 size -= submit_size;
119 ret = psb_2d_wait_available(dev_priv, submit_size);
120 if (ret)
121 break;
122
123 submit_size <<= 2;
124
125 for (i = 0; i < submit_size; i += 4)
126 PSB_WSGX32(*cmdbuf++, PSB_SGX_2D_SLAVE_PORT + i);
127
128 (void)PSB_RSGX32(PSB_SGX_2D_SLAVE_PORT + i - 4);
129 }
130 mutex_unlock(&dev_priv->mutex_2d);
131 return ret;
132}
133
134
135/**
136 * psb_accel_2d_copy_direction - compute blit order
137 * @xdir: X direction of move
138 * @ydir: Y direction of move
139 *
140 * Compute the correct order setings to ensure that an overlapping blit
141 * correctly copies all the pixels.
142 */
143static u32 psb_accel_2d_copy_direction(int xdir, int ydir)
144{
145 if (xdir < 0)
146 return (ydir < 0) ? PSB_2D_COPYORDER_BR2TL :
147 PSB_2D_COPYORDER_TR2BL;
148 else
149 return (ydir < 0) ? PSB_2D_COPYORDER_BL2TR :
150 PSB_2D_COPYORDER_TL2BR;
151}
152
153/**
154 * psb_accel_2d_copy - accelerated 2D copy
155 * @dev_priv: our DRM device
156 * @src_offset in bytes
157 * @src_stride in bytes
158 * @src_format psb 2D format defines
159 * @dst_offset in bytes
160 * @dst_stride in bytes
161 * @dst_format psb 2D format defines
162 * @src_x offset in pixels
163 * @src_y offset in pixels
164 * @dst_x offset in pixels
165 * @dst_y offset in pixels
166 * @size_x of the copied area
167 * @size_y of the copied area
168 *
169 * Format and issue a 2D accelerated copy command.
170 */
171static int psb_accel_2d_copy(struct drm_psb_private *dev_priv,
172 uint32_t src_offset, uint32_t src_stride,
173 uint32_t src_format, uint32_t dst_offset,
174 uint32_t dst_stride, uint32_t dst_format,
175 uint16_t src_x, uint16_t src_y,
176 uint16_t dst_x, uint16_t dst_y,
177 uint16_t size_x, uint16_t size_y)
178{
179 uint32_t blit_cmd;
180 uint32_t buffer[10];
181 uint32_t *buf;
182 uint32_t direction;
183
184 buf = buffer;
185
186 direction =
187 psb_accel_2d_copy_direction(src_x - dst_x, src_y - dst_y);
188
189 if (direction == PSB_2D_COPYORDER_BR2TL ||
190 direction == PSB_2D_COPYORDER_TR2BL) {
191 src_x += size_x - 1;
192 dst_x += size_x - 1;
193 }
194 if (direction == PSB_2D_COPYORDER_BR2TL ||
195 direction == PSB_2D_COPYORDER_BL2TR) {
196 src_y += size_y - 1;
197 dst_y += size_y - 1;
198 }
199
200 blit_cmd =
201 PSB_2D_BLIT_BH |
202 PSB_2D_ROT_NONE |
203 PSB_2D_DSTCK_DISABLE |
204 PSB_2D_SRCCK_DISABLE |
205 PSB_2D_USE_PAT | PSB_2D_ROP3_SRCCOPY | direction;
206
207 *buf++ = PSB_2D_FENCE_BH;
208 *buf++ =
209 PSB_2D_DST_SURF_BH | dst_format | (dst_stride <<
210 PSB_2D_DST_STRIDE_SHIFT);
211 *buf++ = dst_offset;
212 *buf++ =
213 PSB_2D_SRC_SURF_BH | src_format | (src_stride <<
214 PSB_2D_SRC_STRIDE_SHIFT);
215 *buf++ = src_offset;
216 *buf++ =
217 PSB_2D_SRC_OFF_BH | (src_x << PSB_2D_SRCOFF_XSTART_SHIFT) |
218 (src_y << PSB_2D_SRCOFF_YSTART_SHIFT);
219 *buf++ = blit_cmd;
220 *buf++ =
221 (dst_x << PSB_2D_DST_XSTART_SHIFT) | (dst_y <<
222 PSB_2D_DST_YSTART_SHIFT);
223 *buf++ =
224 (size_x << PSB_2D_DST_XSIZE_SHIFT) | (size_y <<
225 PSB_2D_DST_YSIZE_SHIFT);
226 *buf++ = PSB_2D_FLUSH_BH;
227
228 return psbfb_2d_submit(dev_priv, buffer, buf - buffer);
229}
230
231/**
232 * psbfb_copyarea_accel - copyarea acceleration for /dev/fb
233 * @info: our framebuffer
234 * @a: copyarea parameters from the framebuffer core
235 *
236 * Perform a 2D copy via the accelerator
237 */
238static void psbfb_copyarea_accel(struct fb_info *info,
239 const struct fb_copyarea *a)
240{
241 struct psb_fbdev *fbdev = info->par;
242 struct psb_framebuffer *psbfb = &fbdev->pfb;
243 struct drm_device *dev = psbfb->base.dev;
244 struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
245 struct drm_psb_private *dev_priv = dev->dev_private;
246 uint32_t offset;
247 uint32_t stride;
248 uint32_t src_format;
249 uint32_t dst_format;
250
251 if (!fb)
252 return;
253
254 offset = psbfb->gtt->offset;
255 stride = fb->pitch;
256
257 switch (fb->depth) {
258 case 8:
259 src_format = PSB_2D_SRC_332RGB;
260 dst_format = PSB_2D_DST_332RGB;
261 break;
262 case 15:
263 src_format = PSB_2D_SRC_555RGB;
264 dst_format = PSB_2D_DST_555RGB;
265 break;
266 case 16:
267 src_format = PSB_2D_SRC_565RGB;
268 dst_format = PSB_2D_DST_565RGB;
269 break;
270 case 24:
271 case 32:
272 /* this is wrong but since we don't do blending its okay */
273 src_format = PSB_2D_SRC_8888ARGB;
274 dst_format = PSB_2D_DST_8888ARGB;
275 break;
276 default:
277 /* software fallback */
278 cfb_copyarea(info, a);
279 return;
280 }
281
282 if (!gma_power_begin(dev, false)) {
283 cfb_copyarea(info, a);
284 return;
285 }
286 psb_accel_2d_copy(dev_priv,
287 offset, stride, src_format,
288 offset, stride, dst_format,
289 a->sx, a->sy, a->dx, a->dy, a->width, a->height);
290 gma_power_end(dev);
291}
292
293/**
294 * psbfb_copyarea - 2D copy interface
295 * @info: our framebuffer
296 * @region: region to copy
297 *
298 * Copy an area of the framebuffer console either by the accelerator
299 * or directly using the cfb helpers according to the request
300 */
301void psbfb_copyarea(struct fb_info *info,
302 const struct fb_copyarea *region)
303{
304 if (unlikely(info->state != FBINFO_STATE_RUNNING))
305 return;
306
307 /* Avoid the 8 pixel erratum */
308 if (region->width == 8 || region->height == 8 ||
309 (info->flags & FBINFO_HWACCEL_DISABLED))
310 return cfb_copyarea(info, region);
311
312 psbfb_copyarea_accel(info, region);
313}
314
315/**
316 * psbfb_sync - synchronize 2D
317 * @info: our framebuffer
318 *
319 * Wait for the 2D engine to quiesce so that we can do CPU
320 * access to the framebuffer again
321 */
322int psbfb_sync(struct fb_info *info)
323{
324 struct psb_fbdev *fbdev = info->par;
325 struct psb_framebuffer *psbfb = &fbdev->pfb;
326 struct drm_device *dev = psbfb->base.dev;
327 struct drm_psb_private *dev_priv = dev->dev_private;
328 unsigned long _end = jiffies + DRM_HZ;
329 int busy = 0;
330
331 mutex_lock(&dev_priv->mutex_2d);
332 /*
333 * First idle the 2D engine.
334 */
335
336 if ((PSB_RSGX32(PSB_CR_2D_SOCIF) == _PSB_C2_SOCIF_EMPTY) &&
337 ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) & _PSB_C2B_STATUS_BUSY) == 0))
338 goto out;
339
340 do {
341 busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
342 cpu_relax();
343 } while (busy && !time_after_eq(jiffies, _end));
344
345 if (busy)
346 busy = (PSB_RSGX32(PSB_CR_2D_SOCIF) != _PSB_C2_SOCIF_EMPTY);
347 if (busy)
348 goto out;
349
350 do {
351 busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
352 _PSB_C2B_STATUS_BUSY) != 0);
353 cpu_relax();
354 } while (busy && !time_after_eq(jiffies, _end));
355 if (busy)
356 busy = ((PSB_RSGX32(PSB_CR_2D_BLIT_STATUS) &
357 _PSB_C2B_STATUS_BUSY) != 0);
358
359out:
360 mutex_unlock(&dev_priv->mutex_2d);
361 return (busy) ? -EBUSY : 0;
362}
363
364int psb_accel_ioctl(struct drm_device *dev, void *data, struct drm_file *file)
365{
366 struct drm_psb_private *dev_priv = dev->dev_private;
367 struct drm_psb_2d_op *op = data;
368 u32 *op_ptr = &op->cmd[0];
369 int i;
370 struct drm_gem_object *obj;
371 struct gtt_range *gtt;
372 int err = -EINVAL;
373
374 if (!dev_priv->ops->accel_2d)
375 return -EOPNOTSUPP;
376 if (op->size > PSB_2D_OP_BUFLEN)
377 return -EINVAL;
378
379 /* The GEM object being used. We need to support separate src/dst/etc
380 in the end but for now keep them all the same */
381 obj = drm_gem_object_lookup(dev, file, op->src);
382 if (obj == NULL)
383 return -ENOENT;
384 gtt = container_of(obj, struct gtt_range, gem);
385
386 if (psb_gtt_pin(gtt) < 0)
387 goto bad_2;
388 for (i = 0; i < op->size; i++, op_ptr++) {
389 u32 r = *op_ptr & 0xF0000000;
390 /* Fill in the GTT offsets for the command buffer */
391 if (r == PSB_2D_SRC_SURF_BH ||
392 r == PSB_2D_DST_SURF_BH ||
393 r == PSB_2D_MASK_SURF_BH ||
394 r == PSB_2D_PAT_SURF_BH) {
395 i++;
396 op_ptr++;
397 if (i == op->size)
398 goto bad;
399 if (*op_ptr)
400 goto bad;
401 *op_ptr = gtt->offset;
402 continue;
403 }
404 }
405 psbfb_2d_submit(dev_priv, op->cmd, op->size);
406 err = 0;
407bad:
408 psb_gtt_unpin(gtt);
409bad_2:
410 drm_gem_object_unreference(obj);
411 return err;
412}
diff --git a/drivers/staging/gma500/backlight.c b/drivers/staging/gma500/backlight.c
new file mode 100644
index 00000000000..20793951fca
--- /dev/null
+++ b/drivers/staging/gma500/backlight.c
@@ -0,0 +1,49 @@
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
29int 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
39void 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
new file mode 100644
index 00000000000..87614e0d396
--- /dev/null
+++ b/drivers/staging/gma500/cdv_device.c
@@ -0,0 +1,351 @@
1/**************************************************************************
2 * Copyright (c) 2011, Intel Corporation.
3 * All Rights Reserved.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms and conditions of the GNU General Public License,
7 * version 2, as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
17 *
18 **************************************************************************/
19
20#include <linux/backlight.h>
21#include <drm/drmP.h>
22#include <drm/drm.h>
23#include "psb_drm.h"
24#include "psb_drv.h"
25#include "psb_reg.h"
26#include "psb_intel_reg.h"
27#include "intel_bios.h"
28#include "cdv_device.h"
29
30#define VGA_SR_INDEX 0x3c4
31#define VGA_SR_DATA 0x3c5
32
33/* FIXME: should check if we are the active VGA device ?? */
34static void cdv_disable_vga(struct drm_device *dev)
35{
36 u8 sr1;
37 u32 vga_reg;
38
39 vga_reg = VGACNTRL;
40
41 outb(1, VGA_SR_INDEX);
42 sr1 = inb(VGA_SR_DATA);
43 outb(sr1 | 1<<5, VGA_SR_DATA);
44 udelay(300);
45
46 REG_WRITE(vga_reg, VGA_DISP_DISABLE);
47 REG_READ(vga_reg);
48}
49
50static int cdv_output_init(struct drm_device *dev)
51{
52 struct drm_psb_private *dev_priv = dev->dev_private;
53 cdv_disable_vga(dev);
54
55 cdv_intel_crt_init(dev, &dev_priv->mode_dev);
56 cdv_intel_lvds_init(dev, &dev_priv->mode_dev);
57
58 /* These bits indicate HDMI not SDVO on CDV, but we don't yet support
59 the HDMI interface */
60 if (REG_READ(SDVOB) & SDVO_DETECTED)
61 cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOB);
62 if (REG_READ(SDVOC) & SDVO_DETECTED)
63 cdv_hdmi_init(dev, &dev_priv->mode_dev, SDVOC);
64 return 0;
65}
66
67#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
68
69/*
70 * Poulsbo Backlight Interfaces
71 */
72
73#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
74#define BLC_PWM_FREQ_CALC_CONSTANT 32
75#define MHz 1000000
76
77#define PSB_BLC_PWM_PRECISION_FACTOR 10
78#define PSB_BLC_MAX_PWM_REG_FREQ 0xFFFE
79#define PSB_BLC_MIN_PWM_REG_FREQ 0x2
80
81#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
82#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
83
84static int cdv_brightness;
85static struct backlight_device *cdv_backlight_device;
86
87static int cdv_get_brightness(struct backlight_device *bd)
88{
89 /* return locally cached var instead of HW read (due to DPST etc.) */
90 /* FIXME: ideally return actual value in case firmware fiddled with
91 it */
92 return cdv_brightness;
93}
94
95
96static int cdv_backlight_setup(struct drm_device *dev)
97{
98 struct drm_psb_private *dev_priv = dev->dev_private;
99 unsigned long core_clock;
100 /* u32 bl_max_freq; */
101 /* unsigned long value; */
102 u16 bl_max_freq;
103 uint32_t value;
104 uint32_t blc_pwm_precision_factor;
105
106 /* get bl_max_freq and pol from dev_priv*/
107 if (!dev_priv->lvds_bl) {
108 dev_err(dev->dev, "Has no valid LVDS backlight info\n");
109 return -ENOENT;
110 }
111 bl_max_freq = dev_priv->lvds_bl->freq;
112 blc_pwm_precision_factor = PSB_BLC_PWM_PRECISION_FACTOR;
113
114 core_clock = dev_priv->core_freq;
115
116 value = (core_clock * MHz) / BLC_PWM_FREQ_CALC_CONSTANT;
117 value *= blc_pwm_precision_factor;
118 value /= bl_max_freq;
119 value /= blc_pwm_precision_factor;
120
121 if (value > (unsigned long long)PSB_BLC_MAX_PWM_REG_FREQ ||
122 value < (unsigned long long)PSB_BLC_MIN_PWM_REG_FREQ)
123 return -ERANGE;
124 else {
125 /* FIXME */
126 }
127 return 0;
128}
129
130static int cdv_set_brightness(struct backlight_device *bd)
131{
132 int level = bd->props.brightness;
133
134 /* Percentage 1-100% being valid */
135 if (level < 1)
136 level = 1;
137
138 /*cdv_intel_lvds_set_brightness(dev, level); FIXME */
139 cdv_brightness = level;
140 return 0;
141}
142
143static const struct backlight_ops cdv_ops = {
144 .get_brightness = cdv_get_brightness,
145 .update_status = cdv_set_brightness,
146};
147
148static int cdv_backlight_init(struct drm_device *dev)
149{
150 struct drm_psb_private *dev_priv = dev->dev_private;
151 int ret;
152 struct backlight_properties props;
153
154 memset(&props, 0, sizeof(struct backlight_properties));
155 props.max_brightness = 100;
156 props.type = BACKLIGHT_PLATFORM;
157
158 cdv_backlight_device = backlight_device_register("psb-bl",
159 NULL, (void *)dev, &cdv_ops, &props);
160 if (IS_ERR(cdv_backlight_device))
161 return PTR_ERR(cdv_backlight_device);
162
163 ret = cdv_backlight_setup(dev);
164 if (ret < 0) {
165 backlight_device_unregister(cdv_backlight_device);
166 cdv_backlight_device = NULL;
167 return ret;
168 }
169 cdv_backlight_device->props.brightness = 100;
170 cdv_backlight_device->props.max_brightness = 100;
171 backlight_update_status(cdv_backlight_device);
172 dev_priv->backlight_device = cdv_backlight_device;
173 return 0;
174}
175
176#endif
177
178/*
179 * Provide the Cedarview specific chip logic and low level methods
180 * for power management
181 *
182 * FIXME: we need to implement the apm/ospm base management bits
183 * for this and the MID devices.
184 */
185
186static inline u32 CDV_MSG_READ32(uint port, uint offset)
187{
188 int mcr = (0x10<<24) | (port << 16) | (offset << 8);
189 uint32_t ret_val = 0;
190 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
191 pci_write_config_dword(pci_root, 0xD0, mcr);
192 pci_read_config_dword(pci_root, 0xD4, &ret_val);
193 pci_dev_put(pci_root);
194 return ret_val;
195}
196
197static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value)
198{
199 int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
200 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
201 pci_write_config_dword(pci_root, 0xD4, value);
202 pci_write_config_dword(pci_root, 0xD0, mcr);
203 pci_dev_put(pci_root);
204}
205
206#define PSB_APM_CMD 0x0
207#define PSB_APM_STS 0x04
208#define PSB_PM_SSC 0x20
209#define PSB_PM_SSS 0x30
210#define PSB_PWRGT_GFX_MASK 0x3
211#define CDV_PWRGT_DISPLAY_CNTR 0x000fc00c
212#define CDV_PWRGT_DISPLAY_STS 0x000fc00c
213
214static void cdv_init_pm(struct drm_device *dev)
215{
216 struct drm_psb_private *dev_priv = dev->dev_private;
217 u32 pwr_cnt;
218 int i;
219
220 dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
221 PSB_APMBA) & 0xFFFF;
222 dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
223 PSB_OSPMBA) & 0xFFFF;
224
225 /* Force power on for now */
226 pwr_cnt = inl(dev_priv->apm_base + PSB_APM_CMD);
227 pwr_cnt &= ~PSB_PWRGT_GFX_MASK;
228
229 outl(pwr_cnt, dev_priv->apm_base + PSB_APM_CMD);
230 for (i = 0; i < 5; i++) {
231 u32 pwr_sts = inl(dev_priv->apm_base + PSB_APM_STS);
232 if ((pwr_sts & PSB_PWRGT_GFX_MASK) == 0)
233 break;
234 udelay(10);
235 }
236 pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
237 pwr_cnt &= ~CDV_PWRGT_DISPLAY_CNTR;
238 outl(pwr_cnt, dev_priv->ospm_base + PSB_PM_SSC);
239 for (i = 0; i < 5; i++) {
240 u32 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
241 if ((pwr_sts & CDV_PWRGT_DISPLAY_STS) == 0)
242 break;
243 udelay(10);
244 }
245}
246
247/**
248 * cdv_save_display_registers - save registers lost on suspend
249 * @dev: our DRM device
250 *
251 * Save the state we need in order to be able to restore the interface
252 * upon resume from suspend
253 *
254 * FIXME: review
255 */
256static int cdv_save_display_registers(struct drm_device *dev)
257{
258 return 0;
259}
260
261/**
262 * cdv_restore_display_registers - restore lost register state
263 * @dev: our DRM device
264 *
265 * Restore register state that was lost during suspend and resume.
266 *
267 * FIXME: review
268 */
269static int cdv_restore_display_registers(struct drm_device *dev)
270{
271 return 0;
272}
273
274static int cdv_power_down(struct drm_device *dev)
275{
276 return 0;
277}
278
279static int cdv_power_up(struct drm_device *dev)
280{
281 return 0;
282}
283
284/* FIXME ? - shared with Poulsbo */
285static void cdv_get_core_freq(struct drm_device *dev)
286{
287 uint32_t clock;
288 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
289 struct drm_psb_private *dev_priv = dev->dev_private;
290
291 pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
292 pci_read_config_dword(pci_root, 0xD4, &clock);
293 pci_dev_put(pci_root);
294
295 switch (clock & 0x07) {
296 case 0:
297 dev_priv->core_freq = 100;
298 break;
299 case 1:
300 dev_priv->core_freq = 133;
301 break;
302 case 2:
303 dev_priv->core_freq = 150;
304 break;
305 case 3:
306 dev_priv->core_freq = 178;
307 break;
308 case 4:
309 dev_priv->core_freq = 200;
310 break;
311 case 5:
312 case 6:
313 case 7:
314 dev_priv->core_freq = 266;
315 default:
316 dev_priv->core_freq = 0;
317 }
318}
319
320static int cdv_chip_setup(struct drm_device *dev)
321{
322 cdv_get_core_freq(dev);
323 gma_intel_opregion_init(dev);
324 psb_intel_init_bios(dev);
325 return 0;
326}
327
328/* CDV is much like Poulsbo but has MID like SGX offsets and PM */
329
330const struct psb_ops cdv_chip_ops = {
331 .name = "Cedartrail",
332 .accel_2d = 0,
333 .pipes = 2,
334 .sgx_offset = MRST_SGX_OFFSET,
335 .chip_setup = cdv_chip_setup,
336
337 .crtc_helper = &cdv_intel_helper_funcs,
338 .crtc_funcs = &cdv_intel_crtc_funcs,
339
340 .output_init = cdv_output_init,
341
342#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
343 .backlight_init = cdv_backlight_init,
344#endif
345
346 .init_pm = cdv_init_pm,
347 .save_regs = cdv_save_display_registers,
348 .restore_regs = cdv_restore_display_registers,
349 .power_down = cdv_power_down,
350 .power_up = cdv_power_up,
351};
diff --git a/drivers/staging/gma500/cdv_device.h b/drivers/staging/gma500/cdv_device.h
new file mode 100644
index 00000000000..2a88b7beb55
--- /dev/null
+++ b/drivers/staging/gma500/cdv_device.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright © 2011 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 */
17
18extern const struct drm_crtc_helper_funcs cdv_intel_helper_funcs;
19extern const struct drm_crtc_funcs cdv_intel_crtc_funcs;
20extern void cdv_intel_crt_init(struct drm_device *dev,
21 struct psb_intel_mode_device *mode_dev);
22extern void cdv_intel_lvds_init(struct drm_device *dev,
23 struct psb_intel_mode_device *mode_dev);
24extern void cdv_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev,
25 int reg);
26extern struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
27 struct drm_crtc *crtc);
28
29extern inline void cdv_intel_wait_for_vblank(struct drm_device *dev)
30{
31 /* Wait for 20ms, i.e. one cycle at 50hz. */
32 /* FIXME: msleep ?? */
33 mdelay(20);
34}
35
36
diff --git a/drivers/staging/gma500/cdv_intel_crt.c b/drivers/staging/gma500/cdv_intel_crt.c
new file mode 100644
index 00000000000..efda63b97b4
--- /dev/null
+++ b/drivers/staging/gma500/cdv_intel_crt.c
@@ -0,0 +1,326 @@
1/*
2 * Copyright © 2006-2007 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Eric Anholt <eric@anholt.net>
25 */
26
27#include <linux/i2c.h>
28#include <drm/drmP.h>
29
30#include "intel_bios.h"
31#include "psb_drv.h"
32#include "psb_intel_drv.h"
33#include "psb_intel_reg.h"
34#include "power.h"
35#include <linux/pm_runtime.h>
36
37
38static void cdv_intel_crt_dpms(struct drm_encoder *encoder, int mode)
39{
40 struct drm_device *dev = encoder->dev;
41 u32 temp, reg;
42 reg = ADPA;
43
44 temp = REG_READ(reg);
45 temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
46 temp &= ~ADPA_DAC_ENABLE;
47
48 switch (mode) {
49 case DRM_MODE_DPMS_ON:
50 temp |= ADPA_DAC_ENABLE;
51 break;
52 case DRM_MODE_DPMS_STANDBY:
53 temp |= ADPA_DAC_ENABLE | ADPA_HSYNC_CNTL_DISABLE;
54 break;
55 case DRM_MODE_DPMS_SUSPEND:
56 temp |= ADPA_DAC_ENABLE | ADPA_VSYNC_CNTL_DISABLE;
57 break;
58 case DRM_MODE_DPMS_OFF:
59 temp |= ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE;
60 break;
61 }
62
63 REG_WRITE(reg, temp);
64}
65
66static int cdv_intel_crt_mode_valid(struct drm_connector *connector,
67 struct drm_display_mode *mode)
68{
69 int max_clock = 0;
70 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
71 return MODE_NO_DBLESCAN;
72
73 /* The lowest clock for CDV is 20000KHz */
74 if (mode->clock < 20000)
75 return MODE_CLOCK_LOW;
76
77 /* The max clock for CDV is 355 instead of 400 */
78 max_clock = 355000;
79 if (mode->clock > max_clock)
80 return MODE_CLOCK_HIGH;
81
82 if (mode->hdisplay > 1680 || mode->vdisplay > 1050)
83 return MODE_PANEL;
84
85 return MODE_OK;
86}
87
88static bool cdv_intel_crt_mode_fixup(struct drm_encoder *encoder,
89 struct drm_display_mode *mode,
90 struct drm_display_mode *adjusted_mode)
91{
92 return true;
93}
94
95static void cdv_intel_crt_mode_set(struct drm_encoder *encoder,
96 struct drm_display_mode *mode,
97 struct drm_display_mode *adjusted_mode)
98{
99
100 struct drm_device *dev = encoder->dev;
101 struct drm_crtc *crtc = encoder->crtc;
102 struct psb_intel_crtc *psb_intel_crtc =
103 to_psb_intel_crtc(crtc);
104 int dpll_md_reg;
105 u32 adpa, dpll_md;
106 u32 adpa_reg;
107
108 if (psb_intel_crtc->pipe == 0)
109 dpll_md_reg = DPLL_A_MD;
110 else
111 dpll_md_reg = DPLL_B_MD;
112
113 adpa_reg = ADPA;
114
115 /*
116 * Disable separate mode multiplier used when cloning SDVO to CRT
117 * XXX this needs to be adjusted when we really are cloning
118 */
119 {
120 dpll_md = REG_READ(dpll_md_reg);
121 REG_WRITE(dpll_md_reg,
122 dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK);
123 }
124
125 adpa = 0;
126 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
127 adpa |= ADPA_HSYNC_ACTIVE_HIGH;
128 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
129 adpa |= ADPA_VSYNC_ACTIVE_HIGH;
130
131 if (psb_intel_crtc->pipe == 0)
132 adpa |= ADPA_PIPE_A_SELECT;
133 else
134 adpa |= ADPA_PIPE_B_SELECT;
135
136 REG_WRITE(adpa_reg, adpa);
137}
138
139
140/**
141 * Uses CRT_HOTPLUG_EN and CRT_HOTPLUG_STAT to detect CRT presence.
142 *
143 * \return true if CRT is connected.
144 * \return false if CRT is disconnected.
145 */
146static bool cdv_intel_crt_detect_hotplug(struct drm_connector *connector,
147 bool force)
148{
149 struct drm_device *dev = connector->dev;
150 u32 hotplug_en;
151 int i, tries = 0, ret = false;
152 u32 adpa_orig;
153
154 /* disable the DAC when doing the hotplug detection */
155
156 adpa_orig = REG_READ(ADPA);
157
158 REG_WRITE(ADPA, adpa_orig & ~(ADPA_DAC_ENABLE));
159
160 /*
161 * On a CDV thep, CRT detect sequence need to be done twice
162 * to get a reliable result.
163 */
164 tries = 2;
165
166 hotplug_en = REG_READ(PORT_HOTPLUG_EN);
167 hotplug_en &= ~(CRT_HOTPLUG_DETECT_MASK);
168 hotplug_en |= CRT_HOTPLUG_FORCE_DETECT;
169
170 hotplug_en |= CRT_HOTPLUG_ACTIVATION_PERIOD_64;
171 hotplug_en |= CRT_HOTPLUG_VOLTAGE_COMPARE_50;
172
173 for (i = 0; i < tries ; i++) {
174 unsigned long timeout;
175 /* turn on the FORCE_DETECT */
176 REG_WRITE(PORT_HOTPLUG_EN, hotplug_en);
177 timeout = jiffies + msecs_to_jiffies(1000);
178 /* wait for FORCE_DETECT to go off */
179 do {
180 if (!(REG_READ(PORT_HOTPLUG_EN) &
181 CRT_HOTPLUG_FORCE_DETECT))
182 break;
183 msleep(1);
184 } while (time_after(timeout, jiffies));
185 }
186
187 if ((REG_READ(PORT_HOTPLUG_STAT) & CRT_HOTPLUG_MONITOR_MASK) !=
188 CRT_HOTPLUG_MONITOR_NONE)
189 ret = true;
190
191 /* Restore the saved ADPA */
192 REG_WRITE(ADPA, adpa_orig);
193 return ret;
194}
195
196static enum drm_connector_status cdv_intel_crt_detect(
197 struct drm_connector *connector, bool force)
198{
199 if (cdv_intel_crt_detect_hotplug(connector, force))
200 return connector_status_connected;
201 else
202 return connector_status_disconnected;
203}
204
205static void cdv_intel_crt_destroy(struct drm_connector *connector)
206{
207 struct psb_intel_output *intel_output = to_psb_intel_output(connector);
208
209 psb_intel_i2c_destroy(intel_output->ddc_bus);
210 drm_sysfs_connector_remove(connector);
211 drm_connector_cleanup(connector);
212 kfree(connector);
213}
214
215static int cdv_intel_crt_get_modes(struct drm_connector *connector)
216{
217 struct psb_intel_output *intel_output =
218 to_psb_intel_output(connector);
219 return psb_intel_ddc_get_modes(intel_output);
220}
221
222static int cdv_intel_crt_set_property(struct drm_connector *connector,
223 struct drm_property *property,
224 uint64_t value)
225{
226 return 0;
227}
228
229/*
230 * Routines for controlling stuff on the analog port
231 */
232
233static const struct drm_encoder_helper_funcs cdv_intel_crt_helper_funcs = {
234 .dpms = cdv_intel_crt_dpms,
235 .mode_fixup = cdv_intel_crt_mode_fixup,
236 .prepare = psb_intel_encoder_prepare,
237 .commit = psb_intel_encoder_commit,
238 .mode_set = cdv_intel_crt_mode_set,
239};
240
241static const struct drm_connector_funcs cdv_intel_crt_connector_funcs = {
242 .dpms = drm_helper_connector_dpms,
243 .detect = cdv_intel_crt_detect,
244 .fill_modes = drm_helper_probe_single_connector_modes,
245 .destroy = cdv_intel_crt_destroy,
246 .set_property = cdv_intel_crt_set_property,
247};
248
249static const struct drm_connector_helper_funcs
250 cdv_intel_crt_connector_helper_funcs = {
251 .mode_valid = cdv_intel_crt_mode_valid,
252 .get_modes = cdv_intel_crt_get_modes,
253 .best_encoder = psb_intel_best_encoder,
254};
255
256static void cdv_intel_crt_enc_destroy(struct drm_encoder *encoder)
257{
258 drm_encoder_cleanup(encoder);
259}
260
261static const struct drm_encoder_funcs cdv_intel_crt_enc_funcs = {
262 .destroy = cdv_intel_crt_enc_destroy,
263};
264
265void cdv_intel_crt_init(struct drm_device *dev,
266 struct psb_intel_mode_device *mode_dev)
267{
268
269 struct psb_intel_output *psb_intel_output;
270 struct drm_connector *connector;
271 struct drm_encoder *encoder;
272
273 u32 i2c_reg;
274
275 psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
276 if (!psb_intel_output)
277 return;
278
279 psb_intel_output->mode_dev = mode_dev;
280 connector = &psb_intel_output->base;
281 drm_connector_init(dev, connector,
282 &cdv_intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA);
283
284 encoder = &psb_intel_output->enc;
285 drm_encoder_init(dev, encoder,
286 &cdv_intel_crt_enc_funcs, DRM_MODE_ENCODER_DAC);
287
288 drm_mode_connector_attach_encoder(&psb_intel_output->base,
289 &psb_intel_output->enc);
290
291 /* Set up the DDC bus. */
292 i2c_reg = GPIOA;
293 /* Remove the following code for CDV */
294 /*
295 if (dev_priv->crt_ddc_bus != 0)
296 i2c_reg = dev_priv->crt_ddc_bus;
297 }*/
298 psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
299 i2c_reg, "CRTDDC_A");
300 if (!psb_intel_output->ddc_bus) {
301 dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration "
302 "failed.\n");
303 goto failed_ddc;
304 }
305
306 psb_intel_output->type = INTEL_OUTPUT_ANALOG;
307 /*
308 psb_intel_output->clone_mask = (1 << INTEL_ANALOG_CLONE_BIT);
309 psb_intel_output->crtc_mask = (1 << 0) | (1 << 1);
310 */
311 connector->interlace_allowed = 0;
312 connector->doublescan_allowed = 0;
313
314 drm_encoder_helper_add(encoder, &cdv_intel_crt_helper_funcs);
315 drm_connector_helper_add(connector,
316 &cdv_intel_crt_connector_helper_funcs);
317
318 drm_sysfs_connector_add(connector);
319
320 return;
321failed_ddc:
322 drm_encoder_cleanup(&psb_intel_output->enc);
323 drm_connector_cleanup(&psb_intel_output->base);
324 kfree(psb_intel_output);
325 return;
326}
diff --git a/drivers/staging/gma500/cdv_intel_display.c b/drivers/staging/gma500/cdv_intel_display.c
new file mode 100644
index 00000000000..7b97c600eff
--- /dev/null
+++ b/drivers/staging/gma500/cdv_intel_display.c
@@ -0,0 +1,1508 @@
1/*
2 * Copyright © 2006-2011 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 * Authors:
18 * Eric Anholt <eric@anholt.net>
19 */
20
21#include <linux/i2c.h>
22#include <linux/pm_runtime.h>
23
24#include <drm/drmP.h>
25#include "framebuffer.h"
26#include "psb_drv.h"
27#include "psb_intel_drv.h"
28#include "psb_intel_reg.h"
29#include "psb_intel_display.h"
30#include "power.h"
31#include "cdv_device.h"
32
33
34struct cdv_intel_range_t {
35 int min, max;
36};
37
38struct cdv_intel_p2_t {
39 int dot_limit;
40 int p2_slow, p2_fast;
41};
42
43struct cdv_intel_clock_t {
44 /* given values */
45 int n;
46 int m1, m2;
47 int p1, p2;
48 /* derived values */
49 int dot;
50 int vco;
51 int m;
52 int p;
53};
54
55#define INTEL_P2_NUM 2
56
57struct cdv_intel_limit_t {
58 struct cdv_intel_range_t dot, vco, n, m, m1, m2, p, p1;
59 struct cdv_intel_p2_t p2;
60};
61
62#define CDV_LIMIT_SINGLE_LVDS_96 0
63#define CDV_LIMIT_SINGLE_LVDS_100 1
64#define CDV_LIMIT_DAC_HDMI_27 2
65#define CDV_LIMIT_DAC_HDMI_96 3
66
67static const struct cdv_intel_limit_t cdv_intel_limits[] = {
68 { /* CDV_SIGNLE_LVDS_96MHz */
69 .dot = {.min = 20000, .max = 115500},
70 .vco = {.min = 1800000, .max = 3600000},
71 .n = {.min = 2, .max = 6},
72 .m = {.min = 60, .max = 160},
73 .m1 = {.min = 0, .max = 0},
74 .m2 = {.min = 58, .max = 158},
75 .p = {.min = 28, .max = 140},
76 .p1 = {.min = 2, .max = 10},
77 .p2 = {.dot_limit = 200000,
78 .p2_slow = 14, .p2_fast = 14},
79 },
80 { /* CDV_SINGLE_LVDS_100MHz */
81 .dot = {.min = 20000, .max = 115500},
82 .vco = {.min = 1800000, .max = 3600000},
83 .n = {.min = 2, .max = 6},
84 .m = {.min = 60, .max = 160},
85 .m1 = {.min = 0, .max = 0},
86 .m2 = {.min = 58, .max = 158},
87 .p = {.min = 28, .max = 140},
88 .p1 = {.min = 2, .max = 10},
89 /* The single-channel range is 25-112Mhz, and dual-channel
90 * is 80-224Mhz. Prefer single channel as much as possible.
91 */
92 .p2 = {.dot_limit = 200000, .p2_slow = 14, .p2_fast = 14},
93 },
94 { /* CDV_DAC_HDMI_27MHz */
95 .dot = {.min = 20000, .max = 400000},
96 .vco = {.min = 1809000, .max = 3564000},
97 .n = {.min = 1, .max = 1},
98 .m = {.min = 67, .max = 132},
99 .m1 = {.min = 0, .max = 0},
100 .m2 = {.min = 65, .max = 130},
101 .p = {.min = 5, .max = 90},
102 .p1 = {.min = 1, .max = 9},
103 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
104 },
105 { /* CDV_DAC_HDMI_96MHz */
106 .dot = {.min = 20000, .max = 400000},
107 .vco = {.min = 1800000, .max = 3600000},
108 .n = {.min = 2, .max = 6},
109 .m = {.min = 60, .max = 160},
110 .m1 = {.min = 0, .max = 0},
111 .m2 = {.min = 58, .max = 158},
112 .p = {.min = 5, .max = 100},
113 .p1 = {.min = 1, .max = 10},
114 .p2 = {.dot_limit = 225000, .p2_slow = 10, .p2_fast = 5},
115 },
116};
117
118#define _wait_for(COND, MS, W) ({ \
119 unsigned long timeout__ = jiffies + msecs_to_jiffies(MS); \
120 int ret__ = 0; \
121 while (!(COND)) { \
122 if (time_after(jiffies, timeout__)) { \
123 ret__ = -ETIMEDOUT; \
124 break; \
125 } \
126 if (W && !in_dbg_master()) \
127 msleep(W); \
128 } \
129 ret__; \
130})
131
132#define wait_for(COND, MS) _wait_for(COND, MS, 1)
133
134
135static int cdv_sb_read(struct drm_device *dev, u32 reg, u32 *val)
136{
137 int ret;
138
139 ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
140 if (ret) {
141 DRM_ERROR("timeout waiting for SB to idle before read\n");
142 return ret;
143 }
144
145 REG_WRITE(SB_ADDR, reg);
146 REG_WRITE(SB_PCKT,
147 SET_FIELD(SB_OPCODE_READ, SB_OPCODE) |
148 SET_FIELD(SB_DEST_DPLL, SB_DEST) |
149 SET_FIELD(0xf, SB_BYTE_ENABLE));
150
151 ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
152 if (ret) {
153 DRM_ERROR("timeout waiting for SB to idle after read\n");
154 return ret;
155 }
156
157 *val = REG_READ(SB_DATA);
158
159 return 0;
160}
161
162static int cdv_sb_write(struct drm_device *dev, u32 reg, u32 val)
163{
164 int ret;
165 static bool dpio_debug = true;
166 u32 temp;
167
168 if (dpio_debug) {
169 if (cdv_sb_read(dev, reg, &temp) == 0)
170 DRM_DEBUG_KMS("0x%08x: 0x%08x (before)\n", reg, temp);
171 DRM_DEBUG_KMS("0x%08x: 0x%08x\n", reg, val);
172 }
173
174 ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
175 if (ret) {
176 DRM_ERROR("timeout waiting for SB to idle before write\n");
177 return ret;
178 }
179
180 REG_WRITE(SB_ADDR, reg);
181 REG_WRITE(SB_DATA, val);
182 REG_WRITE(SB_PCKT,
183 SET_FIELD(SB_OPCODE_WRITE, SB_OPCODE) |
184 SET_FIELD(SB_DEST_DPLL, SB_DEST) |
185 SET_FIELD(0xf, SB_BYTE_ENABLE));
186
187 ret = wait_for((REG_READ(SB_PCKT) & SB_BUSY) == 0, 1000);
188 if (ret) {
189 DRM_ERROR("timeout waiting for SB to idle after write\n");
190 return ret;
191 }
192
193 if (dpio_debug) {
194 if (cdv_sb_read(dev, reg, &temp) == 0)
195 DRM_DEBUG_KMS("0x%08x: 0x%08x (after)\n", reg, temp);
196 }
197
198 return 0;
199}
200
201/* Reset the DPIO configuration register. The BIOS does this at every
202 * mode set.
203 */
204static void cdv_sb_reset(struct drm_device *dev)
205{
206
207 REG_WRITE(DPIO_CFG, 0);
208 REG_READ(DPIO_CFG);
209 REG_WRITE(DPIO_CFG, DPIO_MODE_SELECT_0 | DPIO_CMN_RESET_N);
210}
211
212/* Unlike most Intel display engines, on Cedarview the DPLL registers
213 * are behind this sideband bus. They must be programmed while the
214 * DPLL reference clock is on in the DPLL control register, but before
215 * the DPLL is enabled in the DPLL control register.
216 */
217static int
218cdv_dpll_set_clock_cdv(struct drm_device *dev, struct drm_crtc *crtc,
219 struct cdv_intel_clock_t *clock)
220{
221 struct psb_intel_crtc *psb_crtc =
222 to_psb_intel_crtc(crtc);
223 int pipe = psb_crtc->pipe;
224 u32 m, n_vco, p;
225 int ret = 0;
226 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
227 u32 ref_value;
228
229 cdv_sb_reset(dev);
230
231 if ((REG_READ(dpll_reg) & DPLL_SYNCLOCK_ENABLE) == 0) {
232 DRM_ERROR("Attempting to set DPLL with refclk disabled\n");
233 return -EBUSY;
234 }
235
236 /* Follow the BIOS and write the REF/SFR Register. Hardcoded value */
237 ref_value = 0x68A701;
238
239 cdv_sb_write(dev, SB_REF_SFR(pipe), ref_value);
240
241 /* We don't know what the other fields of these regs are, so
242 * leave them in place.
243 */
244 ret = cdv_sb_read(dev, SB_M(pipe), &m);
245 if (ret)
246 return ret;
247 m &= ~SB_M_DIVIDER_MASK;
248 m |= ((clock->m2) << SB_M_DIVIDER_SHIFT);
249 ret = cdv_sb_write(dev, SB_M(pipe), m);
250 if (ret)
251 return ret;
252
253 ret = cdv_sb_read(dev, SB_N_VCO(pipe), &n_vco);
254 if (ret)
255 return ret;
256
257 /* Follow the BIOS to program the N_DIVIDER REG */
258 n_vco &= 0xFFFF;
259 n_vco |= 0x107;
260 n_vco &= ~(SB_N_VCO_SEL_MASK |
261 SB_N_DIVIDER_MASK |
262 SB_N_CB_TUNE_MASK);
263
264 n_vco |= ((clock->n) << SB_N_DIVIDER_SHIFT);
265
266 if (clock->vco < 2250000) {
267 n_vco |= (2 << SB_N_CB_TUNE_SHIFT);
268 n_vco |= (0 << SB_N_VCO_SEL_SHIFT);
269 } else if (clock->vco < 2750000) {
270 n_vco |= (1 << SB_N_CB_TUNE_SHIFT);
271 n_vco |= (1 << SB_N_VCO_SEL_SHIFT);
272 } else if (clock->vco < 3300000) {
273 n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
274 n_vco |= (2 << SB_N_VCO_SEL_SHIFT);
275 } else {
276 n_vco |= (0 << SB_N_CB_TUNE_SHIFT);
277 n_vco |= (3 << SB_N_VCO_SEL_SHIFT);
278 }
279
280 ret = cdv_sb_write(dev, SB_N_VCO(pipe), n_vco);
281 if (ret)
282 return ret;
283
284 ret = cdv_sb_read(dev, SB_P(pipe), &p);
285 if (ret)
286 return ret;
287 p &= ~(SB_P2_DIVIDER_MASK | SB_P1_DIVIDER_MASK);
288 p |= SET_FIELD(clock->p1, SB_P1_DIVIDER);
289 switch (clock->p2) {
290 case 5:
291 p |= SET_FIELD(SB_P2_5, SB_P2_DIVIDER);
292 break;
293 case 10:
294 p |= SET_FIELD(SB_P2_10, SB_P2_DIVIDER);
295 break;
296 case 14:
297 p |= SET_FIELD(SB_P2_14, SB_P2_DIVIDER);
298 break;
299 case 7:
300 p |= SET_FIELD(SB_P2_7, SB_P2_DIVIDER);
301 break;
302 default:
303 DRM_ERROR("Bad P2 clock: %d\n", clock->p2);
304 return -EINVAL;
305 }
306 ret = cdv_sb_write(dev, SB_P(pipe), p);
307 if (ret)
308 return ret;
309
310 /* always Program the Lane Register for the Pipe A*/
311 if (pipe == 0) {
312 /* Program the Lane0/1 for HDMI B */
313 u32 lane_reg, lane_value;
314
315 lane_reg = PSB_LANE0;
316 cdv_sb_read(dev, lane_reg, &lane_value);
317 lane_value &= ~(LANE_PLL_MASK);
318 lane_value |= LANE_PLL_ENABLE;
319 cdv_sb_write(dev, lane_reg, lane_value);
320
321 lane_reg = PSB_LANE1;
322 cdv_sb_read(dev, lane_reg, &lane_value);
323 lane_value &= ~(LANE_PLL_MASK);
324 lane_value |= LANE_PLL_ENABLE;
325 cdv_sb_write(dev, lane_reg, lane_value);
326
327 /* Program the Lane2/3 for HDMI C */
328 lane_reg = PSB_LANE2;
329 cdv_sb_read(dev, lane_reg, &lane_value);
330 lane_value &= ~(LANE_PLL_MASK);
331 lane_value |= LANE_PLL_ENABLE;
332 cdv_sb_write(dev, lane_reg, lane_value);
333
334 lane_reg = PSB_LANE3;
335 cdv_sb_read(dev, lane_reg, &lane_value);
336 lane_value &= ~(LANE_PLL_MASK);
337 lane_value |= LANE_PLL_ENABLE;
338 cdv_sb_write(dev, lane_reg, lane_value);
339 }
340
341 return 0;
342}
343
344/*
345 * Returns whether any output on the specified pipe is of the specified type
346 */
347bool cdv_intel_pipe_has_type(struct drm_crtc *crtc, int type)
348{
349 struct drm_device *dev = crtc->dev;
350 struct drm_mode_config *mode_config = &dev->mode_config;
351 struct drm_connector *l_entry;
352
353 list_for_each_entry(l_entry, &mode_config->connector_list, head) {
354 if (l_entry->encoder && l_entry->encoder->crtc == crtc) {
355 struct psb_intel_output *psb_intel_output =
356 to_psb_intel_output(l_entry);
357 if (psb_intel_output->type == type)
358 return true;
359 }
360 }
361 return false;
362}
363
364static const struct cdv_intel_limit_t *cdv_intel_limit(struct drm_crtc *crtc,
365 int refclk)
366{
367 const struct cdv_intel_limit_t *limit;
368 if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
369 /*
370 * Now only single-channel LVDS is supported on CDV. If it is
371 * incorrect, please add the dual-channel LVDS.
372 */
373 if (refclk == 96000)
374 limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_96];
375 else
376 limit = &cdv_intel_limits[CDV_LIMIT_SINGLE_LVDS_100];
377 } else {
378 if (refclk == 27000)
379 limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_27];
380 else
381 limit = &cdv_intel_limits[CDV_LIMIT_DAC_HDMI_96];
382 }
383 return limit;
384}
385
386/* m1 is reserved as 0 in CDV, n is a ring counter */
387static void cdv_intel_clock(struct drm_device *dev,
388 int refclk, struct cdv_intel_clock_t *clock)
389{
390 clock->m = clock->m2 + 2;
391 clock->p = clock->p1 * clock->p2;
392 clock->vco = (refclk * clock->m) / clock->n;
393 clock->dot = clock->vco / clock->p;
394}
395
396
397#define INTELPllInvalid(s) { /* ErrorF (s) */; return false; }
398static bool cdv_intel_PLL_is_valid(struct drm_crtc *crtc,
399 const struct cdv_intel_limit_t *limit,
400 struct cdv_intel_clock_t *clock)
401{
402 if (clock->p1 < limit->p1.min || limit->p1.max < clock->p1)
403 INTELPllInvalid("p1 out of range\n");
404 if (clock->p < limit->p.min || limit->p.max < clock->p)
405 INTELPllInvalid("p out of range\n");
406 /* unnecessary to check the range of m(m1/M2)/n again */
407 if (clock->vco < limit->vco.min || limit->vco.max < clock->vco)
408 INTELPllInvalid("vco out of range\n");
409 /* XXX: We may need to be checking "Dot clock"
410 * depending on the multiplier, connector, etc.,
411 * rather than just a single range.
412 */
413 if (clock->dot < limit->dot.min || limit->dot.max < clock->dot)
414 INTELPllInvalid("dot out of range\n");
415
416 return true;
417}
418
419static bool cdv_intel_find_best_PLL(struct drm_crtc *crtc, int target,
420 int refclk,
421 struct cdv_intel_clock_t *best_clock)
422{
423 struct drm_device *dev = crtc->dev;
424 struct cdv_intel_clock_t clock;
425 const struct cdv_intel_limit_t *limit = cdv_intel_limit(crtc, refclk);
426 int err = target;
427
428
429 if (cdv_intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) &&
430 (REG_READ(LVDS) & LVDS_PORT_EN) != 0) {
431 /*
432 * For LVDS, if the panel is on, just rely on its current
433 * settings for dual-channel. We haven't figured out how to
434 * reliably set up different single/dual channel state, if we
435 * even can.
436 */
437 if ((REG_READ(LVDS) & LVDS_CLKB_POWER_MASK) ==
438 LVDS_CLKB_POWER_UP)
439 clock.p2 = limit->p2.p2_fast;
440 else
441 clock.p2 = limit->p2.p2_slow;
442 } else {
443 if (target < limit->p2.dot_limit)
444 clock.p2 = limit->p2.p2_slow;
445 else
446 clock.p2 = limit->p2.p2_fast;
447 }
448
449 memset(best_clock, 0, sizeof(*best_clock));
450 clock.m1 = 0;
451 /* m1 is reserved as 0 in CDV, n is a ring counter.
452 So skip the m1 loop */
453 for (clock.n = limit->n.min; clock.n <= limit->n.max; clock.n++) {
454 for (clock.m2 = limit->m2.min; clock.m2 <= limit->m2.max;
455 clock.m2++) {
456 for (clock.p1 = limit->p1.min;
457 clock.p1 <= limit->p1.max;
458 clock.p1++) {
459 int this_err;
460
461 cdv_intel_clock(dev, refclk, &clock);
462
463 if (!cdv_intel_PLL_is_valid(crtc,
464 limit, &clock))
465 continue;
466
467 this_err = abs(clock.dot - target);
468 if (this_err < err) {
469 *best_clock = clock;
470 err = this_err;
471 }
472 }
473 }
474 }
475
476 return err != target;
477}
478
479int cdv_intel_pipe_set_base(struct drm_crtc *crtc,
480 int x, int y, struct drm_framebuffer *old_fb)
481{
482 struct drm_device *dev = crtc->dev;
483 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
484 struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
485 int pipe = psb_intel_crtc->pipe;
486 unsigned long start, offset;
487 int dspbase = (pipe == 0 ? DSPABASE : DSPBBASE);
488 int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
489 int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
490 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
491 u32 dspcntr;
492 int ret = 0;
493
494 if (!gma_power_begin(dev, true))
495 return 0;
496
497 /* no fb bound */
498 if (!crtc->fb) {
499 dev_err(dev->dev, "No FB bound\n");
500 goto psb_intel_pipe_cleaner;
501 }
502
503
504 /* We are displaying this buffer, make sure it is actually loaded
505 into the GTT */
506 ret = psb_gtt_pin(psbfb->gtt);
507 if (ret < 0)
508 goto psb_intel_pipe_set_base_exit;
509 start = psbfb->gtt->offset;
510 offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
511
512 REG_WRITE(dspstride, crtc->fb->pitch);
513
514 dspcntr = REG_READ(dspcntr_reg);
515 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
516
517 switch (crtc->fb->bits_per_pixel) {
518 case 8:
519 dspcntr |= DISPPLANE_8BPP;
520 break;
521 case 16:
522 if (crtc->fb->depth == 15)
523 dspcntr |= DISPPLANE_15_16BPP;
524 else
525 dspcntr |= DISPPLANE_16BPP;
526 break;
527 case 24:
528 case 32:
529 dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
530 break;
531 default:
532 dev_err(dev->dev, "Unknown color depth\n");
533 ret = -EINVAL;
534 goto psb_intel_pipe_set_base_exit;
535 }
536 REG_WRITE(dspcntr_reg, dspcntr);
537
538 dev_dbg(dev->dev,
539 "Writing base %08lX %08lX %d %d\n", start, offset, x, y);
540
541 REG_WRITE(dspbase, offset);
542 REG_READ(dspbase);
543 REG_WRITE(dspsurf, start);
544 REG_READ(dspsurf);
545
546psb_intel_pipe_cleaner:
547 /* If there was a previous display we can now unpin it */
548 if (old_fb)
549 psb_gtt_unpin(to_psb_fb(old_fb)->gtt);
550
551psb_intel_pipe_set_base_exit:
552 gma_power_end(dev);
553 return ret;
554}
555
556/**
557 * Sets the power management mode of the pipe and plane.
558 *
559 * This code should probably grow support for turning the cursor off and back
560 * on appropriately at the same time as we're turning the pipe off/on.
561 */
562static void cdv_intel_crtc_dpms(struct drm_crtc *crtc, int mode)
563{
564 struct drm_device *dev = crtc->dev;
565 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
566 int pipe = psb_intel_crtc->pipe;
567 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
568 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
569 int dspbase_reg = (pipe == 0) ? DSPABASE : DSPBBASE;
570 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
571 u32 temp;
572 bool enabled;
573
574 /* XXX: When our outputs are all unaware of DPMS modes other than off
575 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
576 */
577 switch (mode) {
578 case DRM_MODE_DPMS_ON:
579 case DRM_MODE_DPMS_STANDBY:
580 case DRM_MODE_DPMS_SUSPEND:
581 /* Enable the DPLL */
582 temp = REG_READ(dpll_reg);
583 if ((temp & DPLL_VCO_ENABLE) == 0) {
584 REG_WRITE(dpll_reg, temp);
585 REG_READ(dpll_reg);
586 /* Wait for the clocks to stabilize. */
587 udelay(150);
588 REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
589 REG_READ(dpll_reg);
590 /* Wait for the clocks to stabilize. */
591 udelay(150);
592 REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
593 REG_READ(dpll_reg);
594 /* Wait for the clocks to stabilize. */
595 udelay(150);
596 }
597
598 /* Jim Bish - switch plan and pipe per scott */
599 /* Enable the plane */
600 temp = REG_READ(dspcntr_reg);
601 if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
602 REG_WRITE(dspcntr_reg,
603 temp | DISPLAY_PLANE_ENABLE);
604 /* Flush the plane changes */
605 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
606 }
607
608 udelay(150);
609
610 /* Enable the pipe */
611 temp = REG_READ(pipeconf_reg);
612 if ((temp & PIPEACONF_ENABLE) == 0)
613 REG_WRITE(pipeconf_reg, temp | PIPEACONF_ENABLE);
614
615 psb_intel_crtc_load_lut(crtc);
616
617 /* Give the overlay scaler a chance to enable
618 * if it's on this pipe */
619 /* psb_intel_crtc_dpms_video(crtc, true); TODO */
620 break;
621 case DRM_MODE_DPMS_OFF:
622 /* Give the overlay scaler a chance to disable
623 * if it's on this pipe */
624 /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
625
626 /* Disable the VGA plane that we never use */
627 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
628
629 /* Jim Bish - changed pipe/plane here as well. */
630
631 /* Wait for vblank for the disable to take effect */
632 cdv_intel_wait_for_vblank(dev);
633
634 /* Next, disable display pipes */
635 temp = REG_READ(pipeconf_reg);
636 if ((temp & PIPEACONF_ENABLE) != 0) {
637 REG_WRITE(pipeconf_reg, temp & ~PIPEACONF_ENABLE);
638 REG_READ(pipeconf_reg);
639 }
640
641 /* Wait for vblank for the disable to take effect. */
642 cdv_intel_wait_for_vblank(dev);
643
644 udelay(150);
645
646 /* Disable display plane */
647 temp = REG_READ(dspcntr_reg);
648 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
649 REG_WRITE(dspcntr_reg,
650 temp & ~DISPLAY_PLANE_ENABLE);
651 /* Flush the plane changes */
652 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
653 REG_READ(dspbase_reg);
654 }
655
656 temp = REG_READ(dpll_reg);
657 if ((temp & DPLL_VCO_ENABLE) != 0) {
658 REG_WRITE(dpll_reg, temp & ~DPLL_VCO_ENABLE);
659 REG_READ(dpll_reg);
660 }
661
662 /* Wait for the clocks to turn off. */
663 udelay(150);
664 break;
665 }
666 enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
667 /*Set FIFO Watermarks*/
668 REG_WRITE(DSPARB, 0x3F3E);
669}
670
671static void cdv_intel_crtc_prepare(struct drm_crtc *crtc)
672{
673 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
674 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
675}
676
677static void cdv_intel_crtc_commit(struct drm_crtc *crtc)
678{
679 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
680 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
681}
682
683void cdv_intel_encoder_prepare(struct drm_encoder *encoder)
684{
685 struct drm_encoder_helper_funcs *encoder_funcs =
686 encoder->helper_private;
687 /* lvds has its own version of prepare see cdv_intel_lvds_prepare */
688 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
689}
690
691void cdv_intel_encoder_commit(struct drm_encoder *encoder)
692{
693 struct drm_encoder_helper_funcs *encoder_funcs =
694 encoder->helper_private;
695 /* lvds has its own version of commit see cdv_intel_lvds_commit */
696 encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
697}
698
699static bool cdv_intel_crtc_mode_fixup(struct drm_crtc *crtc,
700 struct drm_display_mode *mode,
701 struct drm_display_mode *adjusted_mode)
702{
703 return true;
704}
705
706
707/**
708 * Return the pipe currently connected to the panel fitter,
709 * or -1 if the panel fitter is not present or not in use
710 */
711static int cdv_intel_panel_fitter_pipe(struct drm_device *dev)
712{
713 u32 pfit_control;
714
715 pfit_control = REG_READ(PFIT_CONTROL);
716
717 /* See if the panel fitter is in use */
718 if ((pfit_control & PFIT_ENABLE) == 0)
719 return -1;
720 return (pfit_control >> 29) & 0x3;
721}
722
723static int cdv_intel_crtc_mode_set(struct drm_crtc *crtc,
724 struct drm_display_mode *mode,
725 struct drm_display_mode *adjusted_mode,
726 int x, int y,
727 struct drm_framebuffer *old_fb)
728{
729 struct drm_device *dev = crtc->dev;
730 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
731 int pipe = psb_intel_crtc->pipe;
732 int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
733 int dpll_md_reg = (psb_intel_crtc->pipe == 0) ? DPLL_A_MD : DPLL_B_MD;
734 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
735 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
736 int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
737 int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
738 int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
739 int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
740 int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
741 int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
742 int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
743 int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
744 int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
745 int refclk;
746 struct cdv_intel_clock_t clock;
747 u32 dpll = 0, dspcntr, pipeconf;
748 bool ok, is_sdvo = false, is_dvo = false;
749 bool is_crt = false, is_lvds = false, is_tv = false;
750 bool is_hdmi = false;
751 struct drm_mode_config *mode_config = &dev->mode_config;
752 struct drm_connector *connector;
753
754 list_for_each_entry(connector, &mode_config->connector_list, head) {
755 struct psb_intel_output *psb_intel_output =
756 to_psb_intel_output(connector);
757
758 if (!connector->encoder
759 || connector->encoder->crtc != crtc)
760 continue;
761
762 switch (psb_intel_output->type) {
763 case INTEL_OUTPUT_LVDS:
764 is_lvds = true;
765 break;
766 case INTEL_OUTPUT_SDVO:
767 is_sdvo = true;
768 break;
769 case INTEL_OUTPUT_DVO:
770 is_dvo = true;
771 break;
772 case INTEL_OUTPUT_TVOUT:
773 is_tv = true;
774 break;
775 case INTEL_OUTPUT_ANALOG:
776 is_crt = true;
777 break;
778 case INTEL_OUTPUT_HDMI:
779 is_hdmi = true;
780 break;
781 }
782 }
783
784 refclk = 96000;
785
786 /* Hack selection about ref clk for CRT */
787 /* Select 27MHz as the reference clk for HDMI */
788 if (is_crt || is_hdmi)
789 refclk = 27000;
790
791 drm_mode_debug_printmodeline(adjusted_mode);
792
793 ok = cdv_intel_find_best_PLL(crtc, adjusted_mode->clock, refclk,
794 &clock);
795 if (!ok) {
796 dev_err(dev->dev, "Couldn't find PLL settings for mode!\n");
797 return 0;
798 }
799
800 dpll = DPLL_VGA_MODE_DIS;
801 if (is_tv) {
802 /* XXX: just matching BIOS for now */
803/* dpll |= PLL_REF_INPUT_TVCLKINBC; */
804 dpll |= 3;
805 }
806 dpll |= PLL_REF_INPUT_DREFCLK;
807
808 dpll |= DPLL_SYNCLOCK_ENABLE;
809 dpll |= DPLL_VGA_MODE_DIS;
810 if (is_lvds)
811 dpll |= DPLLB_MODE_LVDS;
812 else
813 dpll |= DPLLB_MODE_DAC_SERIAL;
814 /* dpll |= (2 << 11); */
815
816 /* setup pipeconf */
817 pipeconf = REG_READ(pipeconf_reg);
818
819 /* Set up the display plane register */
820 dspcntr = DISPPLANE_GAMMA_ENABLE;
821
822 if (pipe == 0)
823 dspcntr |= DISPPLANE_SEL_PIPE_A;
824 else
825 dspcntr |= DISPPLANE_SEL_PIPE_B;
826
827 dspcntr |= DISPLAY_PLANE_ENABLE;
828 pipeconf |= PIPEACONF_ENABLE;
829
830 REG_WRITE(dpll_reg, dpll | DPLL_VGA_MODE_DIS | DPLL_SYNCLOCK_ENABLE);
831 REG_READ(dpll_reg);
832
833 cdv_dpll_set_clock_cdv(dev, crtc, &clock);
834
835 udelay(150);
836
837
838 /* The LVDS pin pair needs to be on before the DPLLs are enabled.
839 * This is an exception to the general rule that mode_set doesn't turn
840 * things on.
841 */
842 if (is_lvds) {
843 u32 lvds = REG_READ(LVDS);
844
845 lvds |=
846 LVDS_PORT_EN | LVDS_A0A2_CLKA_POWER_UP |
847 LVDS_PIPEB_SELECT;
848 /* Set the B0-B3 data pairs corresponding to
849 * whether we're going to
850 * set the DPLLs for dual-channel mode or not.
851 */
852 if (clock.p2 == 7)
853 lvds |= LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP;
854 else
855 lvds &= ~(LVDS_B0B3_POWER_UP | LVDS_CLKB_POWER_UP);
856
857 /* It would be nice to set 24 vs 18-bit mode (LVDS_A3_POWER_UP)
858 * appropriately here, but we need to look more
859 * thoroughly into how panels behave in the two modes.
860 */
861
862 REG_WRITE(LVDS, lvds);
863 REG_READ(LVDS);
864 }
865
866 dpll |= DPLL_VCO_ENABLE;
867
868 /* Disable the panel fitter if it was on our pipe */
869 if (cdv_intel_panel_fitter_pipe(dev) == pipe)
870 REG_WRITE(PFIT_CONTROL, 0);
871
872 DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
873 drm_mode_debug_printmodeline(mode);
874
875 REG_WRITE(dpll_reg,
876 (REG_READ(dpll_reg) & ~DPLL_LOCK) | DPLL_VCO_ENABLE);
877 REG_READ(dpll_reg);
878 /* Wait for the clocks to stabilize. */
879 udelay(150); /* 42 usec w/o calibration, 110 with. rounded up. */
880
881 if (!(REG_READ(dpll_reg) & DPLL_LOCK)) {
882 dev_err(dev->dev, "Failed to get DPLL lock\n");
883 return -EBUSY;
884 }
885
886 {
887 int sdvo_pixel_multiply = adjusted_mode->clock / mode->clock;
888 REG_WRITE(dpll_md_reg, (0 << DPLL_MD_UDI_DIVIDER_SHIFT) | ((sdvo_pixel_multiply - 1) << DPLL_MD_UDI_MULTIPLIER_SHIFT));
889 }
890
891 REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
892 ((adjusted_mode->crtc_htotal - 1) << 16));
893 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
894 ((adjusted_mode->crtc_hblank_end - 1) << 16));
895 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
896 ((adjusted_mode->crtc_hsync_end - 1) << 16));
897 REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
898 ((adjusted_mode->crtc_vtotal - 1) << 16));
899 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
900 ((adjusted_mode->crtc_vblank_end - 1) << 16));
901 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
902 ((adjusted_mode->crtc_vsync_end - 1) << 16));
903 /* pipesrc and dspsize control the size that is scaled from,
904 * which should always be the user's requested size.
905 */
906 REG_WRITE(dspsize_reg,
907 ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
908 REG_WRITE(dsppos_reg, 0);
909 REG_WRITE(pipesrc_reg,
910 ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
911 REG_WRITE(pipeconf_reg, pipeconf);
912 REG_READ(pipeconf_reg);
913
914 cdv_intel_wait_for_vblank(dev);
915
916 REG_WRITE(dspcntr_reg, dspcntr);
917
918 /* Flush the plane changes */
919 {
920 struct drm_crtc_helper_funcs *crtc_funcs =
921 crtc->helper_private;
922 crtc_funcs->mode_set_base(crtc, x, y, old_fb);
923 }
924
925 cdv_intel_wait_for_vblank(dev);
926
927 return 0;
928}
929
930/** Loads the palette/gamma unit for the CRTC with the prepared values */
931void cdv_intel_crtc_load_lut(struct drm_crtc *crtc)
932{
933 struct drm_device *dev = crtc->dev;
934 struct drm_psb_private *dev_priv =
935 (struct drm_psb_private *)dev->dev_private;
936 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
937 int palreg = PALETTE_A;
938 int i;
939
940 /* The clocks have to be on to load the palette. */
941 if (!crtc->enabled)
942 return;
943
944 switch (psb_intel_crtc->pipe) {
945 case 0:
946 break;
947 case 1:
948 palreg = PALETTE_B;
949 break;
950 case 2:
951 palreg = PALETTE_C;
952 break;
953 default:
954 dev_err(dev->dev, "Illegal Pipe Number.\n");
955 return;
956 }
957
958 if (gma_power_begin(dev, false)) {
959 for (i = 0; i < 256; i++) {
960 REG_WRITE(palreg + 4 * i,
961 ((psb_intel_crtc->lut_r[i] +
962 psb_intel_crtc->lut_adj[i]) << 16) |
963 ((psb_intel_crtc->lut_g[i] +
964 psb_intel_crtc->lut_adj[i]) << 8) |
965 (psb_intel_crtc->lut_b[i] +
966 psb_intel_crtc->lut_adj[i]));
967 }
968 gma_power_end(dev);
969 } else {
970 for (i = 0; i < 256; i++) {
971 dev_priv->save_palette_a[i] =
972 ((psb_intel_crtc->lut_r[i] +
973 psb_intel_crtc->lut_adj[i]) << 16) |
974 ((psb_intel_crtc->lut_g[i] +
975 psb_intel_crtc->lut_adj[i]) << 8) |
976 (psb_intel_crtc->lut_b[i] +
977 psb_intel_crtc->lut_adj[i]);
978 }
979
980 }
981}
982
983/**
984 * Save HW states of giving crtc
985 */
986static void cdv_intel_crtc_save(struct drm_crtc *crtc)
987{
988 struct drm_device *dev = crtc->dev;
989 /* struct drm_psb_private *dev_priv =
990 (struct drm_psb_private *)dev->dev_private; */
991 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
992 struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
993 int pipeA = (psb_intel_crtc->pipe == 0);
994 uint32_t paletteReg;
995 int i;
996
997 if (!crtc_state) {
998 dev_dbg(dev->dev, "No CRTC state found\n");
999 return;
1000 }
1001
1002 crtc_state->saveDSPCNTR = REG_READ(pipeA ? DSPACNTR : DSPBCNTR);
1003 crtc_state->savePIPECONF = REG_READ(pipeA ? PIPEACONF : PIPEBCONF);
1004 crtc_state->savePIPESRC = REG_READ(pipeA ? PIPEASRC : PIPEBSRC);
1005 crtc_state->saveFP0 = REG_READ(pipeA ? FPA0 : FPB0);
1006 crtc_state->saveFP1 = REG_READ(pipeA ? FPA1 : FPB1);
1007 crtc_state->saveDPLL = REG_READ(pipeA ? DPLL_A : DPLL_B);
1008 crtc_state->saveHTOTAL = REG_READ(pipeA ? HTOTAL_A : HTOTAL_B);
1009 crtc_state->saveHBLANK = REG_READ(pipeA ? HBLANK_A : HBLANK_B);
1010 crtc_state->saveHSYNC = REG_READ(pipeA ? HSYNC_A : HSYNC_B);
1011 crtc_state->saveVTOTAL = REG_READ(pipeA ? VTOTAL_A : VTOTAL_B);
1012 crtc_state->saveVBLANK = REG_READ(pipeA ? VBLANK_A : VBLANK_B);
1013 crtc_state->saveVSYNC = REG_READ(pipeA ? VSYNC_A : VSYNC_B);
1014 crtc_state->saveDSPSTRIDE = REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE);
1015
1016 /*NOTE: DSPSIZE DSPPOS only for psb*/
1017 crtc_state->saveDSPSIZE = REG_READ(pipeA ? DSPASIZE : DSPBSIZE);
1018 crtc_state->saveDSPPOS = REG_READ(pipeA ? DSPAPOS : DSPBPOS);
1019
1020 crtc_state->saveDSPBASE = REG_READ(pipeA ? DSPABASE : DSPBBASE);
1021
1022 DRM_DEBUG("(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
1023 crtc_state->saveDSPCNTR,
1024 crtc_state->savePIPECONF,
1025 crtc_state->savePIPESRC,
1026 crtc_state->saveFP0,
1027 crtc_state->saveFP1,
1028 crtc_state->saveDPLL,
1029 crtc_state->saveHTOTAL,
1030 crtc_state->saveHBLANK,
1031 crtc_state->saveHSYNC,
1032 crtc_state->saveVTOTAL,
1033 crtc_state->saveVBLANK,
1034 crtc_state->saveVSYNC,
1035 crtc_state->saveDSPSTRIDE,
1036 crtc_state->saveDSPSIZE,
1037 crtc_state->saveDSPPOS,
1038 crtc_state->saveDSPBASE
1039 );
1040
1041 paletteReg = pipeA ? PALETTE_A : PALETTE_B;
1042 for (i = 0; i < 256; ++i)
1043 crtc_state->savePalette[i] = REG_READ(paletteReg + (i << 2));
1044}
1045
1046/**
1047 * Restore HW states of giving crtc
1048 */
1049static void cdv_intel_crtc_restore(struct drm_crtc *crtc)
1050{
1051 struct drm_device *dev = crtc->dev;
1052 /* struct drm_psb_private * dev_priv =
1053 (struct drm_psb_private *)dev->dev_private; */
1054 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1055 struct psb_intel_crtc_state *crtc_state = psb_intel_crtc->crtc_state;
1056 /* struct drm_crtc_helper_funcs * crtc_funcs = crtc->helper_private; */
1057 int pipeA = (psb_intel_crtc->pipe == 0);
1058 uint32_t paletteReg;
1059 int i;
1060
1061 if (!crtc_state) {
1062 dev_dbg(dev->dev, "No crtc state\n");
1063 return;
1064 }
1065
1066 DRM_DEBUG(
1067 "current:(%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
1068 REG_READ(pipeA ? DSPACNTR : DSPBCNTR),
1069 REG_READ(pipeA ? PIPEACONF : PIPEBCONF),
1070 REG_READ(pipeA ? PIPEASRC : PIPEBSRC),
1071 REG_READ(pipeA ? FPA0 : FPB0),
1072 REG_READ(pipeA ? FPA1 : FPB1),
1073 REG_READ(pipeA ? DPLL_A : DPLL_B),
1074 REG_READ(pipeA ? HTOTAL_A : HTOTAL_B),
1075 REG_READ(pipeA ? HBLANK_A : HBLANK_B),
1076 REG_READ(pipeA ? HSYNC_A : HSYNC_B),
1077 REG_READ(pipeA ? VTOTAL_A : VTOTAL_B),
1078 REG_READ(pipeA ? VBLANK_A : VBLANK_B),
1079 REG_READ(pipeA ? VSYNC_A : VSYNC_B),
1080 REG_READ(pipeA ? DSPASTRIDE : DSPBSTRIDE),
1081 REG_READ(pipeA ? DSPASIZE : DSPBSIZE),
1082 REG_READ(pipeA ? DSPAPOS : DSPBPOS),
1083 REG_READ(pipeA ? DSPABASE : DSPBBASE)
1084 );
1085
1086 DRM_DEBUG(
1087 "saved: (%x %x %x %x %x %x %x %x %x %x %x %x %x %x %x %x)\n",
1088 crtc_state->saveDSPCNTR,
1089 crtc_state->savePIPECONF,
1090 crtc_state->savePIPESRC,
1091 crtc_state->saveFP0,
1092 crtc_state->saveFP1,
1093 crtc_state->saveDPLL,
1094 crtc_state->saveHTOTAL,
1095 crtc_state->saveHBLANK,
1096 crtc_state->saveHSYNC,
1097 crtc_state->saveVTOTAL,
1098 crtc_state->saveVBLANK,
1099 crtc_state->saveVSYNC,
1100 crtc_state->saveDSPSTRIDE,
1101 crtc_state->saveDSPSIZE,
1102 crtc_state->saveDSPPOS,
1103 crtc_state->saveDSPBASE
1104 );
1105
1106
1107 if (crtc_state->saveDPLL & DPLL_VCO_ENABLE) {
1108 REG_WRITE(pipeA ? DPLL_A : DPLL_B,
1109 crtc_state->saveDPLL & ~DPLL_VCO_ENABLE);
1110 REG_READ(pipeA ? DPLL_A : DPLL_B);
1111 DRM_DEBUG("write dpll: %x\n",
1112 REG_READ(pipeA ? DPLL_A : DPLL_B));
1113 udelay(150);
1114 }
1115
1116 REG_WRITE(pipeA ? FPA0 : FPB0, crtc_state->saveFP0);
1117 REG_READ(pipeA ? FPA0 : FPB0);
1118
1119 REG_WRITE(pipeA ? FPA1 : FPB1, crtc_state->saveFP1);
1120 REG_READ(pipeA ? FPA1 : FPB1);
1121
1122 REG_WRITE(pipeA ? DPLL_A : DPLL_B, crtc_state->saveDPLL);
1123 REG_READ(pipeA ? DPLL_A : DPLL_B);
1124 udelay(150);
1125
1126 REG_WRITE(pipeA ? HTOTAL_A : HTOTAL_B, crtc_state->saveHTOTAL);
1127 REG_WRITE(pipeA ? HBLANK_A : HBLANK_B, crtc_state->saveHBLANK);
1128 REG_WRITE(pipeA ? HSYNC_A : HSYNC_B, crtc_state->saveHSYNC);
1129 REG_WRITE(pipeA ? VTOTAL_A : VTOTAL_B, crtc_state->saveVTOTAL);
1130 REG_WRITE(pipeA ? VBLANK_A : VBLANK_B, crtc_state->saveVBLANK);
1131 REG_WRITE(pipeA ? VSYNC_A : VSYNC_B, crtc_state->saveVSYNC);
1132 REG_WRITE(pipeA ? DSPASTRIDE : DSPBSTRIDE, crtc_state->saveDSPSTRIDE);
1133
1134 REG_WRITE(pipeA ? DSPASIZE : DSPBSIZE, crtc_state->saveDSPSIZE);
1135 REG_WRITE(pipeA ? DSPAPOS : DSPBPOS, crtc_state->saveDSPPOS);
1136
1137 REG_WRITE(pipeA ? PIPEASRC : PIPEBSRC, crtc_state->savePIPESRC);
1138 REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
1139 REG_WRITE(pipeA ? PIPEACONF : PIPEBCONF, crtc_state->savePIPECONF);
1140
1141 cdv_intel_wait_for_vblank(dev);
1142
1143 REG_WRITE(pipeA ? DSPACNTR : DSPBCNTR, crtc_state->saveDSPCNTR);
1144 REG_WRITE(pipeA ? DSPABASE : DSPBBASE, crtc_state->saveDSPBASE);
1145
1146 cdv_intel_wait_for_vblank(dev);
1147
1148 paletteReg = pipeA ? PALETTE_A : PALETTE_B;
1149 for (i = 0; i < 256; ++i)
1150 REG_WRITE(paletteReg + (i << 2), crtc_state->savePalette[i]);
1151}
1152
1153static int cdv_intel_crtc_cursor_set(struct drm_crtc *crtc,
1154 struct drm_file *file_priv,
1155 uint32_t handle,
1156 uint32_t width, uint32_t height)
1157{
1158 struct drm_device *dev = crtc->dev;
1159 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1160 int pipe = psb_intel_crtc->pipe;
1161 uint32_t control = (pipe == 0) ? CURACNTR : CURBCNTR;
1162 uint32_t base = (pipe == 0) ? CURABASE : CURBBASE;
1163 uint32_t temp;
1164 size_t addr = 0;
1165 struct gtt_range *gt;
1166 struct drm_gem_object *obj;
1167 int ret;
1168
1169 /* if we want to turn of the cursor ignore width and height */
1170 if (!handle) {
1171 /* turn off the cursor */
1172 temp = CURSOR_MODE_DISABLE;
1173
1174 if (gma_power_begin(dev, false)) {
1175 REG_WRITE(control, temp);
1176 REG_WRITE(base, 0);
1177 gma_power_end(dev);
1178 }
1179
1180 /* unpin the old GEM object */
1181 if (psb_intel_crtc->cursor_obj) {
1182 gt = container_of(psb_intel_crtc->cursor_obj,
1183 struct gtt_range, gem);
1184 psb_gtt_unpin(gt);
1185 drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
1186 psb_intel_crtc->cursor_obj = NULL;
1187 }
1188
1189 return 0;
1190 }
1191
1192 /* Currently we only support 64x64 cursors */
1193 if (width != 64 || height != 64) {
1194 dev_dbg(dev->dev, "we currently only support 64x64 cursors\n");
1195 return -EINVAL;
1196 }
1197
1198 obj = drm_gem_object_lookup(dev, file_priv, handle);
1199 if (!obj)
1200 return -ENOENT;
1201
1202 if (obj->size < width * height * 4) {
1203 dev_dbg(dev->dev, "buffer is to small\n");
1204 return -ENOMEM;
1205 }
1206
1207 gt = container_of(obj, struct gtt_range, gem);
1208
1209 /* Pin the memory into the GTT */
1210 ret = psb_gtt_pin(gt);
1211 if (ret) {
1212 dev_err(dev->dev, "Can not pin down handle 0x%x\n", handle);
1213 return ret;
1214 }
1215
1216 addr = gt->offset; /* Or resource.start ??? */
1217
1218 psb_intel_crtc->cursor_addr = addr;
1219
1220 temp = 0;
1221 /* set the pipe for the cursor */
1222 temp |= (pipe << 28);
1223 temp |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
1224
1225 if (gma_power_begin(dev, false)) {
1226 REG_WRITE(control, temp);
1227 REG_WRITE(base, addr);
1228 gma_power_end(dev);
1229 }
1230
1231 /* unpin the old GEM object */
1232 if (psb_intel_crtc->cursor_obj) {
1233 gt = container_of(psb_intel_crtc->cursor_obj,
1234 struct gtt_range, gem);
1235 psb_gtt_unpin(gt);
1236 drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
1237 psb_intel_crtc->cursor_obj = obj;
1238 }
1239 return 0;
1240}
1241
1242static int cdv_intel_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
1243{
1244 struct drm_device *dev = crtc->dev;
1245 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1246 int pipe = psb_intel_crtc->pipe;
1247 uint32_t temp = 0;
1248 uint32_t adder;
1249
1250
1251 if (x < 0) {
1252 temp |= (CURSOR_POS_SIGN << CURSOR_X_SHIFT);
1253 x = -x;
1254 }
1255 if (y < 0) {
1256 temp |= (CURSOR_POS_SIGN << CURSOR_Y_SHIFT);
1257 y = -y;
1258 }
1259
1260 temp |= ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT);
1261 temp |= ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
1262
1263 adder = psb_intel_crtc->cursor_addr;
1264
1265 if (gma_power_begin(dev, false)) {
1266 REG_WRITE((pipe == 0) ? CURAPOS : CURBPOS, temp);
1267 REG_WRITE((pipe == 0) ? CURABASE : CURBBASE, adder);
1268 gma_power_end(dev);
1269 }
1270 return 0;
1271}
1272
1273static void cdv_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
1274 u16 *green, u16 *blue, uint32_t start, uint32_t size)
1275{
1276 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1277 int i;
1278 int end = (start + size > 256) ? 256 : start + size;
1279
1280 for (i = start; i < end; i++) {
1281 psb_intel_crtc->lut_r[i] = red[i] >> 8;
1282 psb_intel_crtc->lut_g[i] = green[i] >> 8;
1283 psb_intel_crtc->lut_b[i] = blue[i] >> 8;
1284 }
1285
1286 cdv_intel_crtc_load_lut(crtc);
1287}
1288
1289static int cdv_crtc_set_config(struct drm_mode_set *set)
1290{
1291 int ret = 0;
1292 struct drm_device *dev = set->crtc->dev;
1293 struct drm_psb_private *dev_priv = dev->dev_private;
1294
1295 if (!dev_priv->rpm_enabled)
1296 return drm_crtc_helper_set_config(set);
1297
1298 pm_runtime_forbid(&dev->pdev->dev);
1299
1300 ret = drm_crtc_helper_set_config(set);
1301
1302 pm_runtime_allow(&dev->pdev->dev);
1303
1304 return ret;
1305}
1306
1307/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
1308
1309/* FIXME: why are we using this, should it be cdv_ in this tree ? */
1310
1311static void i8xx_clock(int refclk, struct cdv_intel_clock_t *clock)
1312{
1313 clock->m = 5 * (clock->m1 + 2) + (clock->m2 + 2);
1314 clock->p = clock->p1 * clock->p2;
1315 clock->vco = refclk * clock->m / (clock->n + 2);
1316 clock->dot = clock->vco / clock->p;
1317}
1318
1319/* Returns the clock of the currently programmed mode of the given pipe. */
1320static int cdv_intel_crtc_clock_get(struct drm_device *dev,
1321 struct drm_crtc *crtc)
1322{
1323 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1324 int pipe = psb_intel_crtc->pipe;
1325 u32 dpll;
1326 u32 fp;
1327 struct cdv_intel_clock_t clock;
1328 bool is_lvds;
1329 struct drm_psb_private *dev_priv = dev->dev_private;
1330
1331 if (gma_power_begin(dev, false)) {
1332 dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
1333 if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
1334 fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
1335 else
1336 fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
1337 is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
1338 gma_power_end(dev);
1339 } else {
1340 dpll = (pipe == 0) ?
1341 dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
1342
1343 if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
1344 fp = (pipe == 0) ?
1345 dev_priv->saveFPA0 :
1346 dev_priv->saveFPB0;
1347 else
1348 fp = (pipe == 0) ?
1349 dev_priv->saveFPA1 :
1350 dev_priv->saveFPB1;
1351
1352 is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
1353 }
1354
1355 clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
1356 clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
1357 clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
1358
1359 if (is_lvds) {
1360 clock.p1 =
1361 ffs((dpll &
1362 DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
1363 DPLL_FPA01_P1_POST_DIV_SHIFT);
1364 if (clock.p1 == 0) {
1365 clock.p1 = 4;
1366 dev_err(dev->dev, "PLL %d\n", dpll);
1367 }
1368 clock.p2 = 14;
1369
1370 if ((dpll & PLL_REF_INPUT_MASK) ==
1371 PLLB_REF_INPUT_SPREADSPECTRUMIN) {
1372 /* XXX: might not be 66MHz */
1373 i8xx_clock(66000, &clock);
1374 } else
1375 i8xx_clock(48000, &clock);
1376 } else {
1377 if (dpll & PLL_P1_DIVIDE_BY_TWO)
1378 clock.p1 = 2;
1379 else {
1380 clock.p1 =
1381 ((dpll &
1382 DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
1383 DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
1384 }
1385 if (dpll & PLL_P2_DIVIDE_BY_4)
1386 clock.p2 = 4;
1387 else
1388 clock.p2 = 2;
1389
1390 i8xx_clock(48000, &clock);
1391 }
1392
1393 /* XXX: It would be nice to validate the clocks, but we can't reuse
1394 * i830PllIsValid() because it relies on the xf86_config connector
1395 * configuration being accurate, which it isn't necessarily.
1396 */
1397
1398 return clock.dot;
1399}
1400
1401/** Returns the currently programmed mode of the given pipe. */
1402struct drm_display_mode *cdv_intel_crtc_mode_get(struct drm_device *dev,
1403 struct drm_crtc *crtc)
1404{
1405 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1406 int pipe = psb_intel_crtc->pipe;
1407 struct drm_display_mode *mode;
1408 int htot;
1409 int hsync;
1410 int vtot;
1411 int vsync;
1412 struct drm_psb_private *dev_priv = dev->dev_private;
1413
1414 if (gma_power_begin(dev, false)) {
1415 htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
1416 hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
1417 vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
1418 vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
1419 gma_power_end(dev);
1420 } else {
1421 htot = (pipe == 0) ?
1422 dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
1423 hsync = (pipe == 0) ?
1424 dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
1425 vtot = (pipe == 0) ?
1426 dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
1427 vsync = (pipe == 0) ?
1428 dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
1429 }
1430
1431 mode = kzalloc(sizeof(*mode), GFP_KERNEL);
1432 if (!mode)
1433 return NULL;
1434
1435 mode->clock = cdv_intel_crtc_clock_get(dev, crtc);
1436 mode->hdisplay = (htot & 0xffff) + 1;
1437 mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
1438 mode->hsync_start = (hsync & 0xffff) + 1;
1439 mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
1440 mode->vdisplay = (vtot & 0xffff) + 1;
1441 mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
1442 mode->vsync_start = (vsync & 0xffff) + 1;
1443 mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
1444
1445 drm_mode_set_name(mode);
1446 drm_mode_set_crtcinfo(mode, 0);
1447
1448 return mode;
1449}
1450
1451static void cdv_intel_crtc_destroy(struct drm_crtc *crtc)
1452{
1453 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1454
1455 kfree(psb_intel_crtc->crtc_state);
1456 drm_crtc_cleanup(crtc);
1457 kfree(psb_intel_crtc);
1458}
1459
1460const struct drm_crtc_helper_funcs cdv_intel_helper_funcs = {
1461 .dpms = cdv_intel_crtc_dpms,
1462 .mode_fixup = cdv_intel_crtc_mode_fixup,
1463 .mode_set = cdv_intel_crtc_mode_set,
1464 .mode_set_base = cdv_intel_pipe_set_base,
1465 .prepare = cdv_intel_crtc_prepare,
1466 .commit = cdv_intel_crtc_commit,
1467};
1468
1469const struct drm_crtc_funcs cdv_intel_crtc_funcs = {
1470 .save = cdv_intel_crtc_save,
1471 .restore = cdv_intel_crtc_restore,
1472 .cursor_set = cdv_intel_crtc_cursor_set,
1473 .cursor_move = cdv_intel_crtc_cursor_move,
1474 .gamma_set = cdv_intel_crtc_gamma_set,
1475 .set_config = cdv_crtc_set_config,
1476 .destroy = cdv_intel_crtc_destroy,
1477};
1478
1479/*
1480 * Set the default value of cursor control and base register
1481 * to zero. This is a workaround for h/w defect on oaktrail
1482 */
1483void cdv_intel_cursor_init(struct drm_device *dev, int pipe)
1484{
1485 uint32_t control;
1486 uint32_t base;
1487
1488 switch (pipe) {
1489 case 0:
1490 control = CURACNTR;
1491 base = CURABASE;
1492 break;
1493 case 1:
1494 control = CURBCNTR;
1495 base = CURBBASE;
1496 break;
1497 case 2:
1498 control = CURCCNTR;
1499 base = CURCBASE;
1500 break;
1501 default:
1502 return;
1503 }
1504
1505 REG_WRITE(control, 0);
1506 REG_WRITE(base, 0);
1507}
1508
diff --git a/drivers/staging/gma500/cdv_intel_hdmi.c b/drivers/staging/gma500/cdv_intel_hdmi.c
new file mode 100644
index 00000000000..cbca2b0c7d5
--- /dev/null
+++ b/drivers/staging/gma500/cdv_intel_hdmi.c
@@ -0,0 +1,376 @@
1/*
2 * Copyright © 2006-2011 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * jim liu <jim.liu@intel.com>
25 *
26 * FIXME:
27 * We should probably make this generic and share it with Medfield
28 */
29
30#include <drm/drmP.h>
31#include <drm/drm.h>
32#include <drm/drm_crtc.h>
33#include <drm/drm_edid.h>
34#include "psb_intel_drv.h"
35#include "psb_drv.h"
36#include "psb_intel_reg.h"
37#include <linux/pm_runtime.h>
38
39/* hdmi control bits */
40#define HDMI_NULL_PACKETS_DURING_VSYNC (1 << 9)
41#define HDMI_BORDER_ENABLE (1 << 7)
42#define HDMI_AUDIO_ENABLE (1 << 6)
43#define HDMI_VSYNC_ACTIVE_HIGH (1 << 4)
44#define HDMI_HSYNC_ACTIVE_HIGH (1 << 3)
45/* hdmi-b control bits */
46#define HDMIB_PIPE_B_SELECT (1 << 30)
47
48
49struct mid_intel_hdmi_priv {
50 u32 hdmi_reg;
51 u32 save_HDMIB;
52 bool has_hdmi_sink;
53 bool has_hdmi_audio;
54 /* Should set this when detect hotplug */
55 bool hdmi_device_connected;
56 struct mdfld_hdmi_i2c *i2c_bus;
57 struct i2c_adapter *hdmi_i2c_adapter; /* for control functions */
58 struct drm_device *dev;
59};
60
61static void cdv_hdmi_mode_set(struct drm_encoder *encoder,
62 struct drm_display_mode *mode,
63 struct drm_display_mode *adjusted_mode)
64{
65 struct drm_device *dev = encoder->dev;
66 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
67 struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
68 u32 hdmib;
69 struct drm_crtc *crtc = encoder->crtc;
70 struct psb_intel_crtc *intel_crtc = to_psb_intel_crtc(crtc);
71
72 hdmib = (2 << 10);
73
74 if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
75 hdmib |= HDMI_VSYNC_ACTIVE_HIGH;
76 if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
77 hdmib |= HDMI_HSYNC_ACTIVE_HIGH;
78
79 if (intel_crtc->pipe == 1)
80 hdmib |= HDMIB_PIPE_B_SELECT;
81
82 if (hdmi_priv->has_hdmi_audio) {
83 hdmib |= HDMI_AUDIO_ENABLE;
84 hdmib |= HDMI_NULL_PACKETS_DURING_VSYNC;
85 }
86
87 REG_WRITE(hdmi_priv->hdmi_reg, hdmib);
88 REG_READ(hdmi_priv->hdmi_reg);
89}
90
91static bool cdv_hdmi_mode_fixup(struct drm_encoder *encoder,
92 struct drm_display_mode *mode,
93 struct drm_display_mode *adjusted_mode)
94{
95 return true;
96}
97
98static void cdv_hdmi_dpms(struct drm_encoder *encoder, int mode)
99{
100 struct drm_device *dev = encoder->dev;
101 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
102 struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
103 u32 hdmib;
104
105 hdmib = REG_READ(hdmi_priv->hdmi_reg);
106
107 if (mode != DRM_MODE_DPMS_ON)
108 REG_WRITE(hdmi_priv->hdmi_reg, hdmib & ~HDMIB_PORT_EN);
109 else
110 REG_WRITE(hdmi_priv->hdmi_reg, hdmib | HDMIB_PORT_EN);
111 REG_READ(hdmi_priv->hdmi_reg);
112}
113
114static void cdv_hdmi_save(struct drm_connector *connector)
115{
116 struct drm_device *dev = connector->dev;
117 struct psb_intel_output *output = to_psb_intel_output(connector);
118 struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
119
120 hdmi_priv->save_HDMIB = REG_READ(hdmi_priv->hdmi_reg);
121}
122
123static void cdv_hdmi_restore(struct drm_connector *connector)
124{
125 struct drm_device *dev = connector->dev;
126 struct psb_intel_output *output = to_psb_intel_output(connector);
127 struct mid_intel_hdmi_priv *hdmi_priv = output->dev_priv;
128
129 REG_WRITE(hdmi_priv->hdmi_reg, hdmi_priv->save_HDMIB);
130 REG_READ(hdmi_priv->hdmi_reg);
131}
132
133static enum drm_connector_status cdv_hdmi_detect(
134 struct drm_connector *connector, bool force)
135{
136 struct psb_intel_output *psb_intel_output =
137 to_psb_intel_output(connector);
138 struct mid_intel_hdmi_priv *hdmi_priv = psb_intel_output->dev_priv;
139 struct edid *edid = NULL;
140 enum drm_connector_status status = connector_status_disconnected;
141
142 edid = drm_get_edid(&psb_intel_output->base,
143 psb_intel_output->hdmi_i2c_adapter);
144
145 hdmi_priv->has_hdmi_sink = false;
146 hdmi_priv->has_hdmi_audio = false;
147 if (edid) {
148 if (edid->input & DRM_EDID_INPUT_DIGITAL) {
149 status = connector_status_connected;
150 hdmi_priv->has_hdmi_sink =
151 drm_detect_hdmi_monitor(edid);
152 hdmi_priv->has_hdmi_audio =
153 drm_detect_monitor_audio(edid);
154 }
155
156 psb_intel_output->base.display_info.raw_edid = NULL;
157 kfree(edid);
158 }
159 return status;
160}
161
162static int cdv_hdmi_set_property(struct drm_connector *connector,
163 struct drm_property *property,
164 uint64_t value)
165{
166 struct drm_encoder *encoder = connector->encoder;
167
168 if (!strcmp(property->name, "scaling mode") && encoder) {
169 struct psb_intel_crtc *crtc = to_psb_intel_crtc(encoder->crtc);
170 bool centre;
171 uint64_t curValue;
172
173 if (!crtc)
174 return -1;
175
176 switch (value) {
177 case DRM_MODE_SCALE_FULLSCREEN:
178 break;
179 case DRM_MODE_SCALE_NO_SCALE:
180 break;
181 case DRM_MODE_SCALE_ASPECT:
182 break;
183 default:
184 return -1;
185 }
186
187 if (drm_connector_property_get_value(connector,
188 property, &curValue))
189 return -1;
190
191 if (curValue == value)
192 return 0;
193
194 if (drm_connector_property_set_value(connector,
195 property, value))
196 return -1;
197
198 centre = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
199 (value == DRM_MODE_SCALE_NO_SCALE);
200
201 if (crtc->saved_mode.hdisplay != 0 &&
202 crtc->saved_mode.vdisplay != 0) {
203 if (centre) {
204 if (!drm_crtc_helper_set_mode(encoder->crtc, &crtc->saved_mode,
205 encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
206 return -1;
207 } else {
208 struct drm_encoder_helper_funcs *helpers
209 = encoder->helper_private;
210 helpers->mode_set(encoder, &crtc->saved_mode,
211 &crtc->saved_adjusted_mode);
212 }
213 }
214 }
215 return 0;
216}
217
218/*
219 * Return the list of HDMI DDC modes if available.
220 */
221static int cdv_hdmi_get_modes(struct drm_connector *connector)
222{
223 struct psb_intel_output *psb_intel_output =
224 to_psb_intel_output(connector);
225 struct edid *edid = NULL;
226 int ret = 0;
227
228 edid = drm_get_edid(&psb_intel_output->base,
229 psb_intel_output->hdmi_i2c_adapter);
230 if (edid) {
231 drm_mode_connector_update_edid_property(&psb_intel_output->
232 base, edid);
233 ret = drm_add_edid_modes(&psb_intel_output->base, edid);
234 kfree(edid);
235 }
236 return ret;
237}
238
239static int cdv_hdmi_mode_valid(struct drm_connector *connector,
240 struct drm_display_mode *mode)
241{
242
243 if (mode->clock > 165000)
244 return MODE_CLOCK_HIGH;
245 if (mode->clock < 20000)
246 return MODE_CLOCK_HIGH;
247
248 /* just in case */
249 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
250 return MODE_NO_DBLESCAN;
251
252 /* just in case */
253 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
254 return MODE_NO_INTERLACE;
255
256 /*
257 * FIXME: for now we limit the size to 1680x1050 on CDV, otherwise it
258 * will go beyond the stolen memory size allocated to the framebuffer
259 */
260 if (mode->hdisplay > 1680)
261 return MODE_PANEL;
262 if (mode->vdisplay > 1050)
263 return MODE_PANEL;
264 return MODE_OK;
265}
266
267static void cdv_hdmi_destroy(struct drm_connector *connector)
268{
269 struct psb_intel_output *psb_intel_output =
270 to_psb_intel_output(connector);
271
272 if (psb_intel_output->ddc_bus)
273 psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
274 drm_sysfs_connector_remove(connector);
275 drm_connector_cleanup(connector);
276 kfree(connector);
277}
278
279static const struct drm_encoder_helper_funcs cdv_hdmi_helper_funcs = {
280 .dpms = cdv_hdmi_dpms,
281 .mode_fixup = cdv_hdmi_mode_fixup,
282 .prepare = psb_intel_encoder_prepare,
283 .mode_set = cdv_hdmi_mode_set,
284 .commit = psb_intel_encoder_commit,
285};
286
287static const struct drm_connector_helper_funcs
288 cdv_hdmi_connector_helper_funcs = {
289 .get_modes = cdv_hdmi_get_modes,
290 .mode_valid = cdv_hdmi_mode_valid,
291 .best_encoder = psb_intel_best_encoder,
292};
293
294static const struct drm_connector_funcs cdv_hdmi_connector_funcs = {
295 .dpms = drm_helper_connector_dpms,
296 .save = cdv_hdmi_save,
297 .restore = cdv_hdmi_restore,
298 .detect = cdv_hdmi_detect,
299 .fill_modes = drm_helper_probe_single_connector_modes,
300 .set_property = cdv_hdmi_set_property,
301 .destroy = cdv_hdmi_destroy,
302};
303
304void cdv_hdmi_init(struct drm_device *dev,
305 struct psb_intel_mode_device *mode_dev, int reg)
306{
307 struct psb_intel_output *psb_intel_output;
308 struct drm_connector *connector;
309 struct drm_encoder *encoder;
310 struct mid_intel_hdmi_priv *hdmi_priv;
311 int ddc_bus;
312
313 psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
314 sizeof(struct mid_intel_hdmi_priv), GFP_KERNEL);
315 if (!psb_intel_output)
316 return;
317
318 hdmi_priv = (struct mid_intel_hdmi_priv *)(psb_intel_output + 1);
319 psb_intel_output->mode_dev = mode_dev;
320 connector = &psb_intel_output->base;
321 encoder = &psb_intel_output->enc;
322 drm_connector_init(dev, &psb_intel_output->base,
323 &cdv_hdmi_connector_funcs,
324 DRM_MODE_CONNECTOR_DVID);
325
326 drm_encoder_init(dev, &psb_intel_output->enc, &psb_intel_lvds_enc_funcs,
327 DRM_MODE_ENCODER_TMDS);
328
329 drm_mode_connector_attach_encoder(&psb_intel_output->base,
330 &psb_intel_output->enc);
331 psb_intel_output->type = INTEL_OUTPUT_HDMI;
332 hdmi_priv->hdmi_reg = reg;
333 hdmi_priv->has_hdmi_sink = false;
334 psb_intel_output->dev_priv = hdmi_priv;
335
336 drm_encoder_helper_add(encoder, &cdv_hdmi_helper_funcs);
337 drm_connector_helper_add(connector,
338 &cdv_hdmi_connector_helper_funcs);
339 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
340 connector->interlace_allowed = false;
341 connector->doublescan_allowed = false;
342
343 drm_connector_attach_property(connector,
344 dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
345
346 switch (reg) {
347 case SDVOB:
348 ddc_bus = GPIOE;
349 break;
350 case SDVOC:
351 ddc_bus = GPIOD;
352 break;
353 default:
354 DRM_ERROR("unknown reg 0x%x for HDMI\n", reg);
355 goto failed_ddc;
356 break;
357 }
358
359 psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
360 ddc_bus, (reg == SDVOB) ? "HDMIB" : "HDMIC");
361
362 if (!psb_intel_output->ddc_bus) {
363 dev_err(dev->dev, "No ddc adapter available!\n");
364 goto failed_ddc;
365 }
366 psb_intel_output->hdmi_i2c_adapter =
367 &(psb_intel_output->ddc_bus->adapter);
368 hdmi_priv->dev = dev;
369 drm_sysfs_connector_add(connector);
370 return;
371
372failed_ddc:
373 drm_encoder_cleanup(&psb_intel_output->enc);
374 drm_connector_cleanup(&psb_intel_output->base);
375 kfree(psb_intel_output);
376}
diff --git a/drivers/staging/gma500/cdv_intel_lvds.c b/drivers/staging/gma500/cdv_intel_lvds.c
new file mode 100644
index 00000000000..988b2d0acf4
--- /dev/null
+++ b/drivers/staging/gma500/cdv_intel_lvds.c
@@ -0,0 +1,721 @@
1/*
2 * Copyright © 2006-2011 Intel Corporation
3 *
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc.,
15 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
16 *
17 * Authors:
18 * Eric Anholt <eric@anholt.net>
19 * Dave Airlie <airlied@linux.ie>
20 * Jesse Barnes <jesse.barnes@intel.com>
21 */
22
23#include <linux/i2c.h>
24#include <linux/dmi.h>
25#include <drm/drmP.h>
26
27#include "intel_bios.h"
28#include "psb_drv.h"
29#include "psb_intel_drv.h"
30#include "psb_intel_reg.h"
31#include "power.h"
32#include <linux/pm_runtime.h>
33#include "cdv_device.h"
34
35/**
36 * LVDS I2C backlight control macros
37 */
38#define BRIGHTNESS_MAX_LEVEL 100
39#define BRIGHTNESS_MASK 0xFF
40#define BLC_I2C_TYPE 0x01
41#define BLC_PWM_TYPT 0x02
42
43#define BLC_POLARITY_NORMAL 0
44#define BLC_POLARITY_INVERSE 1
45
46#define PSB_BLC_MAX_PWM_REG_FREQ (0xFFFE)
47#define PSB_BLC_MIN_PWM_REG_FREQ (0x2)
48#define PSB_BLC_PWM_PRECISION_FACTOR (10)
49#define PSB_BACKLIGHT_PWM_CTL_SHIFT (16)
50#define PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
51
52struct cdv_intel_lvds_priv {
53 /**
54 * Saved LVDO output states
55 */
56 uint32_t savePP_ON;
57 uint32_t savePP_OFF;
58 uint32_t saveLVDS;
59 uint32_t savePP_CONTROL;
60 uint32_t savePP_CYCLE;
61 uint32_t savePFIT_CONTROL;
62 uint32_t savePFIT_PGM_RATIOS;
63 uint32_t saveBLC_PWM_CTL;
64};
65
66/*
67 * Returns the maximum level of the backlight duty cycle field.
68 */
69static u32 cdv_intel_lvds_get_max_backlight(struct drm_device *dev)
70{
71 struct drm_psb_private *dev_priv = dev->dev_private;
72 u32 retval;
73
74 if (gma_power_begin(dev, false)) {
75 retval = ((REG_READ(BLC_PWM_CTL) &
76 BACKLIGHT_MODULATION_FREQ_MASK) >>
77 BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
78
79 gma_power_end(dev);
80 } else
81 retval = ((dev_priv->saveBLC_PWM_CTL &
82 BACKLIGHT_MODULATION_FREQ_MASK) >>
83 BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
84
85 return retval;
86}
87
88/*
89 * Set LVDS backlight level by I2C command
90 */
91static int cdv_lvds_i2c_set_brightness(struct drm_device *dev,
92 unsigned int level)
93{
94 struct drm_psb_private *dev_priv = dev->dev_private;
95 struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
96 u8 out_buf[2];
97 unsigned int blc_i2c_brightness;
98
99 struct i2c_msg msgs[] = {
100 {
101 .addr = lvds_i2c_bus->slave_addr,
102 .flags = 0,
103 .len = 2,
104 .buf = out_buf,
105 }
106 };
107
108 blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
109 BRIGHTNESS_MASK /
110 BRIGHTNESS_MAX_LEVEL);
111
112 if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
113 blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
114
115 out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
116 out_buf[1] = (u8)blc_i2c_brightness;
117
118 if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1)
119 return 0;
120
121 DRM_ERROR("I2C transfer error\n");
122 return -1;
123}
124
125
126static int cdv_lvds_pwm_set_brightness(struct drm_device *dev, int level)
127{
128 struct drm_psb_private *dev_priv = dev->dev_private;
129
130 u32 max_pwm_blc;
131 u32 blc_pwm_duty_cycle;
132
133 max_pwm_blc = cdv_intel_lvds_get_max_backlight(dev);
134
135 /*BLC_PWM_CTL Should be initiated while backlight device init*/
136 BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
137
138 blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
139
140 if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
141 blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
142
143 blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
144 REG_WRITE(BLC_PWM_CTL,
145 (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
146 (blc_pwm_duty_cycle));
147
148 return 0;
149}
150
151/*
152 * Set LVDS backlight level either by I2C or PWM
153 */
154void cdv_intel_lvds_set_brightness(struct drm_device *dev, int level)
155{
156 struct drm_psb_private *dev_priv = dev->dev_private;
157
158 if (!dev_priv->lvds_bl) {
159 DRM_ERROR("NO LVDS Backlight Info\n");
160 return;
161 }
162
163 if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
164 cdv_lvds_i2c_set_brightness(dev, level);
165 else
166 cdv_lvds_pwm_set_brightness(dev, level);
167}
168
169/**
170 * Sets the backlight level.
171 *
172 * level backlight level, from 0 to cdv_intel_lvds_get_max_backlight().
173 */
174static void cdv_intel_lvds_set_backlight(struct drm_device *dev, int level)
175{
176 struct drm_psb_private *dev_priv = dev->dev_private;
177 u32 blc_pwm_ctl;
178
179 if (gma_power_begin(dev, false)) {
180 blc_pwm_ctl =
181 REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
182 REG_WRITE(BLC_PWM_CTL,
183 (blc_pwm_ctl |
184 (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
185 gma_power_end(dev);
186 } else {
187 blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
188 ~BACKLIGHT_DUTY_CYCLE_MASK;
189 dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
190 (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
191 }
192}
193
194/**
195 * Sets the power state for the panel.
196 */
197static void cdv_intel_lvds_set_power(struct drm_device *dev,
198 struct psb_intel_output *output, bool on)
199{
200 u32 pp_status;
201
202 if (!gma_power_begin(dev, true))
203 return;
204
205 if (on) {
206 REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
207 POWER_TARGET_ON);
208 do {
209 pp_status = REG_READ(PP_STATUS);
210 } while ((pp_status & PP_ON) == 0);
211
212 cdv_intel_lvds_set_backlight(dev,
213 output->
214 mode_dev->backlight_duty_cycle);
215 } else {
216 cdv_intel_lvds_set_backlight(dev, 0);
217
218 REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
219 ~POWER_TARGET_ON);
220 do {
221 pp_status = REG_READ(PP_STATUS);
222 } while (pp_status & PP_ON);
223 }
224 gma_power_end(dev);
225}
226
227static void cdv_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
228{
229 struct drm_device *dev = encoder->dev;
230 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
231 if (mode == DRM_MODE_DPMS_ON)
232 cdv_intel_lvds_set_power(dev, output, true);
233 else
234 cdv_intel_lvds_set_power(dev, output, false);
235 /* XXX: We never power down the LVDS pairs. */
236}
237
238static void cdv_intel_lvds_save(struct drm_connector *connector)
239{
240}
241
242static void cdv_intel_lvds_restore(struct drm_connector *connector)
243{
244}
245
246int cdv_intel_lvds_mode_valid(struct drm_connector *connector,
247 struct drm_display_mode *mode)
248{
249 struct psb_intel_output *psb_intel_output =
250 to_psb_intel_output(connector);
251 struct drm_display_mode *fixed_mode =
252 psb_intel_output->mode_dev->panel_fixed_mode;
253
254 /* just in case */
255 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
256 return MODE_NO_DBLESCAN;
257
258 /* just in case */
259 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
260 return MODE_NO_INTERLACE;
261
262 if (fixed_mode) {
263 if (mode->hdisplay > fixed_mode->hdisplay)
264 return MODE_PANEL;
265 if (mode->vdisplay > fixed_mode->vdisplay)
266 return MODE_PANEL;
267 }
268 return MODE_OK;
269}
270
271bool cdv_intel_lvds_mode_fixup(struct drm_encoder *encoder,
272 struct drm_display_mode *mode,
273 struct drm_display_mode *adjusted_mode)
274{
275 struct psb_intel_mode_device *mode_dev =
276 enc_to_psb_intel_output(encoder)->mode_dev;
277 struct drm_device *dev = encoder->dev;
278 struct drm_encoder *tmp_encoder;
279 struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
280
281 /* Should never happen!! */
282 list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
283 head) {
284 if (tmp_encoder != encoder
285 && tmp_encoder->crtc == encoder->crtc) {
286 printk(KERN_ERR "Can't enable LVDS and another "
287 "encoder on the same pipe\n");
288 return false;
289 }
290 }
291
292 /*
293 * If we have timings from the BIOS for the panel, put them in
294 * to the adjusted mode. The CRTC will be set up for this mode,
295 * with the panel scaling set up to source from the H/VDisplay
296 * of the original mode.
297 */
298 if (panel_fixed_mode != NULL) {
299 adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
300 adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
301 adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
302 adjusted_mode->htotal = panel_fixed_mode->htotal;
303 adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
304 adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
305 adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
306 adjusted_mode->vtotal = panel_fixed_mode->vtotal;
307 adjusted_mode->clock = panel_fixed_mode->clock;
308 drm_mode_set_crtcinfo(adjusted_mode,
309 CRTC_INTERLACE_HALVE_V);
310 }
311
312 /*
313 * XXX: It would be nice to support lower refresh rates on the
314 * panels to reduce power consumption, and perhaps match the
315 * user's requested refresh rate.
316 */
317
318 return true;
319}
320
321static void cdv_intel_lvds_prepare(struct drm_encoder *encoder)
322{
323 struct drm_device *dev = encoder->dev;
324 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
325 struct psb_intel_mode_device *mode_dev = output->mode_dev;
326
327 if (!gma_power_begin(dev, true))
328 return;
329
330 mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
331 mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
332 BACKLIGHT_DUTY_CYCLE_MASK);
333
334 cdv_intel_lvds_set_power(dev, output, false);
335
336 gma_power_end(dev);
337}
338
339static void cdv_intel_lvds_commit(struct drm_encoder *encoder)
340{
341 struct drm_device *dev = encoder->dev;
342 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
343 struct psb_intel_mode_device *mode_dev = output->mode_dev;
344
345 if (mode_dev->backlight_duty_cycle == 0)
346 mode_dev->backlight_duty_cycle =
347 cdv_intel_lvds_get_max_backlight(dev);
348
349 cdv_intel_lvds_set_power(dev, output, true);
350}
351
352static void cdv_intel_lvds_mode_set(struct drm_encoder *encoder,
353 struct drm_display_mode *mode,
354 struct drm_display_mode *adjusted_mode)
355{
356 struct drm_device *dev = encoder->dev;
357 struct drm_psb_private *dev_priv = dev->dev_private;
358 u32 pfit_control;
359
360 /*
361 * The LVDS pin pair will already have been turned on in the
362 * cdv_intel_crtc_mode_set since it has a large impact on the DPLL
363 * settings.
364 */
365
366 /*
367 * Enable automatic panel scaling so that non-native modes fill the
368 * screen. Should be enabled before the pipe is enabled, according to
369 * register description and PRM.
370 */
371 if (mode->hdisplay != adjusted_mode->hdisplay ||
372 mode->vdisplay != adjusted_mode->vdisplay)
373 pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
374 HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
375 HORIZ_INTERP_BILINEAR);
376 else
377 pfit_control = 0;
378
379 if (dev_priv->lvds_dither)
380 pfit_control |= PANEL_8TO6_DITHER_ENABLE;
381
382 REG_WRITE(PFIT_CONTROL, pfit_control);
383}
384
385/**
386 * Detect the LVDS connection.
387 *
388 * This always returns CONNECTOR_STATUS_CONNECTED.
389 * This connector should only have
390 * been set up if the LVDS was actually connected anyway.
391 */
392static enum drm_connector_status cdv_intel_lvds_detect(
393 struct drm_connector *connector, bool force)
394{
395 return connector_status_connected;
396}
397
398/**
399 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
400 */
401static int cdv_intel_lvds_get_modes(struct drm_connector *connector)
402{
403 struct drm_device *dev = connector->dev;
404 struct psb_intel_output *psb_intel_output =
405 to_psb_intel_output(connector);
406 struct psb_intel_mode_device *mode_dev =
407 psb_intel_output->mode_dev;
408 int ret;
409
410 ret = psb_intel_ddc_get_modes(psb_intel_output);
411
412 if (ret)
413 return ret;
414
415 /* Didn't get an EDID, so
416 * Set wide sync ranges so we get all modes
417 * handed to valid_mode for checking
418 */
419 connector->display_info.min_vfreq = 0;
420 connector->display_info.max_vfreq = 200;
421 connector->display_info.min_hfreq = 0;
422 connector->display_info.max_hfreq = 200;
423 if (mode_dev->panel_fixed_mode != NULL) {
424 struct drm_display_mode *mode =
425 drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
426 drm_mode_probed_add(connector, mode);
427 return 1;
428 }
429
430 return 0;
431}
432
433/**
434 * cdv_intel_lvds_destroy - unregister and free LVDS structures
435 * @connector: connector to free
436 *
437 * Unregister the DDC bus for this connector then free the driver private
438 * structure.
439 */
440void cdv_intel_lvds_destroy(struct drm_connector *connector)
441{
442 struct psb_intel_output *psb_intel_output =
443 to_psb_intel_output(connector);
444
445 if (psb_intel_output->ddc_bus)
446 psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
447 drm_sysfs_connector_remove(connector);
448 drm_connector_cleanup(connector);
449 kfree(connector);
450}
451
452int cdv_intel_lvds_set_property(struct drm_connector *connector,
453 struct drm_property *property,
454 uint64_t value)
455{
456 struct drm_encoder *encoder = connector->encoder;
457
458 if (!strcmp(property->name, "scaling mode") && encoder) {
459 struct psb_intel_crtc *crtc =
460 to_psb_intel_crtc(encoder->crtc);
461 uint64_t curValue;
462
463 if (!crtc)
464 return -1;
465
466 switch (value) {
467 case DRM_MODE_SCALE_FULLSCREEN:
468 break;
469 case DRM_MODE_SCALE_NO_SCALE:
470 break;
471 case DRM_MODE_SCALE_ASPECT:
472 break;
473 default:
474 return -1;
475 }
476
477 if (drm_connector_property_get_value(connector,
478 property,
479 &curValue))
480 return -1;
481
482 if (curValue == value)
483 return 0;
484
485 if (drm_connector_property_set_value(connector,
486 property,
487 value))
488 return -1;
489
490 if (crtc->saved_mode.hdisplay != 0 &&
491 crtc->saved_mode.vdisplay != 0) {
492 if (!drm_crtc_helper_set_mode(encoder->crtc,
493 &crtc->saved_mode,
494 encoder->crtc->x,
495 encoder->crtc->y,
496 encoder->crtc->fb))
497 return -1;
498 }
499 } else if (!strcmp(property->name, "backlight") && encoder) {
500 if (drm_connector_property_set_value(connector,
501 property,
502 value))
503 return -1;
504 else {
505#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
506 struct drm_psb_private *dev_priv =
507 encoder->dev->dev_private;
508 struct backlight_device *bd =
509 dev_priv->backlight_device;
510 bd->props.brightness = value;
511 backlight_update_status(bd);
512#endif
513 }
514 } else if (!strcmp(property->name, "DPMS") && encoder) {
515 struct drm_encoder_helper_funcs *helpers =
516 encoder->helper_private;
517 helpers->dpms(encoder, value);
518 }
519 return 0;
520}
521
522static const struct drm_encoder_helper_funcs
523 cdv_intel_lvds_helper_funcs = {
524 .dpms = cdv_intel_lvds_encoder_dpms,
525 .mode_fixup = cdv_intel_lvds_mode_fixup,
526 .prepare = cdv_intel_lvds_prepare,
527 .mode_set = cdv_intel_lvds_mode_set,
528 .commit = cdv_intel_lvds_commit,
529};
530
531static const struct drm_connector_helper_funcs
532 cdv_intel_lvds_connector_helper_funcs = {
533 .get_modes = cdv_intel_lvds_get_modes,
534 .mode_valid = cdv_intel_lvds_mode_valid,
535 .best_encoder = psb_intel_best_encoder,
536};
537
538static const struct drm_connector_funcs cdv_intel_lvds_connector_funcs = {
539 .dpms = drm_helper_connector_dpms,
540 .save = cdv_intel_lvds_save,
541 .restore = cdv_intel_lvds_restore,
542 .detect = cdv_intel_lvds_detect,
543 .fill_modes = drm_helper_probe_single_connector_modes,
544 .set_property = cdv_intel_lvds_set_property,
545 .destroy = cdv_intel_lvds_destroy,
546};
547
548
549static void cdv_intel_lvds_enc_destroy(struct drm_encoder *encoder)
550{
551 drm_encoder_cleanup(encoder);
552}
553
554const struct drm_encoder_funcs cdv_intel_lvds_enc_funcs = {
555 .destroy = cdv_intel_lvds_enc_destroy,
556};
557
558/**
559 * cdv_intel_lvds_init - setup LVDS connectors on this device
560 * @dev: drm device
561 *
562 * Create the connector, register the LVDS DDC bus, and try to figure out what
563 * modes we can display on the LVDS panel (if present).
564 */
565void cdv_intel_lvds_init(struct drm_device *dev,
566 struct psb_intel_mode_device *mode_dev)
567{
568 struct psb_intel_output *psb_intel_output;
569 struct cdv_intel_lvds_priv *lvds_priv;
570 struct drm_connector *connector;
571 struct drm_encoder *encoder;
572 struct drm_display_mode *scan;
573 struct drm_crtc *crtc;
574 struct drm_psb_private *dev_priv = dev->dev_private;
575 u32 lvds;
576 int pipe;
577
578 psb_intel_output = kzalloc(sizeof(struct psb_intel_output) +
579 sizeof(struct cdv_intel_lvds_priv), GFP_KERNEL);
580 if (!psb_intel_output)
581 return;
582
583 lvds_priv = (struct cdv_intel_lvds_priv *)(psb_intel_output + 1);
584
585 psb_intel_output->dev_priv = lvds_priv;
586
587 psb_intel_output->mode_dev = mode_dev;
588 connector = &psb_intel_output->base;
589 encoder = &psb_intel_output->enc;
590
591
592 drm_connector_init(dev, &psb_intel_output->base,
593 &cdv_intel_lvds_connector_funcs,
594 DRM_MODE_CONNECTOR_LVDS);
595
596 drm_encoder_init(dev, &psb_intel_output->enc,
597 &cdv_intel_lvds_enc_funcs,
598 DRM_MODE_ENCODER_LVDS);
599
600
601 drm_mode_connector_attach_encoder(&psb_intel_output->base,
602 &psb_intel_output->enc);
603 psb_intel_output->type = INTEL_OUTPUT_LVDS;
604
605 drm_encoder_helper_add(encoder, &cdv_intel_lvds_helper_funcs);
606 drm_connector_helper_add(connector,
607 &cdv_intel_lvds_connector_helper_funcs);
608 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
609 connector->interlace_allowed = false;
610 connector->doublescan_allowed = false;
611
612 /*Attach connector properties*/
613 drm_connector_attach_property(connector,
614 dev->mode_config.scaling_mode_property,
615 DRM_MODE_SCALE_FULLSCREEN);
616 drm_connector_attach_property(connector,
617 dev_priv->backlight_property,
618 BRIGHTNESS_MAX_LEVEL);
619
620 /**
621 * Set up I2C bus
622 * FIXME: distroy i2c_bus when exit
623 */
624 psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
625 GPIOB,
626 "LVDSBLC_B");
627 if (!psb_intel_output->i2c_bus) {
628 dev_printk(KERN_ERR,
629 &dev->pdev->dev, "I2C bus registration failed.\n");
630 goto failed_blc_i2c;
631 }
632 psb_intel_output->i2c_bus->slave_addr = 0x2C;
633 dev_priv->lvds_i2c_bus = psb_intel_output->i2c_bus;
634
635 /*
636 * LVDS discovery:
637 * 1) check for EDID on DDC
638 * 2) check for VBT data
639 * 3) check to see if LVDS is already on
640 * if none of the above, no panel
641 * 4) make sure lid is open
642 * if closed, act like it's not there for now
643 */
644
645 /* Set up the DDC bus. */
646 psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
647 GPIOC,
648 "LVDSDDC_C");
649 if (!psb_intel_output->ddc_bus) {
650 dev_printk(KERN_ERR, &dev->pdev->dev,
651 "DDC bus registration " "failed.\n");
652 goto failed_ddc;
653 }
654
655 /*
656 * Attempt to get the fixed panel mode from DDC. Assume that the
657 * preferred mode is the right one.
658 */
659 psb_intel_ddc_get_modes(psb_intel_output);
660 list_for_each_entry(scan, &connector->probed_modes, head) {
661 if (scan->type & DRM_MODE_TYPE_PREFERRED) {
662 mode_dev->panel_fixed_mode =
663 drm_mode_duplicate(dev, scan);
664 goto out; /* FIXME: check for quirks */
665 }
666 }
667
668 /* Failed to get EDID, what about VBT? do we need this?*/
669 if (dev_priv->lfp_lvds_vbt_mode) {
670 mode_dev->panel_fixed_mode =
671 drm_mode_duplicate(dev, dev_priv->lfp_lvds_vbt_mode);
672 if (mode_dev->panel_fixed_mode) {
673 mode_dev->panel_fixed_mode->type |=
674 DRM_MODE_TYPE_PREFERRED;
675 goto out; /* FIXME: check for quirks */
676 }
677 }
678 /*
679 * If we didn't get EDID, try checking if the panel is already turned
680 * on. If so, assume that whatever is currently programmed is the
681 * correct mode.
682 */
683 lvds = REG_READ(LVDS);
684 pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
685 crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
686
687 if (crtc && (lvds & LVDS_PORT_EN)) {
688 mode_dev->panel_fixed_mode =
689 cdv_intel_crtc_mode_get(dev, crtc);
690 if (mode_dev->panel_fixed_mode) {
691 mode_dev->panel_fixed_mode->type |=
692 DRM_MODE_TYPE_PREFERRED;
693 goto out; /* FIXME: check for quirks */
694 }
695 }
696
697 /* If we still don't have a mode after all that, give up. */
698 if (!mode_dev->panel_fixed_mode) {
699 DRM_DEBUG
700 ("Found no modes on the lvds, ignoring the LVDS\n");
701 goto failed_find;
702 }
703
704out:
705 drm_sysfs_connector_add(connector);
706 return;
707
708failed_find:
709 printk(KERN_ERR "Failed find\n");
710 if (psb_intel_output->ddc_bus)
711 psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
712failed_ddc:
713 printk(KERN_ERR "Failed DDC\n");
714 if (psb_intel_output->i2c_bus)
715 psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
716failed_blc_i2c:
717 printk(KERN_ERR "Failed BLC\n");
718 drm_encoder_cleanup(encoder);
719 drm_connector_cleanup(connector);
720 kfree(connector);
721}
diff --git a/drivers/staging/gma500/displays/hdmi.h b/drivers/staging/gma500/displays/hdmi.h
new file mode 100644
index 00000000000..d58ba9bd010
--- /dev/null
+++ b/drivers/staging/gma500/displays/hdmi.h
@@ -0,0 +1,33 @@
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
31extern 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
new file mode 100644
index 00000000000..84bae5c8c55
--- /dev/null
+++ b/drivers/staging/gma500/displays/pyr_cmd.h
@@ -0,0 +1,34 @@
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
31extern 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
new file mode 100644
index 00000000000..ce98860fa68
--- /dev/null
+++ b/drivers/staging/gma500/displays/pyr_vid.h
@@ -0,0 +1,34 @@
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
31extern void pyr_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
32extern 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
new file mode 100644
index 00000000000..641e85eedec
--- /dev/null
+++ b/drivers/staging/gma500/displays/tmd_cmd.h
@@ -0,0 +1,34 @@
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
31extern void tmd_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs);
32extern 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
new file mode 100644
index 00000000000..7a5fa3b935e
--- /dev/null
+++ b/drivers/staging/gma500/displays/tmd_vid.h
@@ -0,0 +1,34 @@
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
31extern void tmd_vid_init(struct drm_device *dev, struct panel_funcs *p_funcs);
32extern 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
new file mode 100644
index 00000000000..610552730d7
--- /dev/null
+++ b/drivers/staging/gma500/displays/tpo_cmd.h
@@ -0,0 +1,35 @@
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
31extern 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
new file mode 100644
index 00000000000..c24f05722de
--- /dev/null
+++ b/drivers/staging/gma500/displays/tpo_vid.h
@@ -0,0 +1,33 @@
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
31extern 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
new file mode 100644
index 00000000000..ebfde13ec18
--- /dev/null
+++ b/drivers/staging/gma500/framebuffer.c
@@ -0,0 +1,787 @@
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
36#include "psb_drv.h"
37#include "psb_intel_reg.h"
38#include "psb_intel_drv.h"
39#include "framebuffer.h"
40
41#include "mdfld_output.h"
42
43static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb);
44static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
45 struct drm_file *file_priv,
46 unsigned int *handle);
47
48static const struct drm_framebuffer_funcs psb_fb_funcs = {
49 .destroy = psb_user_framebuffer_destroy,
50 .create_handle = psb_user_framebuffer_create_handle,
51};
52
53#define CMAP_TOHW(_val, _width) ((((_val) << (_width)) + 0x7FFF - (_val)) >> 16)
54
55static int psbfb_setcolreg(unsigned regno, unsigned red, unsigned green,
56 unsigned blue, unsigned transp,
57 struct fb_info *info)
58{
59 struct psb_fbdev *fbdev = info->par;
60 struct drm_framebuffer *fb = fbdev->psb_fb_helper.fb;
61 uint32_t v;
62
63 if (!fb)
64 return -ENOMEM;
65
66 if (regno > 255)
67 return 1;
68
69 red = CMAP_TOHW(red, info->var.red.length);
70 blue = CMAP_TOHW(blue, info->var.blue.length);
71 green = CMAP_TOHW(green, info->var.green.length);
72 transp = CMAP_TOHW(transp, info->var.transp.length);
73
74 v = (red << info->var.red.offset) |
75 (green << info->var.green.offset) |
76 (blue << info->var.blue.offset) |
77 (transp << info->var.transp.offset);
78
79 if (regno < 16) {
80 switch (fb->bits_per_pixel) {
81 case 16:
82 ((uint32_t *) info->pseudo_palette)[regno] = v;
83 break;
84 case 24:
85 case 32:
86 ((uint32_t *) info->pseudo_palette)[regno] = v;
87 break;
88 }
89 }
90
91 return 0;
92}
93
94
95void psbfb_suspend(struct drm_device *dev)
96{
97 struct drm_framebuffer *fb = 0;
98 struct psb_framebuffer *psbfb = to_psb_fb(fb);
99
100 console_lock();
101 mutex_lock(&dev->mode_config.mutex);
102 list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
103 struct fb_info *info = psbfb->fbdev;
104 fb_set_suspend(info, 1);
105 drm_fb_helper_blank(FB_BLANK_POWERDOWN, info);
106 }
107 mutex_unlock(&dev->mode_config.mutex);
108 console_unlock();
109}
110
111void psbfb_resume(struct drm_device *dev)
112{
113 struct drm_framebuffer *fb = 0;
114 struct psb_framebuffer *psbfb = to_psb_fb(fb);
115
116 console_lock();
117 mutex_lock(&dev->mode_config.mutex);
118 list_for_each_entry(fb, &dev->mode_config.fb_list, head) {
119 struct fb_info *info = psbfb->fbdev;
120 fb_set_suspend(info, 0);
121 drm_fb_helper_blank(FB_BLANK_UNBLANK, info);
122 }
123 mutex_unlock(&dev->mode_config.mutex);
124 console_unlock();
125 drm_helper_disable_unused_functions(dev);
126}
127
128static int psbfb_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
129{
130 struct psb_framebuffer *psbfb = vma->vm_private_data;
131 struct drm_device *dev = psbfb->base.dev;
132 struct drm_psb_private *dev_priv = dev->dev_private;
133 int page_num;
134 int i;
135 unsigned long address;
136 int ret;
137 unsigned long pfn;
138 /* FIXME: assumes fb at stolen base which may not be true */
139 unsigned long phys_addr = (unsigned long)dev_priv->stolen_base;
140
141 page_num = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
142 address = (unsigned long)vmf->virtual_address;
143
144 vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
145
146 for (i = 0; i < page_num; i++) {
147 pfn = (phys_addr >> PAGE_SHIFT);
148
149 ret = vm_insert_mixed(vma, address, pfn);
150 if (unlikely((ret == -EBUSY) || (ret != 0 && i > 0)))
151 break;
152 else if (unlikely(ret != 0)) {
153 ret = (ret == -ENOMEM) ? VM_FAULT_OOM : VM_FAULT_SIGBUS;
154 return ret;
155 }
156 address += PAGE_SIZE;
157 phys_addr += PAGE_SIZE;
158 }
159 return VM_FAULT_NOPAGE;
160}
161
162static void psbfb_vm_open(struct vm_area_struct *vma)
163{
164}
165
166static void psbfb_vm_close(struct vm_area_struct *vma)
167{
168}
169
170static struct vm_operations_struct psbfb_vm_ops = {
171 .fault = psbfb_vm_fault,
172 .open = psbfb_vm_open,
173 .close = psbfb_vm_close
174};
175
176static int psbfb_mmap(struct fb_info *info, struct vm_area_struct *vma)
177{
178 struct psb_fbdev *fbdev = info->par;
179 struct psb_framebuffer *psbfb = &fbdev->pfb;
180
181 if (vma->vm_pgoff != 0)
182 return -EINVAL;
183 if (vma->vm_pgoff > (~0UL >> PAGE_SHIFT))
184 return -EINVAL;
185
186 if (!psbfb->addr_space)
187 psbfb->addr_space = vma->vm_file->f_mapping;
188 /*
189 * If this is a GEM object then info->screen_base is the virtual
190 * kernel remapping of the object. FIXME: Review if this is
191 * suitable for our mmap work
192 */
193 vma->vm_ops = &psbfb_vm_ops;
194 vma->vm_private_data = (void *)psbfb;
195 vma->vm_flags |= VM_RESERVED | VM_IO |
196 VM_MIXEDMAP | VM_DONTEXPAND;
197 return 0;
198}
199
200static int psbfb_ioctl(struct fb_info *info, unsigned int cmd,
201 unsigned long arg)
202{
203 return -ENOTTY;
204}
205
206static struct fb_ops psbfb_ops = {
207 .owner = THIS_MODULE,
208 .fb_check_var = drm_fb_helper_check_var,
209 .fb_set_par = drm_fb_helper_set_par,
210 .fb_blank = drm_fb_helper_blank,
211 .fb_setcolreg = psbfb_setcolreg,
212 .fb_fillrect = cfb_fillrect,
213 .fb_copyarea = psbfb_copyarea,
214 .fb_imageblit = cfb_imageblit,
215 .fb_mmap = psbfb_mmap,
216 .fb_sync = psbfb_sync,
217 .fb_ioctl = psbfb_ioctl,
218};
219
220static struct fb_ops psbfb_unaccel_ops = {
221 .owner = THIS_MODULE,
222 .fb_check_var = drm_fb_helper_check_var,
223 .fb_set_par = drm_fb_helper_set_par,
224 .fb_blank = drm_fb_helper_blank,
225 .fb_setcolreg = psbfb_setcolreg,
226 .fb_fillrect = cfb_fillrect,
227 .fb_copyarea = cfb_copyarea,
228 .fb_imageblit = cfb_imageblit,
229 .fb_mmap = psbfb_mmap,
230 .fb_ioctl = psbfb_ioctl,
231};
232
233/**
234 * psb_framebuffer_init - initialize a framebuffer
235 * @dev: our DRM device
236 * @fb: framebuffer to set up
237 * @mode_cmd: mode description
238 * @gt: backing object
239 *
240 * Configure and fill in the boilerplate for our frame buffer. Return
241 * 0 on success or an error code if we fail.
242 */
243static int psb_framebuffer_init(struct drm_device *dev,
244 struct psb_framebuffer *fb,
245 struct drm_mode_fb_cmd *mode_cmd,
246 struct gtt_range *gt)
247{
248 int ret;
249
250 if (mode_cmd->pitch & 63)
251 return -EINVAL;
252 switch (mode_cmd->bpp) {
253 case 8:
254 case 16:
255 case 24:
256 case 32:
257 break;
258 default:
259 return -EINVAL;
260 }
261 ret = drm_framebuffer_init(dev, &fb->base, &psb_fb_funcs);
262 if (ret) {
263 dev_err(dev->dev, "framebuffer init failed: %d\n", ret);
264 return ret;
265 }
266 drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
267 fb->gtt = gt;
268 return 0;
269}
270
271/**
272 * psb_framebuffer_create - create a framebuffer backed by gt
273 * @dev: our DRM device
274 * @mode_cmd: the description of the requested mode
275 * @gt: the backing object
276 *
277 * Create a framebuffer object backed by the gt, and fill in the
278 * boilerplate required
279 *
280 * TODO: review object references
281 */
282
283static struct drm_framebuffer *psb_framebuffer_create
284 (struct drm_device *dev,
285 struct drm_mode_fb_cmd *mode_cmd,
286 struct gtt_range *gt)
287{
288 struct psb_framebuffer *fb;
289 int ret;
290
291 fb = kzalloc(sizeof(*fb), GFP_KERNEL);
292 if (!fb)
293 return ERR_PTR(-ENOMEM);
294
295 ret = psb_framebuffer_init(dev, fb, mode_cmd, gt);
296 if (ret) {
297 kfree(fb);
298 return ERR_PTR(ret);
299 }
300 return &fb->base;
301}
302
303/**
304 * psbfb_alloc - allocate frame buffer memory
305 * @dev: the DRM device
306 * @aligned_size: space needed
307 *
308 * Allocate the frame buffer. In the usual case we get a GTT range that
309 * is stolen memory backed and life is simple. If there isn't sufficient
310 * stolen memory or the system has no stolen memory we allocate a range
311 * and back it with a GEM object.
312 *
313 * In this case the GEM object has no handle.
314 *
315 * FIXME: console speed up - allocate twice the space if room and use
316 * hardware scrolling for acceleration.
317 */
318static struct gtt_range *psbfb_alloc(struct drm_device *dev, int aligned_size)
319{
320 struct gtt_range *backing;
321 /* Begin by trying to use stolen memory backing */
322 backing = psb_gtt_alloc_range(dev, aligned_size, "fb", 1);
323 if (backing) {
324 if (drm_gem_private_object_init(dev,
325 &backing->gem, aligned_size) == 0)
326 return backing;
327 psb_gtt_free_range(dev, backing);
328 }
329 /* Next try using GEM host memory */
330 backing = psb_gtt_alloc_range(dev, aligned_size, "fb(gem)", 0);
331 if (backing == NULL)
332 return NULL;
333
334 /* Now back it with an object */
335 if (drm_gem_object_init(dev, &backing->gem, aligned_size) != 0) {
336 psb_gtt_free_range(dev, backing);
337 return NULL;
338 }
339 return backing;
340}
341
342/**
343 * psbfb_create - create a framebuffer
344 * @fbdev: the framebuffer device
345 * @sizes: specification of the layout
346 *
347 * Create a framebuffer to the specifications provided
348 */
349static int psbfb_create(struct psb_fbdev *fbdev,
350 struct drm_fb_helper_surface_size *sizes)
351{
352 struct drm_device *dev = fbdev->psb_fb_helper.dev;
353 struct drm_psb_private *dev_priv = dev->dev_private;
354 struct fb_info *info;
355 struct drm_framebuffer *fb;
356 struct psb_framebuffer *psbfb = &fbdev->pfb;
357 struct drm_mode_fb_cmd mode_cmd;
358 struct device *device = &dev->pdev->dev;
359 int size;
360 int ret;
361 struct gtt_range *backing;
362
363 mode_cmd.width = sizes->surface_width;
364 mode_cmd.height = sizes->surface_height;
365 mode_cmd.bpp = sizes->surface_bpp;
366
367 /* No 24bit packed */
368 if (mode_cmd.bpp == 24)
369 mode_cmd.bpp = 32;
370
371 /* HW requires pitch to be 64 byte aligned */
372 mode_cmd.pitch = ALIGN(mode_cmd.width * ((mode_cmd.bpp + 7) / 8), 64);
373 mode_cmd.depth = sizes->surface_depth;
374
375 size = mode_cmd.pitch * mode_cmd.height;
376 size = ALIGN(size, PAGE_SIZE);
377
378 /* Allocate the framebuffer in the GTT with stolen page backing */
379 backing = psbfb_alloc(dev, size);
380 if (backing == NULL)
381 return -ENOMEM;
382
383 mutex_lock(&dev->struct_mutex);
384
385 info = framebuffer_alloc(0, device);
386 if (!info) {
387 ret = -ENOMEM;
388 goto out_err1;
389 }
390 info->par = fbdev;
391
392 ret = psb_framebuffer_init(dev, psbfb, &mode_cmd, backing);
393 if (ret)
394 goto out_unref;
395
396 fb = &psbfb->base;
397 psbfb->fbdev = info;
398
399 fbdev->psb_fb_helper.fb = fb;
400 fbdev->psb_fb_helper.fbdev = info;
401
402 strcpy(info->fix.id, "psbfb");
403
404 info->flags = FBINFO_DEFAULT;
405 /* No 2D engine */
406 if (!dev_priv->ops->accel_2d)
407 info->fbops = &psbfb_unaccel_ops;
408 else
409 info->fbops = &psbfb_ops;
410
411 ret = fb_alloc_cmap(&info->cmap, 256, 0);
412 if (ret) {
413 ret = -ENOMEM;
414 goto out_unref;
415 }
416
417 info->fix.smem_start = dev->mode_config.fb_base;
418 info->fix.smem_len = size;
419
420 if (backing->stolen) {
421 /* Accessed stolen memory directly */
422 info->screen_base = (char *)dev_priv->vram_addr +
423 backing->offset;
424 } else {
425 /* Pin the pages into the GTT and create a mapping to them */
426 psb_gtt_pin(backing);
427 info->screen_base = vm_map_ram(backing->pages, backing->npage,
428 -1, PAGE_KERNEL);
429 if (info->screen_base == NULL) {
430 psb_gtt_unpin(backing);
431 ret = -ENOMEM;
432 goto out_unref;
433 }
434 psbfb->vm_map = 1;
435 }
436 info->screen_size = size;
437
438 if (dev_priv->gtt.stolen_size) {
439 info->apertures = alloc_apertures(1);
440 if (!info->apertures) {
441 ret = -ENOMEM;
442 goto out_unref;
443 }
444 info->apertures->ranges[0].base = dev->mode_config.fb_base;
445 info->apertures->ranges[0].size = dev_priv->gtt.stolen_size;
446 }
447
448 drm_fb_helper_fill_fix(info, fb->pitch, fb->depth);
449 drm_fb_helper_fill_var(info, &fbdev->psb_fb_helper,
450 sizes->fb_width, sizes->fb_height);
451
452 info->fix.mmio_start = pci_resource_start(dev->pdev, 0);
453 info->fix.mmio_len = pci_resource_len(dev->pdev, 0);
454
455 info->pixmap.size = 64 * 1024;
456 info->pixmap.buf_align = 8;
457 info->pixmap.access_align = 32;
458 info->pixmap.flags = FB_PIXMAP_SYSTEM;
459 info->pixmap.scan_align = 1;
460
461 dev_info(dev->dev, "allocated %dx%d fb\n",
462 psbfb->base.width, psbfb->base.height);
463
464 mutex_unlock(&dev->struct_mutex);
465 return 0;
466out_unref:
467 if (backing->stolen)
468 psb_gtt_free_range(dev, backing);
469 else {
470 if (psbfb->vm_map)
471 vm_unmap_ram(info->screen_base, backing->npage);
472 drm_gem_object_unreference(&backing->gem);
473 }
474out_err1:
475 mutex_unlock(&dev->struct_mutex);
476 psb_gtt_free_range(dev, backing);
477 return ret;
478}
479
480/**
481 * psb_user_framebuffer_create - create framebuffer
482 * @dev: our DRM device
483 * @filp: client file
484 * @cmd: mode request
485 *
486 * Create a new framebuffer backed by a userspace GEM object
487 */
488static struct drm_framebuffer *psb_user_framebuffer_create
489 (struct drm_device *dev, struct drm_file *filp,
490 struct drm_mode_fb_cmd *cmd)
491{
492 struct gtt_range *r;
493 struct drm_gem_object *obj;
494
495 /*
496 * Find the GEM object and thus the gtt range object that is
497 * to back this space
498 */
499 obj = drm_gem_object_lookup(dev, filp, cmd->handle);
500 if (obj == NULL)
501 return ERR_PTR(-ENOENT);
502
503 /* Let the core code do all the work */
504 r = container_of(obj, struct gtt_range, gem);
505 return psb_framebuffer_create(dev, cmd, r);
506}
507
508static void psbfb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
509 u16 blue, int regno)
510{
511}
512
513static void psbfb_gamma_get(struct drm_crtc *crtc, u16 *red,
514 u16 *green, u16 *blue, int regno)
515{
516}
517
518static int psbfb_probe(struct drm_fb_helper *helper,
519 struct drm_fb_helper_surface_size *sizes)
520{
521 struct psb_fbdev *psb_fbdev = (struct psb_fbdev *)helper;
522 int new_fb = 0;
523 int ret;
524
525 if (!helper->fb) {
526 ret = psbfb_create(psb_fbdev, sizes);
527 if (ret)
528 return ret;
529 new_fb = 1;
530 }
531 return new_fb;
532}
533
534struct drm_fb_helper_funcs psb_fb_helper_funcs = {
535 .gamma_set = psbfb_gamma_set,
536 .gamma_get = psbfb_gamma_get,
537 .fb_probe = psbfb_probe,
538};
539
540int psb_fbdev_destroy(struct drm_device *dev, struct psb_fbdev *fbdev)
541{
542 struct fb_info *info;
543 struct psb_framebuffer *psbfb = &fbdev->pfb;
544
545 if (fbdev->psb_fb_helper.fbdev) {
546 info = fbdev->psb_fb_helper.fbdev;
547
548 /* If this is our base framebuffer then kill any virtual map
549 for the framebuffer layer and unpin it */
550 if (psbfb->vm_map) {
551 vm_unmap_ram(info->screen_base, psbfb->gtt->npage);
552 psb_gtt_unpin(psbfb->gtt);
553 }
554 unregister_framebuffer(info);
555 if (info->cmap.len)
556 fb_dealloc_cmap(&info->cmap);
557 framebuffer_release(info);
558 }
559 drm_fb_helper_fini(&fbdev->psb_fb_helper);
560 drm_framebuffer_cleanup(&psbfb->base);
561
562 if (psbfb->gtt)
563 drm_gem_object_unreference(&psbfb->gtt->gem);
564 return 0;
565}
566
567int psb_fbdev_init(struct drm_device *dev)
568{
569 struct psb_fbdev *fbdev;
570 struct drm_psb_private *dev_priv = dev->dev_private;
571
572 fbdev = kzalloc(sizeof(struct psb_fbdev), GFP_KERNEL);
573 if (!fbdev) {
574 dev_err(dev->dev, "no memory\n");
575 return -ENOMEM;
576 }
577
578 dev_priv->fbdev = fbdev;
579 fbdev->psb_fb_helper.funcs = &psb_fb_helper_funcs;
580
581 drm_fb_helper_init(dev, &fbdev->psb_fb_helper, dev_priv->ops->crtcs,
582 INTELFB_CONN_LIMIT);
583
584 drm_fb_helper_single_add_all_connectors(&fbdev->psb_fb_helper);
585 drm_fb_helper_initial_config(&fbdev->psb_fb_helper, 32);
586 return 0;
587}
588
589void psb_fbdev_fini(struct drm_device *dev)
590{
591 struct drm_psb_private *dev_priv = dev->dev_private;
592
593 if (!dev_priv->fbdev)
594 return;
595
596 psb_fbdev_destroy(dev, dev_priv->fbdev);
597 kfree(dev_priv->fbdev);
598 dev_priv->fbdev = NULL;
599}
600
601static void psbfb_output_poll_changed(struct drm_device *dev)
602{
603 struct drm_psb_private *dev_priv = dev->dev_private;
604 struct psb_fbdev *fbdev = (struct psb_fbdev *)dev_priv->fbdev;
605 drm_fb_helper_hotplug_event(&fbdev->psb_fb_helper);
606}
607
608/**
609 * psb_user_framebuffer_create_handle - add hamdle to a framebuffer
610 * @fb: framebuffer
611 * @file_priv: our DRM file
612 * @handle: returned handle
613 *
614 * Our framebuffer object is a GTT range which also contains a GEM
615 * object. We need to turn it into a handle for userspace. GEM will do
616 * the work for us
617 */
618static int psb_user_framebuffer_create_handle(struct drm_framebuffer *fb,
619 struct drm_file *file_priv,
620 unsigned int *handle)
621{
622 struct psb_framebuffer *psbfb = to_psb_fb(fb);
623 struct gtt_range *r = psbfb->gtt;
624 return drm_gem_handle_create(file_priv, &r->gem, handle);
625}
626
627/**
628 * psb_user_framebuffer_destroy - destruct user created fb
629 * @fb: framebuffer
630 *
631 * User framebuffers are backed by GEM objects so all we have to do is
632 * clean up a bit and drop the reference, GEM will handle the fallout
633 */
634static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
635{
636 struct psb_framebuffer *psbfb = to_psb_fb(fb);
637 struct gtt_range *r = psbfb->gtt;
638 struct drm_device *dev = fb->dev;
639 struct drm_psb_private *dev_priv = dev->dev_private;
640 struct psb_fbdev *fbdev = dev_priv->fbdev;
641 struct drm_crtc *crtc;
642 int reset = 0;
643
644 /* Should never get stolen memory for a user fb */
645 WARN_ON(r->stolen);
646
647 /* Check if we are erroneously live */
648 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
649 if (crtc->fb == fb)
650 reset = 1;
651
652 if (reset)
653 /*
654 * Now force a sane response before we permit the DRM CRTC
655 * layer to do stupid things like blank the display. Instead
656 * we reset this framebuffer as if the user had forced a reset.
657 * We must do this before the cleanup so that the DRM layer
658 * doesn't get a chance to stick its oar in where it isn't
659 * wanted.
660 */
661 drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
662
663 /* Let DRM do its clean up */
664 drm_framebuffer_cleanup(fb);
665 /* We are no longer using the resource in GEM */
666 drm_gem_object_unreference_unlocked(&r->gem);
667 kfree(fb);
668}
669
670static const struct drm_mode_config_funcs psb_mode_funcs = {
671 .fb_create = psb_user_framebuffer_create,
672 .output_poll_changed = psbfb_output_poll_changed,
673};
674
675static int psb_create_backlight_property(struct drm_device *dev)
676{
677 struct drm_psb_private *dev_priv = dev->dev_private;
678 struct drm_property *backlight;
679
680 if (dev_priv->backlight_property)
681 return 0;
682
683 backlight = drm_property_create(dev, DRM_MODE_PROP_RANGE,
684 "backlight", 2);
685 backlight->values[0] = 0;
686 backlight->values[1] = 100;
687
688 dev_priv->backlight_property = backlight;
689
690 return 0;
691}
692
693static void psb_setup_outputs(struct drm_device *dev)
694{
695 struct drm_psb_private *dev_priv = dev->dev_private;
696 struct drm_connector *connector;
697
698 drm_mode_create_scaling_mode_property(dev);
699 psb_create_backlight_property(dev);
700
701 dev_priv->ops->output_init(dev);
702
703 list_for_each_entry(connector, &dev->mode_config.connector_list,
704 head) {
705 struct psb_intel_output *psb_intel_output =
706 to_psb_intel_output(connector);
707 struct drm_encoder *encoder = &psb_intel_output->enc;
708 int crtc_mask = 0, clone_mask = 0;
709
710 /* valid crtcs */
711 switch (psb_intel_output->type) {
712 case INTEL_OUTPUT_ANALOG:
713 crtc_mask = (1 << 0);
714 clone_mask = (1 << INTEL_OUTPUT_ANALOG);
715 break;
716 case INTEL_OUTPUT_SDVO:
717 crtc_mask = ((1 << 0) | (1 << 1));
718 clone_mask = (1 << INTEL_OUTPUT_SDVO);
719 break;
720 case INTEL_OUTPUT_LVDS:
721 if (IS_MRST(dev))
722 crtc_mask = (1 << 0);
723 else
724 crtc_mask = (1 << 1);
725 clone_mask = (1 << INTEL_OUTPUT_LVDS);
726 break;
727 case INTEL_OUTPUT_MIPI:
728 crtc_mask = (1 << 0);
729 clone_mask = (1 << INTEL_OUTPUT_MIPI);
730 break;
731 case INTEL_OUTPUT_MIPI2:
732 crtc_mask = (1 << 2);
733 clone_mask = (1 << INTEL_OUTPUT_MIPI2);
734 break;
735 case INTEL_OUTPUT_HDMI:
736 if (IS_MFLD(dev))
737 crtc_mask = (1 << 1);
738 else /* FIXME: review Oaktrail */
739 crtc_mask = (1 << 0); /* Cedarview */
740 clone_mask = (1 << INTEL_OUTPUT_HDMI);
741 break;
742 }
743 encoder->possible_crtcs = crtc_mask;
744 encoder->possible_clones =
745 psb_intel_connector_clones(dev, clone_mask);
746 }
747}
748
749void psb_modeset_init(struct drm_device *dev)
750{
751 struct drm_psb_private *dev_priv =
752 (struct drm_psb_private *) dev->dev_private;
753 struct psb_intel_mode_device *mode_dev = &dev_priv->mode_dev;
754 int i;
755
756 drm_mode_config_init(dev);
757
758 dev->mode_config.min_width = 0;
759 dev->mode_config.min_height = 0;
760
761 dev->mode_config.funcs = (void *) &psb_mode_funcs;
762
763 /* set memory base */
764 /* MRST and PSB should use BAR 2*/
765 pci_read_config_dword(dev->pdev, PSB_BSM, (u32 *)
766 &(dev->mode_config.fb_base));
767
768 /* num pipes is 2 for PSB but 1 for Mrst */
769 for (i = 0; i < dev_priv->num_pipe; i++)
770 psb_intel_crtc_init(dev, i, mode_dev);
771
772 dev->mode_config.max_width = 2048;
773 dev->mode_config.max_height = 2048;
774
775 psb_setup_outputs(dev);
776}
777
778void psb_modeset_cleanup(struct drm_device *dev)
779{
780 mutex_lock(&dev->struct_mutex);
781
782 drm_kms_helper_poll_fini(dev);
783 psb_fbdev_fini(dev);
784 drm_mode_config_cleanup(dev);
785
786 mutex_unlock(&dev->struct_mutex);
787}
diff --git a/drivers/staging/gma500/framebuffer.h b/drivers/staging/gma500/framebuffer.h
new file mode 100644
index 00000000000..d1b2289447f
--- /dev/null
+++ b/drivers/staging/gma500/framebuffer.h
@@ -0,0 +1,48 @@
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
30struct 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
38struct 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
45extern 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
new file mode 100644
index 00000000000..65fdd6b8ab1
--- /dev/null
+++ b/drivers/staging/gma500/gem.c
@@ -0,0 +1,295 @@
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
31int psb_gem_init_object(struct drm_gem_object *obj)
32{
33 return -EINVAL;
34}
35
36void 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
44int 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 */
59int 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;
86out:
87 drm_gem_object_unreference(obj);
88unlock:
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 */
104static 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 and we don't have an
124 EGEMSUCKS so make something up for now - FIXME */
125 dev_err(dev->dev, "GEM init failed for %lld\n", size);
126 return -ENOMEM;
127 }
128 /* Give the object a handle so we can carry it more easily */
129 ret = drm_gem_handle_create(file, &r->gem, &handle);
130 if (ret) {
131 dev_err(dev->dev, "GEM handle failed for %p, %lld\n",
132 &r->gem, size);
133 drm_gem_object_release(&r->gem);
134 psb_gtt_free_range(dev, r);
135 return ret;
136 }
137 /* We have the initial and handle reference but need only one now */
138 drm_gem_object_unreference(&r->gem);
139 *handlep = handle;
140 return 0;
141}
142
143/**
144 * psb_gem_dumb_create - create a dumb buffer
145 * @drm_file: our client file
146 * @dev: our device
147 * @args: the requested arguments copied from userspace
148 *
149 * Allocate a buffer suitable for use for a frame buffer of the
150 * form described by user space. Give userspace a handle by which
151 * to reference it.
152 */
153int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
154 struct drm_mode_create_dumb *args)
155{
156 args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
157 args->size = args->pitch * args->height;
158 return psb_gem_create(file, dev, args->size, &args->handle);
159}
160
161/**
162 * psb_gem_dumb_destroy - destroy a dumb buffer
163 * @file: client file
164 * @dev: our DRM device
165 * @handle: the object handle
166 *
167 * Destroy a handle that was created via psb_gem_dumb_create, at least
168 * we hope it was created that way. i915 seems to assume the caller
169 * does the checking but that might be worth review ! FIXME
170 */
171int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
172 uint32_t handle)
173{
174 /* No special work needed, drop the reference and see what falls out */
175 return drm_gem_handle_delete(file, handle);
176}
177
178/**
179 * psb_gem_fault - pagefault handler for GEM objects
180 * @vma: the VMA of the GEM object
181 * @vmf: fault detail
182 *
183 * Invoked when a fault occurs on an mmap of a GEM managed area. GEM
184 * does most of the work for us including the actual map/unmap calls
185 * but we need to do the actual page work.
186 *
187 * This code eventually needs to handle faulting objects in and out
188 * of the GTT and repacking it when we run out of space. We can put
189 * that off for now and for our simple uses
190 *
191 * The VMA was set up by GEM. In doing so it also ensured that the
192 * vma->vm_private_data points to the GEM object that is backing this
193 * mapping.
194 *
195 * FIXME
196 */
197int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
198{
199 struct drm_gem_object *obj;
200 struct gtt_range *r;
201 int ret;
202 unsigned long pfn;
203 pgoff_t page_offset;
204 struct drm_device *dev;
205 struct drm_psb_private *dev_priv;
206
207 obj = vma->vm_private_data; /* GEM object */
208 dev = obj->dev;
209 dev_priv = dev->dev_private;
210
211 r = container_of(obj, struct gtt_range, gem); /* Get the gtt range */
212
213 /* Make sure we don't parallel update on a fault, nor move or remove
214 something from beneath our feet */
215 mutex_lock(&dev->struct_mutex);
216
217 /* For now the mmap pins the object and it stays pinned. As things
218 stand that will do us no harm */
219 if (r->mmapping == 0) {
220 ret = psb_gtt_pin(r);
221 if (ret < 0) {
222 dev_err(dev->dev, "gma500: pin failed: %d\n", ret);
223 goto fail;
224 }
225 r->mmapping = 1;
226 }
227
228 /* Page relative to the VMA start - we must calculate this ourselves
229 because vmf->pgoff is the fake GEM offset */
230 page_offset = ((unsigned long) vmf->virtual_address - vma->vm_start)
231 >> PAGE_SHIFT;
232
233 /* CPU view of the page, don't go via the GART for CPU writes */
234 if (r->stolen)
235 pfn = (dev_priv->stolen_base + r->offset) >> PAGE_SHIFT;
236 else
237 pfn = page_to_pfn(r->pages[page_offset]);
238 ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
239
240fail:
241 mutex_unlock(&dev->struct_mutex);
242 switch (ret) {
243 case 0:
244 case -ERESTARTSYS:
245 case -EINTR:
246 return VM_FAULT_NOPAGE;
247 case -ENOMEM:
248 return VM_FAULT_OOM;
249 default:
250 return VM_FAULT_SIGBUS;
251 }
252}
253
254static int psb_gem_create_stolen(struct drm_file *file, struct drm_device *dev,
255 int size, u32 *handle)
256{
257 struct gtt_range *gtt = psb_gtt_alloc_range(dev, size, "gem", 1);
258 if (gtt == NULL)
259 return -ENOMEM;
260 if (drm_gem_private_object_init(dev, &gtt->gem, size) != 0)
261 goto free_gtt;
262 if (drm_gem_handle_create(file, &gtt->gem, handle) == 0)
263 return 0;
264free_gtt:
265 psb_gtt_free_range(dev, gtt);
266 return -ENOMEM;
267}
268
269/*
270 * GEM interfaces for our specific client
271 */
272int psb_gem_create_ioctl(struct drm_device *dev, void *data,
273 struct drm_file *file)
274{
275 struct drm_psb_gem_create *args = data;
276 int ret;
277 if (args->flags & PSB_GEM_CREATE_STOLEN) {
278 ret = psb_gem_create_stolen(file, dev, args->size,
279 &args->handle);
280 if (ret == 0)
281 return 0;
282 /* Fall throguh */
283 args->flags &= ~PSB_GEM_CREATE_STOLEN;
284 }
285 return psb_gem_create(file, dev, args->size, &args->handle);
286}
287
288int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
289 struct drm_file *file)
290{
291 struct drm_psb_gem_mmap *args = data;
292 return dev->driver->dumb_map_offset(file, dev,
293 args->handle, &args->offset);
294}
295
diff --git a/drivers/staging/gma500/gem_glue.c b/drivers/staging/gma500/gem_glue.c
new file mode 100644
index 00000000000..daac1212065
--- /dev/null
+++ b/drivers/staging/gma500/gem_glue.c
@@ -0,0 +1,89 @@
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
23void 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 */
44int 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
83free_mm:
84 drm_mm_put_block(list->file_offset_node);
85free_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
new file mode 100644
index 00000000000..ce5ce30f74d
--- /dev/null
+++ b/drivers/staging/gma500/gem_glue.h
@@ -0,0 +1,2 @@
1extern void drm_gem_object_release_wrap(struct drm_gem_object *obj);
2extern int gem_create_mmap_offset(struct drm_gem_object *obj);
diff --git a/drivers/staging/gma500/gtt.c b/drivers/staging/gma500/gtt.c
new file mode 100644
index 00000000000..461ead251bb
--- /dev/null
+++ b/drivers/staging/gma500/gtt.c
@@ -0,0 +1,500 @@
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 */
37static 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 */
59u32 *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.
76 *
77 * FIXME: gtt lock ?
78 */
79static int psb_gtt_insert(struct drm_device *dev, struct gtt_range *r)
80{
81 u32 *gtt_slot, pte;
82 struct page **pages;
83 int i;
84
85 if (r->pages == NULL) {
86 WARN_ON(1);
87 return -EINVAL;
88 }
89
90 WARN_ON(r->stolen); /* refcount these maybe ? */
91
92 gtt_slot = psb_gtt_entry(dev, r);
93 pages = r->pages;
94
95 /* Make sure changes are visible to the GPU */
96 set_pages_array_uc(pages, r->npage);
97
98 /* Write our page entries into the GTT itself */
99 for (i = 0; i < r->npage; i++) {
100 pte = psb_gtt_mask_pte(page_to_pfn(*pages++), 0/*type*/);
101 iowrite32(pte, gtt_slot++);
102 }
103 /* Make sure all the entries are set before we return */
104 ioread32(gtt_slot - 1);
105 return 0;
106}
107
108/**
109 * psb_gtt_remove - remove an object from the GTT
110 * @dev: our DRM device
111 * @r: our GTT range
112 *
113 * Remove a preallocated GTT range from the GTT. Overwrite all the
114 * page table entries with the dummy page
115 */
116
117static void psb_gtt_remove(struct drm_device *dev, struct gtt_range *r)
118{
119 struct drm_psb_private *dev_priv = dev->dev_private;
120 u32 *gtt_slot, pte;
121 int i;
122
123 WARN_ON(r->stolen);
124
125 gtt_slot = psb_gtt_entry(dev, r);
126 pte = psb_gtt_mask_pte(page_to_pfn(dev_priv->scratch_page), 0);
127
128 for (i = 0; i < r->npage; i++)
129 iowrite32(pte, gtt_slot++);
130 ioread32(gtt_slot - 1);
131 set_pages_array_wb(r->pages, r->npage);
132}
133
134/**
135 * psb_gtt_attach_pages - attach and pin GEM pages
136 * @gt: the gtt range
137 *
138 * Pin and build an in kernel list of the pages that back our GEM object.
139 * While we hold this the pages cannot be swapped out
140 */
141static int psb_gtt_attach_pages(struct gtt_range *gt)
142{
143 struct inode *inode;
144 struct address_space *mapping;
145 int i;
146 struct page *p;
147 int pages = gt->gem.size / PAGE_SIZE;
148
149 WARN_ON(gt->pages);
150
151 /* This is the shared memory object that backs the GEM resource */
152 inode = gt->gem.filp->f_path.dentry->d_inode;
153 mapping = inode->i_mapping;
154
155 gt->pages = kmalloc(pages * sizeof(struct page *), GFP_KERNEL);
156 if (gt->pages == NULL)
157 return -ENOMEM;
158 gt->npage = pages;
159
160 for (i = 0; i < pages; i++) {
161 /* FIXME: review flags later */
162 p = read_cache_page_gfp(mapping, i,
163 __GFP_COLD | GFP_KERNEL);
164 if (IS_ERR(p))
165 goto err;
166 gt->pages[i] = p;
167 }
168 return 0;
169
170err:
171 while (i--)
172 page_cache_release(gt->pages[i]);
173 kfree(gt->pages);
174 gt->pages = NULL;
175 return PTR_ERR(p);
176}
177
178/**
179 * psb_gtt_detach_pages - attach and pin GEM pages
180 * @gt: the gtt range
181 *
182 * Undo the effect of psb_gtt_attach_pages. At this point the pages
183 * must have been removed from the GTT as they could now be paged out
184 * and move bus address.
185 */
186static void psb_gtt_detach_pages(struct gtt_range *gt)
187{
188 int i;
189 for (i = 0; i < gt->npage; i++) {
190 /* FIXME: do we need to force dirty */
191 set_page_dirty(gt->pages[i]);
192 page_cache_release(gt->pages[i]);
193 }
194 kfree(gt->pages);
195 gt->pages = NULL;
196}
197
198/**
199 * psb_gtt_pin - pin pages into the GTT
200 * @gt: range to pin
201 *
202 * Pin a set of pages into the GTT. The pins are refcounted so that
203 * multiple pins need multiple unpins to undo.
204 *
205 * Non GEM backed objects treat this as a no-op as they are always GTT
206 * backed objects.
207 */
208int psb_gtt_pin(struct gtt_range *gt)
209{
210 int ret = 0;
211 struct drm_device *dev = gt->gem.dev;
212 struct drm_psb_private *dev_priv = dev->dev_private;
213
214 mutex_lock(&dev_priv->gtt_mutex);
215
216 if (gt->in_gart == 0 && gt->stolen == 0) {
217 ret = psb_gtt_attach_pages(gt);
218 if (ret < 0)
219 goto out;
220 ret = psb_gtt_insert(dev, gt);
221 if (ret < 0) {
222 psb_gtt_detach_pages(gt);
223 goto out;
224 }
225 }
226 gt->in_gart++;
227out:
228 mutex_unlock(&dev_priv->gtt_mutex);
229 return ret;
230}
231
232/**
233 * psb_gtt_unpin - Drop a GTT pin requirement
234 * @gt: range to pin
235 *
236 * Undoes the effect of psb_gtt_pin. On the last drop the GEM object
237 * will be removed from the GTT which will also drop the page references
238 * and allow the VM to clean up or page stuff.
239 *
240 * Non GEM backed objects treat this as a no-op as they are always GTT
241 * backed objects.
242 */
243void psb_gtt_unpin(struct gtt_range *gt)
244{
245 struct drm_device *dev = gt->gem.dev;
246 struct drm_psb_private *dev_priv = dev->dev_private;
247
248 mutex_lock(&dev_priv->gtt_mutex);
249
250 WARN_ON(!gt->in_gart);
251
252 gt->in_gart--;
253 if (gt->in_gart == 0 && gt->stolen == 0) {
254 psb_gtt_remove(dev, gt);
255 psb_gtt_detach_pages(gt);
256 }
257 mutex_unlock(&dev_priv->gtt_mutex);
258}
259
260/*
261 * GTT resource allocator - allocate and manage GTT address space
262 */
263
264/**
265 * psb_gtt_alloc_range - allocate GTT address space
266 * @dev: Our DRM device
267 * @len: length (bytes) of address space required
268 * @name: resource name
269 * @backed: resource should be backed by stolen pages
270 *
271 * Ask the kernel core to find us a suitable range of addresses
272 * to use for a GTT mapping.
273 *
274 * Returns a gtt_range structure describing the object, or NULL on
275 * error. On successful return the resource is both allocated and marked
276 * as in use.
277 */
278struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
279 const char *name, int backed)
280{
281 struct drm_psb_private *dev_priv = dev->dev_private;
282 struct gtt_range *gt;
283 struct resource *r = dev_priv->gtt_mem;
284 int ret;
285 unsigned long start, end;
286
287 if (backed) {
288 /* The start of the GTT is the stolen pages */
289 start = r->start;
290 end = r->start + dev_priv->gtt.stolen_size - 1;
291 } else {
292 /* The rest we will use for GEM backed objects */
293 start = r->start + dev_priv->gtt.stolen_size;
294 end = r->end;
295 }
296
297 gt = kzalloc(sizeof(struct gtt_range), GFP_KERNEL);
298 if (gt == NULL)
299 return NULL;
300 gt->resource.name = name;
301 gt->stolen = backed;
302 gt->in_gart = backed;
303 /* Ensure this is set for non GEM objects */
304 gt->gem.dev = dev;
305 ret = allocate_resource(dev_priv->gtt_mem, &gt->resource,
306 len, start, end, PAGE_SIZE, NULL, NULL);
307 if (ret == 0) {
308 gt->offset = gt->resource.start - r->start;
309 return gt;
310 }
311 kfree(gt);
312 return NULL;
313}
314
315/**
316 * psb_gtt_free_range - release GTT address space
317 * @dev: our DRM device
318 * @gt: a mapping created with psb_gtt_alloc_range
319 *
320 * Release a resource that was allocated with psb_gtt_alloc_range. If the
321 * object has been pinned by mmap users we clean this up here currently.
322 */
323void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt)
324{
325 /* Undo the mmap pin if we are destroying the object */
326 if (gt->mmapping) {
327 psb_gtt_unpin(gt);
328 gt->mmapping = 0;
329 }
330 WARN_ON(gt->in_gart && !gt->stolen);
331 release_resource(&gt->resource);
332 kfree(gt);
333}
334
335void psb_gtt_alloc(struct drm_device *dev)
336{
337 struct drm_psb_private *dev_priv = dev->dev_private;
338 init_rwsem(&dev_priv->gtt.sem);
339}
340
341void psb_gtt_takedown(struct drm_device *dev)
342{
343 struct drm_psb_private *dev_priv = dev->dev_private;
344
345 if (dev_priv->gtt_map) {
346 iounmap(dev_priv->gtt_map);
347 dev_priv->gtt_map = NULL;
348 }
349 if (dev_priv->gtt_initialized) {
350 pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
351 dev_priv->gmch_ctrl);
352 PSB_WVDC32(dev_priv->pge_ctl, PSB_PGETBL_CTL);
353 (void) PSB_RVDC32(PSB_PGETBL_CTL);
354 }
355 if (dev_priv->vram_addr)
356 iounmap(dev_priv->gtt_map);
357}
358
359int psb_gtt_init(struct drm_device *dev, int resume)
360{
361 struct drm_psb_private *dev_priv = dev->dev_private;
362 unsigned gtt_pages;
363 unsigned long stolen_size, vram_stolen_size;
364 unsigned i, num_pages;
365 unsigned pfn_base;
366 uint32_t vram_pages;
367 uint32_t dvmt_mode = 0;
368 struct psb_gtt *pg;
369
370 int ret = 0;
371 uint32_t pte;
372
373 mutex_init(&dev_priv->gtt_mutex);
374
375 psb_gtt_alloc(dev);
376 pg = &dev_priv->gtt;
377
378 /* Enable the GTT */
379 pci_read_config_word(dev->pdev, PSB_GMCH_CTRL, &dev_priv->gmch_ctrl);
380 pci_write_config_word(dev->pdev, PSB_GMCH_CTRL,
381 dev_priv->gmch_ctrl | _PSB_GMCH_ENABLED);
382
383 dev_priv->pge_ctl = PSB_RVDC32(PSB_PGETBL_CTL);
384 PSB_WVDC32(dev_priv->pge_ctl | _PSB_PGETBL_ENABLED, PSB_PGETBL_CTL);
385 (void) PSB_RVDC32(PSB_PGETBL_CTL);
386
387 /* The root resource we allocate address space from */
388 dev_priv->gtt_initialized = 1;
389
390 pg->gtt_phys_start = dev_priv->pge_ctl & PAGE_MASK;
391
392 /*
393 * FIXME: video mmu has hw bug to access 0x0D0000000,
394 * then make gatt start at 0x0e000,0000
395 */
396 pg->mmu_gatt_start = 0xE0000000;
397
398 pg->gtt_start = pci_resource_start(dev->pdev, PSB_GTT_RESOURCE);
399 gtt_pages = pci_resource_len(dev->pdev, PSB_GTT_RESOURCE)
400 >> PAGE_SHIFT;
401 /* CDV workaround */
402 if (pg->gtt_start == 0 || gtt_pages == 0) {
403 dev_err(dev->dev, "GTT PCI BAR not initialized.\n");
404 gtt_pages = 64;
405 pg->gtt_start = dev_priv->pge_ctl;
406 }
407
408 pg->gatt_start = pci_resource_start(dev->pdev, PSB_GATT_RESOURCE);
409 pg->gatt_pages = pci_resource_len(dev->pdev, PSB_GATT_RESOURCE)
410 >> PAGE_SHIFT;
411 dev_priv->gtt_mem = &dev->pdev->resource[PSB_GATT_RESOURCE];
412
413 if (pg->gatt_pages == 0 || pg->gatt_start == 0) {
414 static struct resource fudge; /* Preferably peppermint */
415
416 /* This can occur on CDV SDV systems. Fudge it in this case.
417 We really don't care what imaginary space is being allocated
418 at this point */
419 dev_err(dev->dev, "GATT PCI BAR not initialized.\n");
420 pg->gatt_start = 0x40000000;
421 pg->gatt_pages = (128 * 1024 * 1024) >> PAGE_SHIFT;
422 fudge.start = 0x40000000;
423 fudge.end = 0x40000000 + 128 * 1024 * 1024 - 1;
424 fudge.name = "fudge";
425 fudge.flags = IORESOURCE_MEM;
426 dev_priv->gtt_mem = &fudge;
427 }
428
429 pci_read_config_dword(dev->pdev, PSB_BSM, &dev_priv->stolen_base);
430 vram_stolen_size = pg->gtt_phys_start - dev_priv->stolen_base
431 - PAGE_SIZE;
432
433 stolen_size = vram_stolen_size;
434
435 printk(KERN_INFO "Stolen memory information\n");
436 printk(KERN_INFO " base in RAM: 0x%x\n", dev_priv->stolen_base);
437 printk(KERN_INFO " size: %luK, calculated by (GTT RAM base) - (Stolen base), seems wrong\n",
438 vram_stolen_size/1024);
439 dvmt_mode = (dev_priv->gmch_ctrl >> 4) & 0x7;
440 printk(KERN_INFO " the correct size should be: %dM(dvmt mode=%d)\n",
441 (dvmt_mode == 1) ? 1 : (2 << (dvmt_mode - 1)), dvmt_mode);
442
443 if (resume && (gtt_pages != pg->gtt_pages) &&
444 (stolen_size != pg->stolen_size)) {
445 dev_err(dev->dev, "GTT resume error.\n");
446 ret = -EINVAL;
447 goto out_err;
448 }
449
450 pg->gtt_pages = gtt_pages;
451 pg->stolen_size = stolen_size;
452 dev_priv->vram_stolen_size = vram_stolen_size;
453
454 /*
455 * Map the GTT and the stolen memory area
456 */
457 dev_priv->gtt_map = ioremap_nocache(pg->gtt_phys_start,
458 gtt_pages << PAGE_SHIFT);
459 if (!dev_priv->gtt_map) {
460 dev_err(dev->dev, "Failure to map gtt.\n");
461 ret = -ENOMEM;
462 goto out_err;
463 }
464
465 dev_priv->vram_addr = ioremap_wc(dev_priv->stolen_base, stolen_size);
466 if (!dev_priv->vram_addr) {
467 dev_err(dev->dev, "Failure to map stolen base.\n");
468 ret = -ENOMEM;
469 goto out_err;
470 }
471
472 /*
473 * Insert vram stolen pages into the GTT
474 */
475
476 pfn_base = dev_priv->stolen_base >> PAGE_SHIFT;
477 vram_pages = num_pages = vram_stolen_size >> PAGE_SHIFT;
478 printk(KERN_INFO"Set up %d stolen pages starting at 0x%08x, GTT offset %dK\n",
479 num_pages, pfn_base << PAGE_SHIFT, 0);
480 for (i = 0; i < num_pages; ++i) {
481 pte = psb_gtt_mask_pte(pfn_base + i, 0);
482 iowrite32(pte, dev_priv->gtt_map + i);
483 }
484
485 /*
486 * Init rest of GTT to the scratch page to avoid accidents or scribbles
487 */
488
489 pfn_base = page_to_pfn(dev_priv->scratch_page);
490 pte = psb_gtt_mask_pte(pfn_base, 0);
491 for (; i < gtt_pages; ++i)
492 iowrite32(pte, dev_priv->gtt_map + i);
493
494 (void) ioread32(dev_priv->gtt_map + i - 1);
495 return 0;
496
497out_err:
498 psb_gtt_takedown(dev);
499 return ret;
500}
diff --git a/drivers/staging/gma500/gtt.h b/drivers/staging/gma500/gtt.h
new file mode 100644
index 00000000000..e0e1cb6f9bd
--- /dev/null
+++ b/drivers/staging/gma500/gtt.h
@@ -0,0 +1,61 @@
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 */
26struct 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 */
39extern int psb_gtt_init(struct drm_device *dev, int resume);
40extern void psb_gtt_takedown(struct drm_device *dev);
41
42/* Each gtt_range describes an allocation in the GTT area */
43struct 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};
53
54extern struct gtt_range *psb_gtt_alloc_range(struct drm_device *dev, int len,
55 const char *name, int backed);
56extern void psb_gtt_kref_put(struct gtt_range *gt);
57extern void psb_gtt_free_range(struct drm_device *dev, struct gtt_range *gt);
58extern int psb_gtt_pin(struct gtt_range *gt);
59extern void psb_gtt_unpin(struct gtt_range *gt);
60
61#endif
diff --git a/drivers/staging/gma500/intel_bios.c b/drivers/staging/gma500/intel_bios.c
new file mode 100644
index 00000000000..096757f9bc8
--- /dev/null
+++ b/drivers/staging/gma500/intel_bios.c
@@ -0,0 +1,303 @@
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
30static 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
55static 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
87static 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 */
117static 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 */
168static 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
198static 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 */
234bool 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 */
278void 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
new file mode 100644
index 00000000000..70f1bf01818
--- /dev/null
+++ b/drivers/staging/gma500/intel_bios.h
@@ -0,0 +1,430 @@
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
27struct 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
39struct 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 */
47struct 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
103struct 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
133struct 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
156struct 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
170struct 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 */
183struct 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
192struct 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 */
198struct 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
214struct 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
242struct 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
250struct 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
256struct bdb_lvds_lfp_data {
257 struct bdb_lvds_lfp_data_entry data[16];
258} __attribute__((packed));
259
260struct 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
268struct aimdb_block {
269 u8 aimdb_id;
270 u16 aimdb_size;
271} __attribute__((packed));
272
273struct 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
284struct vch_bdb_22 {
285 struct aimdb_block aimdb_block;
286 struct vch_panel_data panels[16];
287} __attribute__((packed));
288
289struct 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
306extern bool psb_intel_init_bios(struct drm_device *dev);
307extern 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
new file mode 100644
index 00000000000..e33432df510
--- /dev/null
+++ b/drivers/staging/gma500/intel_i2c.c
@@ -0,0 +1,169 @@
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
24#include "psb_drv.h"
25#include "psb_intel_reg.h"
26
27/*
28 * Intel GPIO access functions
29 */
30
31#define I2C_RISEFALL_TIME 20
32
33static int get_clock(void *data)
34{
35 struct psb_intel_i2c_chan *chan = data;
36 struct drm_device *dev = chan->drm_dev;
37 u32 val;
38
39 val = REG_READ(chan->reg);
40 return (val & GPIO_CLOCK_VAL_IN) != 0;
41}
42
43static int get_data(void *data)
44{
45 struct psb_intel_i2c_chan *chan = data;
46 struct drm_device *dev = chan->drm_dev;
47 u32 val;
48
49 val = REG_READ(chan->reg);
50 return (val & GPIO_DATA_VAL_IN) != 0;
51}
52
53static void set_clock(void *data, int state_high)
54{
55 struct psb_intel_i2c_chan *chan = data;
56 struct drm_device *dev = chan->drm_dev;
57 u32 reserved = 0, clock_bits;
58
59 /* On most chips, these bits must be preserved in software. */
60 reserved =
61 REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
62 GPIO_CLOCK_PULLUP_DISABLE);
63
64 if (state_high)
65 clock_bits = GPIO_CLOCK_DIR_IN | GPIO_CLOCK_DIR_MASK;
66 else
67 clock_bits = GPIO_CLOCK_DIR_OUT | GPIO_CLOCK_DIR_MASK |
68 GPIO_CLOCK_VAL_MASK;
69 REG_WRITE(chan->reg, reserved | clock_bits);
70 udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
71}
72
73static void set_data(void *data, int state_high)
74{
75 struct psb_intel_i2c_chan *chan = data;
76 struct drm_device *dev = chan->drm_dev;
77 u32 reserved = 0, data_bits;
78
79 /* On most chips, these bits must be preserved in software. */
80 reserved =
81 REG_READ(chan->reg) & (GPIO_DATA_PULLUP_DISABLE |
82 GPIO_CLOCK_PULLUP_DISABLE);
83
84 if (state_high)
85 data_bits = GPIO_DATA_DIR_IN | GPIO_DATA_DIR_MASK;
86 else
87 data_bits =
88 GPIO_DATA_DIR_OUT | GPIO_DATA_DIR_MASK |
89 GPIO_DATA_VAL_MASK;
90
91 REG_WRITE(chan->reg, reserved | data_bits);
92 udelay(I2C_RISEFALL_TIME); /* wait for the line to change state */
93}
94
95/**
96 * psb_intel_i2c_create - instantiate an Intel i2c bus using the specified GPIO reg
97 * @dev: DRM device
98 * @output: driver specific output device
99 * @reg: GPIO reg to use
100 * @name: name for this bus
101 *
102 * Creates and registers a new i2c bus with the Linux i2c layer, for use
103 * in output probing and control (e.g. DDC or SDVO control functions).
104 *
105 * Possible values for @reg include:
106 * %GPIOA
107 * %GPIOB
108 * %GPIOC
109 * %GPIOD
110 * %GPIOE
111 * %GPIOF
112 * %GPIOG
113 * %GPIOH
114 * see PRM for details on how these different busses are used.
115 */
116struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
117 const u32 reg, const char *name)
118{
119 struct psb_intel_i2c_chan *chan;
120
121 chan = kzalloc(sizeof(struct psb_intel_i2c_chan), GFP_KERNEL);
122 if (!chan)
123 goto out_free;
124
125 chan->drm_dev = dev;
126 chan->reg = reg;
127 snprintf(chan->adapter.name, I2C_NAME_SIZE, "intel drm %s", name);
128 chan->adapter.owner = THIS_MODULE;
129 chan->adapter.algo_data = &chan->algo;
130 chan->adapter.dev.parent = &dev->pdev->dev;
131 chan->algo.setsda = set_data;
132 chan->algo.setscl = set_clock;
133 chan->algo.getsda = get_data;
134 chan->algo.getscl = get_clock;
135 chan->algo.udelay = 20;
136 chan->algo.timeout = usecs_to_jiffies(2200);
137 chan->algo.data = chan;
138
139 i2c_set_adapdata(&chan->adapter, chan);
140
141 if (i2c_bit_add_bus(&chan->adapter))
142 goto out_free;
143
144 /* JJJ: raise SCL and SDA? */
145 set_data(chan, 1);
146 set_clock(chan, 1);
147 udelay(20);
148
149 return chan;
150
151out_free:
152 kfree(chan);
153 return NULL;
154}
155
156/**
157 * psb_intel_i2c_destroy - unregister and free i2c bus resources
158 * @output: channel to free
159 *
160 * Unregister the adapter from the i2c layer, then free the structure.
161 */
162void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan)
163{
164 if (!chan)
165 return;
166
167 i2c_del_adapter(&chan->adapter);
168 kfree(chan);
169}
diff --git a/drivers/staging/gma500/intel_opregion.c b/drivers/staging/gma500/intel_opregion.c
new file mode 100644
index 00000000000..d2e60376982
--- /dev/null
+++ b/drivers/staging/gma500/intel_opregion.c
@@ -0,0 +1,80 @@
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 */
24
25#include "psb_drv.h"
26
27struct opregion_header {
28 u8 signature[16];
29 u32 size;
30 u32 opregion_ver;
31 u8 bios_ver[32];
32 u8 vbios_ver[16];
33 u8 driver_ver[16];
34 u32 mboxes;
35 u8 reserved[164];
36} __packed;
37
38struct opregion_apci {
39 /*FIXME: add it later*/
40} __packed;
41
42struct opregion_swsci {
43 /*FIXME: add it later*/
44} __packed;
45
46struct opregion_acpi {
47 /*FIXME: add it later*/
48} __packed;
49
50int gma_intel_opregion_init(struct drm_device *dev)
51{
52 struct drm_psb_private *dev_priv = dev->dev_private;
53 u32 opregion_phy;
54 void *base;
55 u32 *lid_state;
56
57 dev_priv->lid_state = NULL;
58
59 pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy);
60 if (opregion_phy == 0)
61 return -ENOTSUPP;
62
63 base = ioremap(opregion_phy, 8*1024);
64 if (!base)
65 return -ENOMEM;
66
67 lid_state = base + 0x01ac;
68
69 dev_priv->lid_state = lid_state;
70 dev_priv->lid_last_state = readl(lid_state);
71 return 0;
72}
73
74int gma_intel_opregion_exit(struct drm_device *dev)
75{
76 struct drm_psb_private *dev_priv = dev->dev_private;
77 if (dev_priv->lid_state)
78 iounmap(dev_priv->lid_state);
79 return 0;
80}
diff --git a/drivers/staging/gma500/mdfld_device.c b/drivers/staging/gma500/mdfld_device.c
new file mode 100644
index 00000000000..f47aeb7a203
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_device.c
@@ -0,0 +1,714 @@
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
37static int mdfld_brightness;
38struct backlight_device *mdfld_backlight_device;
39
40static 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
78int 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
86static const struct backlight_ops mfld_ops = {
87 .get_brightness = psb_get_brightness,
88 .update_status = mfld_set_brightness,
89};
90
91static 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
121static 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 */
134static 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 */
316static 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 */
360static 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 */
604static 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 */
648static 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 */
669static 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
678static int mdfld_power_down(struct drm_device *dev)
679{
680 /* FIXME */
681 return 0;
682}
683
684static int mdfld_power_up(struct drm_device *dev)
685{
686 /* FIXME */
687 return 0;
688}
689
690const 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
new file mode 100644
index 00000000000..fd211f3467c
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.c
@@ -0,0 +1,761 @@
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
35int enable_gfx_rtpm;
36
37extern struct drm_device *gpDrmDevice;
38extern int gfxrtdelay;
39int enter_dsr;
40struct mdfld_dsi_dbi_output *gdbi_output;
41extern bool gbgfxsuspended;
42extern int enable_gfx_rtpm;
43extern int gfxrtdelay;
44
45#define MDFLD_DSR_MAX_IDLE_COUNT 2
46
47/*
48 * set refreshing area
49 */
50int 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);
112err_out:
113 return err;
114}
115
116/*
117 * set panel's power state
118 */
119int 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 &param,
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);
228power_err:
229 return err;
230}
231
232/*
233 * send a generic DCS command with a parameter list
234 */
235int 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 */
260void 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
330static 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 */
410void 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
441static 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 */
456void 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
537int 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
554void 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
565void 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*/
618static 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*/
627static 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 */
638struct 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;
758out_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
new file mode 100644
index 00000000000..f0fa986fd93
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi.h
@@ -0,0 +1,173 @@
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 */
48struct 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
80struct 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
95static 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
115static 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
135static 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
154extern void mdfld_dsi_dbi_output_init(struct drm_device *dev,
155 struct psb_intel_mode_device *mode_dev, int pipe);
156extern void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src);
157extern void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output,
158 int pipe);
159extern int mdfld_dbi_dsr_init(struct drm_device *dev);
160extern void mdfld_dbi_dsr_exit(struct drm_device *dev);
161extern 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);
164extern int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
165 u8 dcs, u8 *param, u32 num, u8 data_src);
166extern int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
167 u16 x1, u16 y1, u16 x2, u16 y2);
168extern int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
169 int mode);
170extern 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
new file mode 100644
index 00000000000..a4e2ff442b1
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.c
@@ -0,0 +1,778 @@
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
35static 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 }
98cursor_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
132static 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 */
154static 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
161int 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
196int 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
232int 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
249static 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
272static 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
307static 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 */
316static 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
362static 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
382static 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
430static 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
512static 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
596int 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
628static 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
649static 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
679void 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
699static 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
719void 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
732int 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
765void 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
new file mode 100644
index 00000000000..42367ed48c0
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dbi_dpu.h
@@ -0,0 +1,154 @@
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
33typedef 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
46struct 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
58struct 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
88static 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
107static 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
126static 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
142extern int mdfld_dsi_dbi_dsr_off(struct drm_device *dev,
143 struct psb_drm_dpu_rect *rect);
144extern int mdfld_dbi_dpu_report_damage(struct drm_device *dev,
145 mdfld_plane_t plane,
146 struct psb_drm_dpu_rect *rect);
147extern int mdfld_dbi_dpu_report_fullscreen_damage(struct drm_device *dev);
148extern int mdfld_dpu_exit_dsr(struct drm_device *dev);
149extern void mdfld_dbi_dpu_timer_start(struct mdfld_dbi_dpu_info *dpu_info);
150extern int mdfld_dbi_dpu_init(struct drm_device *dev);
151extern void mdfld_dbi_dpu_exit(struct drm_device *dev);
152extern 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
new file mode 100644
index 00000000000..e685f1217ba
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dpi.c
@@ -0,0 +1,805 @@
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
33static 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
53static 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
72static 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
93static 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\* ************************************************************************* */
122void 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
312static 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 */
324int 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
361void 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
444void 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
479static 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
508shutdown_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
527void 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
584void 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
602bool 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
626void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder)
627{
628 mdfld_dsi_dpi_set_power(encoder, false);
629}
630
631void mdfld_dsi_dpi_commit(struct drm_encoder *encoder)
632{
633 mdfld_dsi_dpi_set_power(encoder, true);
634}
635
636void 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 */
712struct 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
new file mode 100644
index 00000000000..ed92d45ee74
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_dpi.h
@@ -0,0 +1,78 @@
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
34struct 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
44struct 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
57extern 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);
60extern 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 */
65extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode);
66extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
67 struct drm_display_mode *mode,
68 struct drm_display_mode *adjusted_mode);
69extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder);
70extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder);
71extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
72 struct drm_display_mode *mode,
73 struct drm_display_mode *adjusted_mode);
74extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output,
75 int pipe);
76extern 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
new file mode 100644
index 00000000000..9050c0f78b1
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_output.c
@@ -0,0 +1,1013 @@
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
36#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
37
38static int CABC_control = 1;
39static int LABC_control = 1;
40
41module_param (CABC_control, int, 0644);
42module_param (LABC_control, int, 0644);
43
44/**
45 * make these MCS command global
46 * we don't need 'movl' everytime we send them.
47 * FIXME: these datas were provided by OEM, we should get them from GCT.
48 **/
49static u32 mdfld_dbi_mcs_hysteresis[] = {
50 0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
51 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
52 0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
53 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
54 0x000000ff,
55};
56
57static u32 mdfld_dbi_mcs_display_profile[] = {
58 0x50281450, 0x0000c882, 0x00000000, 0x00000000,
59 0x00000000,
60};
61
62static u32 mdfld_dbi_mcs_kbbc_profile[] = {
63 0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
64};
65
66static u32 mdfld_dbi_mcs_gamma_profile[] = {
67 0x81111158, 0x88888888, 0x88888888,
68};
69
70/*
71 * write hysteresis values.
72 */
73static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config *dsi_config,
74 int pipe)
75{
76 struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
77
78 if(!sender) {
79 WARN_ON(1);
80 return;
81 }
82 mdfld_dsi_send_mcs_long_hs(sender,
83 mdfld_dbi_mcs_hysteresis,
84 17,
85 MDFLD_DSI_SEND_PACKAGE);
86}
87
88/*
89 * write display profile values.
90 */
91static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config *dsi_config, int pipe)
92{
93 struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
94
95 if(!sender) {
96 WARN_ON(1);
97 return;
98 }
99 mdfld_dsi_send_mcs_long_hs(sender,
100 mdfld_dbi_mcs_display_profile,
101 5,
102 MDFLD_DSI_SEND_PACKAGE);
103}
104
105/*
106 * write KBBC profile values.
107 */
108static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe)
109{
110 struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
111
112 if(!sender) {
113 WARN_ON(1);
114 return;
115 }
116 mdfld_dsi_send_mcs_long_hs(sender,
117 mdfld_dbi_mcs_kbbc_profile,
118 4,
119 MDFLD_DSI_SEND_PACKAGE);
120}
121
122/*
123 * write gamma setting.
124 */
125static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config *dsi_config, int pipe)
126{
127 struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
128
129 if(!sender) {
130 WARN_ON(1);
131 return;
132 }
133 mdfld_dsi_send_mcs_long_hs(sender,
134 mdfld_dbi_mcs_gamma_profile,
135 3,
136 MDFLD_DSI_SEND_PACKAGE);
137}
138
139/*
140 * Check and see if the generic control or data buffer is empty and ready.
141 */
142void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat)
143{
144 u32 GEN_BF_time_out_count = 0;
145
146 /* Check MIPI Adatper command registers */
147 for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++)
148 {
149 if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
150 break;
151 udelay (100);
152 }
153
154 if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
155 dev_err(dev->dev,
156 "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n",
157 gen_fifo_stat_reg);
158}
159
160/*
161 * Manage the DSI MIPI keyboard and display brightness.
162 * FIXME: this is exported to OSPM code. should work out an specific
163 * display interface to OSPM.
164 */
165void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
166{
167 struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
168 struct drm_device *dev = sender->dev;
169 struct drm_psb_private *dev_priv = dev->dev_private;
170 u32 gen_ctrl_val;
171
172 if(!sender) {
173 WARN_ON(1);
174 return;
175 }
176 /* Set default display backlight value to 85% (0xd8)*/
177 mdfld_dsi_send_mcs_short_hs(sender,
178 write_display_brightness,
179 0xd8,
180 1,
181 MDFLD_DSI_SEND_PACKAGE);
182
183 /* Set minimum brightness setting of CABC function to 20% (0x33)*/
184 mdfld_dsi_send_mcs_short_hs(sender,
185 write_cabc_min_bright,
186 0x33,
187 1,
188 MDFLD_DSI_SEND_PACKAGE);
189
190 mdfld_dsi_write_hysteresis(dsi_config, pipe);
191 mdfld_dsi_write_display_profile (dsi_config, pipe);
192 mdfld_dsi_write_kbbc_profile (dsi_config, pipe);
193 mdfld_dsi_write_gamma_setting (dsi_config, pipe);
194
195 /* Enable backlight or/and LABC */
196 gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON;
197 if (LABC_control == 1 || CABC_control == 1)
198 gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO;
199
200 if (LABC_control == 1)
201 gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
202
203 dev_priv->mipi_ctrl_display = gen_ctrl_val;
204
205 mdfld_dsi_send_mcs_short_hs(sender,
206 write_ctrl_display,
207 (u8)gen_ctrl_val,
208 1,
209 MDFLD_DSI_SEND_PACKAGE);
210
211 if (CABC_control == 0)
212 return;
213 mdfld_dsi_send_mcs_short_hs(sender,
214 write_ctrl_cabc,
215 UI_IMAGE,
216 1,
217 MDFLD_DSI_SEND_PACKAGE);
218}
219
220/*
221 * Manage the mipi display brightness.
222 * TODO: refine this interface later
223 */
224void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
225{
226 struct mdfld_dsi_pkg_sender *sender;
227 struct drm_psb_private *dev_priv;
228 struct mdfld_dsi_config *dsi_config;
229 u32 gen_ctrl_val;
230 int p_type;
231
232 if (!dev || (pipe != 0 && pipe != 2)) {
233 dev_err(dev->dev, "Invalid parameter\n");
234 return;
235 }
236
237 p_type = mdfld_get_panel_type(dev, 0);
238
239 dev_priv = dev->dev_private;
240
241 if(pipe)
242 dsi_config = dev_priv->dsi_configs[1];
243 else
244 dsi_config = dev_priv->dsi_configs[0];
245
246 sender = mdfld_dsi_get_pkg_sender(dsi_config);
247
248 if(!sender) {
249 WARN_ON(1);
250 return;
251 }
252
253 gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
254
255 dev_dbg(dev->dev,
256 "pipe = %d, gen_ctrl_val = %d. \n", pipe, gen_ctrl_val);
257
258 if(p_type == TMD_VID || p_type == TMD_CMD){
259 /* Set display backlight value */
260 mdfld_dsi_send_mcs_short_hs(sender,
261 tmd_write_display_brightness,
262 (u8)gen_ctrl_val,
263 1,
264 MDFLD_DSI_SEND_PACKAGE);
265 } else {
266 /* Set display backlight value */
267 mdfld_dsi_send_mcs_short_hs(sender,
268 write_display_brightness,
269 (u8)gen_ctrl_val,
270 1,
271 MDFLD_DSI_SEND_PACKAGE);
272
273
274 /* Enable backlight control */
275 if (level == 0)
276 gen_ctrl_val = 0;
277 else
278 gen_ctrl_val = dev_priv->mipi_ctrl_display;
279
280 mdfld_dsi_send_mcs_short_hs(sender,
281 write_ctrl_display,
282 (u8)gen_ctrl_val,
283 1,
284 MDFLD_DSI_SEND_PACKAGE);
285 }
286}
287
288/*
289 * shut down DSI controller
290 */
291void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe)
292{
293 struct drm_device * dev;
294 u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
295 int retry = 100;
296
297 if (!dsi_config) {
298 WARN_ON(1);
299 return;
300 }
301
302 dev = dsi_config->dev;
303
304 if (!gma_power_begin(dev, true)) {
305 dev_err(dev->dev, "hw begin failed\n");
306 return;
307 }
308
309 if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY))
310 goto shutdown_out;
311
312 /* Send shut down package, clean packet send bit first */
313 if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
314 REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset),
315 (REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT));
316 }
317
318 /*send shut down package in HS*/
319 REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
320
321
322 /*
323 * make sure shut down is sent.
324 * FIXME: add max retry counter
325 */
326 while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
327 retry--;
328
329 if(!retry) {
330 dev_err(dev->dev, "timeout\n");
331 break;
332 }
333 }
334
335 /*sleep 1 ms to ensure shutdown finished*/
336 msleep(100);
337
338 /*un-ready device*/
339 REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
340 (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & ~DSI_DEVICE_READY));
341
342shutdown_out:
343 gma_power_end(dev);
344}
345
346void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe)
347{
348 struct drm_device * dev;
349 u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
350 int retry = 100;
351
352
353 if (!dsi_config) {
354 WARN_ON(1);
355 return;
356 }
357
358 dev = dsi_config->dev;
359 dev_dbg(dev->dev, "starting up DSI controller on pipe %d...\n", pipe);
360
361 if (!gma_power_begin(dev, true)) {
362 dev_err(dev->dev, "hw begin failed\n");
363 return;
364 }
365
366 if((REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY))
367 goto startup_out;
368
369 /*if config DPI, turn on DPI interface*/
370 if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
371 if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
372 REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
373 }
374
375 REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
376
377 /*
378 * make sure shut down is sent.
379 * FIXME: add max retry counter
380 */
381 while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
382 retry--;
383 if(!retry) {
384 dev_err(dev->dev, "timeout\n");
385 break;
386 }
387 }
388
389 msleep(100);
390 }
391
392 /*set device ready*/
393 REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
394 (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) | DSI_DEVICE_READY));
395
396startup_out:
397 gma_power_end(dev);
398}
399
400
401static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
402 u8 dcs,
403 u32 *data,
404 u8 transmission)
405{
406 struct mdfld_dsi_pkg_sender *sender
407 = mdfld_dsi_get_pkg_sender(dsi_config);
408
409 if (!sender || !data) {
410 DRM_ERROR("Invalid parameter\n");
411 return -EINVAL;
412 }
413
414 if (transmission == MDFLD_DSI_HS_TRANSMISSION)
415 return mdfld_dsi_read_mcs_hs(sender, dcs, data, 1);
416 else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
417 return mdfld_dsi_read_mcs_lp(sender, dcs, data, 1);
418 else
419 return -EINVAL;
420}
421
422int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
423 u32 *mode,
424 u8 transmission)
425{
426 if (!dsi_config || !mode) {
427 DRM_ERROR("Invalid parameter\n");
428 return -EINVAL;
429 }
430
431 return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, transmission);
432}
433
434int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
435 u32 *result,
436 u8 transmission)
437{
438 if (!dsi_config || !result) {
439 DRM_ERROR("Invalid parameter\n");
440 return -EINVAL;
441 }
442
443 return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result,
444 transmission);
445}
446
447/*
448 * NOTE: this function was used by OSPM.
449 * TODO: will be removed later, should work out display interfaces for OSPM
450 */
451void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
452{
453 if(!dsi_config || ((pipe != 0) && (pipe != 2))) {
454 WARN_ON(1);
455 return;
456 }
457
458 if(dsi_config->type)
459 mdfld_dsi_dpi_controller_init(dsi_config, pipe);
460 else
461 mdfld_dsi_controller_dbi_init(dsi_config, pipe);
462}
463
464static void mdfld_dsi_connector_save(struct drm_connector * connector)
465{
466}
467
468static void mdfld_dsi_connector_restore(struct drm_connector * connector)
469{
470}
471
472static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force)
473{
474 struct psb_intel_output *psb_output
475 = to_psb_intel_output(connector);
476 struct mdfld_dsi_connector *dsi_connector
477 = MDFLD_DSI_CONNECTOR(psb_output);
478 return dsi_connector->status;
479}
480
481static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
482 struct drm_property *property,
483 uint64_t value)
484{
485 struct drm_encoder *encoder = connector->encoder;
486
487 if (!strcmp(property->name, "scaling mode") && encoder) {
488 struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
489 bool bTransitionFromToCentered;
490 uint64_t curValue;
491
492 if (!psb_crtc)
493 goto set_prop_error;
494
495 switch (value) {
496 case DRM_MODE_SCALE_FULLSCREEN:
497 break;
498 case DRM_MODE_SCALE_NO_SCALE:
499 break;
500 case DRM_MODE_SCALE_ASPECT:
501 break;
502 default:
503 goto set_prop_error;
504 }
505
506 if (drm_connector_property_get_value(connector, property, &curValue))
507 goto set_prop_error;
508
509 if (curValue == value)
510 goto set_prop_done;
511
512 if (drm_connector_property_set_value(connector, property, value))
513 goto set_prop_error;
514
515 bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
516 (value == DRM_MODE_SCALE_NO_SCALE);
517
518 if (psb_crtc->saved_mode.hdisplay != 0 &&
519 psb_crtc->saved_mode.vdisplay != 0) {
520 if (bTransitionFromToCentered) {
521 if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode,
522 encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
523 goto set_prop_error;
524 } else {
525 struct drm_encoder_helper_funcs *pEncHFuncs = encoder->helper_private;
526 pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode,
527 &psb_crtc->saved_adjusted_mode);
528 }
529 }
530#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
531 } else if (!strcmp(property->name, "backlight") && encoder) {
532 struct drm_psb_private *dev_priv = encoder->dev->dev_private;
533 struct backlight_device *psb_bd = dev_priv->backlight_device;
534 dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value);
535 if (drm_connector_property_set_value(connector, property, value))
536 goto set_prop_error;
537 else {
538 dev_dbg(encoder->dev->dev,
539 "set brightness to %d", (int)value);
540 if (psb_bd) {
541 psb_bd->props.brightness = value;
542 backlight_update_status(psb_bd);
543 }
544 }
545#endif
546 }
547set_prop_done:
548 return 0;
549set_prop_error:
550 return -1;
551}
552
553static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
554{
555 struct psb_intel_output * psb_output = to_psb_intel_output(connector);
556 struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
557 struct mdfld_dsi_pkg_sender * sender;
558
559 if(!dsi_connector)
560 return;
561
562 drm_sysfs_connector_remove(connector);
563 drm_connector_cleanup(connector);
564
565 sender = dsi_connector->pkg_sender;
566
567 mdfld_dsi_pkg_sender_destroy(sender);
568
569 kfree(dsi_connector);
570}
571
572static int mdfld_dsi_connector_get_modes(struct drm_connector * connector)
573{
574 struct psb_intel_output * psb_output = to_psb_intel_output(connector);
575 struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
576 struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
577 struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
578 struct drm_display_mode * dup_mode = NULL;
579 struct drm_device * dev = connector->dev;
580
581 connector->display_info.min_vfreq = 0;
582 connector->display_info.max_vfreq = 200;
583 connector->display_info.min_hfreq = 0;
584 connector->display_info.max_hfreq = 200;
585
586 if(fixed_mode) {
587 dev_dbg(dev->dev, "fixed_mode %dx%d\n",
588 fixed_mode->hdisplay, fixed_mode->vdisplay);
589
590 dup_mode = drm_mode_duplicate(dev, fixed_mode);
591 drm_mode_probed_add(connector, dup_mode);
592 return 1;
593 }
594 dev_err(dev->dev, "Didn't get any modes!\n");
595 return 0;
596}
597
598static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode)
599{
600 struct psb_intel_output * psb_output = to_psb_intel_output(connector);
601 struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
602 struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
603 struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
604
605 dev_dbg(connector->dev->dev, "mode %p, fixed mode %p\n",
606 mode, fixed_mode);
607
608 if(mode->flags & DRM_MODE_FLAG_DBLSCAN)
609 return MODE_NO_DBLESCAN;
610
611 if(mode->flags & DRM_MODE_FLAG_INTERLACE)
612 return MODE_NO_INTERLACE;
613
614 /**
615 * FIXME: current DC has no fitting unit, reject any mode setting request
616 * will figure out a way to do up-scaling(pannel fitting) later.
617 **/
618 if(fixed_mode) {
619 if(mode->hdisplay != fixed_mode->hdisplay)
620 return MODE_PANEL;
621
622 if(mode->vdisplay != fixed_mode->vdisplay)
623 return MODE_PANEL;
624 }
625 dev_dbg(connector->dev->dev, "mode ok\n");
626
627 return MODE_OK;
628}
629
630static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
631{
632#ifdef CONFIG_PM_RUNTIME
633 struct drm_device * dev = connector->dev;
634 struct drm_psb_private * dev_priv = dev->dev_private;
635 bool panel_on, panel_on2;
636#endif
637 /* First, execute DPMS */
638 drm_helper_connector_dpms(connector, mode);
639
640#ifdef CONFIG_PM_RUNTIME
641 if(mdfld_panel_dpi(dev)) {
642 /* DPI panel */
643 panel_on = dev_priv->dpi_panel_on;
644 panel_on2 = dev_priv->dpi_panel_on2;
645 } else {
646 /* DBI panel */
647 panel_on = dev_priv->dbi_panel_on;
648 panel_on2 = dev_priv->dbi_panel_on2;
649 }
650
651 /* Then check all display panels + monitors status */
652 /* Make sure that the Display (B) sub-system status isn't i3 when
653 * R/W the DC register, otherwise "Fabric error" issue would occur
654 * during S0i3 state. */
655 if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL)
656 & HDMIB_PORT_EN)) {
657 /* Request rpm idle */
658 if(dev_priv->rpm_enabled)
659 pm_request_idle(&dev->pdev->dev);
660 }
661 /*
662 * if rpm wasn't enabled yet, try to allow it
663 * FIXME: won't enable rpm for DPI since DPI
664 * CRTC setting is a little messy now.
665 * Enable it later!
666 */
667#if 0
668 if(!dev_priv->rpm_enabled && !mdfld_panel_dpi(dev))
669 ospm_runtime_pm_allow(dev);
670#endif
671#endif
672}
673
674static struct drm_encoder *mdfld_dsi_connector_best_encoder(
675 struct drm_connector *connector)
676{
677 struct psb_intel_output * psb_output = to_psb_intel_output(connector);
678 struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
679 struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
680 struct mdfld_dsi_encoder * encoder = NULL;
681
682 if(dsi_config->type == MDFLD_DSI_ENCODER_DBI)
683 encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI];
684 else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI)
685 encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI];
686
687 dev_dbg(connector->dev->dev, "get encoder %p\n", encoder);
688
689 if(!encoder) {
690 dev_err(connector->dev->dev,
691 "Invalid encoder for type %d\n", dsi_config->type);
692 return NULL;
693 }
694 dsi_config->encoder = encoder;
695 return &encoder->base;
696}
697
698/* DSI connector funcs */
699static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
700 .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
701 .save = mdfld_dsi_connector_save,
702 .restore = mdfld_dsi_connector_restore,
703 .detect = mdfld_dsi_connector_detect,
704 .fill_modes = drm_helper_probe_single_connector_modes,
705 .set_property = mdfld_dsi_connector_set_property,
706 .destroy = mdfld_dsi_connector_destroy,
707};
708
709/* DSI connector helper funcs */
710static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = {
711 .get_modes = mdfld_dsi_connector_get_modes,
712 .mode_valid = mdfld_dsi_connector_mode_valid,
713 .best_encoder = mdfld_dsi_connector_best_encoder,
714};
715
716static int mdfld_dsi_get_default_config(struct drm_device * dev,
717 struct mdfld_dsi_config * config, int pipe)
718{
719 if(!dev || !config) {
720 WARN_ON(1);
721 return -EINVAL;
722 }
723
724 config->bpp = 24;
725 config->type = mdfld_panel_dpi(dev);
726 config->lane_count = 2;
727 config->channel_num = 0;
728 /*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
729 if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
730 config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
731 } else {
732 config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
733 }
734
735 return 0;
736}
737
738/*
739 * Returns the panel fixed mode from configuration.
740 */
741struct drm_display_mode *
742mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
743{
744 struct drm_device *dev = dsi_config->dev;
745 struct drm_display_mode *mode;
746 struct drm_psb_private *dev_priv = dev->dev_private;
747 struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
748 bool use_gct = false;
749
750 mode = kzalloc(sizeof(*mode), GFP_KERNEL);
751 if (!mode) {
752 dev_err(dev->dev, "Out of memory for mode\n");
753 return NULL;
754 }
755 if (use_gct) {
756 dev_dbg(dev->dev, "gct find MIPI panel.\n");
757
758 mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
759 mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
760 mode->hsync_start = mode->hdisplay + \
761 ((ti->hsync_offset_hi << 8) | \
762 ti->hsync_offset_lo);
763 mode->hsync_end = mode->hsync_start + \
764 ((ti->hsync_pulse_width_hi << 8) | \
765 ti->hsync_pulse_width_lo);
766 mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
767 ti->hblank_lo);
768 mode->vsync_start = \
769 mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
770 ti->vsync_offset_lo);
771 mode->vsync_end = \
772 mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
773 ti->vsync_pulse_width_lo);
774 mode->vtotal = mode->vdisplay + \
775 ((ti->vblank_hi << 8) | ti->vblank_lo);
776 mode->clock = ti->pixel_clock * 10;
777 } else {
778 if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
779 if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
780 mode->hdisplay = 480;
781 mode->vdisplay = 854;
782 mode->hsync_start = 487;
783 mode->hsync_end = 490;
784 mode->htotal = 499;
785 mode->vsync_start = 861;
786 mode->vsync_end = 865;
787 mode->vtotal = 873;
788 mode->clock = 33264;
789 } else {
790 mode->hdisplay = 864;
791 mode->vdisplay = 480;
792 mode->hsync_start = 873;
793 mode->hsync_end = 876;
794 mode->htotal = 887;
795 mode->vsync_start = 487;
796 mode->vsync_end = 490;
797 mode->vtotal = 499;
798 mode->clock = 33264;
799 }
800 } else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
801 mode->hdisplay = 864;
802 mode->vdisplay = 480;
803 mode->hsync_start = 872;
804 mode->hsync_end = 876;
805 mode->htotal = 884;
806 mode->vsync_start = 482;
807 mode->vsync_end = 494;
808 mode->vtotal = 486;
809 mode->clock = 25777;
810
811 }
812 }
813
814 drm_mode_set_name(mode);
815 drm_mode_set_crtcinfo(mode, 0);
816
817 mode->type |= DRM_MODE_TYPE_PREFERRED;
818
819 return mode;
820}
821
822int mdfld_dsi_panel_reset(int pipe)
823{
824 unsigned gpio;
825 int ret = 0;
826
827 switch (pipe) {
828 case 0:
829 gpio = 128;
830 break;
831 case 2:
832 gpio = 34;
833 break;
834 default:
835 DRM_ERROR("Invalid output\n");
836 return -EINVAL;
837 }
838
839 ret = gpio_request(gpio, "gfx");
840 if (ret) {
841 DRM_ERROR("gpio_rqueset failed\n");
842 return ret;
843 }
844
845 ret = gpio_direction_output(gpio, 1);
846 if (ret) {
847 DRM_ERROR("gpio_direction_output failed\n");
848 goto gpio_error;
849 }
850
851 gpio_get_value(128);
852
853gpio_error:
854 if (gpio_is_valid(gpio))
855 gpio_free(gpio);
856
857 return ret;
858}
859
860/*
861 * MIPI output init
862 * @dev drm device
863 * @pipe pipe number. 0 or 2
864 * @config
865 *
866 * Do the initialization of a MIPI output, including create DRM mode objects
867 * initialization of DSI output on @pipe
868 */
869void mdfld_dsi_output_init(struct drm_device *dev,
870 int pipe,
871 struct mdfld_dsi_config *config,
872 struct panel_funcs* p_cmd_funcs,
873 struct panel_funcs* p_vid_funcs)
874{
875 struct mdfld_dsi_config * dsi_config;
876 struct mdfld_dsi_connector * dsi_connector;
877 struct psb_intel_output * psb_output;
878 struct drm_connector * connector;
879 struct mdfld_dsi_encoder * encoder;
880 struct drm_psb_private * dev_priv = dev->dev_private;
881 struct panel_info dsi_panel_info;
882 u32 width_mm, height_mm;
883
884 dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
885
886 if(!dev || ((pipe != 0) && (pipe != 2))) {
887 WARN_ON(1);
888 return;
889 }
890
891 /*create a new connetor*/
892 dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
893 if(!dsi_connector) {
894 DRM_ERROR("No memory");
895 return;
896 }
897
898 dsi_connector->pipe = pipe;
899
900 /*set DSI config*/
901 if(config) {
902 dsi_config = config;
903 } else {
904 dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL);
905 if(!dsi_config) {
906 dev_err(dev->dev,
907 "cannot allocate memory for DSI config\n");
908 goto dsi_init_err0;
909 }
910
911 mdfld_dsi_get_default_config(dev, dsi_config, pipe);
912 }
913
914 dsi_connector->private = dsi_config;
915
916 dsi_config->changed = 1;
917 dsi_config->dev = dev;
918
919 /* Init fixed mode basing on DSI config type */
920 if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
921 dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev);
922 if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
923 goto dsi_init_err0;
924 } else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
925 dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
926 if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
927 goto dsi_init_err0;
928 }
929
930 width_mm = dsi_panel_info.width_mm;
931 height_mm = dsi_panel_info.height_mm;
932
933 dsi_config->mode = dsi_config->fixed_mode;
934 dsi_config->connector = dsi_connector;
935
936 if(!dsi_config->fixed_mode) {
937 dev_err(dev->dev, "No pannel fixed mode was found\n");
938 goto dsi_init_err0;
939 }
940
941 if(pipe && dev_priv->dsi_configs[0]) {
942 dsi_config->dvr_ic_inited = 0;
943 dev_priv->dsi_configs[1] = dsi_config;
944 } else if(pipe == 0) {
945 dsi_config->dvr_ic_inited = 1;
946 dev_priv->dsi_configs[0] = dsi_config;
947 } else {
948 dev_err(dev->dev, "Trying to init MIPI1 before MIPI0\n");
949 goto dsi_init_err0;
950 }
951
952 /*init drm connector object*/
953 psb_output = &dsi_connector->base;
954
955 psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2;
956
957 connector = &psb_output->base;
958 /* Revisit type if MIPI/HDMI bridges ever appear on Medfield */
959 drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs,
960 DRM_MODE_CONNECTOR_LVDS);
961 drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
962
963 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
964 connector->display_info.width_mm = width_mm;
965 connector->display_info.height_mm = height_mm;
966 connector->interlace_allowed = false;
967 connector->doublescan_allowed = false;
968
969 /* Attach properties */
970 drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
971 drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
972
973 /* Init DSI package sender on this output */
974 if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
975 DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe);
976 goto dsi_init_err0;
977 }
978
979 /* Init DBI & DPI encoders */
980 if (p_cmd_funcs) {
981 encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs);
982 if(!encoder) {
983 dev_err(dev->dev, "Create DBI encoder failed\n");
984 goto dsi_init_err1;
985 }
986 encoder->private = dsi_config;
987 dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder;
988 }
989
990 if(p_vid_funcs) {
991 encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
992 if(!encoder) {
993 dev_err(dev->dev, "Create DPI encoder failed\n");
994 goto dsi_init_err1;
995 }
996 encoder->private = dsi_config;
997 dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder;
998 }
999
1000 drm_sysfs_connector_add(connector);
1001 return;
1002
1003 /*TODO: add code to destroy outputs on error*/
1004dsi_init_err1:
1005 /*destroy sender*/
1006 mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
1007
1008 drm_connector_cleanup(connector);
1009 kfree(dsi_config->fixed_mode);
1010 kfree(dsi_config);
1011dsi_init_err0:
1012 kfree(dsi_connector);
1013}
diff --git a/drivers/staging/gma500/mdfld_dsi_output.h b/drivers/staging/gma500/mdfld_dsi_output.h
new file mode 100644
index 00000000000..4699267efd6
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_output.h
@@ -0,0 +1,138 @@
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
46static 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
54static 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
69static 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
77static 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
92static 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
104static 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
118extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev,
119 u32 gen_fifo_stat_reg, u32 fifo_stat);
120extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config,
121 int pipe);
122extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe,
123 int level);
124extern 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);
128extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config,
129 int pipe);
130extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
131 u32 *mode,
132 u8 transmission);
133extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
134 u32 *result,
135 u8 transmission);
136extern 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
new file mode 100644
index 00000000000..9b96a5c9abc
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_pkg_sender.c
@@ -0,0 +1,1484 @@
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
38static 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
73static 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
90static 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
96static 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
101static 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
106static 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
111static 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
184static 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
207static 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 */
230static 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
271static 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
303static 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
351static 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
357static 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
363static 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
369static 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
375static 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
417static 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
457static 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
505static 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? */
527send_pkg_err:
528 return err;
529}
530
531static 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
546static 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
554static 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
583static 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
589static 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
607static 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
625static 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
649static 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
681static 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
723static 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
750static 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
812static 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
859static 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
890void 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
938void 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
1021static 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
1036void mdfld_dsi_cmds_kick_out(struct mdfld_dsi_pkg_sender *sender)
1037{
1038 process_pkg_list(sender);
1039}
1040
1041int 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
1149int 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
1160int 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
1171int 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
1184int 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
1197int 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
1208int 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
1219int 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
1232int 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
1245int 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
1263int 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
1280int 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
1294int 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
1308int 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
1451pkg_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);
1459mapping_err:
1460 kfree(pkg_sender);
1461 dsi_connector->pkg_sender = NULL;
1462 return ret;
1463}
1464
1465void 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
new file mode 100644
index 00000000000..f24abc70068
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_dsi_pkg_sender.h
@@ -0,0 +1,184 @@
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
34enum {
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
49enum {
50 MDFLD_DSI_LP_TRANSMISSION,
51 MDFLD_DSI_HS_TRANSMISSION,
52 MDFLD_DSI_DCS,
53};
54
55enum {
56 MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
57};
58
59enum {
60 MDFLD_DSI_PKG_SENDER_FREE = 0x0,
61 MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
62};
63
64enum {
65 MDFLD_DSI_SEND_PACKAGE,
66 MDFLD_DSI_QUEUE_PACKAGE,
67};
68
69struct mdfld_dsi_gen_short_pkg {
70 u8 cmd;
71 u8 param;
72};
73
74struct mdfld_dsi_gen_long_pkg {
75 u32 *data;
76 u32 len;
77};
78
79struct mdfld_dsi_dcs_pkg {
80 u8 cmd;
81 u8 param[MDFLD_MAX_DCS_PARAM];
82 u32 param_num;
83 u8 data_src;
84};
85
86struct 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
99struct 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
151extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
152 int pipe);
153extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender);
154extern int mdfld_dsi_send_dcs(struct mdfld_dsi_pkg_sender *sender, u8 dcs,
155 u8 *param, u32 param_num, u8 data_src, int delay);
156extern int mdfld_dsi_send_mcs_short_hs(struct mdfld_dsi_pkg_sender *sender,
157 u8 cmd, u8 param, u8 param_num, int delay);
158extern int mdfld_dsi_send_mcs_short_lp(struct mdfld_dsi_pkg_sender *sender,
159 u8 cmd, u8 param, u8 param_num, int delay);
160extern int mdfld_dsi_send_mcs_long_hs(struct mdfld_dsi_pkg_sender *sender,
161 u32 *data, u32 len, int delay);
162extern int mdfld_dsi_send_mcs_long_lp(struct mdfld_dsi_pkg_sender *sender,
163 u32 *data, u32 len, int delay);
164extern int mdfld_dsi_send_gen_short_hs(struct mdfld_dsi_pkg_sender *sender,
165 u8 param0, u8 param1, u8 param_num, int delay);
166extern int mdfld_dsi_send_gen_short_lp(struct mdfld_dsi_pkg_sender *sender,
167 u8 param0, u8 param1, u8 param_num, int delay);
168extern int mdfld_dsi_send_gen_long_hs(struct mdfld_dsi_pkg_sender *sender,
169 u32 *data, u32 len, int delay);
170extern int mdfld_dsi_send_gen_long_lp(struct mdfld_dsi_pkg_sender *sender,
171 u32 *data, u32 len, int delay);
172
173extern int mdfld_dsi_read_gen_hs(struct mdfld_dsi_pkg_sender *sender,
174 u8 param0, u8 param1, u8 param_num, u32 *data, u16 len);
175extern int mdfld_dsi_read_gen_lp(struct mdfld_dsi_pkg_sender *sender,
176 u8 param0, u8 param1, u8 param_num, u32 *data, u16 len);
177extern int mdfld_dsi_read_mcs_hs(struct mdfld_dsi_pkg_sender *sender,
178 u8 cmd, u32 *data, u16 len);
179extern int mdfld_dsi_read_mcs_lp(struct mdfld_dsi_pkg_sender *sender,
180 u8 cmd, u32 *data, u16 len);
181
182extern 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
new file mode 100644
index 00000000000..aa2ff559383
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_intel_display.c
@@ -0,0 +1,1402 @@
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 */
42static int ksel = KSEL_CRYSTAL_19;
43
44extern void mdfld_save_display(struct drm_device *dev);
45extern bool gbgfxsuspended;
46
47struct psb_intel_range_t {
48 int min, max;
49};
50
51struct mdfld_limit_t {
52 struct psb_intel_range_t dot, m, p1;
53};
54
55struct 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
71void 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
102void 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
134static 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
243static 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 enalbe 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
312const 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
320static struct drm_device globle_dev;
321
322void 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
341int 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->pitch + x * (crtc->fb->bits_per_pixel / 8);
394
395 REG_WRITE(dspstride, crtc->fb->pitch);
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
428psb_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
433psb_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 */
442void 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 */
529static 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
565/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
566/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
567
568 switch (pipe) {
569 case 0:
570 break;
571 case 1:
572 dpll_reg = DPLL_B;
573 dspcntr_reg = DSPBCNTR;
574 dspbase_reg = MRST_DSPBBASE;
575 pipeconf_reg = PIPEBCONF;
576 pipeconf = dev_priv->pipeconf1;
577 dspcntr = dev_priv->dspcntr1;
578 dpll_reg = MDFLD_DPLL_B;
579 break;
580 case 2:
581 dpll_reg = MRST_DPLL_A;
582 dspcntr_reg = DSPCCNTR;
583 dspbase_reg = MDFLD_DSPCBASE;
584 pipeconf_reg = PIPECCONF;
585 pipestat_reg = PIPECSTAT;
586 pipeconf = dev_priv->pipeconf2;
587 dspcntr = dev_priv->dspcntr2;
588 gen_fifo_stat_reg = GEN_FIFO_STAT_REG + MIPIC_REG_OFFSET;
589 mipi_enable_reg = MIPIA_DEVICE_READY_REG + MIPIC_REG_OFFSET;
590 break;
591 default:
592 dev_err(dev->dev, "Illegal Pipe Number.\n");
593 return;
594 }
595
596 /* XXX: When our outputs are all unaware of DPMS modes other than off
597 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
598 */
599 switch (mode) {
600 case DRM_MODE_DPMS_ON:
601 case DRM_MODE_DPMS_STANDBY:
602 case DRM_MODE_DPMS_SUSPEND:
603 /* Enable the DPLL */
604 temp = REG_READ(dpll_reg);
605
606 if ((temp & DPLL_VCO_ENABLE) == 0) {
607 /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
608 if (temp & MDFLD_PWR_GATE_EN) {
609 temp &= ~MDFLD_PWR_GATE_EN;
610 REG_WRITE(dpll_reg, temp);
611 /* FIXME_MDFLD PO - change 500 to 1 after PO */
612 udelay(500);
613 }
614
615 REG_WRITE(dpll_reg, temp);
616 REG_READ(dpll_reg);
617 /* FIXME_MDFLD PO - change 500 to 1 after PO */
618 udelay(500);
619
620 REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
621 REG_READ(dpll_reg);
622
623 /**
624 * wait for DSI PLL to lock
625 * NOTE: only need to poll status of pipe 0 and pipe 1,
626 * since both MIPI pipes share the same PLL.
627 */
628 while ((pipe != 2) && (timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
629 udelay(150);
630 timeout ++;
631 }
632 }
633
634 /* Enable the plane */
635 temp = REG_READ(dspcntr_reg);
636 if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
637 REG_WRITE(dspcntr_reg,
638 temp | DISPLAY_PLANE_ENABLE);
639 /* Flush the plane changes */
640 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
641 }
642
643 /* Enable the pipe */
644 temp = REG_READ(pipeconf_reg);
645 if ((temp & PIPEACONF_ENABLE) == 0) {
646 REG_WRITE(pipeconf_reg, pipeconf);
647
648 /* Wait for for the pipe enable to take effect. */
649 mdfldWaitForPipeEnable(dev, pipe);
650 }
651
652 /*workaround for sighting 3741701 Random X blank display*/
653 /*perform w/a in video mode only on pipe A or C*/
654 if ((pipe == 0 || pipe == 2) &&
655 (mdfld_panel_dpi(dev) == true)) {
656 REG_WRITE(pipestat_reg, REG_READ(pipestat_reg));
657 msleep(100);
658 if(PIPE_VBLANK_STATUS & REG_READ(pipestat_reg)) {
659 printk(KERN_ALERT "OK");
660 } else {
661 printk(KERN_ALERT "STUCK!!!!");
662 /*shutdown controller*/
663 temp = REG_READ(dspcntr_reg);
664 REG_WRITE(dspcntr_reg, temp & ~DISPLAY_PLANE_ENABLE);
665 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
666 /*mdfld_dsi_dpi_shut_down(dev, pipe);*/
667 REG_WRITE(0xb048, 1);
668 msleep(100);
669 temp = REG_READ(pipeconf_reg);
670 temp &= ~PIPEACONF_ENABLE;
671 REG_WRITE(pipeconf_reg, temp);
672 msleep(100); /*wait for pipe disable*/
673 /*printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
674 printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));*/
675 REG_WRITE(mipi_enable_reg, 0);
676 msleep(100);
677 printk(KERN_ALERT "70008 is %x\n", REG_READ(0x70008));
678 printk(KERN_ALERT "b074 is %x\n", REG_READ(0xb074));
679 REG_WRITE(0xb004, REG_READ(0xb004));
680 /* try to bring the controller back up again*/
681 REG_WRITE(mipi_enable_reg, 1);
682 temp = REG_READ(dspcntr_reg);
683 REG_WRITE(dspcntr_reg, temp | DISPLAY_PLANE_ENABLE);
684 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
685 /*mdfld_dsi_dpi_turn_on(dev, pipe);*/
686 REG_WRITE(0xb048, 2);
687 msleep(100);
688 temp = REG_READ(pipeconf_reg);
689 temp |= PIPEACONF_ENABLE;
690 REG_WRITE(pipeconf_reg, temp);
691 }
692 }
693
694 psb_intel_crtc_load_lut(crtc);
695
696 /* Give the overlay scaler a chance to enable
697 if it's on this pipe */
698 /* psb_intel_crtc_dpms_video(crtc, true); TODO */
699
700 break;
701 case DRM_MODE_DPMS_OFF:
702 /* Give the overlay scaler a chance to disable
703 * if it's on this pipe */
704 /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
705 if (pipe != 1)
706 mdfld_dsi_gen_fifo_ready (dev, gen_fifo_stat_reg, HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
707
708 /* Disable the VGA plane that we never use */
709 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
710
711 /* Disable display plane */
712 temp = REG_READ(dspcntr_reg);
713 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
714 REG_WRITE(dspcntr_reg,
715 temp & ~DISPLAY_PLANE_ENABLE);
716 /* Flush the plane changes */
717 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
718 REG_READ(dspbase_reg);
719 }
720
721 /* FIXME_JLIU7 MDFLD_PO revisit */
722 /* Wait for vblank for the disable to take effect */
723// MDFLD_PO_JLIU7 psb_intel_wait_for_vblank(dev);
724
725 /* Next, disable display pipes */
726 temp = REG_READ(pipeconf_reg);
727 if ((temp & PIPEACONF_ENABLE) != 0) {
728 temp &= ~PIPEACONF_ENABLE;
729 temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
730 REG_WRITE(pipeconf_reg, temp);
731// REG_WRITE(pipeconf_reg, 0);
732 REG_READ(pipeconf_reg);
733
734 /* Wait for for the pipe disable to take effect. */
735 mdfldWaitForPipeDisable(dev, pipe);
736 }
737
738 temp = REG_READ(dpll_reg);
739 if (temp & DPLL_VCO_ENABLE) {
740 if (((pipe != 1) && !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
741 || (pipe == 1)){
742 temp &= ~(DPLL_VCO_ENABLE);
743 REG_WRITE(dpll_reg, temp);
744 REG_READ(dpll_reg);
745 /* Wait for the clocks to turn off. */
746 /* FIXME_MDFLD PO may need more delay */
747 udelay(500);
748#if 0 /* MDFLD_PO_JLIU7 */
749 if (!(temp & MDFLD_PWR_GATE_EN)) {
750 /* gating power of DPLL */
751 REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
752 /* FIXME_MDFLD PO - change 500 to 1 after PO */
753 udelay(5000);
754 }
755#endif /* MDFLD_PO_JLIU7 */
756 }
757 }
758 break;
759 }
760
761 enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
762
763#if 0 /* JB: Add vblank support later */
764 if (enabled)
765 dev_priv->vblank_pipe |= (1 << pipe);
766 else
767 dev_priv->vblank_pipe &= ~(1 << pipe);
768#endif
769
770 gma_power_end(dev);
771}
772
773
774#define MDFLD_LIMT_DPLL_19 0
775#define MDFLD_LIMT_DPLL_25 1
776#define MDFLD_LIMT_DPLL_83 2
777#define MDFLD_LIMT_DPLL_100 3
778#define MDFLD_LIMT_DSIPLL_19 4
779#define MDFLD_LIMT_DSIPLL_25 5
780#define MDFLD_LIMT_DSIPLL_83 6
781#define MDFLD_LIMT_DSIPLL_100 7
782
783#define MDFLD_DOT_MIN 19750 /* FIXME_MDFLD JLIU7 need to find out min & max for MDFLD */
784#define MDFLD_DOT_MAX 120000
785#define MDFLD_DPLL_M_MIN_19 113
786#define MDFLD_DPLL_M_MAX_19 155
787#define MDFLD_DPLL_P1_MIN_19 2
788#define MDFLD_DPLL_P1_MAX_19 10
789#define MDFLD_DPLL_M_MIN_25 101
790#define MDFLD_DPLL_M_MAX_25 130
791#define MDFLD_DPLL_P1_MIN_25 2
792#define MDFLD_DPLL_P1_MAX_25 10
793#define MDFLD_DPLL_M_MIN_83 64
794#define MDFLD_DPLL_M_MAX_83 64
795#define MDFLD_DPLL_P1_MIN_83 2
796#define MDFLD_DPLL_P1_MAX_83 2
797#define MDFLD_DPLL_M_MIN_100 64
798#define MDFLD_DPLL_M_MAX_100 64
799#define MDFLD_DPLL_P1_MIN_100 2
800#define MDFLD_DPLL_P1_MAX_100 2
801#define MDFLD_DSIPLL_M_MIN_19 131
802#define MDFLD_DSIPLL_M_MAX_19 175
803#define MDFLD_DSIPLL_P1_MIN_19 3
804#define MDFLD_DSIPLL_P1_MAX_19 8
805#define MDFLD_DSIPLL_M_MIN_25 97
806#define MDFLD_DSIPLL_M_MAX_25 140
807#define MDFLD_DSIPLL_P1_MIN_25 3
808#define MDFLD_DSIPLL_P1_MAX_25 9
809#define MDFLD_DSIPLL_M_MIN_83 33
810#define MDFLD_DSIPLL_M_MAX_83 92
811#define MDFLD_DSIPLL_P1_MIN_83 2
812#define MDFLD_DSIPLL_P1_MAX_83 3
813#define MDFLD_DSIPLL_M_MIN_100 97
814#define MDFLD_DSIPLL_M_MAX_100 140
815#define MDFLD_DSIPLL_P1_MIN_100 3
816#define MDFLD_DSIPLL_P1_MAX_100 9
817
818static const struct mdfld_limit_t mdfld_limits[] = {
819 { /* MDFLD_LIMT_DPLL_19 */
820 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
821 .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19},
822 .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19},
823 },
824 { /* MDFLD_LIMT_DPLL_25 */
825 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
826 .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25},
827 .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25},
828 },
829 { /* MDFLD_LIMT_DPLL_83 */
830 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
831 .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83},
832 .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83},
833 },
834 { /* MDFLD_LIMT_DPLL_100 */
835 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
836 .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100},
837 .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100},
838 },
839 { /* MDFLD_LIMT_DSIPLL_19 */
840 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
841 .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19},
842 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19},
843 },
844 { /* MDFLD_LIMT_DSIPLL_25 */
845 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
846 .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25},
847 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25},
848 },
849 { /* MDFLD_LIMT_DSIPLL_83 */
850 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
851 .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83},
852 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83},
853 },
854 { /* MDFLD_LIMT_DSIPLL_100 */
855 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
856 .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100},
857 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100},
858 },
859};
860
861#define MDFLD_M_MIN 21
862#define MDFLD_M_MAX 180
863static const u32 mdfld_m_converts[] = {
864/* M configuration table from 9-bit LFSR table */
865 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */
866 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */
867 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */
868 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */
869 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */
870 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
871 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
872 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */
873 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */
874 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */
875 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */
876 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */
877 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */
878 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */
879 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */
880 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */
881};
882
883static const struct mdfld_limit_t *mdfld_limit(struct drm_crtc *crtc)
884{
885 const struct mdfld_limit_t *limit = NULL;
886 struct drm_device *dev = crtc->dev;
887 struct drm_psb_private *dev_priv = dev->dev_private;
888
889 if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)
890 || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) {
891 if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
892 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19];
893 else if (ksel == KSEL_BYPASS_25)
894 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25];
895 else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
896 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83];
897 else if ((ksel == KSEL_BYPASS_83_100) &&
898 (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
899 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100];
900 } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
901 if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
902 limit = &mdfld_limits[MDFLD_LIMT_DPLL_19];
903 else if (ksel == KSEL_BYPASS_25)
904 limit = &mdfld_limits[MDFLD_LIMT_DPLL_25];
905 else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166))
906 limit = &mdfld_limits[MDFLD_LIMT_DPLL_83];
907 else if ((ksel == KSEL_BYPASS_83_100) &&
908 (dev_priv->core_freq == 100 || dev_priv->core_freq == 200))
909 limit = &mdfld_limits[MDFLD_LIMT_DPLL_100];
910 } else {
911 limit = NULL;
912 dev_err(dev->dev, "mdfld_limit Wrong display type.\n");
913 }
914
915 return limit;
916}
917
918/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
919static void mdfld_clock(int refclk, struct mdfld_intel_clock_t *clock)
920{
921 clock->dot = (refclk * clock->m) / clock->p1;
922}
923
924/**
925 * Returns a set of divisors for the desired target clock with the given refclk,
926 * or FALSE. Divisor values are the actual divisors for
927 */
928static bool
929mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
930 struct mdfld_intel_clock_t *best_clock)
931{
932 struct mdfld_intel_clock_t clock;
933 const struct mdfld_limit_t *limit = mdfld_limit(crtc);
934 int err = target;
935
936 memset(best_clock, 0, sizeof(*best_clock));
937
938 for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
939 for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
940 clock.p1++) {
941 int this_err;
942
943 mdfld_clock(refclk, &clock);
944
945 this_err = abs(clock.dot - target);
946 if (this_err < err) {
947 *best_clock = clock;
948 err = this_err;
949 }
950 }
951 }
952 return err != target;
953}
954
955/**
956 * Return the pipe currently connected to the panel fitter,
957 * or -1 if the panel fitter is not present or not in use
958 */
959static int mdfld_panel_fitter_pipe(struct drm_device *dev)
960{
961 u32 pfit_control;
962
963 pfit_control = REG_READ(PFIT_CONTROL);
964
965 /* See if the panel fitter is in use */
966 if ((pfit_control & PFIT_ENABLE) == 0)
967 return -1;
968 return (pfit_control >> 29) & 3;
969}
970
971static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
972 struct drm_display_mode *mode,
973 struct drm_display_mode *adjusted_mode,
974 int x, int y,
975 struct drm_framebuffer *old_fb)
976{
977 struct drm_device *dev = crtc->dev;
978 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
979 struct drm_psb_private *dev_priv = dev->dev_private;
980 int pipe = psb_intel_crtc->pipe;
981 int fp_reg = MRST_FPA0;
982 int dpll_reg = MRST_DPLL_A;
983 int dspcntr_reg = DSPACNTR;
984 int pipeconf_reg = PIPEACONF;
985 int htot_reg = HTOTAL_A;
986 int hblank_reg = HBLANK_A;
987 int hsync_reg = HSYNC_A;
988 int vtot_reg = VTOTAL_A;
989 int vblank_reg = VBLANK_A;
990 int vsync_reg = VSYNC_A;
991 int dspsize_reg = DSPASIZE;
992 int dsppos_reg = DSPAPOS;
993 int pipesrc_reg = PIPEASRC;
994 u32 *pipeconf = &dev_priv->pipeconf;
995 u32 *dspcntr = &dev_priv->dspcntr;
996 int refclk = 0;
997 int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0, clk_tmp = 0;
998 struct mdfld_intel_clock_t clock;
999 bool ok;
1000 u32 dpll = 0, fp = 0;
1001 bool is_crt = false, is_lvds = false, is_tv = false;
1002 bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
1003 struct drm_mode_config *mode_config = &dev->mode_config;
1004 struct psb_intel_output *psb_intel_output = NULL;
1005 uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
1006 struct drm_encoder *encoder;
1007 struct drm_connector *connector;
1008 int timeout = 0;
1009
1010 dev_dbg(dev->dev, "pipe = 0x%x \n", pipe);
1011
1012 switch (pipe) {
1013 case 0:
1014 break;
1015 case 1:
1016 fp_reg = FPB0;
1017 dpll_reg = DPLL_B;
1018 dspcntr_reg = DSPBCNTR;
1019 pipeconf_reg = PIPEBCONF;
1020 htot_reg = HTOTAL_B;
1021 hblank_reg = HBLANK_B;
1022 hsync_reg = HSYNC_B;
1023 vtot_reg = VTOTAL_B;
1024 vblank_reg = VBLANK_B;
1025 vsync_reg = VSYNC_B;
1026 dspsize_reg = DSPBSIZE;
1027 dsppos_reg = DSPBPOS;
1028 pipesrc_reg = PIPEBSRC;
1029 pipeconf = &dev_priv->pipeconf1;
1030 dspcntr = &dev_priv->dspcntr1;
1031 fp_reg = MDFLD_DPLL_DIV0;
1032 dpll_reg = MDFLD_DPLL_B;
1033 break;
1034 case 2:
1035 dpll_reg = MRST_DPLL_A;
1036 dspcntr_reg = DSPCCNTR;
1037 pipeconf_reg = PIPECCONF;
1038 htot_reg = HTOTAL_C;
1039 hblank_reg = HBLANK_C;
1040 hsync_reg = HSYNC_C;
1041 vtot_reg = VTOTAL_C;
1042 vblank_reg = VBLANK_C;
1043 vsync_reg = VSYNC_C;
1044 dspsize_reg = DSPCSIZE;
1045 dsppos_reg = DSPCPOS;
1046 pipesrc_reg = PIPECSRC;
1047 pipeconf = &dev_priv->pipeconf2;
1048 dspcntr = &dev_priv->dspcntr2;
1049 break;
1050 default:
1051 DRM_ERROR("Illegal Pipe Number. \n");
1052 return 0;
1053 }
1054
1055 dev_dbg(dev->dev, "adjusted_hdisplay = %d\n",
1056 adjusted_mode->hdisplay);
1057 dev_dbg(dev->dev, "adjusted_vdisplay = %d\n",
1058 adjusted_mode->vdisplay);
1059 dev_dbg(dev->dev, "adjusted_hsync_start = %d\n",
1060 adjusted_mode->hsync_start);
1061 dev_dbg(dev->dev, "adjusted_hsync_end = %d\n",
1062 adjusted_mode->hsync_end);
1063 dev_dbg(dev->dev, "adjusted_htotal = %d\n",
1064 adjusted_mode->htotal);
1065 dev_dbg(dev->dev, "adjusted_vsync_start = %d\n",
1066 adjusted_mode->vsync_start);
1067 dev_dbg(dev->dev, "adjusted_vsync_end = %d\n",
1068 adjusted_mode->vsync_end);
1069 dev_dbg(dev->dev, "adjusted_vtotal = %d\n",
1070 adjusted_mode->vtotal);
1071 dev_dbg(dev->dev, "adjusted_clock = %d\n",
1072 adjusted_mode->clock);
1073 dev_dbg(dev->dev, "hdisplay = %d\n",
1074 mode->hdisplay);
1075 dev_dbg(dev->dev, "vdisplay = %d\n",
1076 mode->vdisplay);
1077
1078 if (!gma_power_begin(dev, true))
1079 return 0;
1080
1081 memcpy(&psb_intel_crtc->saved_mode, mode, sizeof(struct drm_display_mode));
1082 memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode, sizeof(struct drm_display_mode));
1083
1084 list_for_each_entry(connector, &mode_config->connector_list, head) {
1085
1086 encoder = connector->encoder;
1087
1088 if(!encoder)
1089 continue;
1090
1091 if (encoder->crtc != crtc)
1092 continue;
1093
1094 psb_intel_output = to_psb_intel_output(connector);
1095
1096 dev_dbg(dev->dev, "output->type = 0x%x \n", psb_intel_output->type);
1097
1098 switch (psb_intel_output->type) {
1099 case INTEL_OUTPUT_LVDS:
1100 is_lvds = true;
1101 break;
1102 case INTEL_OUTPUT_TVOUT:
1103 is_tv = true;
1104 break;
1105 case INTEL_OUTPUT_ANALOG:
1106 is_crt = true;
1107 break;
1108 case INTEL_OUTPUT_MIPI:
1109 is_mipi = true;
1110 break;
1111 case INTEL_OUTPUT_MIPI2:
1112 is_mipi2 = true;
1113 break;
1114 case INTEL_OUTPUT_HDMI:
1115 is_hdmi = true;
1116 break;
1117 }
1118 }
1119
1120 /* Disable the VGA plane that we never use */
1121 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
1122
1123 /* Disable the panel fitter if it was on our pipe */
1124 if (mdfld_panel_fitter_pipe(dev) == pipe)
1125 REG_WRITE(PFIT_CONTROL, 0);
1126
1127 /* pipesrc and dspsize control the size that is scaled from,
1128 * which should always be the user's requested size.
1129 */
1130 if (pipe == 1) {
1131 /* FIXME: To make HDMI display with 864x480 (TPO), 480x864 (PYR) or 480x854 (TMD), set the sprite
1132 * width/height and souce image size registers with the adjusted mode for pipe B. */
1133
1134 /* The defined sprite rectangle must always be completely contained within the displayable
1135 * area of the screen image (frame buffer). */
1136 REG_WRITE(dspsize_reg, ((MIN(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
1137 | (MIN(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
1138 /* Set the CRTC with encoder mode. */
1139 REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16)
1140 | (mode->crtc_vdisplay - 1));
1141 } else {
1142 REG_WRITE(dspsize_reg, ((mode->crtc_vdisplay - 1) << 16) | (mode->crtc_hdisplay - 1));
1143 REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
1144 }
1145
1146 REG_WRITE(dsppos_reg, 0);
1147
1148 if (psb_intel_output)
1149 drm_connector_property_get_value(&psb_intel_output->base,
1150 dev->mode_config.scaling_mode_property, &scalingType);
1151
1152 if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
1153 /*Moorestown doesn't have register support for centering so we need to
1154 mess with the h/vblank and h/vsync start and ends to get centering*/
1155 int offsetX = 0, offsetY = 0;
1156
1157 offsetX = (adjusted_mode->crtc_hdisplay - mode->crtc_hdisplay) / 2;
1158 offsetY = (adjusted_mode->crtc_vdisplay - mode->crtc_vdisplay) / 2;
1159
1160 REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
1161 ((adjusted_mode->crtc_htotal - 1) << 16));
1162 REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
1163 ((adjusted_mode->crtc_vtotal - 1) << 16));
1164 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - offsetX - 1) |
1165 ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
1166 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - offsetX - 1) |
1167 ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
1168 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - offsetY - 1) |
1169 ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
1170 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - offsetY - 1) |
1171 ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
1172 } else {
1173 REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
1174 ((adjusted_mode->crtc_htotal - 1) << 16));
1175 REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
1176 ((adjusted_mode->crtc_vtotal - 1) << 16));
1177 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
1178 ((adjusted_mode->crtc_hblank_end - 1) << 16));
1179 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
1180 ((adjusted_mode->crtc_hsync_end - 1) << 16));
1181 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
1182 ((adjusted_mode->crtc_vblank_end - 1) << 16));
1183 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
1184 ((adjusted_mode->crtc_vsync_end - 1) << 16));
1185 }
1186
1187 /* Flush the plane changes */
1188 {
1189 struct drm_crtc_helper_funcs *crtc_funcs =
1190 crtc->helper_private;
1191 crtc_funcs->mode_set_base(crtc, x, y, old_fb);
1192 }
1193
1194 /* setup pipeconf */
1195 *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
1196
1197 /* Set up the display plane register */
1198 *dspcntr = REG_READ(dspcntr_reg);
1199 *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS;
1200 *dspcntr |= DISPLAY_PLANE_ENABLE;
1201/* MDFLD_PO_JLIU7 dspcntr |= DISPPLANE_BOTTOM; */
1202/* MDFLD_PO_JLIU7 dspcntr |= DISPPLANE_GAMMA_ENABLE; */
1203
1204 if (is_mipi2)
1205 {
1206 goto mrst_crtc_mode_set_exit;
1207 }
1208/* FIXME JLIU7 Add MDFLD HDMI supports */
1209/* FIXME_MDFLD JLIU7 DSIPLL clock *= 8? */
1210/* FIXME_MDFLD JLIU7 need to revist for dual MIPI supports */
1211 clk = adjusted_mode->clock;
1212
1213 if (is_hdmi) {
1214 if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
1215 {
1216 refclk = 19200;
1217
1218 if (is_mipi || is_mipi2)
1219 {
1220 clk_n = 1, clk_p2 = 8;
1221 } else if (is_hdmi) {
1222 clk_n = 1, clk_p2 = 10;
1223 }
1224 } else if (ksel == KSEL_BYPASS_25) {
1225 refclk = 25000;
1226
1227 if (is_mipi || is_mipi2)
1228 {
1229 clk_n = 1, clk_p2 = 8;
1230 } else if (is_hdmi) {
1231 clk_n = 1, clk_p2 = 10;
1232 }
1233 } else if ((ksel == KSEL_BYPASS_83_100) && (dev_priv->core_freq == 166)) {
1234 refclk = 83000;
1235
1236 if (is_mipi || is_mipi2)
1237 {
1238 clk_n = 4, clk_p2 = 8;
1239 } else if (is_hdmi) {
1240 clk_n = 4, clk_p2 = 10;
1241 }
1242 } else if ((ksel == KSEL_BYPASS_83_100) &&
1243 (dev_priv->core_freq == 100 || dev_priv->core_freq == 200)) {
1244 refclk = 100000;
1245 if (is_mipi || is_mipi2)
1246 {
1247 clk_n = 4, clk_p2 = 8;
1248 } else if (is_hdmi) {
1249 clk_n = 4, clk_p2 = 10;
1250 }
1251 }
1252
1253 if (is_mipi)
1254 clk_byte = dev_priv->bpp / 8;
1255 else if (is_mipi2)
1256 clk_byte = dev_priv->bpp2 / 8;
1257
1258 clk_tmp = clk * clk_n * clk_p2 * clk_byte;
1259
1260 dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d. \n", clk, clk_n, clk_p2);
1261 dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d. \n", adjusted_mode->clock, clk_tmp);
1262
1263 ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock);
1264
1265 if (!ok) {
1266 dev_err(dev->dev,
1267 "mdfldFindBestPLL fail in mdfld_crtc_mode_set. \n");
1268 } else {
1269 m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)];
1270
1271 dev_dbg(dev->dev, "dot clock = %d,"
1272 "m = %d, p1 = %d, m_conv = %d. \n", clock.dot, clock.m,
1273 clock.p1, m_conv);
1274 }
1275
1276 dpll = REG_READ(dpll_reg);
1277
1278 if (dpll & DPLL_VCO_ENABLE) {
1279 dpll &= ~DPLL_VCO_ENABLE;
1280 REG_WRITE(dpll_reg, dpll);
1281 REG_READ(dpll_reg);
1282
1283 /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
1284 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1285 udelay(500);
1286
1287 /* reset M1, N1 & P1 */
1288 REG_WRITE(fp_reg, 0);
1289 dpll &= ~MDFLD_P1_MASK;
1290 REG_WRITE(dpll_reg, dpll);
1291 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1292 udelay(500);
1293 }
1294
1295 /* When ungating power of DPLL, needs to wait 0.5us before enable the VCO */
1296 if (dpll & MDFLD_PWR_GATE_EN) {
1297 dpll &= ~MDFLD_PWR_GATE_EN;
1298 REG_WRITE(dpll_reg, dpll);
1299 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1300 udelay(500);
1301 }
1302
1303 dpll = 0;
1304
1305#if 0 /* FIXME revisit later */
1306 if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19) || (ksel == KSEL_BYPASS_25)) {
1307 dpll &= ~MDFLD_INPUT_REF_SEL;
1308 } else if (ksel == KSEL_BYPASS_83_100) {
1309 dpll |= MDFLD_INPUT_REF_SEL;
1310 }
1311#endif /* FIXME revisit later */
1312
1313 if (is_hdmi)
1314 dpll |= MDFLD_VCO_SEL;
1315
1316 fp = (clk_n / 2) << 16;
1317 fp |= m_conv;
1318
1319 /* compute bitmask from p1 value */
1320 dpll |= (1 << (clock.p1 - 2)) << 17;
1321
1322#if 0 /* 1080p30 & 720p */
1323 dpll = 0x00050000;
1324 fp = 0x000001be;
1325#endif
1326#if 0 /* 480p */
1327 dpll = 0x02010000;
1328 fp = 0x000000d2;
1329#endif
1330 } else {
1331#if 0 /*DBI_TPO_480x864*/
1332 dpll = 0x00020000;
1333 fp = 0x00000156;
1334#endif /* DBI_TPO_480x864 */ /* get from spec. */
1335
1336 dpll = 0x00800000;
1337 fp = 0x000000c1;
1338}
1339
1340 REG_WRITE(fp_reg, fp);
1341 REG_WRITE(dpll_reg, dpll);
1342 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1343 udelay(500);
1344
1345 dpll |= DPLL_VCO_ENABLE;
1346 REG_WRITE(dpll_reg, dpll);
1347 REG_READ(dpll_reg);
1348
1349 /* wait for DSI PLL to lock */
1350 while ((timeout < 20000) && !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
1351 udelay(150);
1352 timeout ++;
1353 }
1354
1355 if (is_mipi)
1356 goto mrst_crtc_mode_set_exit;
1357
1358 dev_dbg(dev->dev, "is_mipi = 0x%x \n", is_mipi);
1359
1360 REG_WRITE(pipeconf_reg, *pipeconf);
1361 REG_READ(pipeconf_reg);
1362
1363 /* Wait for for the pipe enable to take effect. */
1364//FIXME_JLIU7 HDMI mrstWaitForPipeEnable(dev);
1365
1366 REG_WRITE(dspcntr_reg, *dspcntr);
1367 psb_intel_wait_for_vblank(dev);
1368
1369mrst_crtc_mode_set_exit:
1370
1371 gma_power_end(dev);
1372
1373 return 0;
1374}
1375
1376static void mdfld_crtc_prepare(struct drm_crtc *crtc)
1377{
1378 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
1379 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
1380}
1381
1382static void mdfld_crtc_commit(struct drm_crtc *crtc)
1383{
1384 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
1385 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
1386}
1387
1388static bool mdfld_crtc_mode_fixup(struct drm_crtc *crtc,
1389 struct drm_display_mode *mode,
1390 struct drm_display_mode *adjusted_mode)
1391{
1392 return true;
1393}
1394
1395const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
1396 .dpms = mdfld_crtc_dpms,
1397 .mode_fixup = mdfld_crtc_mode_fixup,
1398 .mode_set = mdfld_crtc_mode_set,
1399 .mode_set_base = mdfld__intel_pipe_set_base,
1400 .prepare = mdfld_crtc_prepare,
1401 .commit = mdfld_crtc_commit,
1402};
diff --git a/drivers/staging/gma500/mdfld_msic.h b/drivers/staging/gma500/mdfld_msic.h
new file mode 100644
index 00000000000..a7ad6547249
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_msic.h
@@ -0,0 +1,31 @@
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
29int msic_regsiter_driver(void);
30int msic_unregister_driver(void);
31extern void hpd_notify_um(void);
diff --git a/drivers/staging/gma500/mdfld_output.c b/drivers/staging/gma500/mdfld_output.c
new file mode 100644
index 00000000000..ee55f87ba1f
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_output.c
@@ -0,0 +1,170 @@
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 "mdfld_dsi_dbi.h"
30#include "mdfld_dsi_dpi.h"
31#include "mdfld_dsi_output.h"
32#include "mdfld_output.h"
33#include "mdfld_dsi_dbi_dpu.h"
34
35#include "displays/tpo_cmd.h"
36#include "displays/tpo_vid.h"
37#include "displays/tmd_cmd.h"
38#include "displays/tmd_vid.h"
39#include "displays/pyr_cmd.h"
40#include "displays/pyr_vid.h"
41/* #include "displays/hdmi.h" */
42
43static int mdfld_dual_mipi;
44static int mdfld_hdmi;
45static int mdfld_dpu;
46
47module_param(mdfld_dual_mipi, int, 0600);
48MODULE_PARM_DESC(mdfld_dual_mipi, "Enable dual MIPI configuration");
49module_param(mdfld_hdmi, int, 0600);
50MODULE_PARM_DESC(mdfld_hdmi, "Enable Medfield HDMI");
51module_param(mdfld_dpu, int, 0600);
52MODULE_PARM_DESC(mdfld_dpu, "Enable Medfield DPU");
53
54/* For now a single type per device is all we cope with */
55int mdfld_get_panel_type(struct drm_device *dev, int pipe)
56{
57 struct drm_psb_private *dev_priv = dev->dev_private;
58 return dev_priv->panel_id;
59}
60
61int mdfld_panel_dpi(struct drm_device *dev)
62{
63 struct drm_psb_private *dev_priv = dev->dev_private;
64
65 switch (dev_priv->panel_id) {
66 case TMD_VID:
67 case TPO_VID:
68 case PYR_VID:
69 return true;
70 case TMD_CMD:
71 case TPO_CMD:
72 case PYR_CMD:
73 default:
74 return false;
75 }
76}
77
78static int init_panel(struct drm_device *dev, int mipi_pipe, int p_type)
79{
80 struct panel_funcs *p_cmd_funcs;
81 struct panel_funcs *p_vid_funcs;
82
83 /* Oh boy ... FIXME */
84 p_cmd_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
85 if (p_cmd_funcs == NULL)
86 return -ENODEV;
87 p_vid_funcs = kzalloc(sizeof(struct panel_funcs), GFP_KERNEL);
88 if (p_vid_funcs == NULL) {
89 kfree(p_cmd_funcs);
90 return -ENODEV;
91 }
92
93 switch (p_type) {
94 case TPO_CMD:
95 tpo_cmd_init(dev, p_cmd_funcs);
96 mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
97 break;
98 case TPO_VID:
99 tpo_vid_init(dev, p_vid_funcs);
100 mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
101 break;
102 case TMD_CMD:
103 /*tmd_cmd_init(dev, p_cmd_funcs); */
104 mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
105 break;
106 case TMD_VID:
107 tmd_vid_init(dev, p_vid_funcs);
108 mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
109 break;
110 case PYR_CMD:
111 pyr_cmd_init(dev, p_cmd_funcs);
112 mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs, NULL);
113 break;
114 case PYR_VID:
115 mdfld_dsi_output_init(dev, mipi_pipe, NULL, NULL, p_vid_funcs);
116 break;
117 case TPO: /* TPO panel supports both cmd & vid interfaces */
118 tpo_cmd_init(dev, p_cmd_funcs);
119 tpo_vid_init(dev, p_vid_funcs);
120 mdfld_dsi_output_init(dev, mipi_pipe, NULL, p_cmd_funcs,
121 p_vid_funcs);
122 break;
123 case TMD:
124 break;
125 case PYR:
126 break;
127#if 0
128 case HDMI:
129 dev_dbg(dev->dev, "Initializing HDMI");
130 mdfld_hdmi_init(dev, &dev_priv->mode_dev);
131 break;
132#endif
133 default:
134 dev_err(dev->dev, "Unsupported interface %d", p_type);
135 return -ENODEV;
136 }
137 return 0;
138}
139
140int mdfld_output_init(struct drm_device *dev)
141{
142 int type;
143
144 /* MIPI panel 1 */
145 type = mdfld_get_panel_type(dev, 0);
146 dev_info(dev->dev, "panel 1: type is %d\n", type);
147 init_panel(dev, 0, type);
148
149 if (mdfld_dual_mipi) {
150 /* MIPI panel 2 */
151 type = mdfld_get_panel_type(dev, 2);
152 dev_info(dev->dev, "panel 2: type is %d\n", type);
153 init_panel(dev, 2, type);
154 }
155 if (mdfld_hdmi)
156 /* HDMI panel */
157 init_panel(dev, 0, HDMI);
158 return 0;
159}
160
161void mdfld_output_setup(struct drm_device *dev)
162{
163 /* FIXME: this is not the right place for this stuff ! */
164 if (IS_MFLD(dev)) {
165 if (mdfld_dpu)
166 mdfld_dbi_dpu_init(dev);
167 else
168 mdfld_dbi_dsr_init(dev);
169 }
170} \ No newline at end of file
diff --git a/drivers/staging/gma500/mdfld_output.h b/drivers/staging/gma500/mdfld_output.h
new file mode 100644
index 00000000000..daf33e7df9d
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_output.h
@@ -0,0 +1,41 @@
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
31int mdfld_output_init(struct drm_device *dev);
32int mdfld_panel_dpi(struct drm_device *dev);
33int mdfld_get_panel_type(struct drm_device *dev, int pipe);
34void mdfld_disable_crtc (struct drm_device *dev, int pipe);
35
36extern const struct drm_crtc_helper_funcs mdfld_helper_funcs;
37extern const struct drm_crtc_funcs mdfld_intel_crtc_funcs;
38
39extern 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
new file mode 100644
index 00000000000..523f2d8fe4f
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_pyr_cmd.c
@@ -0,0 +1,558 @@
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
37static 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
75static 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
98static 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
174out_err:
175 gma_power_end(dev);
176
177 if (ret)
178 dev_err(dev->dev, "failed\n");
179}
180
181static 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
231static 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 &param, 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
337out_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
346static 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
358static 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
386static 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 */
404static 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;
509update_fb_out0:
510 gma_power_end(dev);
511}
512
513/*
514 * TODO: will be removed later, should work out display interfaces for power
515 */
516void 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
525static 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 */
538static 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 */
547static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
548 .destroy = drm_encoder_cleanup,
549};
550
551void 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
new file mode 100644
index 00000000000..affdc09c676
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_tmd_vid.c
@@ -0,0 +1,206 @@
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 ? */
40struct 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
104static 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
129static 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 */
178static 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 */
188static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
189 .destroy = drm_encoder_cleanup,
190};
191
192void 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
new file mode 100644
index 00000000000..c7f7c9c19bc
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_tpo_cmd.c
@@ -0,0 +1,509 @@
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
37static 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
100static 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
123static 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
222out_err:
223 gma_power_end(dev);
224 if (ret)
225 dev_err(dev->dev, "failed\n");
226}
227
228
229static 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 &param, 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
325out_err:
326 gma_power_end(dev);
327
328 if (ret)
329 dev_err(dev->dev, "mode set failed\n");
330}
331
332static 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
344static 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
371static 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 */
414static 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;
468update_fb_out0:
469 gma_power_end(dev);
470}
471
472static 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 */
487static 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 */
496static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
497 .destroy = drm_encoder_cleanup,
498};
499
500void 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
new file mode 100644
index 00000000000..95490175176
--- /dev/null
+++ b/drivers/staging/gma500/mdfld_tpo_vid.c
@@ -0,0 +1,140 @@
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
37static 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
100static 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*/
114static 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*/
124static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
125 .destroy = drm_encoder_cleanup,
126};
127
128void 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
new file mode 100644
index 00000000000..09e9687431f
--- /dev/null
+++ b/drivers/staging/gma500/medfield.h
@@ -0,0 +1,268 @@
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
155enum {
156 MDFLD_DSI_ENCODER_DBI = 0,
157 MDFLD_DSI_ENCODER_DPI,
158};
159
160enum {
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 */
169enum {
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 */
192struct panel_info {
193 u32 width_mm;
194 u32 height_mm;
195};
196
197struct mdfld_dsi_dbi_output;
198
199struct mdfld_dsi_connector_state {
200 u32 mipi_ctrl_reg;
201};
202
203struct mdfld_dsi_encoder_state {
204
205};
206
207struct 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
222struct 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 */
231struct 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
259struct 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
new file mode 100644
index 00000000000..8cfe301f8fb
--- /dev/null
+++ b/drivers/staging/gma500/mid_bios.c
@@ -0,0 +1,269 @@
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 <drm/drmP.h>
27#include <drm/drm.h>
28#include "psb_drm.h"
29#include "psb_drv.h"
30#include "mid_bios.h"
31#include "mdfld_output.h"
32
33static int panel_id = GCT_DETECT;
34module_param_named(panel_id, panel_id, int, 0600);
35MODULE_PARM_DESC(panel_id, "Panel Identifier");
36
37
38static void mid_get_fuse_settings(struct drm_device *dev)
39{
40 struct drm_psb_private *dev_priv = dev->dev_private;
41 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
42 uint32_t fuse_value = 0;
43 uint32_t fuse_value_tmp = 0;
44
45#define FB_REG06 0xD0810600
46#define FB_MIPI_DISABLE (1 << 11)
47#define FB_REG09 0xD0810900
48#define FB_REG09 0xD0810900
49#define FB_SKU_MASK 0x7000
50#define FB_SKU_SHIFT 12
51#define FB_SKU_100 0
52#define FB_SKU_100L 1
53#define FB_SKU_83 2
54 pci_write_config_dword(pci_root, 0xD0, FB_REG06);
55 pci_read_config_dword(pci_root, 0xD4, &fuse_value);
56
57 /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
58 if (IS_MRST(dev))
59 dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE;
60
61 DRM_INFO("internal display is %s\n",
62 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display");
63
64 /* Prevent runtime suspend at start*/
65 if (dev_priv->iLVDS_enable) {
66 dev_priv->is_lvds_on = true;
67 dev_priv->is_mipi_on = false;
68 } else {
69 dev_priv->is_mipi_on = true;
70 dev_priv->is_lvds_on = false;
71 }
72
73 dev_priv->video_device_fuse = fuse_value;
74
75 pci_write_config_dword(pci_root, 0xD0, FB_REG09);
76 pci_read_config_dword(pci_root, 0xD4, &fuse_value);
77
78 dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value);
79 fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT;
80
81 dev_priv->fuse_reg_value = fuse_value;
82
83 switch (fuse_value_tmp) {
84 case FB_SKU_100:
85 dev_priv->core_freq = 200;
86 break;
87 case FB_SKU_100L:
88 dev_priv->core_freq = 100;
89 break;
90 case FB_SKU_83:
91 dev_priv->core_freq = 166;
92 break;
93 default:
94 dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n",
95 fuse_value_tmp);
96 dev_priv->core_freq = 0;
97 }
98 dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq);
99 pci_dev_put(pci_root);
100}
101
102/*
103 * Get the revison ID, B0:D2:F0;0x08
104 */
105static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
106{
107 uint32_t platform_rev_id = 0;
108 struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
109
110 pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id);
111 dev_priv->platform_rev_id = (uint8_t) platform_rev_id;
112 pci_dev_put(pci_gfx_root);
113 dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n",
114 dev_priv->platform_rev_id);
115}
116
117static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
118{
119 struct drm_device *dev = dev_priv->dev;
120 struct mrst_vbt *vbt = &dev_priv->vbt_data;
121 u32 addr;
122 u16 new_size;
123 u8 *vbt_virtual;
124 u8 bpi;
125 u8 number_desc = 0;
126 struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD;
127 struct gct_r10_timing_info ti;
128 void *pGCT;
129 struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
130
131 /* Get the address of the platform config vbt, B0:D2:F0;0xFC */
132 pci_read_config_dword(pci_gfx_root, 0xFC, &addr);
133 pci_dev_put(pci_gfx_root);
134
135 dev_dbg(dev->dev, "drm platform config address is %x\n", addr);
136
137 /* check for platform config address == 0. */
138 /* this means fw doesn't support vbt */
139
140 if (addr == 0) {
141 vbt->size = 0;
142 return;
143 }
144
145 /* get the virtual address of the vbt */
146 vbt_virtual = ioremap(addr, sizeof(*vbt));
147
148 memcpy(vbt, vbt_virtual, sizeof(*vbt));
149 iounmap(vbt_virtual); /* Free virtual address space */
150
151 dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision);
152
153 switch (vbt->revision) {
154 case 0:
155 vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
156 vbt->size - sizeof(*vbt) + 4);
157 pGCT = vbt->mrst_gct;
158 bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex;
159 dev_priv->gct_data.bpi = bpi;
160 dev_priv->gct_data.pt =
161 ((struct mrst_gct_v1 *)pGCT)->PD.PanelType;
162 memcpy(&dev_priv->gct_data.DTD,
163 &((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD,
164 sizeof(struct mrst_timing_info));
165 dev_priv->gct_data.Panel_Port_Control =
166 ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control;
167 dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
168 ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
169 break;
170 case 1:
171 vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4,
172 vbt->size - sizeof(*vbt) + 4);
173 pGCT = vbt->mrst_gct;
174 bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex;
175 dev_priv->gct_data.bpi = bpi;
176 dev_priv->gct_data.pt =
177 ((struct mrst_gct_v2 *)pGCT)->PD.PanelType;
178 memcpy(&dev_priv->gct_data.DTD,
179 &((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD,
180 sizeof(struct mrst_timing_info));
181 dev_priv->gct_data.Panel_Port_Control =
182 ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control;
183 dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
184 ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor;
185 break;
186 case 0x10:
187 /*header definition changed from rev 01 (v2) to rev 10h. */
188 /*so, some values have changed location*/
189 new_size = vbt->checksum; /*checksum contains lo size byte*/
190 /*LSB of mrst_gct contains hi size byte*/
191 new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8;
192
193 vbt->checksum = vbt->size; /*size contains the checksum*/
194 if (new_size > 0xff)
195 vbt->size = 0xff; /*restrict size to 255*/
196 else
197 vbt->size = new_size;
198
199 /* number of descriptors defined in the GCT */
200 number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8;
201 bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16;
202 vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE,
203 GCT_R10_DISPLAY_DESC_SIZE * number_desc);
204 pGCT = vbt->mrst_gct;
205 pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE);
206 dev_priv->gct_data.bpi = bpi; /*save boot panel id*/
207
208 /*copy the GCT display timings into a temp structure*/
209 memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info));
210
211 /*now copy the temp struct into the dev_priv->gct_data*/
212 dp_ti->pixel_clock = ti.pixel_clock;
213 dp_ti->hactive_hi = ti.hactive_hi;
214 dp_ti->hactive_lo = ti.hactive_lo;
215 dp_ti->hblank_hi = ti.hblank_hi;
216 dp_ti->hblank_lo = ti.hblank_lo;
217 dp_ti->hsync_offset_hi = ti.hsync_offset_hi;
218 dp_ti->hsync_offset_lo = ti.hsync_offset_lo;
219 dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi;
220 dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo;
221 dp_ti->vactive_hi = ti.vactive_hi;
222 dp_ti->vactive_lo = ti.vactive_lo;
223 dp_ti->vblank_hi = ti.vblank_hi;
224 dp_ti->vblank_lo = ti.vblank_lo;
225 dp_ti->vsync_offset_hi = ti.vsync_offset_hi;
226 dp_ti->vsync_offset_lo = ti.vsync_offset_lo;
227 dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi;
228 dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo;
229
230 /* Move the MIPI_Display_Descriptor data from GCT to dev priv */
231 dev_priv->gct_data.Panel_MIPI_Display_Descriptor =
232 *((u8 *)pGCT + 0x0d);
233 dev_priv->gct_data.Panel_MIPI_Display_Descriptor |=
234 (*((u8 *)pGCT + 0x0e)) << 8;
235 break;
236 default:
237 dev_err(dev->dev, "Unknown revision of GCT!\n");
238 vbt->size = 0;
239 }
240 if (IS_MFLD(dev_priv->dev)) {
241 if (panel_id == GCT_DETECT) {
242 if (dev_priv->gct_data.bpi == 2) {
243 dev_info(dev->dev, "[GFX] PYR Panel Detected\n");
244 dev_priv->panel_id = PYR_CMD;
245 panel_id = PYR_CMD;
246 } else if (dev_priv->gct_data.bpi == 0) {
247 dev_info(dev->dev, "[GFX] TMD Panel Detected.\n");
248 dev_priv->panel_id = TMD_VID;
249 panel_id = TMD_VID;
250 } else {
251 dev_info(dev->dev, "[GFX] Default Panel (TPO)\n");
252 dev_priv->panel_id = TPO_CMD;
253 panel_id = TPO_CMD;
254 }
255 } else {
256 dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n");
257 dev_priv->panel_id = panel_id;
258 }
259 }
260}
261
262int mid_chip_setup(struct drm_device *dev)
263{
264 struct drm_psb_private *dev_priv = dev->dev_private;
265 mid_get_fuse_settings(dev);
266 mid_get_vbt_data(dev_priv);
267 mid_get_pci_revID(dev_priv);
268 return 0;
269}
diff --git a/drivers/staging/gma500/mid_bios.h b/drivers/staging/gma500/mid_bios.h
new file mode 100644
index 00000000000..00e7d564b7e
--- /dev/null
+++ b/drivers/staging/gma500/mid_bios.h
@@ -0,0 +1,21 @@
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
20extern int mid_chip_setup(struct drm_device *dev);
21
diff --git a/drivers/staging/gma500/mmu.c b/drivers/staging/gma500/mmu.c
new file mode 100644
index 00000000000..c904d73b1de
--- /dev/null
+++ b/drivers/staging/gma500/mmu.c
@@ -0,0 +1,858 @@
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
50struct 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
73struct psb_mmu_pd;
74
75struct 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
83struct 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
95static inline uint32_t psb_mmu_pt_index(uint32_t offset)
96{
97 return (offset >> PSB_PTE_SHIFT) & 0x3FF;
98}
99
100static inline uint32_t psb_mmu_pd_index(uint32_t offset)
101{
102 return offset >> PSB_PDE_SHIFT;
103}
104
105static inline void psb_clflush(void *addr)
106{
107 __asm__ __volatile__("clflush (%0)\n" : : "r"(addr) : "memory");
108}
109
110static 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
121static 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
138static 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
150static void psb_mmu_flush_pd_locked(struct psb_mmu_driver *driver,
151 int force)
152{
153 atomic_set(&driver->needs_tlbflush, 0);
154}
155
156static 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
163void 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
171void 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
183static 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
191static 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
205struct 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
262out_err4:
263 __free_page(pd->dummy_page);
264out_err3:
265 __free_page(pd->dummy_pt);
266out_err2:
267 __free_page(pd->p);
268out_err1:
269 kfree(pd);
270 return NULL;
271}
272
273void psb_mmu_free_pt(struct psb_mmu_pt *pt)
274{
275 __free_page(pt->p);
276 kfree(pt);
277}
278
279void 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
306static 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
354struct 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
394static 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
411static 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
435static 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
441static 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
448void 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
480struct 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 */
492uint32_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
500void psb_mmu_driver_takedown(struct psb_mmu_driver *driver)
501{
502 psb_mmu_free_pagedir(driver->default_pd);
503 kfree(driver);
504}
505
506struct 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
552out_err1:
553 kfree(driver);
554 return NULL;
555}
556
557static 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
611void 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
638out:
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
650void 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
706int 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
739out:
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
751int 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 }
806out:
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
819int 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);
855out:
856 up_read(&pd->driver->sem);
857 return ret;
858}
diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h
new file mode 100644
index 00000000000..b563dbc7310
--- /dev/null
+++ b/drivers/staging/gma500/mrst.h
@@ -0,0 +1,252 @@
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
22struct 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
30struct 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
63struct 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
87struct 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
116struct 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
146union 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
164struct 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
181struct 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
198struct 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
223struct 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
246extern void mrst_hdmi_setup(struct drm_device *dev);
247extern void mrst_hdmi_teardown(struct drm_device *dev);
248extern int mrst_hdmi_i2c_init(struct pci_dev *dev);
249extern void mrst_hdmi_i2c_exit(struct pci_dev *dev);
250extern void mrst_hdmi_save(struct drm_device *dev);
251extern void mrst_hdmi_restore(struct drm_device *dev);
252extern 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
new file mode 100644
index 00000000000..72464dd0f23
--- /dev/null
+++ b/drivers/staging/gma500/mrst_crtc.c
@@ -0,0 +1,610 @@
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
29struct psb_intel_range_t {
30 int min, max;
31};
32
33struct mrst_limit_t {
34 struct psb_intel_range_t dot, m, p1;
35};
36
37struct 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
60static 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
79static 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
85static 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. */
113static void mrst_clock(int refclk, struct mrst_clock_t *clock)
114{
115 clock->dot = (refclk * clock->m) / (14 * clock->p1);
116}
117
118void 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 */
128static bool
129mrstFindBestPLL(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 */
162static 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 */
276static 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
288static 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
508mrst_crtc_mode_set_exit:
509 gma_power_end(dev);
510 return 0;
511}
512
513static 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
520int 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 drm_i915_master_private *master_priv; */
525 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
526 struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
527 int pipe = psb_intel_crtc->pipe;
528 unsigned long start, offset;
529 /* FIXME: check if we need this surely MRST is pipe 0 only */
530 int dspbase = (pipe == 0 ? DSPALINOFF : DSPBBASE);
531 int dspsurf = (pipe == 0 ? DSPASURF : DSPBSURF);
532 int dspstride = (pipe == 0) ? DSPASTRIDE : DSPBSTRIDE;
533 int dspcntr_reg = (pipe == 0) ? DSPACNTR : DSPBCNTR;
534 u32 dspcntr;
535 int ret = 0;
536
537 /* no fb bound */
538 if (!crtc->fb) {
539 dev_dbg(dev->dev, "No FB bound\n");
540 return 0;
541 }
542
543 if (!gma_power_begin(dev, true))
544 return 0;
545
546 start = psbfb->gtt->offset;
547 offset = y * crtc->fb->pitch + x * (crtc->fb->bits_per_pixel / 8);
548
549 REG_WRITE(dspstride, crtc->fb->pitch);
550
551 dspcntr = REG_READ(dspcntr_reg);
552 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
553
554 switch (crtc->fb->bits_per_pixel) {
555 case 8:
556 dspcntr |= DISPPLANE_8BPP;
557 break;
558 case 16:
559 if (crtc->fb->depth == 15)
560 dspcntr |= DISPPLANE_15_16BPP;
561 else
562 dspcntr |= DISPPLANE_16BPP;
563 break;
564 case 24:
565 case 32:
566 dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
567 break;
568 default:
569 dev_err(dev->dev, "Unknown color depth\n");
570 ret = -EINVAL;
571 goto pipe_set_base_exit;
572 }
573 REG_WRITE(dspcntr_reg, dspcntr);
574
575 if (0 /* FIXMEAC - check what PSB needs */) {
576 REG_WRITE(dspbase, offset);
577 REG_READ(dspbase);
578 REG_WRITE(dspsurf, start);
579 REG_READ(dspsurf);
580 } else {
581 REG_WRITE(dspbase, start + offset);
582 REG_READ(dspbase);
583 }
584
585pipe_set_base_exit:
586 gma_power_end(dev);
587 return ret;
588}
589
590static void mrst_crtc_prepare(struct drm_crtc *crtc)
591{
592 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
593 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
594}
595
596static void mrst_crtc_commit(struct drm_crtc *crtc)
597{
598 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
599 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
600}
601
602const struct drm_crtc_helper_funcs mrst_helper_funcs = {
603 .dpms = mrst_crtc_dpms,
604 .mode_fixup = mrst_crtc_mode_fixup,
605 .mode_set = mrst_crtc_mode_set,
606 .mode_set_base = mrst_pipe_set_base,
607 .prepare = mrst_crtc_prepare,
608 .commit = mrst_crtc_commit,
609};
610
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
new file mode 100644
index 00000000000..6707fafbfa1
--- /dev/null
+++ b/drivers/staging/gma500/mrst_device.c
@@ -0,0 +1,634 @@
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
33static int devtype;
34
35module_param_named(type, devtype, int, 0600);
36MODULE_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
42static 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
66static 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
90static struct backlight_device *mrst_backlight_device;
91static int mrst_brightness;
92
93static 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
131static 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
139static 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
171static const struct backlight_ops mrst_ops = {
172 .get_brightness = mrst_get_brightness,
173 .update_status = mrst_set_brightness,
174};
175
176int 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
211static 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 */
222static 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 */
334static 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 */
447static 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 */
471static 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)
492static 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
501static 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
516static 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
544static void oaktrail_teardown(struct drm_device *dev)
545{
546 mrst_hdmi_teardown(dev);
547}
548
549static 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 */
583static 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
609const 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
new file mode 100644
index 00000000000..e66607eb3d3
--- /dev/null
+++ b/drivers/staging/gma500/mrst_hdmi.c
@@ -0,0 +1,852 @@
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
97struct intel_range {
98 int min, max;
99};
100
101struct mrst_hdmi_limit {
102 struct intel_range vco, np, nr, nf;
103};
104
105struct 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
121static 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
128static 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
135static 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
153static 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
181static 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
196static 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
211void 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
309static 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
330static 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
345static 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
379int 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
506static 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
520static 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
527static enum drm_connector_status
528mrst_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
547static 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
561static 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
597static 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
607static void mrst_hdmi_destroy(struct drm_connector *connector)
608{
609 return;
610}
611
612static 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
620static 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
627static 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
634static void mrst_hdmi_enc_destroy(struct drm_encoder *encoder)
635{
636 drm_encoder_cleanup(encoder);
637}
638
639static const struct drm_encoder_funcs mrst_hdmi_enc_funcs = {
640 .destroy = mrst_hdmi_enc_destroy,
641};
642
643void 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
680static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
681 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
682 {}
683};
684
685void 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
729free:
730 kfree(hdmi_dev);
731out:
732 return;
733}
734
735void 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 */
752void 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 */
803void 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
new file mode 100644
index 00000000000..351b9d897b9
--- /dev/null
+++ b/drivers/staging/gma500/mrst_hdmi_i2c.c
@@ -0,0 +1,327 @@
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 "psb_drv.h"
33
34#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))
35#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg))
36
37#define HDMI_HCR 0x1000
38#define HCR_DETECT_HDP (1 << 6)
39#define HCR_ENABLE_HDCP (1 << 5)
40#define HCR_ENABLE_AUDIO (1 << 2)
41#define HCR_ENABLE_PIXEL (1 << 1)
42#define HCR_ENABLE_TMDS (1 << 0)
43#define HDMI_HICR 0x1004
44#define HDMI_INTR_I2C_ERROR (1 << 4)
45#define HDMI_INTR_I2C_FULL (1 << 3)
46#define HDMI_INTR_I2C_DONE (1 << 2)
47#define HDMI_INTR_HPD (1 << 0)
48#define HDMI_HSR 0x1008
49#define HDMI_HISR 0x100C
50#define HDMI_HI2CRDB0 0x1200
51#define HDMI_HI2CHCR 0x1240
52#define HI2C_HDCP_WRITE (0 << 2)
53#define HI2C_HDCP_RI_READ (1 << 2)
54#define HI2C_HDCP_READ (2 << 2)
55#define HI2C_EDID_READ (3 << 2)
56#define HI2C_READ_CONTINUE (1 << 1)
57#define HI2C_ENABLE_TRANSACTION (1 << 0)
58
59#define HDMI_ICRH 0x1100
60#define HDMI_HI2CTDR0 0x1244
61#define HDMI_HI2CTDR1 0x1248
62
63#define I2C_STAT_INIT 0
64#define I2C_READ_DONE 1
65#define I2C_TRANSACTION_DONE 2
66
67struct hdmi_i2c_dev {
68 struct i2c_adapter *adap;
69 struct mutex i2c_lock;
70 struct completion complete;
71 int status;
72 struct i2c_msg *msg;
73 int buf_offset;
74};
75
76static void hdmi_i2c_irq_enable(struct mrst_hdmi_dev *hdmi_dev)
77{
78 u32 temp;
79
80 temp = HDMI_READ(HDMI_HICR);
81 temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE);
82 HDMI_WRITE(HDMI_HICR, temp);
83 HDMI_READ(HDMI_HICR);
84}
85
86static void hdmi_i2c_irq_disable(struct mrst_hdmi_dev *hdmi_dev)
87{
88 HDMI_WRITE(HDMI_HICR, 0x0);
89 HDMI_READ(HDMI_HICR);
90}
91
92static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
93{
94 struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
95 struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
96 u32 temp;
97
98 i2c_dev->status = I2C_STAT_INIT;
99 i2c_dev->msg = pmsg;
100 i2c_dev->buf_offset = 0;
101 INIT_COMPLETION(i2c_dev->complete);
102
103 /* Enable I2C transaction */
104 temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION;
105 HDMI_WRITE(HDMI_HI2CHCR, temp);
106 HDMI_READ(HDMI_HI2CHCR);
107
108 while (i2c_dev->status != I2C_TRANSACTION_DONE)
109 wait_for_completion_interruptible_timeout(&i2c_dev->complete,
110 10 * HZ);
111
112 return 0;
113}
114
115static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg)
116{
117 /*
118 * XXX: i2c write seems isn't useful for EDID probe, don't do anything
119 */
120 return 0;
121}
122
123static int mrst_hdmi_i2c_access(struct i2c_adapter *adap,
124 struct i2c_msg *pmsg,
125 int num)
126{
127 struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
128 struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
129 int i, err = 0;
130
131 mutex_lock(&i2c_dev->i2c_lock);
132
133 /* Enable i2c unit */
134 HDMI_WRITE(HDMI_ICRH, 0x00008760);
135
136 /* Enable irq */
137 hdmi_i2c_irq_enable(hdmi_dev);
138 for (i = 0; i < num; i++) {
139 if (pmsg->len && pmsg->buf) {
140 if (pmsg->flags & I2C_M_RD)
141 err = xfer_read(adap, pmsg);
142 else
143 err = xfer_write(adap, pmsg);
144 }
145 pmsg++; /* next message */
146 }
147
148 /* Disable irq */
149 hdmi_i2c_irq_disable(hdmi_dev);
150
151 mutex_unlock(&i2c_dev->i2c_lock);
152
153 return i;
154}
155
156static u32 mrst_hdmi_i2c_func(struct i2c_adapter *adapter)
157{
158 return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
159}
160
161static const struct i2c_algorithm mrst_hdmi_i2c_algorithm = {
162 .master_xfer = mrst_hdmi_i2c_access,
163 .functionality = mrst_hdmi_i2c_func,
164};
165
166static struct i2c_adapter mrst_hdmi_i2c_adapter = {
167 .name = "mrst_hdmi_i2c",
168 .nr = 3,
169 .owner = THIS_MODULE,
170 .class = I2C_CLASS_DDC,
171 .algo = &mrst_hdmi_i2c_algorithm,
172};
173
174static void hdmi_i2c_read(struct mrst_hdmi_dev *hdmi_dev)
175{
176 struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
177 struct i2c_msg *msg = i2c_dev->msg;
178 u8 *buf = msg->buf;
179 u32 temp;
180 int i, offset;
181
182 offset = i2c_dev->buf_offset;
183 for (i = 0; i < 0x10; i++) {
184 temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4));
185 memcpy(buf + (offset + i * 4), &temp, 4);
186 }
187 i2c_dev->buf_offset += (0x10 * 4);
188
189 /* clearing read buffer full intr */
190 temp = HDMI_READ(HDMI_HISR);
191 HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL);
192 HDMI_READ(HDMI_HISR);
193
194 /* continue read transaction */
195 temp = HDMI_READ(HDMI_HI2CHCR);
196 HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE);
197 HDMI_READ(HDMI_HI2CHCR);
198
199 i2c_dev->status = I2C_READ_DONE;
200 return;
201}
202
203static void hdmi_i2c_transaction_done(struct mrst_hdmi_dev *hdmi_dev)
204{
205 struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
206 u32 temp;
207
208 /* clear transaction done intr */
209 temp = HDMI_READ(HDMI_HISR);
210 HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE);
211 HDMI_READ(HDMI_HISR);
212
213
214 temp = HDMI_READ(HDMI_HI2CHCR);
215 HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION);
216 HDMI_READ(HDMI_HI2CHCR);
217
218 i2c_dev->status = I2C_TRANSACTION_DONE;
219 return;
220}
221
222static irqreturn_t mrst_hdmi_i2c_handler(int this_irq, void *dev)
223{
224 struct mrst_hdmi_dev *hdmi_dev = dev;
225 struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
226 u32 stat;
227
228 stat = HDMI_READ(HDMI_HISR);
229
230 if (stat & HDMI_INTR_HPD) {
231 HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD);
232 HDMI_READ(HDMI_HISR);
233 }
234
235 if (stat & HDMI_INTR_I2C_FULL)
236 hdmi_i2c_read(hdmi_dev);
237
238 if (stat & HDMI_INTR_I2C_DONE)
239 hdmi_i2c_transaction_done(hdmi_dev);
240
241 complete(&i2c_dev->complete);
242
243 return IRQ_HANDLED;
244}
245
246/*
247 * choose alternate function 2 of GPIO pin 52, 53,
248 * which is used by HDMI I2C logic
249 */
250static void mrst_hdmi_i2c_gpio_fix(void)
251{
252 void *base;
253 unsigned int gpio_base = 0xff12c000;
254 int gpio_len = 0x1000;
255 u32 temp;
256
257 base = ioremap((resource_size_t)gpio_base, gpio_len);
258 if (base == NULL) {
259 DRM_ERROR("gpio ioremap fail\n");
260 return;
261 }
262
263 temp = readl(base + 0x44);
264 DRM_DEBUG_DRIVER("old gpio val %x\n", temp);
265 writel((temp | 0x00000a00), (base + 0x44));
266 temp = readl(base + 0x44);
267 DRM_DEBUG_DRIVER("new gpio val %x\n", temp);
268
269 iounmap(base);
270}
271
272int mrst_hdmi_i2c_init(struct pci_dev *dev)
273{
274 struct mrst_hdmi_dev *hdmi_dev;
275 struct hdmi_i2c_dev *i2c_dev;
276 int ret;
277
278 hdmi_dev = pci_get_drvdata(dev);
279
280 i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL);
281 if (i2c_dev == NULL) {
282 DRM_ERROR("Can't allocate interface\n");
283 ret = -ENOMEM;
284 goto exit;
285 }
286
287 i2c_dev->adap = &mrst_hdmi_i2c_adapter;
288 i2c_dev->status = I2C_STAT_INIT;
289 init_completion(&i2c_dev->complete);
290 mutex_init(&i2c_dev->i2c_lock);
291 i2c_set_adapdata(&mrst_hdmi_i2c_adapter, hdmi_dev);
292 hdmi_dev->i2c_dev = i2c_dev;
293
294 /* Enable HDMI I2C function on gpio */
295 mrst_hdmi_i2c_gpio_fix();
296
297 /* request irq */
298 ret = request_irq(dev->irq, mrst_hdmi_i2c_handler, IRQF_SHARED,
299 mrst_hdmi_i2c_adapter.name, hdmi_dev);
300 if (ret) {
301 DRM_ERROR("Failed to request IRQ for I2C controller\n");
302 goto err;
303 }
304
305 /* Adapter registration */
306 ret = i2c_add_numbered_adapter(&mrst_hdmi_i2c_adapter);
307 return ret;
308
309err:
310 kfree(i2c_dev);
311exit:
312 return ret;
313}
314
315void mrst_hdmi_i2c_exit(struct pci_dev *dev)
316{
317 struct mrst_hdmi_dev *hdmi_dev;
318 struct hdmi_i2c_dev *i2c_dev;
319
320 hdmi_dev = pci_get_drvdata(dev);
321 if (i2c_del_adapter(&mrst_hdmi_i2c_adapter))
322 DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n");
323
324 i2c_dev = hdmi_dev->i2c_dev;
325 kfree(i2c_dev);
326 free_irq(dev->irq, hdmi_dev);
327}
diff --git a/drivers/staging/gma500/mrst_lvds.c b/drivers/staging/gma500/mrst_lvds.c
new file mode 100644
index 00000000000..e7999a2a379
--- /dev/null
+++ b/drivers/staging/gma500/mrst_lvds.c
@@ -0,0 +1,407 @@
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 */
45static 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
77static 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
90static 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
150static 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
166static 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
185static 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
197static 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
205static 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
231static struct drm_display_mode *
232mrst_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 */
289void 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
392out:
393 drm_sysfs_connector_add(connector);
394 return;
395
396failed_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
new file mode 100644
index 00000000000..972bea7c1af
--- /dev/null
+++ b/drivers/staging/gma500/power.c
@@ -0,0 +1,316 @@
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
38static struct mutex power_mutex; /* Serialize power ops */
39static 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 */
47void 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 */
70void 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 */
82static void gma_suspend_display(struct drm_device *dev)
83{
84 struct drm_psb_private *dev_priv = dev->dev_private;
85
86 if (dev_priv->suspended)
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 */
99static 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->suspended == false)
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 */
124static 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 */
154static 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 */
188int 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 */
214int 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 */
234bool 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 */
248bool 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 psb_irq_preinstall(dev);
269 psb_irq_postinstall(dev);
270 pm_runtime_get(&dev->pdev->dev);
271 dev_priv->display_count++;
272 spin_unlock_irqrestore(&power_ctrl_lock, flags);
273 return true;
274 }
275out_false:
276 spin_unlock_irqrestore(&power_ctrl_lock, flags);
277 return false;
278}
279
280/**
281 * gma_power_end - end use of power
282 * @dev: Our DRM device
283 *
284 * Indicate that one of our gma_power_begin() requested periods when
285 * the diplay island power is needed has completed.
286 */
287void gma_power_end(struct drm_device *dev)
288{
289 struct drm_psb_private *dev_priv = dev->dev_private;
290 unsigned long flags;
291 spin_lock_irqsave(&power_ctrl_lock, flags);
292 dev_priv->display_count--;
293 WARN_ON(dev_priv->display_count < 0);
294 spin_unlock_irqrestore(&power_ctrl_lock, flags);
295 pm_runtime_put(&dev->pdev->dev);
296}
297
298int psb_runtime_suspend(struct device *dev)
299{
300 return gma_power_suspend(dev);
301}
302
303int psb_runtime_resume(struct device *dev)
304{
305 return 0;
306}
307
308int psb_runtime_idle(struct device *dev)
309{
310 struct drm_device *drmdev = pci_get_drvdata(to_pci_dev(dev));
311 struct drm_psb_private *dev_priv = drmdev->dev_private;
312 if (dev_priv->display_count)
313 return 0;
314 else
315 return 1;
316}
diff --git a/drivers/staging/gma500/power.h b/drivers/staging/gma500/power.h
new file mode 100644
index 00000000000..1969d2ecb32
--- /dev/null
+++ b/drivers/staging/gma500/power.h
@@ -0,0 +1,67 @@
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
36void gma_power_init(struct drm_device *dev);
37void gma_power_uninit(struct drm_device *dev);
38
39/*
40 * The kernel bus power management will call these functions
41 */
42int gma_power_suspend(struct device *dev);
43int 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 */
49bool gma_power_begin(struct drm_device *dev, bool force);
50void 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 */
58bool gma_power_is_on(struct drm_device *dev);
59
60/*
61 * GFX-Runtime PM callbacks
62 */
63int psb_runtime_suspend(struct device *dev);
64int psb_runtime_resume(struct device *dev);
65int 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
new file mode 100644
index 00000000000..46591323595
--- /dev/null
+++ b/drivers/staging/gma500/psb_device.c
@@ -0,0 +1,353 @@
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
30static 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
55static int psb_brightness;
56static struct backlight_device *psb_backlight_device;
57
58static 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
67static 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
103static 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
117static const struct backlight_ops psb_ops = {
118 .get_brightness = psb_get_brightness,
119 .update_status = psb_set_brightness,
120};
121
122static 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
157static 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 */
175static 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 */
211static 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 int pp_stat;
217
218 /* Display arbitration + watermarks */
219 PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
220 PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
221 PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
222 PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
223 PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
224 PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
225 PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
226 PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
227
228 /*make sure VGA plane is off. it initializes to on after reset!*/
229 PSB_WVDC32(0x80000000, VGACNTRL);
230
231 mutex_lock(&dev->mode_config.mutex);
232 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
233 if (drm_helper_crtc_in_use(crtc))
234 crtc->funcs->restore(crtc);
235
236 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
237 connector->funcs->restore(connector);
238
239 mutex_unlock(&dev->mode_config.mutex);
240
241 if (dev_priv->iLVDS_enable) {
242 /*shutdown the panel*/
243 PSB_WVDC32(0, PP_CONTROL);
244 do {
245 pp_stat = PSB_RVDC32(PP_STATUS);
246 } while (pp_stat & 0x80000000);
247
248 /* Turn off the plane */
249 PSB_WVDC32(0x58000000, DSPACNTR);
250 PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
251 /* Wait ~4 ticks */
252 msleep(4);
253 /* Turn off pipe */
254 PSB_WVDC32(0x0, PIPEACONF);
255 /* Wait ~8 ticks */
256 msleep(8);
257
258 /* Turn off PLLs */
259 PSB_WVDC32(0, MRST_DPLL_A);
260 } else {
261 PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
262 PSB_WVDC32(0x0, PIPEACONF);
263 PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
264 while (REG_READ(0x70008) & 0x40000000)
265 cpu_relax();
266 while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
267 != DPI_FIFO_EMPTY)
268 cpu_relax();
269 PSB_WVDC32(0, DEVICE_READY_REG);
270 }
271 return 0;
272}
273
274static int psb_power_down(struct drm_device *dev)
275{
276 return 0;
277}
278
279static int psb_power_up(struct drm_device *dev)
280{
281 return 0;
282}
283
284static void psb_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, 0xD4, 0x00C32004);*/
291 /*pci_write_config_dword(pci_root, 0xD0, 0xE0033000);*/
292
293 pci_write_config_dword(pci_root, 0xD0, 0xD0050300);
294 pci_read_config_dword(pci_root, 0xD4, &clock);
295 pci_dev_put(pci_root);
296
297 switch (clock & 0x07) {
298 case 0:
299 dev_priv->core_freq = 100;
300 break;
301 case 1:
302 dev_priv->core_freq = 133;
303 break;
304 case 2:
305 dev_priv->core_freq = 150;
306 break;
307 case 3:
308 dev_priv->core_freq = 178;
309 break;
310 case 4:
311 dev_priv->core_freq = 200;
312 break;
313 case 5:
314 case 6:
315 case 7:
316 dev_priv->core_freq = 266;
317 default:
318 dev_priv->core_freq = 0;
319 }
320}
321
322static int psb_chip_setup(struct drm_device *dev)
323{
324 psb_get_core_freq(dev);
325 gma_intel_opregion_init(dev);
326 psb_intel_init_bios(dev);
327 return 0;
328}
329
330const struct psb_ops psb_chip_ops = {
331 .name = "Poulsbo",
332 .accel_2d = 1,
333 .pipes = 2,
334 .crtcs = 2,
335 .sgx_offset = PSB_SGX_OFFSET,
336 .chip_setup = psb_chip_setup,
337
338 .crtc_helper = &psb_intel_helper_funcs,
339 .crtc_funcs = &psb_intel_crtc_funcs,
340
341 .output_init = psb_output_init,
342
343#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
344 .backlight_init = psb_backlight_init,
345#endif
346
347 .init_pm = psb_init_pm,
348 .save_regs = psb_save_display_registers,
349 .restore_regs = psb_restore_display_registers,
350 .power_down = psb_power_down,
351 .power_up = psb_power_up,
352};
353
diff --git a/drivers/staging/gma500/psb_drm.h b/drivers/staging/gma500/psb_drm.h
new file mode 100644
index 00000000000..0da84683568
--- /dev/null
+++ b/drivers/staging/gma500/psb_drm.h
@@ -0,0 +1,219 @@
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
37struct 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
46struct 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
58struct drm_psb_dc_state_arg {
59 u32 flags;
60 u32 obj_id;
61};
62
63struct drm_psb_mode_operation_arg {
64 u32 obj_id;
65 u16 operation;
66 struct drm_mode_modeinfo mode;
67 void *data;
68};
69
70struct 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
94struct 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
174struct 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 */
184struct psb_drm_dpu_rect {
185 int x, y;
186 int width, height;
187};
188
189struct 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
198struct 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
208struct 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
new file mode 100644
index 00000000000..b2cdce7b97e
--- /dev/null
+++ b/drivers/staging/gma500/psb_drv.c
@@ -0,0 +1,1231 @@
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 <acpi/video.h>
39
40static int drm_psb_trap_pagefaults;
41
42int drm_psb_no_fb;
43
44static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent);
45
46MODULE_PARM_DESC(no_fb, "Disable FBdev");
47MODULE_PARM_DESC(trap_pagefaults, "Error and reset on MMU pagefaults");
48module_param_named(no_fb, drm_psb_no_fb, int, 0600);
49module_param_named(trap_pagefaults, drm_psb_trap_pagefaults, int, 0600);
50
51
52static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
53 { 0x8086, 0x8108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
54 { 0x8086, 0x8109, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &psb_chip_ops },
55#if defined(CONFIG_DRM_PSB_MRST)
56 { 0x8086, 0x4100, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
57 { 0x8086, 0x4101, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
58 { 0x8086, 0x4102, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
59 { 0x8086, 0x4103, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
60 { 0x8086, 0x4104, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
61 { 0x8086, 0x4105, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
62 { 0x8086, 0x4106, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
63 { 0x8086, 0x4107, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mrst_chip_ops},
64#endif
65#if defined(CONFIG_DRM_PSB_MFLD)
66 { 0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
67 { 0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
68 { 0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
69 { 0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
70 { 0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
71 { 0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
72 { 0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
73 { 0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
74#endif
75#if defined(CONFIG_DRM_PSB_CDV)
76 { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
77 { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
78 { 0x8086, 0x0be2, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
79 { 0x8086, 0x0be3, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
80 { 0x8086, 0x0be4, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
81 { 0x8086, 0x0be5, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
82 { 0x8086, 0x0be6, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
83 { 0x8086, 0x0be7, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
84#endif
85 { 0, 0, 0}
86};
87MODULE_DEVICE_TABLE(pci, pciidlist);
88
89/*
90 * Standard IOCTLs.
91 */
92
93#define DRM_IOCTL_PSB_SIZES \
94 DRM_IOR(DRM_PSB_SIZES + DRM_COMMAND_BASE, \
95 struct drm_psb_sizes_arg)
96#define DRM_IOCTL_PSB_FUSE_REG \
97 DRM_IOWR(DRM_PSB_FUSE_REG + DRM_COMMAND_BASE, uint32_t)
98#define DRM_IOCTL_PSB_DC_STATE \
99 DRM_IOW(DRM_PSB_DC_STATE + DRM_COMMAND_BASE, \
100 struct drm_psb_dc_state_arg)
101#define DRM_IOCTL_PSB_ADB \
102 DRM_IOWR(DRM_PSB_ADB + DRM_COMMAND_BASE, uint32_t)
103#define DRM_IOCTL_PSB_MODE_OPERATION \
104 DRM_IOWR(DRM_PSB_MODE_OPERATION + DRM_COMMAND_BASE, \
105 struct drm_psb_mode_operation_arg)
106#define DRM_IOCTL_PSB_STOLEN_MEMORY \
107 DRM_IOWR(DRM_PSB_STOLEN_MEMORY + DRM_COMMAND_BASE, \
108 struct drm_psb_stolen_memory_arg)
109#define DRM_IOCTL_PSB_REGISTER_RW \
110 DRM_IOWR(DRM_PSB_REGISTER_RW + DRM_COMMAND_BASE, \
111 struct drm_psb_register_rw_arg)
112#define DRM_IOCTL_PSB_DPST \
113 DRM_IOWR(DRM_PSB_DPST + DRM_COMMAND_BASE, \
114 uint32_t)
115#define DRM_IOCTL_PSB_GAMMA \
116 DRM_IOWR(DRM_PSB_GAMMA + DRM_COMMAND_BASE, \
117 struct drm_psb_dpst_lut_arg)
118#define DRM_IOCTL_PSB_DPST_BL \
119 DRM_IOWR(DRM_PSB_DPST_BL + DRM_COMMAND_BASE, \
120 uint32_t)
121#define DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID \
122 DRM_IOWR(DRM_PSB_GET_PIPE_FROM_CRTC_ID + DRM_COMMAND_BASE, \
123 struct drm_psb_get_pipe_from_crtc_id_arg)
124#define DRM_IOCTL_PSB_GEM_CREATE \
125 DRM_IOWR(DRM_PSB_GEM_CREATE + DRM_COMMAND_BASE, \
126 struct drm_psb_gem_create)
127#define DRM_IOCTL_PSB_2D_OP \
128 DRM_IOW(DRM_PSB_2D_OP + DRM_COMMAND_BASE, \
129 struct drm_psb_2d_op)
130#define DRM_IOCTL_PSB_GEM_MMAP \
131 DRM_IOWR(DRM_PSB_GEM_MMAP + DRM_COMMAND_BASE, \
132 struct drm_psb_gem_mmap)
133
134static int psb_sizes_ioctl(struct drm_device *dev, void *data,
135 struct drm_file *file_priv);
136static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
137 struct drm_file *file_priv);
138static int psb_adb_ioctl(struct drm_device *dev, void *data,
139 struct drm_file *file_priv);
140static int psb_mode_operation_ioctl(struct drm_device *dev, void *data,
141 struct drm_file *file_priv);
142static int psb_stolen_memory_ioctl(struct drm_device *dev, void *data,
143 struct drm_file *file_priv);
144static int psb_register_rw_ioctl(struct drm_device *dev, void *data,
145 struct drm_file *file_priv);
146static int psb_dpst_ioctl(struct drm_device *dev, void *data,
147 struct drm_file *file_priv);
148static int psb_gamma_ioctl(struct drm_device *dev, void *data,
149 struct drm_file *file_priv);
150static int psb_dpst_bl_ioctl(struct drm_device *dev, void *data,
151 struct drm_file *file_priv);
152
153#define PSB_IOCTL_DEF(ioctl, func, flags) \
154 [DRM_IOCTL_NR(ioctl) - DRM_COMMAND_BASE] = {ioctl, flags, func}
155
156static struct drm_ioctl_desc psb_ioctls[] = {
157 PSB_IOCTL_DEF(DRM_IOCTL_PSB_SIZES, psb_sizes_ioctl, DRM_AUTH),
158 PSB_IOCTL_DEF(DRM_IOCTL_PSB_DC_STATE, psb_dc_state_ioctl, DRM_AUTH),
159 PSB_IOCTL_DEF(DRM_IOCTL_PSB_ADB, psb_adb_ioctl, DRM_AUTH),
160 PSB_IOCTL_DEF(DRM_IOCTL_PSB_MODE_OPERATION, psb_mode_operation_ioctl,
161 DRM_AUTH),
162 PSB_IOCTL_DEF(DRM_IOCTL_PSB_STOLEN_MEMORY, psb_stolen_memory_ioctl,
163 DRM_AUTH),
164 PSB_IOCTL_DEF(DRM_IOCTL_PSB_REGISTER_RW, psb_register_rw_ioctl,
165 DRM_AUTH),
166 PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST, psb_dpst_ioctl, DRM_AUTH),
167 PSB_IOCTL_DEF(DRM_IOCTL_PSB_GAMMA, psb_gamma_ioctl, DRM_AUTH),
168 PSB_IOCTL_DEF(DRM_IOCTL_PSB_DPST_BL, psb_dpst_bl_ioctl, DRM_AUTH),
169 PSB_IOCTL_DEF(DRM_IOCTL_PSB_GET_PIPE_FROM_CRTC_ID,
170 psb_intel_get_pipe_from_crtc_id, 0),
171 PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_CREATE, psb_gem_create_ioctl,
172 DRM_UNLOCKED | DRM_AUTH),
173 PSB_IOCTL_DEF(DRM_IOCTL_PSB_2D_OP, psb_accel_ioctl,
174 DRM_UNLOCKED| DRM_AUTH),
175 PSB_IOCTL_DEF(DRM_IOCTL_PSB_GEM_MMAP, psb_gem_mmap_ioctl,
176 DRM_UNLOCKED | DRM_AUTH),
177};
178
179static void psb_lastclose(struct drm_device *dev)
180{
181 return;
182}
183
184static void psb_do_takedown(struct drm_device *dev)
185{
186 /* FIXME: do we need to clean up the gtt here ? */
187}
188
189static 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 mutex_init(&dev_priv->mutex_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;
244out_err:
245 psb_do_takedown(dev);
246 return ret;
247}
248
249static 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
313static 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 dev_priv->num_pipe = dev_priv->ops->pipes;
333
334 resource_start = pci_resource_start(dev->pdev, PSB_MMIO_RESOURCE);
335
336 dev_priv->vdc_reg =
337 ioremap(resource_start + PSB_VDC_OFFSET, PSB_VDC_SIZE);
338 if (!dev_priv->vdc_reg)
339 goto out_err;
340
341 dev_priv->sgx_reg = ioremap(resource_start + dev_priv->ops->sgx_offset,
342 PSB_SGX_SIZE);
343 if (!dev_priv->sgx_reg)
344 goto out_err;
345
346 ret = dev_priv->ops->chip_setup(dev);
347 if (ret)
348 goto out_err;
349
350 /* Init OSPM support */
351 gma_power_init(dev);
352
353 ret = -ENOMEM;
354
355 dev_priv->scratch_page = alloc_page(GFP_DMA32 | __GFP_ZERO);
356 if (!dev_priv->scratch_page)
357 goto out_err;
358
359 set_pages_uc(dev_priv->scratch_page, 1);
360
361 ret = psb_gtt_init(dev, 0);
362 if (ret)
363 goto out_err;
364
365 dev_priv->mmu = psb_mmu_driver_init((void *)0,
366 drm_psb_trap_pagefaults, 0,
367 dev_priv);
368 if (!dev_priv->mmu)
369 goto out_err;
370
371 pg = &dev_priv->gtt;
372
373 tt_pages = (pg->gatt_pages < PSB_TT_PRIV0_PLIMIT) ?
374 (pg->gatt_pages) : PSB_TT_PRIV0_PLIMIT;
375
376
377 dev_priv->pf_pd = psb_mmu_alloc_pd(dev_priv->mmu, 1, 0);
378 if (!dev_priv->pf_pd)
379 goto out_err;
380
381 psb_mmu_set_pd_context(psb_mmu_get_default_pd(dev_priv->mmu), 0);
382 psb_mmu_set_pd_context(dev_priv->pf_pd, 1);
383
384 ret = psb_do_init(dev);
385 if (ret)
386 return ret;
387
388 PSB_WSGX32(0x20000000, PSB_CR_PDS_EXEC_BASE);
389 PSB_WSGX32(0x30000000, PSB_CR_BIF_3D_REQ_BASE);
390
391/* igd_opregion_init(&dev_priv->opregion_dev); */
392 acpi_video_register();
393 if (dev_priv->lid_state)
394 psb_lid_timer_init(dev_priv);
395
396 ret = drm_vblank_init(dev, dev_priv->num_pipe);
397 if (ret)
398 goto out_err;
399
400 /*
401 * Install interrupt handlers prior to powering off SGX or else we will
402 * crash.
403 */
404 dev_priv->vdc_irq_mask = 0;
405 dev_priv->pipestat[0] = 0;
406 dev_priv->pipestat[1] = 0;
407 dev_priv->pipestat[2] = 0;
408 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
409 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
410 PSB_WVDC32(0x00000000, PSB_INT_ENABLE_R);
411 PSB_WVDC32(0xFFFFFFFF, PSB_INT_MASK_R);
412 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
413 if (drm_core_check_feature(dev, DRIVER_MODESET))
414 drm_irq_install(dev);
415
416 dev->vblank_disable_allowed = 1;
417
418 dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
419
420 dev->driver->get_vblank_counter = psb_get_vblank_counter;
421
422#if defined(CONFIG_DRM_PSB_MFLD)
423 /* FIXME: this is not the right place for this stuff ! */
424 mdfld_output_setup(dev);
425#endif
426 if (drm_psb_no_fb == 0) {
427 psb_modeset_init(dev);
428 psb_fbdev_init(dev);
429 drm_kms_helper_poll_init(dev);
430 }
431
432 /* Only add backlight support if we have LVDS output */
433 list_for_each_entry(connector, &dev->mode_config.connector_list,
434 head) {
435 psb_intel_output = to_psb_intel_output(connector);
436
437 switch (psb_intel_output->type) {
438 case INTEL_OUTPUT_LVDS:
439 case INTEL_OUTPUT_MIPI:
440 ret = gma_backlight_init(dev);
441 break;
442 }
443 }
444
445 if (ret)
446 return ret;
447#if 0
448 /*enable runtime pm at last*/
449 pm_runtime_enable(&dev->pdev->dev);
450 pm_runtime_set_active(&dev->pdev->dev);
451#endif
452 /*Intel drm driver load is done, continue doing pvr load*/
453 return 0;
454out_err:
455 psb_driver_unload(dev);
456 return ret;
457}
458
459int psb_driver_device_is_agp(struct drm_device *dev)
460{
461 return 0;
462}
463
464
465static int psb_sizes_ioctl(struct drm_device *dev, void *data,
466 struct drm_file *file_priv)
467{
468 struct drm_psb_private *dev_priv = psb_priv(dev);
469 struct drm_psb_sizes_arg *arg =
470 (struct drm_psb_sizes_arg *) data;
471
472 *arg = dev_priv->sizes;
473 return 0;
474}
475
476static int psb_dc_state_ioctl(struct drm_device *dev, void * data,
477 struct drm_file *file_priv)
478{
479 uint32_t flags;
480 uint32_t obj_id;
481 struct drm_mode_object *obj;
482 struct drm_connector *connector;
483 struct drm_crtc *crtc;
484 struct drm_psb_dc_state_arg *arg =
485 (struct drm_psb_dc_state_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
534static 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
544static 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
555static 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 */
567static 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}
596static 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
626static 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);
718mode_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
730static 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 */
743static 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
1099static int psb_driver_open(struct drm_device *dev, struct drm_file *priv)
1100{
1101 return 0;
1102}
1103
1104static void psb_driver_close(struct drm_device *dev, struct drm_file *priv)
1105{
1106}
1107
1108static 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 struct drm_psb_private *dev_priv = dev->dev_private;
1114 static unsigned int runtime_allowed;
1115
1116 if (runtime_allowed == 1 && dev_priv->is_lvds_on) {
1117 runtime_allowed++;
1118 pm_runtime_allow(&dev->pdev->dev);
1119 dev_priv->rpm_enabled = 1;
1120 }
1121 return drm_ioctl(filp, cmd, arg);
1122 /* FIXME: do we need to wrap the other side of this */
1123}
1124
1125
1126/* When a client dies:
1127 * - Check for and clean up flipped page state
1128 */
1129void psb_driver_preclose(struct drm_device *dev, struct drm_file *priv)
1130{
1131}
1132
1133static void psb_remove(struct pci_dev *pdev)
1134{
1135 struct drm_device *dev = pci_get_drvdata(pdev);
1136 drm_put_dev(dev);
1137}
1138
1139static const struct dev_pm_ops psb_pm_ops = {
1140 .resume = gma_power_resume,
1141 .suspend = gma_power_suspend,
1142 .runtime_suspend = psb_runtime_suspend,
1143 .runtime_resume = psb_runtime_resume,
1144 .runtime_idle = psb_runtime_idle,
1145};
1146
1147static struct vm_operations_struct psb_gem_vm_ops = {
1148 .fault = psb_gem_fault,
1149 .open = drm_gem_vm_open,
1150 .close = drm_gem_vm_close,
1151};
1152
1153static struct drm_driver driver = {
1154 .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | \
1155 DRIVER_IRQ_VBL | DRIVER_MODESET | DRIVER_GEM ,
1156 .load = psb_driver_load,
1157 .unload = psb_driver_unload,
1158
1159 .ioctls = psb_ioctls,
1160 .num_ioctls = DRM_ARRAY_SIZE(psb_ioctls),
1161 .device_is_agp = psb_driver_device_is_agp,
1162 .irq_preinstall = psb_irq_preinstall,
1163 .irq_postinstall = psb_irq_postinstall,
1164 .irq_uninstall = psb_irq_uninstall,
1165 .irq_handler = psb_irq_handler,
1166 .enable_vblank = psb_enable_vblank,
1167 .disable_vblank = psb_disable_vblank,
1168 .get_vblank_counter = psb_get_vblank_counter,
1169 .lastclose = psb_lastclose,
1170 .open = psb_driver_open,
1171 .preclose = psb_driver_preclose,
1172 .postclose = psb_driver_close,
1173 .reclaim_buffers = drm_core_reclaim_buffers,
1174
1175 .gem_init_object = psb_gem_init_object,
1176 .gem_free_object = psb_gem_free_object,
1177 .gem_vm_ops = &psb_gem_vm_ops,
1178 .dumb_create = psb_gem_dumb_create,
1179 .dumb_map_offset = psb_gem_dumb_map_gtt,
1180 .dumb_destroy = psb_gem_dumb_destroy,
1181
1182 .fops = {
1183 .owner = THIS_MODULE,
1184 .open = drm_open,
1185 .release = drm_release,
1186 .unlocked_ioctl = psb_unlocked_ioctl,
1187 .mmap = drm_gem_mmap,
1188 .poll = drm_poll,
1189 .fasync = drm_fasync,
1190 .read = drm_read,
1191 },
1192 .name = DRIVER_NAME,
1193 .desc = DRIVER_DESC,
1194 .date = PSB_DRM_DRIVER_DATE,
1195 .major = PSB_DRM_DRIVER_MAJOR,
1196 .minor = PSB_DRM_DRIVER_MINOR,
1197 .patchlevel = PSB_DRM_DRIVER_PATCHLEVEL
1198};
1199
1200static struct pci_driver psb_pci_driver = {
1201 .name = DRIVER_NAME,
1202 .id_table = pciidlist,
1203 .probe = psb_probe,
1204 .remove = psb_remove,
1205 .driver.pm = &psb_pm_ops,
1206};
1207
1208static int psb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
1209{
1210 /* MLD Added this from Inaky's patch */
1211 if (pci_enable_msi(pdev))
1212 dev_warn(&pdev->dev, "Enable MSI failed!\n");
1213 return drm_get_pci_dev(pdev, ent, &driver);
1214}
1215
1216static int __init psb_init(void)
1217{
1218 return drm_pci_init(&driver, &psb_pci_driver);
1219}
1220
1221static void __exit psb_exit(void)
1222{
1223 drm_pci_exit(&driver, &psb_pci_driver);
1224}
1225
1226late_initcall(psb_init);
1227module_exit(psb_exit);
1228
1229MODULE_AUTHOR("Alan Cox <alan@linux.intel.com> and others");
1230MODULE_DESCRIPTION(DRIVER_DESC);
1231MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
new file mode 100644
index 00000000000..fd4732dd783
--- /dev/null
+++ b/drivers/staging/gma500/psb_drv.h
@@ -0,0 +1,948 @@
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
39enum {
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_MRST(dev) (((dev)->pci_device & 0xfffc) == 0x4100)
47#define IS_MFLD(dev) (((dev)->pci_device & 0xfff8) == 0x0130)
48
49/*
50 * Driver definitions
51 */
52
53#define DRIVER_NAME "gma500"
54#define DRIVER_DESC "DRM driver for the Intel GMA500"
55
56#define PSB_DRM_DRIVER_DATE "2011-06-06"
57#define PSB_DRM_DRIVER_MAJOR 1
58#define PSB_DRM_DRIVER_MINOR 0
59#define PSB_DRM_DRIVER_PATCHLEVEL 0
60
61/*
62 * Hardware offsets
63 */
64#define PSB_VDC_OFFSET 0x00000000
65#define PSB_VDC_SIZE 0x000080000
66#define MRST_MMIO_SIZE 0x0000C0000
67#define MDFLD_MMIO_SIZE 0x000100000
68#define PSB_SGX_SIZE 0x8000
69#define PSB_SGX_OFFSET 0x00040000
70#define MRST_SGX_OFFSET 0x00080000
71/*
72 * PCI resource identifiers
73 */
74#define PSB_MMIO_RESOURCE 0
75#define PSB_GATT_RESOURCE 2
76#define PSB_GTT_RESOURCE 3
77/*
78 * PCI configuration
79 */
80#define PSB_GMCH_CTRL 0x52
81#define PSB_BSM 0x5C
82#define _PSB_GMCH_ENABLED 0x4
83#define PSB_PGETBL_CTL 0x2020
84#define _PSB_PGETBL_ENABLED 0x00000001
85#define PSB_SGX_2D_SLAVE_PORT 0x4000
86
87/* To get rid of */
88#define PSB_TT_PRIV0_LIMIT (256*1024*1024)
89#define PSB_TT_PRIV0_PLIMIT (PSB_TT_PRIV0_LIMIT >> PAGE_SHIFT)
90
91/*
92 * SGX side MMU definitions (these can probably go)
93 */
94
95/*
96 * Flags for external memory type field.
97 */
98#define PSB_MMU_CACHED_MEMORY 0x0001 /* Bind to MMU only */
99#define PSB_MMU_RO_MEMORY 0x0002 /* MMU RO memory */
100#define PSB_MMU_WO_MEMORY 0x0004 /* MMU WO memory */
101/*
102 * PTE's and PDE's
103 */
104#define PSB_PDE_MASK 0x003FFFFF
105#define PSB_PDE_SHIFT 22
106#define PSB_PTE_SHIFT 12
107/*
108 * Cache control
109 */
110#define PSB_PTE_VALID 0x0001 /* PTE / PDE valid */
111#define PSB_PTE_WO 0x0002 /* Write only */
112#define PSB_PTE_RO 0x0004 /* Read only */
113#define PSB_PTE_CACHED 0x0008 /* CPU cache coherent */
114
115/*
116 * VDC registers and bits
117 */
118#define PSB_MSVDX_CLOCKGATING 0x2064
119#define PSB_TOPAZ_CLOCKGATING 0x2068
120#define PSB_HWSTAM 0x2098
121#define PSB_INSTPM 0x20C0
122#define PSB_INT_IDENTITY_R 0x20A4
123#define _MDFLD_PIPEC_EVENT_FLAG (1<<2)
124#define _MDFLD_PIPEC_VBLANK_FLAG (1<<3)
125#define _PSB_DPST_PIPEB_FLAG (1<<4)
126#define _MDFLD_PIPEB_EVENT_FLAG (1<<4)
127#define _PSB_VSYNC_PIPEB_FLAG (1<<5)
128#define _PSB_DPST_PIPEA_FLAG (1<<6)
129#define _PSB_PIPEA_EVENT_FLAG (1<<6)
130#define _PSB_VSYNC_PIPEA_FLAG (1<<7)
131#define _MDFLD_MIPIA_FLAG (1<<16)
132#define _MDFLD_MIPIC_FLAG (1<<17)
133#define _PSB_IRQ_SGX_FLAG (1<<18)
134#define _PSB_IRQ_MSVDX_FLAG (1<<19)
135#define _LNC_IRQ_TOPAZ_FLAG (1<<20)
136
137/* This flag includes all the display IRQ bits excepts the vblank irqs. */
138#define _MDFLD_DISP_ALL_IRQ_FLAG (_MDFLD_PIPEC_EVENT_FLAG | \
139 _MDFLD_PIPEB_EVENT_FLAG | \
140 _PSB_PIPEA_EVENT_FLAG | \
141 _PSB_VSYNC_PIPEA_FLAG | \
142 _MDFLD_MIPIA_FLAG | \
143 _MDFLD_MIPIC_FLAG)
144#define PSB_INT_IDENTITY_R 0x20A4
145#define PSB_INT_MASK_R 0x20A8
146#define PSB_INT_ENABLE_R 0x20A0
147
148#define _PSB_MMU_ER_MASK 0x0001FF00
149#define _PSB_MMU_ER_HOST (1 << 16)
150#define GPIOA 0x5010
151#define GPIOB 0x5014
152#define GPIOC 0x5018
153#define GPIOD 0x501c
154#define GPIOE 0x5020
155#define GPIOF 0x5024
156#define GPIOG 0x5028
157#define GPIOH 0x502c
158#define GPIO_CLOCK_DIR_MASK (1 << 0)
159#define GPIO_CLOCK_DIR_IN (0 << 1)
160#define GPIO_CLOCK_DIR_OUT (1 << 1)
161#define GPIO_CLOCK_VAL_MASK (1 << 2)
162#define GPIO_CLOCK_VAL_OUT (1 << 3)
163#define GPIO_CLOCK_VAL_IN (1 << 4)
164#define GPIO_CLOCK_PULLUP_DISABLE (1 << 5)
165#define GPIO_DATA_DIR_MASK (1 << 8)
166#define GPIO_DATA_DIR_IN (0 << 9)
167#define GPIO_DATA_DIR_OUT (1 << 9)
168#define GPIO_DATA_VAL_MASK (1 << 10)
169#define GPIO_DATA_VAL_OUT (1 << 11)
170#define GPIO_DATA_VAL_IN (1 << 12)
171#define GPIO_DATA_PULLUP_DISABLE (1 << 13)
172
173#define VCLK_DIVISOR_VGA0 0x6000
174#define VCLK_DIVISOR_VGA1 0x6004
175#define VCLK_POST_DIV 0x6010
176
177#define PSB_COMM_2D (PSB_ENGINE_2D << 4)
178#define PSB_COMM_3D (PSB_ENGINE_3D << 4)
179#define PSB_COMM_TA (PSB_ENGINE_TA << 4)
180#define PSB_COMM_HP (PSB_ENGINE_HP << 4)
181#define PSB_COMM_USER_IRQ (1024 >> 2)
182#define PSB_COMM_USER_IRQ_LOST (PSB_COMM_USER_IRQ + 1)
183#define PSB_COMM_FW (2048 >> 2)
184
185#define PSB_UIRQ_VISTEST 1
186#define PSB_UIRQ_OOM_REPLY 2
187#define PSB_UIRQ_FIRE_TA_REPLY 3
188#define PSB_UIRQ_FIRE_RASTER_REPLY 4
189
190#define PSB_2D_SIZE (256*1024*1024)
191#define PSB_MAX_RELOC_PAGES 1024
192
193#define PSB_LOW_REG_OFFS 0x0204
194#define PSB_HIGH_REG_OFFS 0x0600
195
196#define PSB_NUM_VBLANKS 2
197
198
199#define PSB_2D_SIZE (256*1024*1024)
200#define PSB_MAX_RELOC_PAGES 1024
201
202#define PSB_LOW_REG_OFFS 0x0204
203#define PSB_HIGH_REG_OFFS 0x0600
204
205#define PSB_NUM_VBLANKS 2
206#define PSB_WATCHDOG_DELAY (DRM_HZ * 2)
207#define PSB_LID_DELAY (DRM_HZ / 10)
208
209#define MDFLD_PNW_B0 0x04
210#define MDFLD_PNW_C0 0x08
211
212#define MDFLD_DSR_2D_3D_0 (1 << 0)
213#define MDFLD_DSR_2D_3D_2 (1 << 1)
214#define MDFLD_DSR_CURSOR_0 (1 << 2)
215#define MDFLD_DSR_CURSOR_2 (1 << 3)
216#define MDFLD_DSR_OVERLAY_0 (1 << 4)
217#define MDFLD_DSR_OVERLAY_2 (1 << 5)
218#define MDFLD_DSR_MIPI_CONTROL (1 << 6)
219#define MDFLD_DSR_DAMAGE_MASK_0 ((1 << 0) | (1 << 2) | (1 << 4))
220#define MDFLD_DSR_DAMAGE_MASK_2 ((1 << 1) | (1 << 3) | (1 << 5))
221#define MDFLD_DSR_2D_3D (MDFLD_DSR_2D_3D_0 | MDFLD_DSR_2D_3D_2)
222
223#define MDFLD_DSR_RR 45
224#define MDFLD_DPU_ENABLE (1 << 31)
225#define MDFLD_DSR_FULLSCREEN (1 << 30)
226#define MDFLD_DSR_DELAY (DRM_HZ / MDFLD_DSR_RR)
227
228#define PSB_PWR_STATE_ON 1
229#define PSB_PWR_STATE_OFF 2
230
231#define PSB_PMPOLICY_NOPM 0
232#define PSB_PMPOLICY_CLOCKGATING 1
233#define PSB_PMPOLICY_POWERDOWN 2
234
235#define PSB_PMSTATE_POWERUP 0
236#define PSB_PMSTATE_CLOCKGATED 1
237#define PSB_PMSTATE_POWERDOWN 2
238#define PSB_PCIx_MSI_ADDR_LOC 0x94
239#define PSB_PCIx_MSI_DATA_LOC 0x98
240
241/* Medfield crystal settings */
242#define KSEL_CRYSTAL_19 1
243#define KSEL_BYPASS_19 5
244#define KSEL_BYPASS_25 6
245#define KSEL_BYPASS_83_100 7
246
247struct opregion_header;
248struct opregion_acpi;
249struct opregion_swsci;
250struct opregion_asle;
251
252struct psb_intel_opregion {
253 struct opregion_header *header;
254 struct opregion_acpi *acpi;
255 struct opregion_swsci *swsci;
256 struct opregion_asle *asle;
257 int enabled;
258};
259
260struct psb_ops;
261
262struct drm_psb_private {
263 struct drm_device *dev;
264 const struct psb_ops *ops;
265
266 struct psb_gtt gtt;
267
268 /* GTT Memory manager */
269 struct psb_gtt_mm *gtt_mm;
270 struct page *scratch_page;
271 u32 *gtt_map;
272 uint32_t stolen_base;
273 void *vram_addr;
274 unsigned long vram_stolen_size;
275 int gtt_initialized;
276 u16 gmch_ctrl; /* Saved GTT setup */
277 u32 pge_ctl;
278
279 struct mutex gtt_mutex;
280 struct resource *gtt_mem; /* Our PCI resource */
281
282 struct psb_mmu_driver *mmu;
283 struct psb_mmu_pd *pf_pd;
284
285 /*
286 * Register base
287 */
288
289 uint8_t *sgx_reg;
290 uint8_t *vdc_reg;
291 uint32_t gatt_free_offset;
292
293 /*
294 * Fencing / irq.
295 */
296
297 uint32_t vdc_irq_mask;
298 uint32_t pipestat[PSB_NUM_PIPE];
299
300 spinlock_t irqmask_lock;
301
302 /*
303 * Power
304 */
305
306 bool suspended;
307 bool display_power;
308 int display_count;
309
310 /*
311 * Modesetting
312 */
313 struct psb_intel_mode_device mode_dev;
314
315 struct drm_crtc *plane_to_crtc_mapping[PSB_NUM_PIPE];
316 struct drm_crtc *pipe_to_crtc_mapping[PSB_NUM_PIPE];
317 uint32_t num_pipe;
318
319 /*
320 * OSPM info (Power management base) (can go ?)
321 */
322 uint32_t ospm_base;
323
324 /*
325 * Sizes info
326 */
327
328 struct drm_psb_sizes_arg sizes;
329
330 u32 fuse_reg_value;
331 u32 video_device_fuse;
332
333 /* PCI revision ID for B0:D2:F0 */
334 uint8_t platform_rev_id;
335
336 /*
337 * LVDS info
338 */
339 int backlight_duty_cycle; /* restore backlight to this value */
340 bool panel_wants_dither;
341 struct drm_display_mode *panel_fixed_mode;
342 struct drm_display_mode *lfp_lvds_vbt_mode;
343 struct drm_display_mode *sdvo_lvds_vbt_mode;
344
345 struct bdb_lvds_backlight *lvds_bl; /* LVDS backlight info from VBT */
346 struct psb_intel_i2c_chan *lvds_i2c_bus;
347
348 /* Feature bits from the VBIOS */
349 unsigned int int_tv_support:1;
350 unsigned int lvds_dither:1;
351 unsigned int lvds_vbt:1;
352 unsigned int int_crt_support:1;
353 unsigned int lvds_use_ssc:1;
354 int lvds_ssc_freq;
355 bool is_lvds_on;
356 bool is_mipi_on;
357 u32 mipi_ctrl_display;
358
359 unsigned int core_freq;
360 uint32_t iLVDS_enable;
361
362 /* Runtime PM state */
363 int rpm_enabled;
364
365 /* MID specific */
366 struct mrst_vbt vbt_data;
367 struct mrst_gct_data gct_data;
368
369 /* MIPI Panel type etc */
370 int panel_id;
371 bool dual_mipi; /* dual display - DPI & DBI */
372 bool dpi_panel_on; /* The DPI panel power is on */
373 bool dpi_panel_on2; /* The DPI panel power is on */
374 bool dbi_panel_on; /* The DBI panel power is on */
375 bool dbi_panel_on2; /* The DBI panel power is on */
376 u32 dsr_fb_update; /* DSR FB update counter */
377
378 /* Moorestown HDMI state */
379 struct mrst_hdmi_dev *hdmi_priv;
380
381 /* Moorestown pipe config register value cache */
382 uint32_t pipeconf;
383 uint32_t pipeconf1;
384 uint32_t pipeconf2;
385
386 /* Moorestown plane control register value cache */
387 uint32_t dspcntr;
388 uint32_t dspcntr1;
389 uint32_t dspcntr2;
390
391 /* Moorestown MM backlight cache */
392 uint8_t saveBKLTCNT;
393 uint8_t saveBKLTREQ;
394 uint8_t saveBKLTBRTL;
395
396 /*
397 * Register state
398 */
399 uint32_t saveDSPACNTR;
400 uint32_t saveDSPBCNTR;
401 uint32_t savePIPEACONF;
402 uint32_t savePIPEBCONF;
403 uint32_t savePIPEASRC;
404 uint32_t savePIPEBSRC;
405 uint32_t saveFPA0;
406 uint32_t saveFPA1;
407 uint32_t saveDPLL_A;
408 uint32_t saveDPLL_A_MD;
409 uint32_t saveHTOTAL_A;
410 uint32_t saveHBLANK_A;
411 uint32_t saveHSYNC_A;
412 uint32_t saveVTOTAL_A;
413 uint32_t saveVBLANK_A;
414 uint32_t saveVSYNC_A;
415 uint32_t saveDSPASTRIDE;
416 uint32_t saveDSPASIZE;
417 uint32_t saveDSPAPOS;
418 uint32_t saveDSPABASE;
419 uint32_t saveDSPASURF;
420 uint32_t saveDSPASTATUS;
421 uint32_t saveFPB0;
422 uint32_t saveFPB1;
423 uint32_t saveDPLL_B;
424 uint32_t saveDPLL_B_MD;
425 uint32_t saveHTOTAL_B;
426 uint32_t saveHBLANK_B;
427 uint32_t saveHSYNC_B;
428 uint32_t saveVTOTAL_B;
429 uint32_t saveVBLANK_B;
430 uint32_t saveVSYNC_B;
431 uint32_t saveDSPBSTRIDE;
432 uint32_t saveDSPBSIZE;
433 uint32_t saveDSPBPOS;
434 uint32_t saveDSPBBASE;
435 uint32_t saveDSPBSURF;
436 uint32_t saveDSPBSTATUS;
437 uint32_t saveVCLK_DIVISOR_VGA0;
438 uint32_t saveVCLK_DIVISOR_VGA1;
439 uint32_t saveVCLK_POST_DIV;
440 uint32_t saveVGACNTRL;
441 uint32_t saveADPA;
442 uint32_t saveLVDS;
443 uint32_t saveDVOA;
444 uint32_t saveDVOB;
445 uint32_t saveDVOC;
446 uint32_t savePP_ON;
447 uint32_t savePP_OFF;
448 uint32_t savePP_CONTROL;
449 uint32_t savePP_CYCLE;
450 uint32_t savePFIT_CONTROL;
451 uint32_t savePaletteA[256];
452 uint32_t savePaletteB[256];
453 uint32_t saveBLC_PWM_CTL2;
454 uint32_t saveBLC_PWM_CTL;
455 uint32_t saveCLOCKGATING;
456 uint32_t saveDSPARB;
457 uint32_t saveDSPATILEOFF;
458 uint32_t saveDSPBTILEOFF;
459 uint32_t saveDSPAADDR;
460 uint32_t saveDSPBADDR;
461 uint32_t savePFIT_AUTO_RATIOS;
462 uint32_t savePFIT_PGM_RATIOS;
463 uint32_t savePP_ON_DELAYS;
464 uint32_t savePP_OFF_DELAYS;
465 uint32_t savePP_DIVISOR;
466 uint32_t saveBSM;
467 uint32_t saveVBT;
468 uint32_t saveBCLRPAT_A;
469 uint32_t saveBCLRPAT_B;
470 uint32_t saveDSPALINOFF;
471 uint32_t saveDSPBLINOFF;
472 uint32_t savePERF_MODE;
473 uint32_t saveDSPFW1;
474 uint32_t saveDSPFW2;
475 uint32_t saveDSPFW3;
476 uint32_t saveDSPFW4;
477 uint32_t saveDSPFW5;
478 uint32_t saveDSPFW6;
479 uint32_t saveCHICKENBIT;
480 uint32_t saveDSPACURSOR_CTRL;
481 uint32_t saveDSPBCURSOR_CTRL;
482 uint32_t saveDSPACURSOR_BASE;
483 uint32_t saveDSPBCURSOR_BASE;
484 uint32_t saveDSPACURSOR_POS;
485 uint32_t saveDSPBCURSOR_POS;
486 uint32_t save_palette_a[256];
487 uint32_t save_palette_b[256];
488 uint32_t saveOV_OVADD;
489 uint32_t saveOV_OGAMC0;
490 uint32_t saveOV_OGAMC1;
491 uint32_t saveOV_OGAMC2;
492 uint32_t saveOV_OGAMC3;
493 uint32_t saveOV_OGAMC4;
494 uint32_t saveOV_OGAMC5;
495 uint32_t saveOVC_OVADD;
496 uint32_t saveOVC_OGAMC0;
497 uint32_t saveOVC_OGAMC1;
498 uint32_t saveOVC_OGAMC2;
499 uint32_t saveOVC_OGAMC3;
500 uint32_t saveOVC_OGAMC4;
501 uint32_t saveOVC_OGAMC5;
502
503 /* MSI reg save */
504 uint32_t msi_addr;
505 uint32_t msi_data;
506
507 /* Medfield specific register save state */
508 uint32_t saveHDMIPHYMISCCTL;
509 uint32_t saveHDMIB_CONTROL;
510 uint32_t saveDSPCCNTR;
511 uint32_t savePIPECCONF;
512 uint32_t savePIPECSRC;
513 uint32_t saveHTOTAL_C;
514 uint32_t saveHBLANK_C;
515 uint32_t saveHSYNC_C;
516 uint32_t saveVTOTAL_C;
517 uint32_t saveVBLANK_C;
518 uint32_t saveVSYNC_C;
519 uint32_t saveDSPCSTRIDE;
520 uint32_t saveDSPCSIZE;
521 uint32_t saveDSPCPOS;
522 uint32_t saveDSPCSURF;
523 uint32_t saveDSPCSTATUS;
524 uint32_t saveDSPCLINOFF;
525 uint32_t saveDSPCTILEOFF;
526 uint32_t saveDSPCCURSOR_CTRL;
527 uint32_t saveDSPCCURSOR_BASE;
528 uint32_t saveDSPCCURSOR_POS;
529 uint32_t save_palette_c[256];
530 uint32_t saveOV_OVADD_C;
531 uint32_t saveOV_OGAMC0_C;
532 uint32_t saveOV_OGAMC1_C;
533 uint32_t saveOV_OGAMC2_C;
534 uint32_t saveOV_OGAMC3_C;
535 uint32_t saveOV_OGAMC4_C;
536 uint32_t saveOV_OGAMC5_C;
537
538 /* DSI register save */
539 uint32_t saveDEVICE_READY_REG;
540 uint32_t saveINTR_EN_REG;
541 uint32_t saveDSI_FUNC_PRG_REG;
542 uint32_t saveHS_TX_TIMEOUT_REG;
543 uint32_t saveLP_RX_TIMEOUT_REG;
544 uint32_t saveTURN_AROUND_TIMEOUT_REG;
545 uint32_t saveDEVICE_RESET_REG;
546 uint32_t saveDPI_RESOLUTION_REG;
547 uint32_t saveHORIZ_SYNC_PAD_COUNT_REG;
548 uint32_t saveHORIZ_BACK_PORCH_COUNT_REG;
549 uint32_t saveHORIZ_FRONT_PORCH_COUNT_REG;
550 uint32_t saveHORIZ_ACTIVE_AREA_COUNT_REG;
551 uint32_t saveVERT_SYNC_PAD_COUNT_REG;
552 uint32_t saveVERT_BACK_PORCH_COUNT_REG;
553 uint32_t saveVERT_FRONT_PORCH_COUNT_REG;
554 uint32_t saveHIGH_LOW_SWITCH_COUNT_REG;
555 uint32_t saveINIT_COUNT_REG;
556 uint32_t saveMAX_RET_PAK_REG;
557 uint32_t saveVIDEO_FMT_REG;
558 uint32_t saveEOT_DISABLE_REG;
559 uint32_t saveLP_BYTECLK_REG;
560 uint32_t saveHS_LS_DBI_ENABLE_REG;
561 uint32_t saveTXCLKESC_REG;
562 uint32_t saveDPHY_PARAM_REG;
563 uint32_t saveMIPI_CONTROL_REG;
564 uint32_t saveMIPI;
565 uint32_t saveMIPI_C;
566
567 /* DPST register save */
568 uint32_t saveHISTOGRAM_INT_CONTROL_REG;
569 uint32_t saveHISTOGRAM_LOGIC_CONTROL_REG;
570 uint32_t savePWM_CONTROL_LOGIC;
571
572 /*
573 * DSI info.
574 */
575 void * dbi_dsr_info;
576 void * dbi_dpu_info;
577 void * dsi_configs[2];
578 /*
579 * LID-Switch
580 */
581 spinlock_t lid_lock;
582 struct timer_list lid_timer;
583 struct psb_intel_opregion opregion;
584 u32 *lid_state;
585 u32 lid_last_state;
586
587 /*
588 * Watchdog
589 */
590
591 uint32_t apm_reg;
592 uint16_t apm_base;
593
594 /*
595 * Used for modifying backlight from
596 * xrandr -- consider removing and using HAL instead
597 */
598 struct backlight_device *backlight_device;
599 struct drm_property *backlight_property;
600 uint32_t blc_adj1;
601 uint32_t blc_adj2;
602
603 void *fbdev;
604 /* DPST state */
605 uint32_t dsr_idle_count;
606 bool is_in_idle;
607 bool dsr_enable;
608 void (*exit_idle)(struct drm_device *dev, u32 update_src);
609
610 /* 2D acceleration */
611 struct mutex mutex_2d;
612
613 /* FIXME: Arrays anyone ? */
614 struct mdfld_dsi_encoder *encoder0;
615 struct mdfld_dsi_encoder *encoder2;
616 struct mdfld_dsi_dbi_output * dbi_output;
617 struct mdfld_dsi_dbi_output * dbi_output2;
618 u32 bpp;
619 u32 bpp2;
620
621 bool dispstatus;
622};
623
624
625/*
626 * Operations for each board type
627 */
628
629struct psb_ops {
630 const char *name;
631 unsigned int accel_2d:1;
632 int pipes; /* Number of output pipes */
633 int crtcs; /* Number of CRTCs */
634 int sgx_offset; /* Base offset of SGX device */
635
636 /* Sub functions */
637 struct drm_crtc_helper_funcs const *crtc_helper;
638 struct drm_crtc_funcs const *crtc_funcs;
639
640 /* Setup hooks */
641 int (*chip_setup)(struct drm_device *dev);
642 void (*chip_teardown)(struct drm_device *dev);
643
644 /* Display management hooks */
645 int (*output_init)(struct drm_device *dev);
646 /* Power management hooks */
647 void (*init_pm)(struct drm_device *dev);
648 int (*save_regs)(struct drm_device *dev);
649 int (*restore_regs)(struct drm_device *dev);
650 int (*power_up)(struct drm_device *dev);
651 int (*power_down)(struct drm_device *dev);
652
653 void (*lvds_bl_power)(struct drm_device *dev, bool on);
654#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
655 /* Backlight */
656 int (*backlight_init)(struct drm_device *dev);
657#endif
658 int i2c_bus; /* I2C bus identifier for Moorestown */
659};
660
661
662
663struct psb_mmu_driver;
664
665extern int drm_crtc_probe_output_modes(struct drm_device *dev, int, int);
666extern int drm_pick_crtcs(struct drm_device *dev);
667
668static inline struct drm_psb_private *psb_priv(struct drm_device *dev)
669{
670 return (struct drm_psb_private *) dev->dev_private;
671}
672
673/*
674 * MMU stuff.
675 */
676
677extern struct psb_mmu_driver *psb_mmu_driver_init(uint8_t __iomem * registers,
678 int trap_pagefaults,
679 int invalid_type,
680 struct drm_psb_private *dev_priv);
681extern void psb_mmu_driver_takedown(struct psb_mmu_driver *driver);
682extern struct psb_mmu_pd *psb_mmu_get_default_pd(struct psb_mmu_driver
683 *driver);
684extern void psb_mmu_mirror_gtt(struct psb_mmu_pd *pd, uint32_t mmu_offset,
685 uint32_t gtt_start, uint32_t gtt_pages);
686extern struct psb_mmu_pd *psb_mmu_alloc_pd(struct psb_mmu_driver *driver,
687 int trap_pagefaults,
688 int invalid_type);
689extern void psb_mmu_free_pagedir(struct psb_mmu_pd *pd);
690extern void psb_mmu_flush(struct psb_mmu_driver *driver, int rc_prot);
691extern void psb_mmu_remove_pfn_sequence(struct psb_mmu_pd *pd,
692 unsigned long address,
693 uint32_t num_pages);
694extern int psb_mmu_insert_pfn_sequence(struct psb_mmu_pd *pd,
695 uint32_t start_pfn,
696 unsigned long address,
697 uint32_t num_pages, int type);
698extern int psb_mmu_virtual_to_pfn(struct psb_mmu_pd *pd, uint32_t virtual,
699 unsigned long *pfn);
700
701/*
702 * Enable / disable MMU for different requestors.
703 */
704
705
706extern void psb_mmu_set_pd_context(struct psb_mmu_pd *pd, int hw_context);
707extern int psb_mmu_insert_pages(struct psb_mmu_pd *pd, struct page **pages,
708 unsigned long address, uint32_t num_pages,
709 uint32_t desired_tile_stride,
710 uint32_t hw_tile_stride, int type);
711extern void psb_mmu_remove_pages(struct psb_mmu_pd *pd,
712 unsigned long address, uint32_t num_pages,
713 uint32_t desired_tile_stride,
714 uint32_t hw_tile_stride);
715/*
716 *psb_irq.c
717 */
718
719extern irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
720extern int psb_irq_enable_dpst(struct drm_device *dev);
721extern int psb_irq_disable_dpst(struct drm_device *dev);
722extern void psb_irq_preinstall(struct drm_device *dev);
723extern int psb_irq_postinstall(struct drm_device *dev);
724extern void psb_irq_uninstall(struct drm_device *dev);
725extern void psb_irq_turn_on_dpst(struct drm_device *dev);
726extern void psb_irq_turn_off_dpst(struct drm_device *dev);
727
728extern void psb_irq_uninstall_islands(struct drm_device *dev, int hw_islands);
729extern int psb_vblank_wait2(struct drm_device *dev, unsigned int *sequence);
730extern int psb_vblank_wait(struct drm_device *dev, unsigned int *sequence);
731extern int psb_enable_vblank(struct drm_device *dev, int crtc);
732extern void psb_disable_vblank(struct drm_device *dev, int crtc);
733void
734psb_enable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
735
736void
737psb_disable_pipestat(struct drm_psb_private *dev_priv, int pipe, u32 mask);
738
739extern u32 psb_get_vblank_counter(struct drm_device *dev, int crtc);
740
741extern int mdfld_enable_te(struct drm_device *dev, int pipe);
742extern void mdfld_disable_te(struct drm_device *dev, int pipe);
743
744/*
745 * intel_opregion.c
746 */
747extern int gma_intel_opregion_init(struct drm_device *dev);
748extern int gma_intel_opregion_exit(struct drm_device *dev);
749
750/*
751 * framebuffer.c
752 */
753extern int psbfb_probed(struct drm_device *dev);
754extern int psbfb_remove(struct drm_device *dev,
755 struct drm_framebuffer *fb);
756/*
757 * accel_2d.c
758 */
759extern void psbfb_copyarea(struct fb_info *info,
760 const struct fb_copyarea *region);
761extern int psbfb_sync(struct fb_info *info);
762extern void psb_spank(struct drm_psb_private *dev_priv);
763extern int psb_accel_ioctl(struct drm_device *dev, void *data,
764 struct drm_file *file);
765
766/*
767 * psb_reset.c
768 */
769
770extern void psb_lid_timer_init(struct drm_psb_private *dev_priv);
771extern void psb_lid_timer_takedown(struct drm_psb_private *dev_priv);
772extern void psb_print_pagefault(struct drm_psb_private *dev_priv);
773
774/* modesetting */
775extern void psb_modeset_init(struct drm_device *dev);
776extern void psb_modeset_cleanup(struct drm_device *dev);
777extern int psb_fbdev_init(struct drm_device *dev);
778
779/* backlight.c */
780int gma_backlight_init(struct drm_device *dev);
781void gma_backlight_exit(struct drm_device *dev);
782
783/* mrst_crtc.c */
784extern const struct drm_crtc_helper_funcs mrst_helper_funcs;
785
786/* mrst_lvds.c */
787extern void mrst_lvds_init(struct drm_device *dev,
788 struct psb_intel_mode_device *mode_dev);
789
790/* psb_intel_display.c */
791extern const struct drm_crtc_helper_funcs psb_intel_helper_funcs;
792extern const struct drm_crtc_funcs psb_intel_crtc_funcs;
793
794/* psb_intel_lvds.c */
795extern const struct drm_connector_helper_funcs
796 psb_intel_lvds_connector_helper_funcs;
797extern const struct drm_connector_funcs psb_intel_lvds_connector_funcs;
798
799/* gem.c */
800extern int psb_gem_init_object(struct drm_gem_object *obj);
801extern void psb_gem_free_object(struct drm_gem_object *obj);
802extern int psb_gem_get_aperture(struct drm_device *dev, void *data,
803 struct drm_file *file);
804extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
805 struct drm_mode_create_dumb *args);
806extern int psb_gem_dumb_destroy(struct drm_file *file, struct drm_device *dev,
807 uint32_t handle);
808extern int psb_gem_dumb_map_gtt(struct drm_file *file, struct drm_device *dev,
809 uint32_t handle, uint64_t *offset);
810extern int psb_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
811extern int psb_gem_create_ioctl(struct drm_device *dev, void *data,
812 struct drm_file *file);
813extern int psb_gem_mmap_ioctl(struct drm_device *dev, void *data,
814 struct drm_file *file);
815
816/* psb_device.c */
817extern const struct psb_ops psb_chip_ops;
818
819/* mrst_device.c */
820extern const struct psb_ops mrst_chip_ops;
821
822/* mdfld_device.c */
823extern const struct psb_ops mdfld_chip_ops;
824
825/* cdv_device.c */
826extern const struct psb_ops cdv_chip_ops;
827
828/*
829 * Debug print bits setting
830 */
831#define PSB_D_GENERAL (1 << 0)
832#define PSB_D_INIT (1 << 1)
833#define PSB_D_IRQ (1 << 2)
834#define PSB_D_ENTRY (1 << 3)
835/* debug the get H/V BP/FP count */
836#define PSB_D_HV (1 << 4)
837#define PSB_D_DBI_BF (1 << 5)
838#define PSB_D_PM (1 << 6)
839#define PSB_D_RENDER (1 << 7)
840#define PSB_D_REG (1 << 8)
841#define PSB_D_MSVDX (1 << 9)
842#define PSB_D_TOPAZ (1 << 10)
843
844extern int drm_psb_no_fb;
845extern int drm_idle_check_interval;
846
847/*
848 * Utilities
849 */
850
851static inline u32 MRST_MSG_READ32(uint port, uint offset)
852{
853 int mcr = (0xD0<<24) | (port << 16) | (offset << 8);
854 uint32_t ret_val = 0;
855 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
856 pci_write_config_dword(pci_root, 0xD0, mcr);
857 pci_read_config_dword(pci_root, 0xD4, &ret_val);
858 pci_dev_put(pci_root);
859 return ret_val;
860}
861static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value)
862{
863 int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0;
864 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
865 pci_write_config_dword(pci_root, 0xD4, value);
866 pci_write_config_dword(pci_root, 0xD0, mcr);
867 pci_dev_put(pci_root);
868}
869static inline u32 MDFLD_MSG_READ32(uint port, uint offset)
870{
871 int mcr = (0x10<<24) | (port << 16) | (offset << 8);
872 uint32_t ret_val = 0;
873 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
874 pci_write_config_dword(pci_root, 0xD0, mcr);
875 pci_read_config_dword(pci_root, 0xD4, &ret_val);
876 pci_dev_put(pci_root);
877 return ret_val;
878}
879static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
880{
881 int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
882 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
883 pci_write_config_dword(pci_root, 0xD4, value);
884 pci_write_config_dword(pci_root, 0xD0, mcr);
885 pci_dev_put(pci_root);
886}
887
888static inline uint32_t REGISTER_READ(struct drm_device *dev, uint32_t reg)
889{
890 struct drm_psb_private *dev_priv = dev->dev_private;
891 return ioread32(dev_priv->vdc_reg + reg);
892}
893
894#define REG_READ(reg) REGISTER_READ(dev, (reg))
895
896static inline void REGISTER_WRITE(struct drm_device *dev, uint32_t reg,
897 uint32_t val)
898{
899 struct drm_psb_private *dev_priv = dev->dev_private;
900 iowrite32((val), dev_priv->vdc_reg + (reg));
901}
902
903#define REG_WRITE(reg, val) REGISTER_WRITE(dev, (reg), (val))
904
905static inline void REGISTER_WRITE16(struct drm_device *dev,
906 uint32_t reg, uint32_t val)
907{
908 struct drm_psb_private *dev_priv = dev->dev_private;
909 iowrite16((val), dev_priv->vdc_reg + (reg));
910}
911
912#define REG_WRITE16(reg, val) REGISTER_WRITE16(dev, (reg), (val))
913
914static inline void REGISTER_WRITE8(struct drm_device *dev,
915 uint32_t reg, uint32_t val)
916{
917 struct drm_psb_private *dev_priv = dev->dev_private;
918 iowrite8((val), dev_priv->vdc_reg + (reg));
919}
920
921#define REG_WRITE8(reg, val) REGISTER_WRITE8(dev, (reg), (val))
922
923#define PSB_WVDC32(_val, _offs) iowrite32(_val, dev_priv->vdc_reg + (_offs))
924#define PSB_RVDC32(_offs) ioread32(dev_priv->vdc_reg + (_offs))
925
926/* #define TRAP_SGX_PM_FAULT 1 */
927#ifdef TRAP_SGX_PM_FAULT
928#define PSB_RSGX32(_offs) \
929({ \
930 if (inl(dev_priv->apm_base + PSB_APM_STS) & 0x3) { \
931 printk(KERN_ERR \
932 "access sgx when it's off!! (READ) %s, %d\n", \
933 __FILE__, __LINE__); \
934 melay(1000); \
935 } \
936 ioread32(dev_priv->sgx_reg + (_offs)); \
937})
938#else
939#define PSB_RSGX32(_offs) ioread32(dev_priv->sgx_reg + (_offs))
940#endif
941#define PSB_WSGX32(_val, _offs) iowrite32(_val, dev_priv->sgx_reg + (_offs))
942
943#define MSVDX_REG_DUMP 0
944
945#define PSB_WMSVDX32(_val, _offs) iowrite32(_val, dev_priv->msvdx_reg + (_offs))
946#define PSB_RMSVDX32(_offs) ioread32(dev_priv->msvdx_reg + (_offs))
947
948#endif
diff --git a/drivers/staging/gma500/psb_intel_display.c b/drivers/staging/gma500/psb_intel_display.c
new file mode 100644
index 00000000000..4afa671f974
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_display.c
@@ -0,0 +1,1433 @@
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
34struct 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
46struct psb_intel_range_t {
47 int min, max;
48};
49
50struct psb_intel_p2_t {
51 int dot_limit;
52 int p2_slow, p2_fast;
53};
54
55#define INTEL_P2_NUM 2
56
57struct 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
116static 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
171static 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
184static 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
194static 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
202static 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 */
211bool 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
234static 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 */
270static 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
332void 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
338int 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->pitch + x * (crtc->fb->bits_per_pixel / 8);
371
372 REG_WRITE(dspstride, crtc->fb->pitch);
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
410psb_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
415psb_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 */
426static 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
529static 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
535static 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
541void 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
549void 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
557static 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 */
569static 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
582static 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 */
802void 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 */
857static 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 */
901static 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
962static 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
1052static 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
1083void 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
1101static int psb_crtc_set_config(struct drm_mode_set *set)
1102{
1103 int ret;
1104 struct drm_device *dev = set->crtc->dev;
1105 struct drm_psb_private *dev_priv = dev->dev_private;
1106
1107 if (!dev_priv->rpm_enabled)
1108 return drm_crtc_helper_set_config(set);
1109
1110 pm_runtime_forbid(&dev->pdev->dev);
1111 ret = drm_crtc_helper_set_config(set);
1112 pm_runtime_allow(&dev->pdev->dev);
1113 return ret;
1114}
1115
1116/* Returns the clock of the currently programmed mode of the given pipe. */
1117static int psb_intel_crtc_clock_get(struct drm_device *dev,
1118 struct drm_crtc *crtc)
1119{
1120 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1121 int pipe = psb_intel_crtc->pipe;
1122 u32 dpll;
1123 u32 fp;
1124 struct psb_intel_clock_t clock;
1125 bool is_lvds;
1126 struct drm_psb_private *dev_priv = dev->dev_private;
1127
1128 if (gma_power_begin(dev, false)) {
1129 dpll = REG_READ((pipe == 0) ? DPLL_A : DPLL_B);
1130 if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
1131 fp = REG_READ((pipe == 0) ? FPA0 : FPB0);
1132 else
1133 fp = REG_READ((pipe == 0) ? FPA1 : FPB1);
1134 is_lvds = (pipe == 1) && (REG_READ(LVDS) & LVDS_PORT_EN);
1135 gma_power_end(dev);
1136 } else {
1137 dpll = (pipe == 0) ?
1138 dev_priv->saveDPLL_A : dev_priv->saveDPLL_B;
1139
1140 if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
1141 fp = (pipe == 0) ?
1142 dev_priv->saveFPA0 :
1143 dev_priv->saveFPB0;
1144 else
1145 fp = (pipe == 0) ?
1146 dev_priv->saveFPA1 :
1147 dev_priv->saveFPB1;
1148
1149 is_lvds = (pipe == 1) && (dev_priv->saveLVDS & LVDS_PORT_EN);
1150 }
1151
1152 clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
1153 clock.m2 = (fp & FP_M2_DIV_MASK) >> FP_M2_DIV_SHIFT;
1154 clock.n = (fp & FP_N_DIV_MASK) >> FP_N_DIV_SHIFT;
1155
1156 if (is_lvds) {
1157 clock.p1 =
1158 ffs((dpll &
1159 DPLL_FPA01_P1_POST_DIV_MASK_I830_LVDS) >>
1160 DPLL_FPA01_P1_POST_DIV_SHIFT);
1161 clock.p2 = 14;
1162
1163 if ((dpll & PLL_REF_INPUT_MASK) ==
1164 PLLB_REF_INPUT_SPREADSPECTRUMIN) {
1165 /* XXX: might not be 66MHz */
1166 i8xx_clock(66000, &clock);
1167 } else
1168 i8xx_clock(48000, &clock);
1169 } else {
1170 if (dpll & PLL_P1_DIVIDE_BY_TWO)
1171 clock.p1 = 2;
1172 else {
1173 clock.p1 =
1174 ((dpll &
1175 DPLL_FPA01_P1_POST_DIV_MASK_I830) >>
1176 DPLL_FPA01_P1_POST_DIV_SHIFT) + 2;
1177 }
1178 if (dpll & PLL_P2_DIVIDE_BY_4)
1179 clock.p2 = 4;
1180 else
1181 clock.p2 = 2;
1182
1183 i8xx_clock(48000, &clock);
1184 }
1185
1186 /* XXX: It would be nice to validate the clocks, but we can't reuse
1187 * i830PllIsValid() because it relies on the xf86_config connector
1188 * configuration being accurate, which it isn't necessarily.
1189 */
1190
1191 return clock.dot;
1192}
1193
1194/** Returns the currently programmed mode of the given pipe. */
1195struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
1196 struct drm_crtc *crtc)
1197{
1198 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1199 int pipe = psb_intel_crtc->pipe;
1200 struct drm_display_mode *mode;
1201 int htot;
1202 int hsync;
1203 int vtot;
1204 int vsync;
1205 struct drm_psb_private *dev_priv = dev->dev_private;
1206
1207 if (gma_power_begin(dev, false)) {
1208 htot = REG_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
1209 hsync = REG_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
1210 vtot = REG_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
1211 vsync = REG_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
1212 gma_power_end(dev);
1213 } else {
1214 htot = (pipe == 0) ?
1215 dev_priv->saveHTOTAL_A : dev_priv->saveHTOTAL_B;
1216 hsync = (pipe == 0) ?
1217 dev_priv->saveHSYNC_A : dev_priv->saveHSYNC_B;
1218 vtot = (pipe == 0) ?
1219 dev_priv->saveVTOTAL_A : dev_priv->saveVTOTAL_B;
1220 vsync = (pipe == 0) ?
1221 dev_priv->saveVSYNC_A : dev_priv->saveVSYNC_B;
1222 }
1223
1224 mode = kzalloc(sizeof(*mode), GFP_KERNEL);
1225 if (!mode)
1226 return NULL;
1227
1228 mode->clock = psb_intel_crtc_clock_get(dev, crtc);
1229 mode->hdisplay = (htot & 0xffff) + 1;
1230 mode->htotal = ((htot & 0xffff0000) >> 16) + 1;
1231 mode->hsync_start = (hsync & 0xffff) + 1;
1232 mode->hsync_end = ((hsync & 0xffff0000) >> 16) + 1;
1233 mode->vdisplay = (vtot & 0xffff) + 1;
1234 mode->vtotal = ((vtot & 0xffff0000) >> 16) + 1;
1235 mode->vsync_start = (vsync & 0xffff) + 1;
1236 mode->vsync_end = ((vsync & 0xffff0000) >> 16) + 1;
1237
1238 drm_mode_set_name(mode);
1239 drm_mode_set_crtcinfo(mode, 0);
1240
1241 return mode;
1242}
1243
1244void psb_intel_crtc_destroy(struct drm_crtc *crtc)
1245{
1246 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1247 struct gtt_range *gt;
1248
1249 /* Unpin the old GEM object */
1250 if (psb_intel_crtc->cursor_obj) {
1251 gt = container_of(psb_intel_crtc->cursor_obj,
1252 struct gtt_range, gem);
1253 psb_gtt_unpin(gt);
1254 drm_gem_object_unreference(psb_intel_crtc->cursor_obj);
1255 psb_intel_crtc->cursor_obj = NULL;
1256 }
1257 kfree(psb_intel_crtc->crtc_state);
1258 drm_crtc_cleanup(crtc);
1259 kfree(psb_intel_crtc);
1260}
1261
1262const struct drm_crtc_helper_funcs psb_intel_helper_funcs = {
1263 .dpms = psb_intel_crtc_dpms,
1264 .mode_fixup = psb_intel_crtc_mode_fixup,
1265 .mode_set = psb_intel_crtc_mode_set,
1266 .mode_set_base = psb_intel_pipe_set_base,
1267 .prepare = psb_intel_crtc_prepare,
1268 .commit = psb_intel_crtc_commit,
1269};
1270
1271const struct drm_crtc_funcs psb_intel_crtc_funcs = {
1272 .save = psb_intel_crtc_save,
1273 .restore = psb_intel_crtc_restore,
1274 .cursor_set = psb_intel_crtc_cursor_set,
1275 .cursor_move = psb_intel_crtc_cursor_move,
1276 .gamma_set = psb_intel_crtc_gamma_set,
1277 .set_config = psb_crtc_set_config,
1278 .destroy = psb_intel_crtc_destroy,
1279};
1280
1281/*
1282 * Set the default value of cursor control and base register
1283 * to zero. This is a workaround for h/w defect on Oaktrail
1284 */
1285static void psb_intel_cursor_init(struct drm_device *dev, int pipe)
1286{
1287 u32 control[3] = { CURACNTR, CURBCNTR, CURCCNTR };
1288 u32 base[3] = { CURABASE, CURBBASE, CURCBASE };
1289
1290 REG_WRITE(control[pipe], 0);
1291 REG_WRITE(base[pipe], 0);
1292}
1293
1294void psb_intel_crtc_init(struct drm_device *dev, int pipe,
1295 struct psb_intel_mode_device *mode_dev)
1296{
1297 struct drm_psb_private *dev_priv = dev->dev_private;
1298 struct psb_intel_crtc *psb_intel_crtc;
1299 int i;
1300 uint16_t *r_base, *g_base, *b_base;
1301
1302 /* We allocate a extra array of drm_connector pointers
1303 * for fbdev after the crtc */
1304 psb_intel_crtc =
1305 kzalloc(sizeof(struct psb_intel_crtc) +
1306 (INTELFB_CONN_LIMIT * sizeof(struct drm_connector *)),
1307 GFP_KERNEL);
1308 if (psb_intel_crtc == NULL)
1309 return;
1310
1311 psb_intel_crtc->crtc_state =
1312 kzalloc(sizeof(struct psb_intel_crtc_state), GFP_KERNEL);
1313 if (!psb_intel_crtc->crtc_state) {
1314 dev_err(dev->dev, "Crtc state error: No memory\n");
1315 kfree(psb_intel_crtc);
1316 return;
1317 }
1318
1319 /* Set the CRTC operations from the chip specific data */
1320 drm_crtc_init(dev, &psb_intel_crtc->base, dev_priv->ops->crtc_funcs);
1321
1322 drm_mode_crtc_set_gamma_size(&psb_intel_crtc->base, 256);
1323 psb_intel_crtc->pipe = pipe;
1324 psb_intel_crtc->plane = pipe;
1325
1326 r_base = psb_intel_crtc->base.gamma_store;
1327 g_base = r_base + 256;
1328 b_base = g_base + 256;
1329 for (i = 0; i < 256; i++) {
1330 psb_intel_crtc->lut_r[i] = i;
1331 psb_intel_crtc->lut_g[i] = i;
1332 psb_intel_crtc->lut_b[i] = i;
1333 r_base[i] = i << 8;
1334 g_base[i] = i << 8;
1335 b_base[i] = i << 8;
1336
1337 psb_intel_crtc->lut_adj[i] = 0;
1338 }
1339
1340 psb_intel_crtc->mode_dev = mode_dev;
1341 psb_intel_crtc->cursor_addr = 0;
1342
1343 drm_crtc_helper_add(&psb_intel_crtc->base,
1344 dev_priv->ops->crtc_helper);
1345
1346 /* Setup the array of drm_connector pointer array */
1347 psb_intel_crtc->mode_set.crtc = &psb_intel_crtc->base;
1348 BUG_ON(pipe >= ARRAY_SIZE(dev_priv->plane_to_crtc_mapping) ||
1349 dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] != NULL);
1350 dev_priv->plane_to_crtc_mapping[psb_intel_crtc->plane] =
1351 &psb_intel_crtc->base;
1352 dev_priv->pipe_to_crtc_mapping[psb_intel_crtc->pipe] =
1353 &psb_intel_crtc->base;
1354 psb_intel_crtc->mode_set.connectors =
1355 (struct drm_connector **) (psb_intel_crtc + 1);
1356 psb_intel_crtc->mode_set.num_connectors = 0;
1357 psb_intel_cursor_init(dev, pipe);
1358}
1359
1360int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
1361 struct drm_file *file_priv)
1362{
1363 struct drm_psb_private *dev_priv = dev->dev_private;
1364 struct drm_psb_get_pipe_from_crtc_id_arg *pipe_from_crtc_id = data;
1365 struct drm_mode_object *drmmode_obj;
1366 struct psb_intel_crtc *crtc;
1367
1368 if (!dev_priv) {
1369 dev_err(dev->dev, "called with no initialization\n");
1370 return -EINVAL;
1371 }
1372
1373 drmmode_obj = drm_mode_object_find(dev, pipe_from_crtc_id->crtc_id,
1374 DRM_MODE_OBJECT_CRTC);
1375
1376 if (!drmmode_obj) {
1377 dev_err(dev->dev, "no such CRTC id\n");
1378 return -EINVAL;
1379 }
1380
1381 crtc = to_psb_intel_crtc(obj_to_crtc(drmmode_obj));
1382 pipe_from_crtc_id->pipe = crtc->pipe;
1383
1384 return 0;
1385}
1386
1387struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev, int pipe)
1388{
1389 struct drm_crtc *crtc = NULL;
1390
1391 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
1392 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
1393 if (psb_intel_crtc->pipe == pipe)
1394 break;
1395 }
1396 return crtc;
1397}
1398
1399int psb_intel_connector_clones(struct drm_device *dev, int type_mask)
1400{
1401 int index_mask = 0;
1402 struct drm_connector *connector;
1403 int entry = 0;
1404
1405 list_for_each_entry(connector, &dev->mode_config.connector_list,
1406 head) {
1407 struct psb_intel_output *psb_intel_output =
1408 to_psb_intel_output(connector);
1409 if (type_mask & (1 << psb_intel_output->type))
1410 index_mask |= (1 << entry);
1411 entry++;
1412 }
1413 return index_mask;
1414}
1415
1416
1417void psb_intel_modeset_cleanup(struct drm_device *dev)
1418{
1419 drm_mode_config_cleanup(dev);
1420}
1421
1422
1423/* current intel driver doesn't take advantage of encoders
1424 always give back the encoder for the connector
1425*/
1426struct drm_encoder *psb_intel_best_encoder(struct drm_connector *connector)
1427{
1428 struct psb_intel_output *psb_intel_output =
1429 to_psb_intel_output(connector);
1430
1431 return &psb_intel_output->enc;
1432}
1433
diff --git a/drivers/staging/gma500/psb_intel_display.h b/drivers/staging/gma500/psb_intel_display.h
new file mode 100644
index 00000000000..535b49a5e40
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_display.h
@@ -0,0 +1,28 @@
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
23bool psb_intel_pipe_has_type(struct drm_crtc *crtc, int type);
24void psb_intel_crtc_gamma_set(struct drm_crtc *crtc, u16 *red,
25 u16 *green, u16 *blue, uint32_t type, uint32_t size);
26void 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
new file mode 100644
index 00000000000..36b554b5c33
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_drv.h
@@ -0,0 +1,230 @@
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 */
63struct 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
87struct 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
96struct 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
111struct 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
131struct 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
166struct psb_intel_i2c_chan *psb_intel_i2c_create(struct drm_device *dev,
167 const u32 reg, const char *name);
168void psb_intel_i2c_destroy(struct psb_intel_i2c_chan *chan);
169int psb_intel_ddc_get_modes(struct psb_intel_output *psb_intel_output);
170extern bool psb_intel_ddc_probe(struct psb_intel_output *psb_intel_output);
171
172extern void psb_intel_crtc_init(struct drm_device *dev, int pipe,
173 struct psb_intel_mode_device *mode_dev);
174extern void psb_intel_crt_init(struct drm_device *dev);
175extern void psb_intel_sdvo_init(struct drm_device *dev, int output_device);
176extern void psb_intel_dvo_init(struct drm_device *dev);
177extern void psb_intel_tv_init(struct drm_device *dev);
178extern void psb_intel_lvds_init(struct drm_device *dev,
179 struct psb_intel_mode_device *mode_dev);
180extern void psb_intel_lvds_set_brightness(struct drm_device *dev, int level);
181extern void mrst_lvds_init(struct drm_device *dev,
182 struct psb_intel_mode_device *mode_dev);
183extern void mrst_wait_for_INTR_PKT_SENT(struct drm_device *dev);
184extern void mrst_dsi_init(struct drm_device *dev,
185 struct psb_intel_mode_device *mode_dev);
186extern void mid_dsi_init(struct drm_device *dev,
187 struct psb_intel_mode_device *mode_dev, int dsi_num);
188
189extern void psb_intel_crtc_load_lut(struct drm_crtc *crtc);
190extern void psb_intel_encoder_prepare(struct drm_encoder *encoder);
191extern void psb_intel_encoder_commit(struct drm_encoder *encoder);
192
193extern struct drm_encoder *psb_intel_best_encoder(struct drm_connector
194 *connector);
195
196extern struct drm_display_mode *psb_intel_crtc_mode_get(struct drm_device *dev,
197 struct drm_crtc *crtc);
198extern void psb_intel_wait_for_vblank(struct drm_device *dev);
199extern int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
200 struct drm_file *file_priv);
201extern struct drm_crtc *psb_intel_get_crtc_from_pipe(struct drm_device *dev,
202 int pipe);
203extern struct drm_connector *psb_intel_sdvo_find(struct drm_device *dev,
204 int sdvoB);
205extern int psb_intel_sdvo_supports_hotplug(struct drm_connector *connector);
206extern void psb_intel_sdvo_set_hotplug(struct drm_connector *connector,
207 int enable);
208extern int intelfb_probe(struct drm_device *dev);
209extern int intelfb_remove(struct drm_device *dev,
210 struct drm_framebuffer *fb);
211extern 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);
216extern bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
217 struct drm_display_mode *mode,
218 struct drm_display_mode *adjusted_mode);
219extern int psb_intel_lvds_mode_valid(struct drm_connector *connector,
220 struct drm_display_mode *mode);
221extern int psb_intel_lvds_set_property(struct drm_connector *connector,
222 struct drm_property *property,
223 uint64_t value);
224extern void psb_intel_lvds_destroy(struct drm_connector *connector);
225extern const struct drm_encoder_funcs psb_intel_lvds_enc_funcs;
226
227extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe);
228extern 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
new file mode 100644
index 00000000000..c6436da6073
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_lvds.c
@@ -0,0 +1,849 @@
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
50struct 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 */
68static u32 psb_intel_lvds_get_max_backlight(struct drm_device *dev)
69{
70 struct drm_psb_private *dev_priv = dev->dev_private;
71 u32 retVal;
72
73 if (gma_power_begin(dev, false)) {
74 retVal = ((REG_READ(BLC_PWM_CTL) &
75 BACKLIGHT_MODULATION_FREQ_MASK) >>
76 BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
77
78 gma_power_end(dev);
79 } else
80 retVal = ((dev_priv->saveBLC_PWM_CTL &
81 BACKLIGHT_MODULATION_FREQ_MASK) >>
82 BACKLIGHT_MODULATION_FREQ_SHIFT) * 2;
83
84 return retVal;
85}
86
87/*
88 * Set LVDS backlight level by I2C command
89 *
90 * FIXME: at some point we need to both track this for PM and also
91 * disable runtime pm on MRST if the brightness is nil (ie blanked)
92 */
93static int psb_lvds_i2c_set_brightness(struct drm_device *dev,
94 unsigned int level)
95{
96 struct drm_psb_private *dev_priv =
97 (struct drm_psb_private *)dev->dev_private;
98
99 struct psb_intel_i2c_chan *lvds_i2c_bus = dev_priv->lvds_i2c_bus;
100 u8 out_buf[2];
101 unsigned int blc_i2c_brightness;
102
103 struct i2c_msg msgs[] = {
104 {
105 .addr = lvds_i2c_bus->slave_addr,
106 .flags = 0,
107 .len = 2,
108 .buf = out_buf,
109 }
110 };
111
112 blc_i2c_brightness = BRIGHTNESS_MASK & ((unsigned int)level *
113 BRIGHTNESS_MASK /
114 BRIGHTNESS_MAX_LEVEL);
115
116 if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
117 blc_i2c_brightness = BRIGHTNESS_MASK - blc_i2c_brightness;
118
119 out_buf[0] = dev_priv->lvds_bl->brightnesscmd;
120 out_buf[1] = (u8)blc_i2c_brightness;
121
122 if (i2c_transfer(&lvds_i2c_bus->adapter, msgs, 1) == 1) {
123 dev_dbg(dev->dev, "I2C set brightness.(command, value) (%d, %d)\n",
124 dev_priv->lvds_bl->brightnesscmd,
125 blc_i2c_brightness);
126 return 0;
127 }
128
129 dev_err(dev->dev, "I2C transfer error\n");
130 return -1;
131}
132
133
134static int psb_lvds_pwm_set_brightness(struct drm_device *dev, int level)
135{
136 struct drm_psb_private *dev_priv =
137 (struct drm_psb_private *)dev->dev_private;
138
139 u32 max_pwm_blc;
140 u32 blc_pwm_duty_cycle;
141
142 max_pwm_blc = psb_intel_lvds_get_max_backlight(dev);
143
144 /*BLC_PWM_CTL Should be initiated while backlight device init*/
145 BUG_ON((max_pwm_blc & PSB_BLC_MAX_PWM_REG_FREQ) == 0);
146
147 blc_pwm_duty_cycle = level * max_pwm_blc / BRIGHTNESS_MAX_LEVEL;
148
149 if (dev_priv->lvds_bl->pol == BLC_POLARITY_INVERSE)
150 blc_pwm_duty_cycle = max_pwm_blc - blc_pwm_duty_cycle;
151
152 blc_pwm_duty_cycle &= PSB_BACKLIGHT_PWM_POLARITY_BIT_CLEAR;
153 REG_WRITE(BLC_PWM_CTL,
154 (max_pwm_blc << PSB_BACKLIGHT_PWM_CTL_SHIFT) |
155 (blc_pwm_duty_cycle));
156
157 return 0;
158}
159
160/*
161 * Set LVDS backlight level either by I2C or PWM
162 */
163void psb_intel_lvds_set_brightness(struct drm_device *dev, int level)
164{
165 /*u32 blc_pwm_ctl;*/
166 struct drm_psb_private *dev_priv =
167 (struct drm_psb_private *)dev->dev_private;
168
169 dev_dbg(dev->dev, "backlight level is %d\n", level);
170
171 if (!dev_priv->lvds_bl) {
172 dev_err(dev->dev, "NO LVDS Backlight Info\n");
173 return;
174 }
175
176 if (dev_priv->lvds_bl->type == BLC_I2C_TYPE)
177 psb_lvds_i2c_set_brightness(dev, level);
178 else
179 psb_lvds_pwm_set_brightness(dev, level);
180}
181
182/*
183 * Sets the backlight level.
184 *
185 * level: backlight level, from 0 to psb_intel_lvds_get_max_backlight().
186 */
187static void psb_intel_lvds_set_backlight(struct drm_device *dev, int level)
188{
189 struct drm_psb_private *dev_priv = dev->dev_private;
190 u32 blc_pwm_ctl;
191
192 if (gma_power_begin(dev, false)) {
193 blc_pwm_ctl =
194 REG_READ(BLC_PWM_CTL) & ~BACKLIGHT_DUTY_CYCLE_MASK;
195 REG_WRITE(BLC_PWM_CTL,
196 (blc_pwm_ctl |
197 (level << BACKLIGHT_DUTY_CYCLE_SHIFT)));
198 gma_power_end(dev);
199 } else {
200 blc_pwm_ctl = dev_priv->saveBLC_PWM_CTL &
201 ~BACKLIGHT_DUTY_CYCLE_MASK;
202 dev_priv->saveBLC_PWM_CTL = (blc_pwm_ctl |
203 (level << BACKLIGHT_DUTY_CYCLE_SHIFT));
204 }
205}
206
207/*
208 * Sets the power state for the panel.
209 */
210static void psb_intel_lvds_set_power(struct drm_device *dev,
211 struct psb_intel_output *output, bool on)
212{
213 u32 pp_status;
214
215 if (!gma_power_begin(dev, true))
216 return;
217
218 if (on) {
219 REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
220 POWER_TARGET_ON);
221 do {
222 pp_status = REG_READ(PP_STATUS);
223 } while ((pp_status & PP_ON) == 0);
224
225 psb_intel_lvds_set_backlight(dev,
226 output->
227 mode_dev->backlight_duty_cycle);
228 } else {
229 psb_intel_lvds_set_backlight(dev, 0);
230
231 REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) &
232 ~POWER_TARGET_ON);
233 do {
234 pp_status = REG_READ(PP_STATUS);
235 } while (pp_status & PP_ON);
236 }
237
238 gma_power_end(dev);
239}
240
241static void psb_intel_lvds_encoder_dpms(struct drm_encoder *encoder, int mode)
242{
243 struct drm_device *dev = encoder->dev;
244 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
245
246 if (mode == DRM_MODE_DPMS_ON)
247 psb_intel_lvds_set_power(dev, output, true);
248 else
249 psb_intel_lvds_set_power(dev, output, false);
250
251 /* XXX: We never power down the LVDS pairs. */
252}
253
254static void psb_intel_lvds_save(struct drm_connector *connector)
255{
256 struct drm_device *dev = connector->dev;
257 struct drm_psb_private *dev_priv =
258 (struct drm_psb_private *)dev->dev_private;
259 struct psb_intel_output *psb_intel_output =
260 to_psb_intel_output(connector);
261 struct psb_intel_lvds_priv *lvds_priv =
262 (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
263
264 lvds_priv->savePP_ON = REG_READ(LVDSPP_ON);
265 lvds_priv->savePP_OFF = REG_READ(LVDSPP_OFF);
266 lvds_priv->saveLVDS = REG_READ(LVDS);
267 lvds_priv->savePP_CONTROL = REG_READ(PP_CONTROL);
268 lvds_priv->savePP_CYCLE = REG_READ(PP_CYCLE);
269 /*lvds_priv->savePP_DIVISOR = REG_READ(PP_DIVISOR);*/
270 lvds_priv->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
271 lvds_priv->savePFIT_CONTROL = REG_READ(PFIT_CONTROL);
272 lvds_priv->savePFIT_PGM_RATIOS = REG_READ(PFIT_PGM_RATIOS);
273
274 /*TODO: move backlight_duty_cycle to psb_intel_lvds_priv*/
275 dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL &
276 BACKLIGHT_DUTY_CYCLE_MASK);
277
278 /*
279 * If the light is off at server startup,
280 * just make it full brightness
281 */
282 if (dev_priv->backlight_duty_cycle == 0)
283 dev_priv->backlight_duty_cycle =
284 psb_intel_lvds_get_max_backlight(dev);
285
286 dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
287 lvds_priv->savePP_ON,
288 lvds_priv->savePP_OFF,
289 lvds_priv->saveLVDS,
290 lvds_priv->savePP_CONTROL,
291 lvds_priv->savePP_CYCLE,
292 lvds_priv->saveBLC_PWM_CTL);
293}
294
295static void psb_intel_lvds_restore(struct drm_connector *connector)
296{
297 struct drm_device *dev = connector->dev;
298 u32 pp_status;
299
300 /*struct drm_psb_private *dev_priv =
301 (struct drm_psb_private *)dev->dev_private;*/
302 struct psb_intel_output *psb_intel_output =
303 to_psb_intel_output(connector);
304 struct psb_intel_lvds_priv *lvds_priv =
305 (struct psb_intel_lvds_priv *)psb_intel_output->dev_priv;
306
307 dev_dbg(dev->dev, "(0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x)\n",
308 lvds_priv->savePP_ON,
309 lvds_priv->savePP_OFF,
310 lvds_priv->saveLVDS,
311 lvds_priv->savePP_CONTROL,
312 lvds_priv->savePP_CYCLE,
313 lvds_priv->saveBLC_PWM_CTL);
314
315 REG_WRITE(BLC_PWM_CTL, lvds_priv->saveBLC_PWM_CTL);
316 REG_WRITE(PFIT_CONTROL, lvds_priv->savePFIT_CONTROL);
317 REG_WRITE(PFIT_PGM_RATIOS, lvds_priv->savePFIT_PGM_RATIOS);
318 REG_WRITE(LVDSPP_ON, lvds_priv->savePP_ON);
319 REG_WRITE(LVDSPP_OFF, lvds_priv->savePP_OFF);
320 /*REG_WRITE(PP_DIVISOR, lvds_priv->savePP_DIVISOR);*/
321 REG_WRITE(PP_CYCLE, lvds_priv->savePP_CYCLE);
322 REG_WRITE(PP_CONTROL, lvds_priv->savePP_CONTROL);
323 REG_WRITE(LVDS, lvds_priv->saveLVDS);
324
325 if (lvds_priv->savePP_CONTROL & POWER_TARGET_ON) {
326 REG_WRITE(PP_CONTROL, REG_READ(PP_CONTROL) |
327 POWER_TARGET_ON);
328 do {
329 pp_status = REG_READ(PP_STATUS);
330 } while ((pp_status & PP_ON) == 0);
331 } else {
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);
337 }
338}
339
340int psb_intel_lvds_mode_valid(struct drm_connector *connector,
341 struct drm_display_mode *mode)
342{
343 struct psb_intel_output *psb_intel_output =
344 to_psb_intel_output(connector);
345 struct drm_display_mode *fixed_mode =
346 psb_intel_output->mode_dev->panel_fixed_mode;
347
348 if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
349 fixed_mode = psb_intel_output->mode_dev->panel_fixed_mode2;
350
351 /* just in case */
352 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
353 return MODE_NO_DBLESCAN;
354
355 /* just in case */
356 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
357 return MODE_NO_INTERLACE;
358
359 if (fixed_mode) {
360 if (mode->hdisplay > fixed_mode->hdisplay)
361 return MODE_PANEL;
362 if (mode->vdisplay > fixed_mode->vdisplay)
363 return MODE_PANEL;
364 }
365 return MODE_OK;
366}
367
368bool psb_intel_lvds_mode_fixup(struct drm_encoder *encoder,
369 struct drm_display_mode *mode,
370 struct drm_display_mode *adjusted_mode)
371{
372 struct psb_intel_mode_device *mode_dev =
373 enc_to_psb_intel_output(encoder)->mode_dev;
374 struct drm_device *dev = encoder->dev;
375 struct psb_intel_crtc *psb_intel_crtc =
376 to_psb_intel_crtc(encoder->crtc);
377 struct drm_encoder *tmp_encoder;
378 struct drm_display_mode *panel_fixed_mode = mode_dev->panel_fixed_mode;
379 struct psb_intel_output *psb_intel_output =
380 enc_to_psb_intel_output(encoder);
381
382 if (psb_intel_output->type == INTEL_OUTPUT_MIPI2)
383 panel_fixed_mode = mode_dev->panel_fixed_mode2;
384
385 /* FIXME: review for Medfield */
386 /* PSB requires the LVDS is on pipe B, MRST has only one pipe anyway */
387 if (!IS_MRST(dev) && psb_intel_crtc->pipe == 0) {
388 printk(KERN_ERR "Can't support LVDS on pipe A\n");
389 return false;
390 }
391 if (IS_MRST(dev) && psb_intel_crtc->pipe != 0) {
392 printk(KERN_ERR "Must use PIPE A\n");
393 return false;
394 }
395 /* Should never happen!! */
396 list_for_each_entry(tmp_encoder, &dev->mode_config.encoder_list,
397 head) {
398 if (tmp_encoder != encoder
399 && tmp_encoder->crtc == encoder->crtc) {
400 printk(KERN_ERR "Can't enable LVDS and another "
401 "encoder on the same pipe\n");
402 return false;
403 }
404 }
405
406 /*
407 * If we have timings from the BIOS for the panel, put them in
408 * to the adjusted mode. The CRTC will be set up for this mode,
409 * with the panel scaling set up to source from the H/VDisplay
410 * of the original mode.
411 */
412 if (panel_fixed_mode != NULL) {
413 adjusted_mode->hdisplay = panel_fixed_mode->hdisplay;
414 adjusted_mode->hsync_start = panel_fixed_mode->hsync_start;
415 adjusted_mode->hsync_end = panel_fixed_mode->hsync_end;
416 adjusted_mode->htotal = panel_fixed_mode->htotal;
417 adjusted_mode->vdisplay = panel_fixed_mode->vdisplay;
418 adjusted_mode->vsync_start = panel_fixed_mode->vsync_start;
419 adjusted_mode->vsync_end = panel_fixed_mode->vsync_end;
420 adjusted_mode->vtotal = panel_fixed_mode->vtotal;
421 adjusted_mode->clock = panel_fixed_mode->clock;
422 drm_mode_set_crtcinfo(adjusted_mode,
423 CRTC_INTERLACE_HALVE_V);
424 }
425
426 /*
427 * XXX: It would be nice to support lower refresh rates on the
428 * panels to reduce power consumption, and perhaps match the
429 * user's requested refresh rate.
430 */
431
432 return true;
433}
434
435static void psb_intel_lvds_prepare(struct drm_encoder *encoder)
436{
437 struct drm_device *dev = encoder->dev;
438 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
439 struct psb_intel_mode_device *mode_dev = output->mode_dev;
440
441 if (!gma_power_begin(dev, true))
442 return;
443
444 mode_dev->saveBLC_PWM_CTL = REG_READ(BLC_PWM_CTL);
445 mode_dev->backlight_duty_cycle = (mode_dev->saveBLC_PWM_CTL &
446 BACKLIGHT_DUTY_CYCLE_MASK);
447
448 psb_intel_lvds_set_power(dev, output, false);
449
450 gma_power_end(dev);
451}
452
453static void psb_intel_lvds_commit(struct drm_encoder *encoder)
454{
455 struct drm_device *dev = encoder->dev;
456 struct psb_intel_output *output = enc_to_psb_intel_output(encoder);
457 struct psb_intel_mode_device *mode_dev = output->mode_dev;
458
459 if (mode_dev->backlight_duty_cycle == 0)
460 mode_dev->backlight_duty_cycle =
461 psb_intel_lvds_get_max_backlight(dev);
462
463 psb_intel_lvds_set_power(dev, output, true);
464}
465
466static void psb_intel_lvds_mode_set(struct drm_encoder *encoder,
467 struct drm_display_mode *mode,
468 struct drm_display_mode *adjusted_mode)
469{
470 struct drm_device *dev = encoder->dev;
471 struct drm_psb_private *dev_priv = dev->dev_private;
472 u32 pfit_control;
473
474 /*
475 * The LVDS pin pair will already have been turned on in the
476 * psb_intel_crtc_mode_set since it has a large impact on the DPLL
477 * settings.
478 */
479
480 /*
481 * Enable automatic panel scaling so that non-native modes fill the
482 * screen. Should be enabled before the pipe is enabled, according to
483 * register description and PRM.
484 */
485 if (mode->hdisplay != adjusted_mode->hdisplay ||
486 mode->vdisplay != adjusted_mode->vdisplay)
487 pfit_control = (PFIT_ENABLE | VERT_AUTO_SCALE |
488 HORIZ_AUTO_SCALE | VERT_INTERP_BILINEAR |
489 HORIZ_INTERP_BILINEAR);
490 else
491 pfit_control = 0;
492
493 if (dev_priv->lvds_dither)
494 pfit_control |= PANEL_8TO6_DITHER_ENABLE;
495
496 REG_WRITE(PFIT_CONTROL, pfit_control);
497}
498
499/*
500 * Detect the LVDS connection.
501 *
502 * This always returns CONNECTOR_STATUS_CONNECTED.
503 * This connector should only have
504 * been set up if the LVDS was actually connected anyway.
505 */
506static enum drm_connector_status psb_intel_lvds_detect(struct drm_connector
507 *connector, bool force)
508{
509 return connector_status_connected;
510}
511
512/*
513 * Return the list of DDC modes if available, or the BIOS fixed mode otherwise.
514 */
515static int psb_intel_lvds_get_modes(struct drm_connector *connector)
516{
517 struct drm_device *dev = connector->dev;
518 struct psb_intel_output *psb_intel_output =
519 to_psb_intel_output(connector);
520 struct psb_intel_mode_device *mode_dev =
521 psb_intel_output->mode_dev;
522 int ret = 0;
523
524 if (!IS_MRST(dev))
525 ret = psb_intel_ddc_get_modes(psb_intel_output);
526
527 if (ret)
528 return ret;
529
530 /* Didn't get an EDID, so
531 * Set wide sync ranges so we get all modes
532 * handed to valid_mode for checking
533 */
534 connector->display_info.min_vfreq = 0;
535 connector->display_info.max_vfreq = 200;
536 connector->display_info.min_hfreq = 0;
537 connector->display_info.max_hfreq = 200;
538
539 if (mode_dev->panel_fixed_mode != NULL) {
540 struct drm_display_mode *mode =
541 drm_mode_duplicate(dev, mode_dev->panel_fixed_mode);
542 drm_mode_probed_add(connector, mode);
543 return 1;
544 }
545
546 return 0;
547}
548
549/**
550 * psb_intel_lvds_destroy - unregister and free LVDS structures
551 * @connector: connector to free
552 *
553 * Unregister the DDC bus for this connector then free the driver private
554 * structure.
555 */
556void psb_intel_lvds_destroy(struct drm_connector *connector)
557{
558 struct psb_intel_output *psb_intel_output =
559 to_psb_intel_output(connector);
560
561 if (psb_intel_output->ddc_bus)
562 psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
563 drm_sysfs_connector_remove(connector);
564 drm_connector_cleanup(connector);
565 kfree(connector);
566}
567
568int psb_intel_lvds_set_property(struct drm_connector *connector,
569 struct drm_property *property,
570 uint64_t value)
571{
572 struct drm_encoder *encoder = connector->encoder;
573
574 if (!encoder)
575 return -1;
576
577 if (!strcmp(property->name, "scaling mode")) {
578 struct psb_intel_crtc *crtc =
579 to_psb_intel_crtc(encoder->crtc);
580 uint64_t curval;
581
582 if (!crtc)
583 goto set_prop_error;
584
585 switch (value) {
586 case DRM_MODE_SCALE_FULLSCREEN:
587 break;
588 case DRM_MODE_SCALE_NO_SCALE:
589 break;
590 case DRM_MODE_SCALE_ASPECT:
591 break;
592 default:
593 goto set_prop_error;
594 }
595
596 if (drm_connector_property_get_value(connector,
597 property,
598 &curval))
599 goto set_prop_error;
600
601 if (curval == value)
602 goto set_prop_done;
603
604 if (drm_connector_property_set_value(connector,
605 property,
606 value))
607 goto set_prop_error;
608
609 if (crtc->saved_mode.hdisplay != 0 &&
610 crtc->saved_mode.vdisplay != 0) {
611 if (!drm_crtc_helper_set_mode(encoder->crtc,
612 &crtc->saved_mode,
613 encoder->crtc->x,
614 encoder->crtc->y,
615 encoder->crtc->fb))
616 goto set_prop_error;
617 }
618 } else if (!strcmp(property->name, "backlight")) {
619 if (drm_connector_property_set_value(connector,
620 property,
621 value))
622 goto set_prop_error;
623 else {
624#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
625 struct drm_psb_private *devp = encoder->dev->dev_private;
626 struct backlight_device *bd = devp->backlight_device;
627 if (bd) {
628 bd->props.brightness = value;
629 backlight_update_status(bd);
630 }
631#endif
632 }
633 } else if (!strcmp(property->name, "DPMS")) {
634 struct drm_encoder_helper_funcs *hfuncs
635 = encoder->helper_private;
636 hfuncs->dpms(encoder, value);
637 }
638
639set_prop_done:
640 return 0;
641set_prop_error:
642 return -1;
643}
644
645static const struct drm_encoder_helper_funcs psb_intel_lvds_helper_funcs = {
646 .dpms = psb_intel_lvds_encoder_dpms,
647 .mode_fixup = psb_intel_lvds_mode_fixup,
648 .prepare = psb_intel_lvds_prepare,
649 .mode_set = psb_intel_lvds_mode_set,
650 .commit = psb_intel_lvds_commit,
651};
652
653const struct drm_connector_helper_funcs
654 psb_intel_lvds_connector_helper_funcs = {
655 .get_modes = psb_intel_lvds_get_modes,
656 .mode_valid = psb_intel_lvds_mode_valid,
657 .best_encoder = psb_intel_best_encoder,
658};
659
660const struct drm_connector_funcs psb_intel_lvds_connector_funcs = {
661 .dpms = drm_helper_connector_dpms,
662 .save = psb_intel_lvds_save,
663 .restore = psb_intel_lvds_restore,
664 .detect = psb_intel_lvds_detect,
665 .fill_modes = drm_helper_probe_single_connector_modes,
666 .set_property = psb_intel_lvds_set_property,
667 .destroy = psb_intel_lvds_destroy,
668};
669
670
671static void psb_intel_lvds_enc_destroy(struct drm_encoder *encoder)
672{
673 drm_encoder_cleanup(encoder);
674}
675
676const struct drm_encoder_funcs psb_intel_lvds_enc_funcs = {
677 .destroy = psb_intel_lvds_enc_destroy,
678};
679
680
681
682/**
683 * psb_intel_lvds_init - setup LVDS connectors on this device
684 * @dev: drm device
685 *
686 * Create the connector, register the LVDS DDC bus, and try to figure out what
687 * modes we can display on the LVDS panel (if present).
688 */
689void psb_intel_lvds_init(struct drm_device *dev,
690 struct psb_intel_mode_device *mode_dev)
691{
692 struct psb_intel_output *psb_intel_output;
693 struct psb_intel_lvds_priv *lvds_priv;
694 struct drm_connector *connector;
695 struct drm_encoder *encoder;
696 struct drm_display_mode *scan; /* *modes, *bios_mode; */
697 struct drm_crtc *crtc;
698 struct drm_psb_private *dev_priv =
699 (struct drm_psb_private *)dev->dev_private;
700 u32 lvds;
701 int pipe;
702
703 psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
704 if (!psb_intel_output)
705 return;
706
707 lvds_priv = kzalloc(sizeof(struct psb_intel_lvds_priv), GFP_KERNEL);
708 if (!lvds_priv) {
709 kfree(psb_intel_output);
710 dev_err(dev->dev, "LVDS private allocation error\n");
711 return;
712 }
713
714 psb_intel_output->dev_priv = lvds_priv;
715
716 psb_intel_output->mode_dev = mode_dev;
717 connector = &psb_intel_output->base;
718 encoder = &psb_intel_output->enc;
719 drm_connector_init(dev, &psb_intel_output->base,
720 &psb_intel_lvds_connector_funcs,
721 DRM_MODE_CONNECTOR_LVDS);
722
723 drm_encoder_init(dev, &psb_intel_output->enc,
724 &psb_intel_lvds_enc_funcs,
725 DRM_MODE_ENCODER_LVDS);
726
727 drm_mode_connector_attach_encoder(&psb_intel_output->base,
728 &psb_intel_output->enc);
729 psb_intel_output->type = INTEL_OUTPUT_LVDS;
730
731 drm_encoder_helper_add(encoder, &psb_intel_lvds_helper_funcs);
732 drm_connector_helper_add(connector,
733 &psb_intel_lvds_connector_helper_funcs);
734 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
735 connector->interlace_allowed = false;
736 connector->doublescan_allowed = false;
737
738 /*Attach connector properties*/
739 drm_connector_attach_property(connector,
740 dev->mode_config.scaling_mode_property,
741 DRM_MODE_SCALE_FULLSCREEN);
742 drm_connector_attach_property(connector,
743 dev_priv->backlight_property,
744 BRIGHTNESS_MAX_LEVEL);
745
746 /*
747 * Set up I2C bus
748 * FIXME: distroy i2c_bus when exit
749 */
750 psb_intel_output->i2c_bus = psb_intel_i2c_create(dev,
751 GPIOB,
752 "LVDSBLC_B");
753 if (!psb_intel_output->i2c_bus) {
754 dev_printk(KERN_ERR,
755 &dev->pdev->dev, "I2C bus registration failed.\n");
756 goto failed_blc_i2c;
757 }
758 psb_intel_output->i2c_bus->slave_addr = 0x2C;
759 dev_priv->lvds_i2c_bus = psb_intel_output->i2c_bus;
760
761 /*
762 * LVDS discovery:
763 * 1) check for EDID on DDC
764 * 2) check for VBT data
765 * 3) check to see if LVDS is already on
766 * if none of the above, no panel
767 * 4) make sure lid is open
768 * if closed, act like it's not there for now
769 */
770
771 /* Set up the DDC bus. */
772 psb_intel_output->ddc_bus = psb_intel_i2c_create(dev,
773 GPIOC,
774 "LVDSDDC_C");
775 if (!psb_intel_output->ddc_bus) {
776 dev_printk(KERN_ERR, &dev->pdev->dev,
777 "DDC bus registration " "failed.\n");
778 goto failed_ddc;
779 }
780
781 /*
782 * Attempt to get the fixed panel mode from DDC. Assume that the
783 * preferred mode is the right one.
784 */
785 psb_intel_ddc_get_modes(psb_intel_output);
786 list_for_each_entry(scan, &connector->probed_modes, head) {
787 if (scan->type & DRM_MODE_TYPE_PREFERRED) {
788 mode_dev->panel_fixed_mode =
789 drm_mode_duplicate(dev, scan);
790 goto out; /* FIXME: check for quirks */
791 }
792 }
793
794 /* Failed to get EDID, what about VBT? do we need this? */
795 if (mode_dev->vbt_mode)
796 mode_dev->panel_fixed_mode =
797 drm_mode_duplicate(dev, mode_dev->vbt_mode);
798
799 if (!mode_dev->panel_fixed_mode)
800 if (dev_priv->lfp_lvds_vbt_mode)
801 mode_dev->panel_fixed_mode =
802 drm_mode_duplicate(dev,
803 dev_priv->lfp_lvds_vbt_mode);
804
805 /*
806 * If we didn't get EDID, try checking if the panel is already turned
807 * on. If so, assume that whatever is currently programmed is the
808 * correct mode.
809 */
810 lvds = REG_READ(LVDS);
811 pipe = (lvds & LVDS_PIPEB_SELECT) ? 1 : 0;
812 crtc = psb_intel_get_crtc_from_pipe(dev, pipe);
813
814 if (crtc && (lvds & LVDS_PORT_EN)) {
815 mode_dev->panel_fixed_mode =
816 psb_intel_crtc_mode_get(dev, crtc);
817 if (mode_dev->panel_fixed_mode) {
818 mode_dev->panel_fixed_mode->type |=
819 DRM_MODE_TYPE_PREFERRED;
820 goto out; /* FIXME: check for quirks */
821 }
822 }
823
824 /* If we still don't have a mode after all that, give up. */
825 if (!mode_dev->panel_fixed_mode) {
826 dev_err(dev->dev, "Found no modes on the lvds, ignoring the LVDS\n");
827 goto failed_find;
828 }
829
830 /*
831 * Blacklist machines with BIOSes that list an LVDS panel without
832 * actually having one.
833 */
834out:
835 drm_sysfs_connector_add(connector);
836 return;
837
838failed_find:
839 if (psb_intel_output->ddc_bus)
840 psb_intel_i2c_destroy(psb_intel_output->ddc_bus);
841failed_ddc:
842 if (psb_intel_output->i2c_bus)
843 psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
844failed_blc_i2c:
845 drm_encoder_cleanup(encoder);
846 drm_connector_cleanup(connector);
847 kfree(connector);
848}
849
diff --git a/drivers/staging/gma500/psb_intel_modes.c b/drivers/staging/gma500/psb_intel_modes.c
new file mode 100644
index 00000000000..bde1aff9619
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_modes.c
@@ -0,0 +1,77 @@
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 */
29bool 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 */
62int 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
new file mode 100644
index 00000000000..1ac16aa791c
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_reg.h
@@ -0,0 +1,1235 @@
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
450struct 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
470struct 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/* ************************************************************************* *\
964This command causes the display module to stop displaying the image data
965on the display device. The frame memory contents remain unchanged.
966No status bits are changed.
967\* ************************************************************************* */
968#define set_display_on 0x29
969/* ************************************************************************* *\
970This command causes the display module to start displaying the image data
971on the display device. The frame memory contents remain unchanged.
972No 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
new file mode 100644
index 00000000000..a4bad1af4b7
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_sdvo.c
@@ -0,0 +1,1293 @@
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
30struct 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 */
56void 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
81static 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
117static 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 */
141static const struct _sdvo_cmd_name {
142 u8 cmd;
143 char *name;
144} sdvo_cmd_names[] = {
145SDVO_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
195static 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
234static 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
244static 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
289int 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 */
304void 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
314static 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 */
341static 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
361static 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
375static 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
386static 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
414static 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
440static 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
453static 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
473static 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
482static 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
504static 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
513static 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
522static 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
544static 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
561static 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
593static 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
652static 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
663static 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
778static 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
839static 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
872static 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
927static 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
946static 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
965struct 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
992int 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
1017void 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
1056static 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
1077static 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
1092static 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
1104static 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
1112static 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
1121static 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
1128void psb_intel_sdvo_enc_destroy(struct drm_encoder *encoder)
1129{
1130 drm_encoder_cleanup(encoder);
1131}
1132
1133static const struct drm_encoder_funcs psb_intel_sdvo_enc_funcs = {
1134 .destroy = psb_intel_sdvo_enc_destroy,
1135};
1136
1137
1138void 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
1286err_i2c:
1287 psb_intel_i2c_destroy(psb_intel_output->i2c_bus);
1288err_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
new file mode 100644
index 00000000000..96862ea65ab
--- /dev/null
+++ b/drivers/staging/gma500/psb_intel_sdvo_regs.h
@@ -0,0 +1,338 @@
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
40struct 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 */
57struct 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
87struct 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
92struct 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
146struct 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
200struct 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
214struct 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
new file mode 100644
index 00000000000..4a0fa42893f
--- /dev/null
+++ b/drivers/staging/gma500/psb_irq.c
@@ -0,0 +1,616 @@
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
36static inline u32
37psb_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
48static inline u32
49mid_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
60static inline u32
61mid_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
72static inline u32
73mid_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
84void
85psb_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
101void
102psb_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
117void 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
128void 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 vsync/vblank.
143 *
144 */
145static void mid_vblank_handler(struct drm_device *dev, uint32_t pipe)
146{
147 drm_handle_vblank(dev, pipe);
148}
149
150
151/**
152 * Display controller interrupt handler for pipe event.
153 *
154 */
155#define WAIT_STATUS_CLEAR_LOOP_COUNT 0xffff
156static void mid_pipe_event_handler(struct drm_device *dev, uint32_t pipe)
157{
158 struct drm_psb_private *dev_priv =
159 (struct drm_psb_private *) dev->dev_private;
160
161 uint32_t pipe_stat_val = 0;
162 uint32_t pipe_stat_reg = psb_pipestat(pipe);
163 uint32_t pipe_enable = dev_priv->pipestat[pipe];
164 uint32_t pipe_status = dev_priv->pipestat[pipe] >> 16;
165 uint32_t i = 0;
166
167 spin_lock(&dev_priv->irqmask_lock);
168
169 pipe_stat_val = PSB_RVDC32(pipe_stat_reg);
170 pipe_stat_val &= pipe_enable | pipe_status;
171 pipe_stat_val &= pipe_stat_val >> 16;
172
173 spin_unlock(&dev_priv->irqmask_lock);
174
175 /* clear the 2nd level interrupt status bits */
176 /**
177 * FIXME: shouldn't use while loop here. However, the interrupt
178 * status 'sticky' bits cannot be cleared by setting '1' to that
179 * bit once...
180 */
181 for (i = 0; i < WAIT_STATUS_CLEAR_LOOP_COUNT; i++) {
182 PSB_WVDC32(PSB_RVDC32(pipe_stat_reg), pipe_stat_reg);
183 (void) PSB_RVDC32(pipe_stat_reg);
184
185 if ((PSB_RVDC32(pipe_stat_reg) & pipe_status) == 0)
186 break;
187 }
188
189 if (i == WAIT_STATUS_CLEAR_LOOP_COUNT)
190 dev_err(dev->dev,
191 "%s, can't clear the status bits in pipe_stat_reg, its value = 0x%x.\n",
192 __func__, PSB_RVDC32(pipe_stat_reg));
193
194 if (pipe_stat_val & PIPE_VBLANK_STATUS)
195 mid_vblank_handler(dev, pipe);
196
197 if (pipe_stat_val & PIPE_TE_STATUS)
198 drm_handle_vblank(dev, pipe);
199}
200
201/*
202 * Display controller interrupt handler.
203 */
204static void psb_vdc_interrupt(struct drm_device *dev, uint32_t vdc_stat)
205{
206 if (vdc_stat & _PSB_PIPEA_EVENT_FLAG)
207 mid_pipe_event_handler(dev, 0);
208}
209
210irqreturn_t psb_irq_handler(DRM_IRQ_ARGS)
211{
212 struct drm_device *dev = (struct drm_device *) arg;
213 struct drm_psb_private *dev_priv =
214 (struct drm_psb_private *) dev->dev_private;
215
216 uint32_t vdc_stat, dsp_int = 0, sgx_int = 0;
217 int handled = 0;
218
219 spin_lock(&dev_priv->irqmask_lock);
220
221 vdc_stat = PSB_RVDC32(PSB_INT_IDENTITY_R);
222
223 if (vdc_stat & _MDFLD_DISP_ALL_IRQ_FLAG)
224 dsp_int = 1;
225
226 if (vdc_stat & _PSB_IRQ_SGX_FLAG)
227 sgx_int = 1;
228
229 vdc_stat &= dev_priv->vdc_irq_mask;
230 spin_unlock(&dev_priv->irqmask_lock);
231
232 if (dsp_int && gma_power_is_on(dev)) {
233 psb_vdc_interrupt(dev, vdc_stat);
234 handled = 1;
235 }
236
237 if (sgx_int) {
238 /* Not expected - we have it masked, shut it up */
239 u32 s, s2;
240 s = PSB_RSGX32(PSB_CR_EVENT_STATUS);
241 s2 = PSB_RSGX32(PSB_CR_EVENT_STATUS2);
242 PSB_WSGX32(s, PSB_CR_EVENT_HOST_CLEAR);
243 PSB_WSGX32(s2, PSB_CR_EVENT_HOST_CLEAR2);
244 /* if s & _PSB_CE_TWOD_COMPLETE we have 2D done but
245 we may as well poll even if we add that ! */
246 handled = 1;
247 }
248
249 PSB_WVDC32(vdc_stat, PSB_INT_IDENTITY_R);
250 (void) PSB_RVDC32(PSB_INT_IDENTITY_R);
251 DRM_READMEMORYBARRIER();
252
253 if (!handled)
254 return IRQ_NONE;
255
256 return IRQ_HANDLED;
257}
258
259void psb_irq_preinstall(struct drm_device *dev)
260{
261 struct drm_psb_private *dev_priv =
262 (struct drm_psb_private *) dev->dev_private;
263 unsigned long irqflags;
264
265 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
266
267 if (gma_power_is_on(dev))
268 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
269 if (dev->vblank_enabled[0])
270 dev_priv->vdc_irq_mask |= _PSB_PIPEA_EVENT_FLAG;
271 if (dev->vblank_enabled[1])
272 dev_priv->vdc_irq_mask |= _MDFLD_PIPEB_EVENT_FLAG;
273 if (dev->vblank_enabled[2])
274 dev_priv->vdc_irq_mask |= _MDFLD_PIPEC_EVENT_FLAG;
275
276 /*This register is safe even if display island is off*/
277 PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
278 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
279}
280
281int psb_irq_postinstall(struct drm_device *dev)
282{
283 struct drm_psb_private *dev_priv =
284 (struct drm_psb_private *) dev->dev_private;
285 unsigned long irqflags;
286
287 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
288
289 /* This register is safe even if display island is off */
290 PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
291 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
292
293 if (dev->vblank_enabled[0])
294 psb_enable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
295 else
296 psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
297
298 if (dev->vblank_enabled[1])
299 psb_enable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
300 else
301 psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
302
303 if (dev->vblank_enabled[2])
304 psb_enable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
305 else
306 psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
307
308 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
309 return 0;
310}
311
312void psb_irq_uninstall(struct drm_device *dev)
313{
314 struct drm_psb_private *dev_priv =
315 (struct drm_psb_private *) dev->dev_private;
316 unsigned long irqflags;
317
318 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
319
320 PSB_WVDC32(0xFFFFFFFF, PSB_HWSTAM);
321
322 if (dev->vblank_enabled[0])
323 psb_disable_pipestat(dev_priv, 0, PIPE_VBLANK_INTERRUPT_ENABLE);
324
325 if (dev->vblank_enabled[1])
326 psb_disable_pipestat(dev_priv, 1, PIPE_VBLANK_INTERRUPT_ENABLE);
327
328 if (dev->vblank_enabled[2])
329 psb_disable_pipestat(dev_priv, 2, PIPE_VBLANK_INTERRUPT_ENABLE);
330
331 dev_priv->vdc_irq_mask &= _PSB_IRQ_SGX_FLAG |
332 _PSB_IRQ_MSVDX_FLAG |
333 _LNC_IRQ_TOPAZ_FLAG;
334
335 /* These two registers are safe even if display island is off */
336 PSB_WVDC32(~dev_priv->vdc_irq_mask, PSB_INT_MASK_R);
337 PSB_WVDC32(dev_priv->vdc_irq_mask, PSB_INT_ENABLE_R);
338
339 wmb();
340
341 /* This register is safe even if display island is off */
342 PSB_WVDC32(PSB_RVDC32(PSB_INT_IDENTITY_R), PSB_INT_IDENTITY_R);
343 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
344}
345
346void psb_irq_turn_on_dpst(struct drm_device *dev)
347{
348 struct drm_psb_private *dev_priv =
349 (struct drm_psb_private *) dev->dev_private;
350 u32 hist_reg;
351 u32 pwm_reg;
352
353 if (gma_power_begin(dev, false)) {
354 PSB_WVDC32(1 << 31, HISTOGRAM_LOGIC_CONTROL);
355 hist_reg = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
356 PSB_WVDC32(1 << 31, HISTOGRAM_INT_CONTROL);
357 hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
358
359 PSB_WVDC32(0x80010100, PWM_CONTROL_LOGIC);
360 pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
361 PSB_WVDC32(pwm_reg | PWM_PHASEIN_ENABLE
362 | PWM_PHASEIN_INT_ENABLE,
363 PWM_CONTROL_LOGIC);
364 pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
365
366 psb_enable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
367
368 hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
369 PSB_WVDC32(hist_reg | HISTOGRAM_INT_CTRL_CLEAR,
370 HISTOGRAM_INT_CONTROL);
371 pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
372 PSB_WVDC32(pwm_reg | 0x80010100 | PWM_PHASEIN_ENABLE,
373 PWM_CONTROL_LOGIC);
374
375 gma_power_end(dev);
376 }
377}
378
379int psb_irq_enable_dpst(struct drm_device *dev)
380{
381 struct drm_psb_private *dev_priv =
382 (struct drm_psb_private *) dev->dev_private;
383 unsigned long irqflags;
384
385 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
386
387 /* enable DPST */
388 mid_enable_pipe_event(dev_priv, 0);
389 psb_irq_turn_on_dpst(dev);
390
391 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
392 return 0;
393}
394
395void psb_irq_turn_off_dpst(struct drm_device *dev)
396{
397 struct drm_psb_private *dev_priv =
398 (struct drm_psb_private *) dev->dev_private;
399 u32 hist_reg;
400 u32 pwm_reg;
401
402 if (gma_power_begin(dev, false)) {
403 PSB_WVDC32(0x00000000, HISTOGRAM_INT_CONTROL);
404 hist_reg = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
405
406 psb_disable_pipestat(dev_priv, 0, PIPE_DPST_EVENT_ENABLE);
407
408 pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
409 PSB_WVDC32(pwm_reg & !(PWM_PHASEIN_INT_ENABLE),
410 PWM_CONTROL_LOGIC);
411 pwm_reg = PSB_RVDC32(PWM_CONTROL_LOGIC);
412
413 gma_power_end(dev);
414 }
415}
416
417int psb_irq_disable_dpst(struct drm_device *dev)
418{
419 struct drm_psb_private *dev_priv =
420 (struct drm_psb_private *) dev->dev_private;
421 unsigned long irqflags;
422
423 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
424
425 mid_disable_pipe_event(dev_priv, 0);
426 psb_irq_turn_off_dpst(dev);
427
428 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
429
430 return 0;
431}
432
433#ifdef PSB_FIXME
434static int psb_vblank_do_wait(struct drm_device *dev,
435 unsigned int *sequence, atomic_t *counter)
436{
437 unsigned int cur_vblank;
438 int ret = 0;
439 DRM_WAIT_ON(ret, dev->vbl_queue, 3 * DRM_HZ,
440 (((cur_vblank = atomic_read(counter))
441 - *sequence) <= (1 << 23)));
442 *sequence = cur_vblank;
443
444 return ret;
445}
446#endif
447
448/*
449 * It is used to enable VBLANK interrupt
450 */
451int psb_enable_vblank(struct drm_device *dev, int pipe)
452{
453 struct drm_psb_private *dev_priv = dev->dev_private;
454 unsigned long irqflags;
455 uint32_t reg_val = 0;
456 uint32_t pipeconf_reg = mid_pipeconf(pipe);
457
458#if defined(CONFIG_DRM_PSB_MFLD)
459 /* Medfield is different - we should perhaps extract out vblank
460 and blacklight etc ops */
461 if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
462 return mdfld_enable_te(dev, pipe);
463#endif
464 if (gma_power_begin(dev, false)) {
465 reg_val = REG_READ(pipeconf_reg);
466 gma_power_end(dev);
467 }
468
469 if (!(reg_val & PIPEACONF_ENABLE))
470 return -EINVAL;
471
472 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
473
474 mid_enable_pipe_event(dev_priv, pipe);
475 psb_enable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
476
477 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
478
479 return 0;
480}
481
482/*
483 * It is used to disable VBLANK interrupt
484 */
485void psb_disable_vblank(struct drm_device *dev, int pipe)
486{
487 struct drm_psb_private *dev_priv = dev->dev_private;
488 unsigned long irqflags;
489
490#if defined(CONFIG_DRM_PSB_MFLD)
491 if (IS_MFLD(dev) && !mdfld_panel_dpi(dev))
492 mdfld_disable_te(dev, pipe);
493#endif
494 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
495
496 mid_disable_pipe_event(dev_priv, pipe);
497 psb_disable_pipestat(dev_priv, pipe, PIPE_VBLANK_INTERRUPT_ENABLE);
498
499 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
500}
501
502/**
503 * mdfld_enable_te - enable TE events
504 * @dev: our DRM device
505 * @pipe: which pipe to work on
506 *
507 * Enable TE events on a Medfield display pipe. Medfield specific.
508 */
509int mdfld_enable_te(struct drm_device *dev, int pipe)
510{
511 struct drm_psb_private *dev_priv = dev->dev_private;
512 unsigned long flags;
513 uint32_t reg_val = 0;
514 uint32_t pipeconf_reg = mid_pipeconf(pipe);
515
516 if (gma_power_begin(dev, false)) {
517 reg_val = REG_READ(pipeconf_reg);
518 gma_power_end(dev);
519 }
520
521 if (!(reg_val & PIPEACONF_ENABLE))
522 return -EINVAL;
523
524 spin_lock_irqsave(&dev_priv->irqmask_lock, flags);
525
526 mid_enable_pipe_event(dev_priv, pipe);
527 psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
528
529 spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags);
530
531 return 0;
532}
533
534/**
535 * mdfld_disable_te - disable TE events
536 * @dev: our DRM device
537 * @pipe: which pipe to work on
538 *
539 * Disable TE events on a Medfield display pipe. Medfield specific.
540 */
541void mdfld_disable_te(struct drm_device *dev, int pipe)
542{
543 struct drm_psb_private *dev_priv = dev->dev_private;
544 unsigned long flags;
545
546 spin_lock_irqsave(&dev_priv->irqmask_lock, flags);
547
548 mid_disable_pipe_event(dev_priv, pipe);
549 psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
550
551 spin_unlock_irqrestore(&dev_priv->irqmask_lock, flags);
552}
553
554/* Called from drm generic code, passed a 'crtc', which
555 * we use as a pipe index
556 */
557u32 psb_get_vblank_counter(struct drm_device *dev, int pipe)
558{
559 uint32_t high_frame = PIPEAFRAMEHIGH;
560 uint32_t low_frame = PIPEAFRAMEPIXEL;
561 uint32_t pipeconf_reg = PIPEACONF;
562 uint32_t reg_val = 0;
563 uint32_t high1 = 0, high2 = 0, low = 0, count = 0;
564
565 switch (pipe) {
566 case 0:
567 break;
568 case 1:
569 high_frame = PIPEBFRAMEHIGH;
570 low_frame = PIPEBFRAMEPIXEL;
571 pipeconf_reg = PIPEBCONF;
572 break;
573 case 2:
574 high_frame = PIPECFRAMEHIGH;
575 low_frame = PIPECFRAMEPIXEL;
576 pipeconf_reg = PIPECCONF;
577 break;
578 default:
579 dev_err(dev->dev, "%s, invalid pipe.\n", __func__);
580 return 0;
581 }
582
583 if (!gma_power_begin(dev, false))
584 return 0;
585
586 reg_val = REG_READ(pipeconf_reg);
587
588 if (!(reg_val & PIPEACONF_ENABLE)) {
589 dev_err(dev->dev, "trying to get vblank count for disabled pipe %d\n",
590 pipe);
591 goto psb_get_vblank_counter_exit;
592 }
593
594 /*
595 * High & low register fields aren't synchronized, so make sure
596 * we get a low value that's stable across two reads of the high
597 * register.
598 */
599 do {
600 high1 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
601 PIPE_FRAME_HIGH_SHIFT);
602 low = ((REG_READ(low_frame) & PIPE_FRAME_LOW_MASK) >>
603 PIPE_FRAME_LOW_SHIFT);
604 high2 = ((REG_READ(high_frame) & PIPE_FRAME_HIGH_MASK) >>
605 PIPE_FRAME_HIGH_SHIFT);
606 } while (high1 != high2);
607
608 count = (high1 << 8) | low;
609
610psb_get_vblank_counter_exit:
611
612 gma_power_end(dev);
613
614 return count;
615}
616
diff --git a/drivers/staging/gma500/psb_irq.h b/drivers/staging/gma500/psb_irq.h
new file mode 100644
index 00000000000..216fda38b57
--- /dev/null
+++ b/drivers/staging/gma500/psb_irq.h
@@ -0,0 +1,45 @@
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
29bool sysirq_init(struct drm_device *dev);
30void sysirq_uninit(struct drm_device *dev);
31
32void psb_irq_preinstall(struct drm_device *dev);
33int psb_irq_postinstall(struct drm_device *dev);
34void psb_irq_uninstall(struct drm_device *dev);
35irqreturn_t psb_irq_handler(DRM_IRQ_ARGS);
36
37int psb_irq_enable_dpst(struct drm_device *dev);
38int psb_irq_disable_dpst(struct drm_device *dev);
39void psb_irq_turn_on_dpst(struct drm_device *dev);
40void psb_irq_turn_off_dpst(struct drm_device *dev);
41int psb_enable_vblank(struct drm_device *dev, int pipe);
42void psb_disable_vblank(struct drm_device *dev, int pipe);
43u32 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
new file mode 100644
index 00000000000..af328516561
--- /dev/null
+++ b/drivers/staging/gma500/psb_lid.c
@@ -0,0 +1,90 @@
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
26static 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 /* printk(KERN_INFO"%s: lid: closed\n", __FUNCTION__); */
56
57 dev_priv->lid_last_state = readl(lid_state);
58
59lid_timer_schedule:
60 spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
61 if (!timer_pending(lid_timer)) {
62 lid_timer->expires = jiffies + PSB_LID_DELAY;
63 add_timer(lid_timer);
64 }
65 spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
66}
67
68void psb_lid_timer_init(struct drm_psb_private *dev_priv)
69{
70 struct timer_list *lid_timer = &dev_priv->lid_timer;
71 unsigned long irq_flags;
72
73 spin_lock_init(&dev_priv->lid_lock);
74 spin_lock_irqsave(&dev_priv->lid_lock, irq_flags);
75
76 init_timer(lid_timer);
77
78 lid_timer->data = (unsigned long)dev_priv;
79 lid_timer->function = psb_lid_timer_func;
80 lid_timer->expires = jiffies + PSB_LID_DELAY;
81
82 add_timer(lid_timer);
83 spin_unlock_irqrestore(&dev_priv->lid_lock, irq_flags);
84}
85
86void psb_lid_timer_takedown(struct drm_psb_private *dev_priv)
87{
88 del_timer_sync(&dev_priv->lid_timer);
89}
90
diff --git a/drivers/staging/gma500/psb_reg.h b/drivers/staging/gma500/psb_reg.h
new file mode 100644
index 00000000000..b81c7c1e9c2
--- /dev/null
+++ b/drivers/staging/gma500/psb_reg.h
@@ -0,0 +1,582 @@
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