aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/gma500
diff options
context:
space:
mode:
authorKirill A. Shutemov <kirill.shutemov@linux.intel.com>2012-03-08 11:02:20 -0500
committerDave Airlie <airlied@redhat.com>2012-03-10 08:05:48 -0500
commit026abc333205c1fff80138b8c2cac3d0347685f4 (patch)
treedbcb2ad763f96b5f0c99ec5650f477aa103a8528 /drivers/gpu/drm/gma500
parentc6265ff593467d472814aa9f16f89f6c1dc90a5d (diff)
gma500: initial medfield merge
We need to merge this ahead of some of the cleanup because a lot of needed cleanup spans both new and old chips. If we try and clean up and the merge we end up fighting ourselves. Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> [With a load of the cleanup stuff folded in, register stuff reworked sanely] Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/gma500')
-rw-r--r--drivers/gpu/drm/gma500/Kconfig7
-rw-r--r--drivers/gpu/drm/gma500/Makefile10
-rw-r--r--drivers/gpu/drm/gma500/mdfld_device.c691
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_dpi.c1024
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_dpi.h79
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_output.c635
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_output.h389
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c694
-rw-r--r--drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h92
-rw-r--r--drivers/gpu/drm/gma500/mdfld_intel_display.c1192
-rw-r--r--drivers/gpu/drm/gma500/mdfld_output.c77
-rw-r--r--drivers/gpu/drm/gma500/mdfld_output.h77
-rw-r--r--drivers/gpu/drm/gma500/mdfld_tmd_vid.c201
-rw-r--r--drivers/gpu/drm/gma500/mdfld_tpo_vid.c124
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.c10
-rw-r--r--drivers/gpu/drm/gma500/psb_drv.h89
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.c58
-rw-r--r--drivers/gpu/drm/gma500/psb_irq.h2
-rw-r--r--drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c829
-rw-r--r--drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h38
20 files changed, 6318 insertions, 0 deletions
diff --git a/drivers/gpu/drm/gma500/Kconfig b/drivers/gpu/drm/gma500/Kconfig
index f92a7f4208d1..42e665c7e90a 100644
--- a/drivers/gpu/drm/gma500/Kconfig
+++ b/drivers/gpu/drm/gma500/Kconfig
@@ -24,3 +24,10 @@ config DRM_GMA3600
24 help 24 help
25 Say yes to include basic support for Intel GMA3600/3650 (Intel 25 Say yes to include basic support for Intel GMA3600/3650 (Intel
26 Cedar Trail) platforms. 26 Cedar Trail) platforms.
27
28config DRM_MEDFIELD
29 bool "Intel Medfield support (Experimental)"
30 depends on DRM_GMA500 && X86_INTEL_MID
31 help
32 Say yes to include support for the Intel Medfield platform.
33
diff --git a/drivers/gpu/drm/gma500/Makefile b/drivers/gpu/drm/gma500/Makefile
index 81c103be5e21..1583982917ce 100644
--- a/drivers/gpu/drm/gma500/Makefile
+++ b/drivers/gpu/drm/gma500/Makefile
@@ -37,4 +37,14 @@ gma500_gfx-$(CONFIG_DRM_GMA600) += oaktrail_device.o \
37 oaktrail_hdmi.o \ 37 oaktrail_hdmi.o \
38 oaktrail_hdmi_i2c.o 38 oaktrail_hdmi_i2c.o
39 39
40gma500_gfx-$(CONFIG_DRM_MEDFIELD) += mdfld_device.o \
41 mdfld_output.o \
42 mdfld_intel_display.o \
43 mdfld_dsi_output.o \
44 mdfld_dsi_dpi.o \
45 mdfld_dsi_pkg_sender.o \
46 mdfld_tpo_vid.o \
47 mdfld_tmd_vid.o \
48 tc35876x-dsi-lvds.o
49
40obj-$(CONFIG_DRM_GMA500) += gma500_gfx.o 50obj-$(CONFIG_DRM_GMA500) += gma500_gfx.o
diff --git a/drivers/gpu/drm/gma500/mdfld_device.c b/drivers/gpu/drm/gma500/mdfld_device.c
new file mode 100644
index 000000000000..6cfdda90eef1
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_device.c
@@ -0,0 +1,691 @@
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 "psb_drv.h"
21#include "mid_bios.h"
22#include "mdfld_output.h"
23#include "mdfld_dsi_output.h"
24#include "tc35876x-dsi-lvds.h"
25
26#include <asm/intel_scu_ipc.h>
27
28#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
29
30#define MRST_BLC_MAX_PWM_REG_FREQ 0xFFFF
31#define BLC_PWM_PRECISION_FACTOR 100 /* 10000000 */
32#define BLC_PWM_FREQ_CALC_CONSTANT 32
33#define MHz 1000000
34#define BRIGHTNESS_MIN_LEVEL 1
35#define BRIGHTNESS_MAX_LEVEL 100
36#define BRIGHTNESS_MASK 0xFF
37#define BLC_POLARITY_NORMAL 0
38#define BLC_POLARITY_INVERSE 1
39#define BLC_ADJUSTMENT_MAX 100
40
41#define MDFLD_BLC_PWM_PRECISION_FACTOR 10
42#define MDFLD_BLC_MAX_PWM_REG_FREQ 0xFFFE
43#define MDFLD_BLC_MIN_PWM_REG_FREQ 0x2
44
45#define MDFLD_BACKLIGHT_PWM_POLARITY_BIT_CLEAR (0xFFFE)
46#define MDFLD_BACKLIGHT_PWM_CTL_SHIFT (16)
47
48static struct backlight_device *mdfld_backlight_device;
49
50int mdfld_set_brightness(struct backlight_device *bd)
51{
52 struct drm_device *dev =
53 (struct drm_device *)bl_get_data(mdfld_backlight_device);
54 struct drm_psb_private *dev_priv = dev->dev_private;
55 int level = bd->props.brightness;
56
57 DRM_DEBUG_DRIVER("backlight level set to %d\n", level);
58
59 /* Perform value bounds checking */
60 if (level < BRIGHTNESS_MIN_LEVEL)
61 level = BRIGHTNESS_MIN_LEVEL;
62
63 if (gma_power_begin(dev, false)) {
64 u32 adjusted_level = 0;
65
66 /*
67 * Adjust the backlight level with the percent in
68 * dev_priv->blc_adj2
69 */
70 adjusted_level = level * dev_priv->blc_adj2;
71 adjusted_level = adjusted_level / BLC_ADJUSTMENT_MAX;
72 dev_priv->brightness_adjusted = adjusted_level;
73
74 if (mdfld_get_panel_type(dev, 0) == TC35876X) {
75 if (dev_priv->dpi_panel_on[0] ||
76 dev_priv->dpi_panel_on[2])
77 tc35876x_brightness_control(dev,
78 dev_priv->brightness_adjusted);
79 } else {
80 if (dev_priv->dpi_panel_on[0])
81 mdfld_dsi_brightness_control(dev, 0,
82 dev_priv->brightness_adjusted);
83 }
84
85 if (dev_priv->dpi_panel_on[2])
86 mdfld_dsi_brightness_control(dev, 2,
87 dev_priv->brightness_adjusted);
88 gma_power_end(dev);
89 }
90
91 /* cache the brightness for later use */
92 dev_priv->brightness = level;
93 return 0;
94}
95
96int mdfld_get_brightness(struct backlight_device *bd)
97{
98 struct drm_device *dev =
99 (struct drm_device *)bl_get_data(mdfld_backlight_device);
100 struct drm_psb_private *dev_priv = dev->dev_private;
101
102 DRM_DEBUG_DRIVER("brightness = 0x%x \n", dev_priv->brightness);
103
104 /* return locally cached var instead of HW read (due to DPST etc.) */
105 return dev_priv->brightness;
106}
107
108static const struct backlight_ops mdfld_ops = {
109 .get_brightness = mdfld_get_brightness,
110 .update_status = mdfld_set_brightness,
111};
112
113static int device_backlight_init(struct drm_device *dev)
114{
115 struct drm_psb_private *dev_priv = (struct drm_psb_private *)
116 dev->dev_private;
117
118 dev_priv->blc_adj1 = BLC_ADJUSTMENT_MAX;
119 dev_priv->blc_adj2 = BLC_ADJUSTMENT_MAX;
120
121 return 0;
122}
123
124int mdfld_backlight_init(struct drm_device *dev)
125{
126 struct backlight_properties props;
127 int ret = 0;
128
129 memset(&props, 0, sizeof(struct backlight_properties));
130 props.max_brightness = BRIGHTNESS_MAX_LEVEL;
131 props.type = BACKLIGHT_PLATFORM;
132 mdfld_backlight_device = backlight_device_register("mdfld-bl",
133 NULL, (void *)dev, &mdfld_ops, &props);
134
135 if (IS_ERR(mdfld_backlight_device))
136 return PTR_ERR(mdfld_backlight_device);
137
138 ret = device_backlight_init(dev);
139 if (ret)
140 return ret;
141
142 mdfld_backlight_device->props.brightness = BRIGHTNESS_MAX_LEVEL;
143 mdfld_backlight_device->props.max_brightness = BRIGHTNESS_MAX_LEVEL;
144 backlight_update_status(mdfld_backlight_device);
145 return 0;
146}
147#endif
148
149struct backlight_device *mdfld_get_backlight_device(void)
150{
151#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
152 return mdfld_backlight_device;
153#else
154 return NULL;
155#endif
156}
157
158/*
159 * mdfld_save_display_registers
160 *
161 * Description: We are going to suspend so save current display
162 * register state.
163 *
164 * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
165 */
166static int mdfld_save_display_registers(struct drm_device *dev, int pipe)
167{
168 struct drm_psb_private *dev_priv = dev->dev_private;
169 struct medfield_state *regs = &dev_priv->regs.mdfld;
170 int i;
171
172 /* register */
173 u32 dpll_reg = MRST_DPLL_A;
174 u32 fp_reg = MRST_FPA0;
175 u32 pipeconf_reg = PIPEACONF;
176 u32 htot_reg = HTOTAL_A;
177 u32 hblank_reg = HBLANK_A;
178 u32 hsync_reg = HSYNC_A;
179 u32 vtot_reg = VTOTAL_A;
180 u32 vblank_reg = VBLANK_A;
181 u32 vsync_reg = VSYNC_A;
182 u32 pipesrc_reg = PIPEASRC;
183 u32 dspstride_reg = DSPASTRIDE;
184 u32 dsplinoff_reg = DSPALINOFF;
185 u32 dsptileoff_reg = DSPATILEOFF;
186 u32 dspsize_reg = DSPASIZE;
187 u32 dsppos_reg = DSPAPOS;
188 u32 dspsurf_reg = DSPASURF;
189 u32 mipi_reg = MIPI;
190 u32 dspcntr_reg = DSPACNTR;
191 u32 dspstatus_reg = PIPEASTAT;
192 u32 palette_reg = PALETTE_A;
193
194 /* pointer to values */
195 u32 *dpll_val = &regs->saveDPLL_A;
196 u32 *fp_val = &regs->saveFPA0;
197 u32 *pipeconf_val = &regs->savePIPEACONF;
198 u32 *htot_val = &regs->saveHTOTAL_A;
199 u32 *hblank_val = &regs->saveHBLANK_A;
200 u32 *hsync_val = &regs->saveHSYNC_A;
201 u32 *vtot_val = &regs->saveVTOTAL_A;
202 u32 *vblank_val = &regs->saveVBLANK_A;
203 u32 *vsync_val = &regs->saveVSYNC_A;
204 u32 *pipesrc_val = &regs->savePIPEASRC;
205 u32 *dspstride_val = &regs->saveDSPASTRIDE;
206 u32 *dsplinoff_val = &regs->saveDSPALINOFF;
207 u32 *dsptileoff_val = &regs->saveDSPATILEOFF;
208 u32 *dspsize_val = &regs->saveDSPASIZE;
209 u32 *dsppos_val = &regs->saveDSPAPOS;
210 u32 *dspsurf_val = &regs->saveDSPASURF;
211 u32 *mipi_val = &regs->saveMIPI;
212 u32 *dspcntr_val = &regs->saveDSPACNTR;
213 u32 *dspstatus_val = &regs->saveDSPASTATUS;
214 u32 *palette_val = regs->save_palette_a;
215
216 switch (pipe) {
217 case 0:
218 break;
219 case 1:
220 /* regester */
221 dpll_reg = MDFLD_DPLL_B;
222 fp_reg = MDFLD_DPLL_DIV0;
223 pipeconf_reg = PIPEBCONF;
224 htot_reg = HTOTAL_B;
225 hblank_reg = HBLANK_B;
226 hsync_reg = HSYNC_B;
227 vtot_reg = VTOTAL_B;
228 vblank_reg = VBLANK_B;
229 vsync_reg = VSYNC_B;
230 pipesrc_reg = PIPEBSRC;
231 dspstride_reg = DSPBSTRIDE;
232 dsplinoff_reg = DSPBLINOFF;
233 dsptileoff_reg = DSPBTILEOFF;
234 dspsize_reg = DSPBSIZE;
235 dsppos_reg = DSPBPOS;
236 dspsurf_reg = DSPBSURF;
237 dspcntr_reg = DSPBCNTR;
238 dspstatus_reg = PIPEBSTAT;
239 palette_reg = PALETTE_B;
240
241 /* values */
242 dpll_val = &regs->saveDPLL_B;
243 fp_val = &regs->saveFPB0;
244 pipeconf_val = &regs->savePIPEBCONF;
245 htot_val = &regs->saveHTOTAL_B;
246 hblank_val = &regs->saveHBLANK_B;
247 hsync_val = &regs->saveHSYNC_B;
248 vtot_val = &regs->saveVTOTAL_B;
249 vblank_val = &regs->saveVBLANK_B;
250 vsync_val = &regs->saveVSYNC_B;
251 pipesrc_val = &regs->savePIPEBSRC;
252 dspstride_val = &regs->saveDSPBSTRIDE;
253 dsplinoff_val = &regs->saveDSPBLINOFF;
254 dsptileoff_val = &regs->saveDSPBTILEOFF;
255 dspsize_val = &regs->saveDSPBSIZE;
256 dsppos_val = &regs->saveDSPBPOS;
257 dspsurf_val = &regs->saveDSPBSURF;
258 dspcntr_val = &regs->saveDSPBCNTR;
259 dspstatus_val = &regs->saveDSPBSTATUS;
260 palette_val = regs->save_palette_b;
261 break;
262 case 2:
263 /* register */
264 pipeconf_reg = PIPECCONF;
265 htot_reg = HTOTAL_C;
266 hblank_reg = HBLANK_C;
267 hsync_reg = HSYNC_C;
268 vtot_reg = VTOTAL_C;
269 vblank_reg = VBLANK_C;
270 vsync_reg = VSYNC_C;
271 pipesrc_reg = PIPECSRC;
272 dspstride_reg = DSPCSTRIDE;
273 dsplinoff_reg = DSPCLINOFF;
274 dsptileoff_reg = DSPCTILEOFF;
275 dspsize_reg = DSPCSIZE;
276 dsppos_reg = DSPCPOS;
277 dspsurf_reg = DSPCSURF;
278 mipi_reg = MIPI_C;
279 dspcntr_reg = DSPCCNTR;
280 dspstatus_reg = PIPECSTAT;
281 palette_reg = PALETTE_C;
282
283 /* pointer to values */
284 pipeconf_val = &regs->savePIPECCONF;
285 htot_val = &regs->saveHTOTAL_C;
286 hblank_val = &regs->saveHBLANK_C;
287 hsync_val = &regs->saveHSYNC_C;
288 vtot_val = &regs->saveVTOTAL_C;
289 vblank_val = &regs->saveVBLANK_C;
290 vsync_val = &regs->saveVSYNC_C;
291 pipesrc_val = &regs->savePIPECSRC;
292 dspstride_val = &regs->saveDSPCSTRIDE;
293 dsplinoff_val = &regs->saveDSPCLINOFF;
294 dsptileoff_val = &regs->saveDSPCTILEOFF;
295 dspsize_val = &regs->saveDSPCSIZE;
296 dsppos_val = &regs->saveDSPCPOS;
297 dspsurf_val = &regs->saveDSPCSURF;
298 mipi_val = &regs->saveMIPI_C;
299 dspcntr_val = &regs->saveDSPCCNTR;
300 dspstatus_val = &regs->saveDSPCSTATUS;
301 palette_val = regs->save_palette_c;
302 break;
303 default:
304 DRM_ERROR("%s, invalid pipe number.\n", __func__);
305 return -EINVAL;
306 }
307
308 /* Pipe & plane A info */
309 *dpll_val = PSB_RVDC32(dpll_reg);
310 *fp_val = PSB_RVDC32(fp_reg);
311 *pipeconf_val = PSB_RVDC32(pipeconf_reg);
312 *htot_val = PSB_RVDC32(htot_reg);
313 *hblank_val = PSB_RVDC32(hblank_reg);
314 *hsync_val = PSB_RVDC32(hsync_reg);
315 *vtot_val = PSB_RVDC32(vtot_reg);
316 *vblank_val = PSB_RVDC32(vblank_reg);
317 *vsync_val = PSB_RVDC32(vsync_reg);
318 *pipesrc_val = PSB_RVDC32(pipesrc_reg);
319 *dspstride_val = PSB_RVDC32(dspstride_reg);
320 *dsplinoff_val = PSB_RVDC32(dsplinoff_reg);
321 *dsptileoff_val = PSB_RVDC32(dsptileoff_reg);
322 *dspsize_val = PSB_RVDC32(dspsize_reg);
323 *dsppos_val = PSB_RVDC32(dsppos_reg);
324 *dspsurf_val = PSB_RVDC32(dspsurf_reg);
325 *dspcntr_val = PSB_RVDC32(dspcntr_reg);
326 *dspstatus_val = PSB_RVDC32(dspstatus_reg);
327
328 /*save palette (gamma) */
329 for (i = 0; i < 256; i++)
330 palette_val[i] = PSB_RVDC32(palette_reg + (i << 2));
331
332 if (pipe == 1) {
333 regs->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
334 regs->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
335
336 regs->saveHDMIPHYMISCCTL = PSB_RVDC32(HDMIPHYMISCCTL);
337 regs->saveHDMIB_CONTROL = PSB_RVDC32(HDMIB_CONTROL);
338 return 0;
339 }
340
341 *mipi_val = PSB_RVDC32(mipi_reg);
342 return 0;
343}
344
345/*
346 * mdfld_restore_display_registers
347 *
348 * Description: We are going to resume so restore display register state.
349 *
350 * Notes: FIXME_JLIU7 need to add the support for DPI MIPI & HDMI audio
351 */
352static int mdfld_restore_display_registers(struct drm_device *dev, int pipe)
353{
354 /* To get panel out of ULPS mode. */
355 u32 temp = 0;
356 u32 device_ready_reg = DEVICE_READY_REG;
357 struct drm_psb_private *dev_priv = dev->dev_private;
358 struct mdfld_dsi_config *dsi_config = NULL;
359 struct medfield_state *regs = &dev_priv->regs.mdfld;
360 u32 i = 0;
361 u32 dpll = 0;
362 u32 timeout = 0;
363
364 /* regester */
365 u32 dpll_reg = MRST_DPLL_A;
366 u32 fp_reg = MRST_FPA0;
367 u32 pipeconf_reg = PIPEACONF;
368 u32 htot_reg = HTOTAL_A;
369 u32 hblank_reg = HBLANK_A;
370 u32 hsync_reg = HSYNC_A;
371 u32 vtot_reg = VTOTAL_A;
372 u32 vblank_reg = VBLANK_A;
373 u32 vsync_reg = VSYNC_A;
374 u32 pipesrc_reg = PIPEASRC;
375 u32 dspstride_reg = DSPASTRIDE;
376 u32 dsplinoff_reg = DSPALINOFF;
377 u32 dsptileoff_reg = DSPATILEOFF;
378 u32 dspsize_reg = DSPASIZE;
379 u32 dsppos_reg = DSPAPOS;
380 u32 dspsurf_reg = DSPASURF;
381 u32 dspstatus_reg = PIPEASTAT;
382 u32 mipi_reg = MIPI;
383 u32 dspcntr_reg = DSPACNTR;
384 u32 palette_reg = PALETTE_A;
385
386 /* values */
387 u32 dpll_val = regs->saveDPLL_A & ~DPLL_VCO_ENABLE;
388 u32 fp_val = regs->saveFPA0;
389 u32 pipeconf_val = regs->savePIPEACONF;
390 u32 htot_val = regs->saveHTOTAL_A;
391 u32 hblank_val = regs->saveHBLANK_A;
392 u32 hsync_val = regs->saveHSYNC_A;
393 u32 vtot_val = regs->saveVTOTAL_A;
394 u32 vblank_val = regs->saveVBLANK_A;
395 u32 vsync_val = regs->saveVSYNC_A;
396 u32 pipesrc_val = regs->savePIPEASRC;
397 u32 dspstride_val = regs->saveDSPASTRIDE;
398 u32 dsplinoff_val = regs->saveDSPALINOFF;
399 u32 dsptileoff_val = regs->saveDSPATILEOFF;
400 u32 dspsize_val = regs->saveDSPASIZE;
401 u32 dsppos_val = regs->saveDSPAPOS;
402 u32 dspsurf_val = regs->saveDSPASURF;
403 u32 dspstatus_val = regs->saveDSPASTATUS;
404 u32 mipi_val = regs->saveMIPI;
405 u32 dspcntr_val = regs->saveDSPACNTR;
406 u32 *palette_val = regs->save_palette_a;
407
408 switch (pipe) {
409 case 0:
410 dsi_config = dev_priv->dsi_configs[0];
411 break;
412 case 1:
413 /* regester */
414 dpll_reg = MDFLD_DPLL_B;
415 fp_reg = MDFLD_DPLL_DIV0;
416 pipeconf_reg = PIPEBCONF;
417 htot_reg = HTOTAL_B;
418 hblank_reg = HBLANK_B;
419 hsync_reg = HSYNC_B;
420 vtot_reg = VTOTAL_B;
421 vblank_reg = VBLANK_B;
422 vsync_reg = VSYNC_B;
423 pipesrc_reg = PIPEBSRC;
424 dspstride_reg = DSPBSTRIDE;
425 dsplinoff_reg = DSPBLINOFF;
426 dsptileoff_reg = DSPBTILEOFF;
427 dspsize_reg = DSPBSIZE;
428 dsppos_reg = DSPBPOS;
429 dspsurf_reg = DSPBSURF;
430 dspcntr_reg = DSPBCNTR;
431 dspstatus_reg = PIPEBSTAT;
432 palette_reg = PALETTE_B;
433
434 /* values */
435 dpll_val = regs->saveDPLL_B & ~DPLL_VCO_ENABLE;
436 fp_val = regs->saveFPB0;
437 pipeconf_val = regs->savePIPEBCONF;
438 htot_val = regs->saveHTOTAL_B;
439 hblank_val = regs->saveHBLANK_B;
440 hsync_val = regs->saveHSYNC_B;
441 vtot_val = regs->saveVTOTAL_B;
442 vblank_val = regs->saveVBLANK_B;
443 vsync_val = regs->saveVSYNC_B;
444 pipesrc_val = regs->savePIPEBSRC;
445 dspstride_val = regs->saveDSPBSTRIDE;
446 dsplinoff_val = regs->saveDSPBLINOFF;
447 dsptileoff_val = regs->saveDSPBTILEOFF;
448 dspsize_val = regs->saveDSPBSIZE;
449 dsppos_val = regs->saveDSPBPOS;
450 dspsurf_val = regs->saveDSPBSURF;
451 dspcntr_val = regs->saveDSPBCNTR;
452 dspstatus_val = regs->saveDSPBSTATUS;
453 palette_val = regs->save_palette_b;
454 break;
455 case 2:
456 /* regester */
457 pipeconf_reg = PIPECCONF;
458 htot_reg = HTOTAL_C;
459 hblank_reg = HBLANK_C;
460 hsync_reg = HSYNC_C;
461 vtot_reg = VTOTAL_C;
462 vblank_reg = VBLANK_C;
463 vsync_reg = VSYNC_C;
464 pipesrc_reg = PIPECSRC;
465 dspstride_reg = DSPCSTRIDE;
466 dsplinoff_reg = DSPCLINOFF;
467 dsptileoff_reg = DSPCTILEOFF;
468 dspsize_reg = DSPCSIZE;
469 dsppos_reg = DSPCPOS;
470 dspsurf_reg = DSPCSURF;
471 mipi_reg = MIPI_C;
472 dspcntr_reg = DSPCCNTR;
473 dspstatus_reg = PIPECSTAT;
474 palette_reg = PALETTE_C;
475
476 /* values */
477 pipeconf_val = regs->savePIPECCONF;
478 htot_val = regs->saveHTOTAL_C;
479 hblank_val = regs->saveHBLANK_C;
480 hsync_val = regs->saveHSYNC_C;
481 vtot_val = regs->saveVTOTAL_C;
482 vblank_val = regs->saveVBLANK_C;
483 vsync_val = regs->saveVSYNC_C;
484 pipesrc_val = regs->savePIPECSRC;
485 dspstride_val = regs->saveDSPCSTRIDE;
486 dsplinoff_val = regs->saveDSPCLINOFF;
487 dsptileoff_val = regs->saveDSPCTILEOFF;
488 dspsize_val = regs->saveDSPCSIZE;
489 dsppos_val = regs->saveDSPCPOS;
490 dspsurf_val = regs->saveDSPCSURF;
491 mipi_val = regs->saveMIPI_C;
492 dspcntr_val = regs->saveDSPCCNTR;
493 dspstatus_val = regs->saveDSPCSTATUS;
494 palette_val = regs->save_palette_c;
495
496 dsi_config = dev_priv->dsi_configs[1];
497 break;
498 default:
499 DRM_ERROR("%s, invalid pipe number.\n", __func__);
500 return -EINVAL;
501 }
502
503 /*make sure VGA plane is off. it initializes to on after reset!*/
504 PSB_WVDC32(0x80000000, VGACNTRL);
505
506 if (pipe == 1) {
507 PSB_WVDC32(dpll_val & ~DPLL_VCO_ENABLE, dpll_reg);
508 PSB_RVDC32(dpll_reg);
509
510 PSB_WVDC32(fp_val, fp_reg);
511 } else {
512
513 dpll = PSB_RVDC32(dpll_reg);
514
515 if (!(dpll & DPLL_VCO_ENABLE)) {
516
517 /* When ungating power of DPLL, needs to wait 0.5us
518 before enable the VCO */
519 if (dpll & MDFLD_PWR_GATE_EN) {
520 dpll &= ~MDFLD_PWR_GATE_EN;
521 PSB_WVDC32(dpll, dpll_reg);
522 /* FIXME_MDFLD PO - change 500 to 1 after PO */
523 udelay(500);
524 }
525
526 PSB_WVDC32(fp_val, fp_reg);
527 PSB_WVDC32(dpll_val, dpll_reg);
528 /* FIXME_MDFLD PO - change 500 to 1 after PO */
529 udelay(500);
530
531 dpll_val |= DPLL_VCO_ENABLE;
532 PSB_WVDC32(dpll_val, dpll_reg);
533 PSB_RVDC32(dpll_reg);
534
535 /* wait for DSI PLL to lock */
536 while (timeout < 20000 &&
537 !(PSB_RVDC32(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
538 udelay(150);
539 timeout++;
540 }
541
542 if (timeout == 20000) {
543 DRM_ERROR("%s, can't lock DSIPLL.\n",
544 __func__);
545 return -EINVAL;
546 }
547 }
548 }
549 /* Restore mode */
550 PSB_WVDC32(htot_val, htot_reg);
551 PSB_WVDC32(hblank_val, hblank_reg);
552 PSB_WVDC32(hsync_val, hsync_reg);
553 PSB_WVDC32(vtot_val, vtot_reg);
554 PSB_WVDC32(vblank_val, vblank_reg);
555 PSB_WVDC32(vsync_val, vsync_reg);
556 PSB_WVDC32(pipesrc_val, pipesrc_reg);
557 PSB_WVDC32(dspstatus_val, dspstatus_reg);
558
559 /*set up the plane*/
560 PSB_WVDC32(dspstride_val, dspstride_reg);
561 PSB_WVDC32(dsplinoff_val, dsplinoff_reg);
562 PSB_WVDC32(dsptileoff_val, dsptileoff_reg);
563 PSB_WVDC32(dspsize_val, dspsize_reg);
564 PSB_WVDC32(dsppos_val, dsppos_reg);
565 PSB_WVDC32(dspsurf_val, dspsurf_reg);
566
567 if (pipe == 1) {
568 /* restore palette (gamma) */
569 /*DRM_UDELAY(50000); */
570 for (i = 0; i < 256; i++)
571 PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
572
573 PSB_WVDC32(regs->savePFIT_CONTROL, PFIT_CONTROL);
574 PSB_WVDC32(regs->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
575
576 /*TODO: resume HDMI port */
577
578 /*TODO: resume pipe*/
579
580 /*enable the plane*/
581 PSB_WVDC32(dspcntr_val & ~DISPLAY_PLANE_ENABLE, dspcntr_reg);
582
583 return 0;
584 }
585
586 /*set up pipe related registers*/
587 PSB_WVDC32(mipi_val, mipi_reg);
588
589 /*setup MIPI adapter + MIPI IP registers*/
590 if (dsi_config)
591 mdfld_dsi_controller_init(dsi_config, pipe);
592
593 if (in_atomic() || in_interrupt())
594 mdelay(20);
595 else
596 msleep(20);
597
598 /*enable the plane*/
599 PSB_WVDC32(dspcntr_val, dspcntr_reg);
600
601 if (in_atomic() || in_interrupt())
602 mdelay(20);
603 else
604 msleep(20);
605
606 /* LP Hold Release */
607 temp = REG_READ(mipi_reg);
608 temp |= LP_OUTPUT_HOLD_RELEASE;
609 REG_WRITE(mipi_reg, temp);
610 mdelay(1);
611
612
613 /* Set DSI host to exit from Utra Low Power State */
614 temp = REG_READ(device_ready_reg);
615 temp &= ~ULPS_MASK;
616 temp |= 0x3;
617 temp |= EXIT_ULPS_DEV_READY;
618 REG_WRITE(device_ready_reg, temp);
619 mdelay(1);
620
621 temp = REG_READ(device_ready_reg);
622 temp &= ~ULPS_MASK;
623 temp |= EXITING_ULPS;
624 REG_WRITE(device_ready_reg, temp);
625 mdelay(1);
626
627 /*enable the pipe*/
628 PSB_WVDC32(pipeconf_val, pipeconf_reg);
629
630 /* restore palette (gamma) */
631 /*DRM_UDELAY(50000); */
632 for (i = 0; i < 256; i++)
633 PSB_WVDC32(palette_val[i], palette_reg + (i << 2));
634
635 return 0;
636}
637
638static int mdfld_save_registers(struct drm_device *dev)
639{
640 /* mdfld_save_cursor_overlay_registers(dev); */
641 mdfld_save_display_registers(dev, 0);
642 mdfld_save_display_registers(dev, 2);
643 mdfld_disable_crtc(dev, 0);
644 mdfld_disable_crtc(dev, 2);
645
646 return 0;
647}
648
649static int mdfld_restore_registers(struct drm_device *dev)
650{
651 mdfld_restore_display_registers(dev, 2);
652 mdfld_restore_display_registers(dev, 0);
653 /* mdfld_restore_cursor_overlay_registers(dev); */
654
655 return 0;
656}
657
658static int mdfld_power_down(struct drm_device *dev)
659{
660 /* FIXME */
661 return 0;
662}
663
664static int mdfld_power_up(struct drm_device *dev)
665{
666 /* FIXME */
667 return 0;
668}
669
670const struct psb_ops mdfld_chip_ops = {
671 .name = "mdfld",
672 .accel_2d = 0,
673 .pipes = 3,
674 .crtcs = 3,
675 .sgx_offset = MRST_SGX_OFFSET,
676
677 .chip_setup = mid_chip_setup,
678 .crtc_helper = &mdfld_helper_funcs,
679 .crtc_funcs = &psb_intel_crtc_funcs,
680
681 .output_init = mdfld_output_init,
682
683#ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
684 .backlight_init = mdfld_backlight_init,
685#endif
686
687 .save_regs = mdfld_save_registers,
688 .restore_regs = mdfld_restore_registers,
689 .power_down = mdfld_power_down,
690 .power_up = mdfld_power_up,
691};
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
new file mode 100644
index 000000000000..fc0df28a668c
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.c
@@ -0,0 +1,1024 @@
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#include "psb_drv.h"
32#include "tc35876x-dsi-lvds.h"
33
34static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output,
35 int pipe);
36
37static void mdfld_wait_for_HS_DATA_FIFO(struct drm_device *dev, u32 pipe)
38{
39 u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
40 int timeout = 0;
41
42 udelay(500);
43
44 /* This will time out after approximately 2+ seconds */
45 while ((timeout < 20000) &&
46 (REG_READ(gen_fifo_stat_reg) & DSI_FIFO_GEN_HS_DATA_FULL)) {
47 udelay(100);
48 timeout++;
49 }
50
51 if (timeout == 20000)
52 DRM_INFO("MIPI: HS Data FIFO was never cleared!\n");
53}
54
55static void mdfld_wait_for_HS_CTRL_FIFO(struct drm_device *dev, u32 pipe)
56{
57 u32 gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
58 int timeout = 0;
59
60 udelay(500);
61
62 /* This will time out after approximately 2+ seconds */
63 while ((timeout < 20000) && (REG_READ(gen_fifo_stat_reg)
64 & DSI_FIFO_GEN_HS_CTRL_FULL)) {
65 udelay(100);
66 timeout++;
67 }
68 if (timeout == 20000)
69 DRM_INFO("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 = MIPI_GEN_FIFO_STAT_REG(pipe);
75 int timeout = 0;
76
77 udelay(500);
78
79 /* This will time out after approximately 2+ seconds */
80 while ((timeout < 20000) && ((REG_READ(gen_fifo_stat_reg) &
81 DPI_FIFO_EMPTY) != DPI_FIFO_EMPTY)) {
82 udelay(100);
83 timeout++;
84 }
85
86 if (timeout == 20000)
87 DRM_ERROR("MIPI: DPI FIFO was never cleared\n");
88}
89
90static void mdfld_wait_for_SPL_PKG_SENT(struct drm_device *dev, u32 pipe)
91{
92 u32 intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
93 int timeout = 0;
94
95 udelay(500);
96
97 /* This will time out after approximately 2+ seconds */
98 while ((timeout < 20000) && (!(REG_READ(intr_stat_reg)
99 & DSI_INTR_STATE_SPL_PKG_SENT))) {
100 udelay(100);
101 timeout++;
102 }
103
104 if (timeout == 20000)
105 DRM_ERROR("MIPI: SPL_PKT_SENT_INTERRUPT was not sent successfully!\n");
106}
107
108/* For TC35876X */
109
110static void dsi_set_device_ready_state(struct drm_device *dev, int state,
111 int pipe)
112{
113 REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), !!state, 0, 0);
114}
115
116static void dsi_set_pipe_plane_enable_state(struct drm_device *dev,
117 int state, int pipe)
118{
119 struct drm_psb_private *dev_priv = dev->dev_private;
120 u32 pipeconf_reg = PIPEACONF;
121 u32 dspcntr_reg = DSPACNTR;
122
123 u32 dspcntr = dev_priv->dspcntr[pipe];
124 u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
125
126 if (pipe) {
127 pipeconf_reg = PIPECCONF;
128 dspcntr_reg = DSPCCNTR;
129 } else
130 mipi &= (~0x03);
131
132 if (state) {
133 /*Set up pipe */
134 REG_WRITE(pipeconf_reg, BIT(31));
135
136 if (REG_BIT_WAIT(pipeconf_reg, 1, 30))
137 dev_err(&dev->pdev->dev, "%s: Pipe enable timeout\n",
138 __func__);
139
140 /*Set up display plane */
141 REG_WRITE(dspcntr_reg, dspcntr);
142 } else {
143 u32 dspbase_reg = pipe ? MDFLD_DSPCBASE : MRST_DSPABASE;
144
145 /* Put DSI lanes to ULPS to disable pipe */
146 REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 2, 2, 1);
147 REG_READ(MIPI_DEVICE_READY_REG(pipe)); /* posted write? */
148
149 /* LP Hold */
150 REG_FLD_MOD(MIPI_PORT_CONTROL(pipe), 0, 16, 16);
151 REG_READ(MIPI_PORT_CONTROL(pipe)); /* posted write? */
152
153 /* Disable display plane */
154 REG_FLD_MOD(dspcntr_reg, 0, 31, 31);
155
156 /* Flush the plane changes ??? posted write? */
157 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
158 REG_READ(dspbase_reg);
159
160 /* Disable PIPE */
161 REG_FLD_MOD(pipeconf_reg, 0, 31, 31);
162
163 if (REG_BIT_WAIT(pipeconf_reg, 0, 30))
164 dev_err(&dev->pdev->dev, "%s: Pipe disable timeout\n",
165 __func__);
166
167 if (REG_BIT_WAIT(MIPI_GEN_FIFO_STAT_REG(pipe), 1, 28))
168 dev_err(&dev->pdev->dev, "%s: FIFO not empty\n",
169 __func__);
170 }
171}
172
173static void mdfld_dsi_configure_down(struct mdfld_dsi_encoder *dsi_encoder,
174 int pipe)
175{
176 struct mdfld_dsi_dpi_output *dpi_output =
177 MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
178 struct mdfld_dsi_config *dsi_config =
179 mdfld_dsi_encoder_get_config(dsi_encoder);
180 struct drm_device *dev = dsi_config->dev;
181 struct drm_psb_private *dev_priv = dev->dev_private;
182
183 if (!dev_priv->dpi_panel_on[pipe]) {
184 dev_err(dev->dev, "DPI panel is already off\n");
185 return;
186 }
187 tc35876x_toshiba_bridge_panel_off(dev);
188 tc35876x_set_bridge_reset_state(dev, 1);
189 dsi_set_pipe_plane_enable_state(dev, 0, pipe);
190 mdfld_dsi_dpi_shut_down(dpi_output, pipe);
191 dsi_set_device_ready_state(dev, 0, pipe);
192}
193
194static void mdfld_dsi_configure_up(struct mdfld_dsi_encoder *dsi_encoder,
195 int pipe)
196{
197 struct mdfld_dsi_dpi_output *dpi_output =
198 MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
199 struct mdfld_dsi_config *dsi_config =
200 mdfld_dsi_encoder_get_config(dsi_encoder);
201 struct drm_device *dev = dsi_config->dev;
202 struct drm_psb_private *dev_priv = dev->dev_private;
203
204 if (dev_priv->dpi_panel_on[pipe]) {
205 dev_err(dev->dev, "DPI panel is already on\n");
206 return;
207 }
208
209 /* For resume path sequence */
210 mdfld_dsi_dpi_shut_down(dpi_output, pipe);
211 dsi_set_device_ready_state(dev, 0, pipe);
212
213 dsi_set_device_ready_state(dev, 1, pipe);
214 tc35876x_set_bridge_reset_state(dev, 0);
215 tc35876x_configure_lvds_bridge(dev);
216 mdfld_dsi_dpi_turn_on(dpi_output, pipe); /* Send turn on command */
217 dsi_set_pipe_plane_enable_state(dev, 1, pipe);
218}
219/* End for TC35876X */
220
221/* ************************************************************************* *\
222 * FUNCTION: mdfld_dsi_tpo_ic_init
223 *
224 * DESCRIPTION: This function is called only by mrst_dsi_mode_set and
225 * restore_display_registers. since this function does not
226 * acquire the mutex, it is important that the calling function
227 * does!
228\* ************************************************************************* */
229static void mdfld_dsi_tpo_ic_init(struct mdfld_dsi_config *dsi_config, u32 pipe)
230{
231 struct drm_device *dev = dsi_config->dev;
232 u32 dcsChannelNumber = dsi_config->channel_num;
233 u32 gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
234 u32 gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
235 u32 gen_ctrl_val = GEN_LONG_WRITE;
236
237 DRM_INFO("Enter mrst init TPO MIPI display.\n");
238
239 gen_ctrl_val |= dcsChannelNumber << DCS_CHANNEL_NUMBER_POS;
240
241 /* Flip page order */
242 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
243 REG_WRITE(gen_data_reg, 0x00008036);
244 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
245 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
246
247 /* 0xF0 */
248 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
249 REG_WRITE(gen_data_reg, 0x005a5af0);
250 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
251 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
252
253 /* Write protection key */
254 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
255 REG_WRITE(gen_data_reg, 0x005a5af1);
256 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
257 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
258
259 /* 0xFC */
260 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
261 REG_WRITE(gen_data_reg, 0x005a5afc);
262 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
263 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
264
265 /* 0xB7 */
266 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
267 REG_WRITE(gen_data_reg, 0x770000b7);
268 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
269 REG_WRITE(gen_data_reg, 0x00000044);
270 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
271 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x05 << WORD_COUNTS_POS));
272
273 /* 0xB6 */
274 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
275 REG_WRITE(gen_data_reg, 0x000a0ab6);
276 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
277 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
278
279 /* 0xF2 */
280 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
281 REG_WRITE(gen_data_reg, 0x081010f2);
282 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
283 REG_WRITE(gen_data_reg, 0x4a070708);
284 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
285 REG_WRITE(gen_data_reg, 0x000000c5);
286 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
287 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
288
289 /* 0xF8 */
290 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
291 REG_WRITE(gen_data_reg, 0x024003f8);
292 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
293 REG_WRITE(gen_data_reg, 0x01030a04);
294 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
295 REG_WRITE(gen_data_reg, 0x0e020220);
296 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
297 REG_WRITE(gen_data_reg, 0x00000004);
298 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
299 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x0d << WORD_COUNTS_POS));
300
301 /* 0xE2 */
302 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
303 REG_WRITE(gen_data_reg, 0x398fc3e2);
304 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
305 REG_WRITE(gen_data_reg, 0x0000916f);
306 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
307 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x06 << WORD_COUNTS_POS));
308
309 /* 0xB0 */
310 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
311 REG_WRITE(gen_data_reg, 0x000000b0);
312 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
313 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x02 << WORD_COUNTS_POS));
314
315 /* 0xF4 */
316 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
317 REG_WRITE(gen_data_reg, 0x240242f4);
318 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
319 REG_WRITE(gen_data_reg, 0x78ee2002);
320 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
321 REG_WRITE(gen_data_reg, 0x2a071050);
322 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
323 REG_WRITE(gen_data_reg, 0x507fee10);
324 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
325 REG_WRITE(gen_data_reg, 0x10300710);
326 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
327 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x14 << WORD_COUNTS_POS));
328
329 /* 0xBA */
330 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
331 REG_WRITE(gen_data_reg, 0x19fe07ba);
332 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
333 REG_WRITE(gen_data_reg, 0x101c0a31);
334 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
335 REG_WRITE(gen_data_reg, 0x00000010);
336 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
337 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
338
339 /* 0xBB */
340 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
341 REG_WRITE(gen_data_reg, 0x28ff07bb);
342 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
343 REG_WRITE(gen_data_reg, 0x24280a31);
344 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
345 REG_WRITE(gen_data_reg, 0x00000034);
346 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
347 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x09 << WORD_COUNTS_POS));
348
349 /* 0xFB */
350 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
351 REG_WRITE(gen_data_reg, 0x535d05fb);
352 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
353 REG_WRITE(gen_data_reg, 0x1b1a2130);
354 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
355 REG_WRITE(gen_data_reg, 0x221e180e);
356 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
357 REG_WRITE(gen_data_reg, 0x131d2120);
358 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
359 REG_WRITE(gen_data_reg, 0x535d0508);
360 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
361 REG_WRITE(gen_data_reg, 0x1c1a2131);
362 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
363 REG_WRITE(gen_data_reg, 0x231f160d);
364 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
365 REG_WRITE(gen_data_reg, 0x111b2220);
366 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
367 REG_WRITE(gen_data_reg, 0x535c2008);
368 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
369 REG_WRITE(gen_data_reg, 0x1f1d2433);
370 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
371 REG_WRITE(gen_data_reg, 0x2c251a10);
372 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
373 REG_WRITE(gen_data_reg, 0x2c34372d);
374 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
375 REG_WRITE(gen_data_reg, 0x00000023);
376 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
377 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
378
379 /* 0xFA */
380 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
381 REG_WRITE(gen_data_reg, 0x525c0bfa);
382 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
383 REG_WRITE(gen_data_reg, 0x1c1c232f);
384 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
385 REG_WRITE(gen_data_reg, 0x2623190e);
386 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
387 REG_WRITE(gen_data_reg, 0x18212625);
388 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
389 REG_WRITE(gen_data_reg, 0x545d0d0e);
390 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
391 REG_WRITE(gen_data_reg, 0x1e1d2333);
392 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
393 REG_WRITE(gen_data_reg, 0x26231a10);
394 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
395 REG_WRITE(gen_data_reg, 0x1a222725);
396 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
397 REG_WRITE(gen_data_reg, 0x545d280f);
398 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
399 REG_WRITE(gen_data_reg, 0x21202635);
400 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
401 REG_WRITE(gen_data_reg, 0x31292013);
402 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
403 REG_WRITE(gen_data_reg, 0x31393d33);
404 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
405 REG_WRITE(gen_data_reg, 0x00000029);
406 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
407 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x31 << WORD_COUNTS_POS));
408
409 /* Set DM */
410 mdfld_wait_for_HS_DATA_FIFO(dev, pipe);
411 REG_WRITE(gen_data_reg, 0x000100f7);
412 mdfld_wait_for_HS_CTRL_FIFO(dev, pipe);
413 REG_WRITE(gen_ctrl_reg, gen_ctrl_val | (0x03 << WORD_COUNTS_POS));
414}
415
416static u16 mdfld_dsi_dpi_to_byte_clock_count(int pixel_clock_count,
417 int num_lane, int bpp)
418{
419 return (u16)((pixel_clock_count * bpp) / (num_lane * 8));
420}
421
422/*
423 * Calculate the dpi time basing on a given drm mode @mode
424 * return 0 on success.
425 * FIXME: I was using proposed mode value for calculation, may need to
426 * use crtc mode values later
427 */
428int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
429 struct mdfld_dsi_dpi_timing *dpi_timing,
430 int num_lane, int bpp)
431{
432 int pclk_hsync, pclk_hfp, pclk_hbp, pclk_hactive;
433 int pclk_vsync, pclk_vfp, pclk_vbp, pclk_vactive;
434
435 pclk_hactive = mode->hdisplay;
436 pclk_hfp = mode->hsync_start - mode->hdisplay;
437 pclk_hsync = mode->hsync_end - mode->hsync_start;
438 pclk_hbp = mode->htotal - mode->hsync_end;
439
440 pclk_vactive = mode->vdisplay;
441 pclk_vfp = mode->vsync_start - mode->vdisplay;
442 pclk_vsync = mode->vsync_end - mode->vsync_start;
443 pclk_vbp = mode->vtotal - mode->vsync_end;
444
445 /*
446 * byte clock counts were calculated by following formula
447 * bclock_count = pclk_count * bpp / num_lane / 8
448 */
449 dpi_timing->hsync_count = mdfld_dsi_dpi_to_byte_clock_count(
450 pclk_hsync, num_lane, bpp);
451 dpi_timing->hbp_count = mdfld_dsi_dpi_to_byte_clock_count(
452 pclk_hbp, num_lane, bpp);
453 dpi_timing->hfp_count = mdfld_dsi_dpi_to_byte_clock_count(
454 pclk_hfp, num_lane, bpp);
455 dpi_timing->hactive_count = mdfld_dsi_dpi_to_byte_clock_count(
456 pclk_hactive, num_lane, bpp);
457 dpi_timing->vsync_count = mdfld_dsi_dpi_to_byte_clock_count(
458 pclk_vsync, num_lane, bpp);
459 dpi_timing->vbp_count = mdfld_dsi_dpi_to_byte_clock_count(
460 pclk_vbp, num_lane, bpp);
461 dpi_timing->vfp_count = mdfld_dsi_dpi_to_byte_clock_count(
462 pclk_vfp, num_lane, bpp);
463
464 return 0;
465}
466
467void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config,
468 int pipe)
469{
470 struct drm_device *dev = dsi_config->dev;
471 int lane_count = dsi_config->lane_count;
472 struct mdfld_dsi_dpi_timing dpi_timing;
473 struct drm_display_mode *mode = dsi_config->mode;
474 u32 val;
475
476 /*un-ready device*/
477 REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 0, 0, 0);
478
479 /*init dsi adapter before kicking off*/
480 REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
481
482 /*enable all interrupts*/
483 REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
484
485 /*set up func_prg*/
486 val = lane_count;
487 val |= dsi_config->channel_num << DSI_DPI_VIRT_CHANNEL_OFFSET;
488
489 switch (dsi_config->bpp) {
490 case 16:
491 val |= DSI_DPI_COLOR_FORMAT_RGB565;
492 break;
493 case 18:
494 val |= DSI_DPI_COLOR_FORMAT_RGB666;
495 break;
496 case 24:
497 val |= DSI_DPI_COLOR_FORMAT_RGB888;
498 break;
499 default:
500 DRM_ERROR("unsupported color format, bpp = %d\n",
501 dsi_config->bpp);
502 }
503 REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), val);
504
505 REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe),
506 (mode->vtotal * mode->htotal * dsi_config->bpp /
507 (8 * lane_count)) & DSI_HS_TX_TIMEOUT_MASK);
508 REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe),
509 0xffff & DSI_LP_RX_TIMEOUT_MASK);
510
511 /*max value: 20 clock cycles of txclkesc*/
512 REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe),
513 0x14 & DSI_TURN_AROUND_TIMEOUT_MASK);
514
515 /*min 21 txclkesc, max: ffffh*/
516 REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe),
517 0xffff & DSI_RESET_TIMER_MASK);
518
519 REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe),
520 mode->vdisplay << 16 | mode->hdisplay);
521
522 /*set DPI timing registers*/
523 mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing,
524 dsi_config->lane_count, dsi_config->bpp);
525
526 REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe),
527 dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
528 REG_WRITE(MIPI_HBP_COUNT_REG(pipe),
529 dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
530 REG_WRITE(MIPI_HFP_COUNT_REG(pipe),
531 dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
532 REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe),
533 dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
534 REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe),
535 dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
536 REG_WRITE(MIPI_VBP_COUNT_REG(pipe),
537 dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
538 REG_WRITE(MIPI_VFP_COUNT_REG(pipe),
539 dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
540
541 REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x46);
542
543 /*min: 7d0 max: 4e20*/
544 REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0x000007d0);
545
546 /*set up video mode*/
547 val = dsi_config->video_mode | DSI_DPI_COMPLETE_LAST_LINE;
548 REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), val);
549
550 REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
551
552 REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
553
554 /*TODO: figure out how to setup these registers*/
555 if (mdfld_get_panel_type(dev, pipe) == TC35876X)
556 REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008);
557 else
558 REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150c3408);
559
560 REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14);
561
562 if (mdfld_get_panel_type(dev, pipe) == TC35876X)
563 tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */
564
565 /*set device ready*/
566 REG_FLD_MOD(MIPI_DEVICE_READY_REG(pipe), 1, 0, 0);
567}
568
569void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output, int pipe)
570{
571 struct drm_device *dev = output->dev;
572
573 /* clear special packet sent bit */
574 if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
575 REG_WRITE(MIPI_INTR_STAT_REG(pipe),
576 DSI_INTR_STATE_SPL_PKG_SENT);
577
578 /*send turn on package*/
579 REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_TURN_ON);
580
581 /*wait for SPL_PKG_SENT interrupt*/
582 mdfld_wait_for_SPL_PKG_SENT(dev, pipe);
583
584 if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
585 REG_WRITE(MIPI_INTR_STAT_REG(pipe),
586 DSI_INTR_STATE_SPL_PKG_SENT);
587
588 output->panel_on = 1;
589
590 /* FIXME the following is disabled to WA the X slow start issue
591 for TMD panel
592 if (pipe == 2)
593 dev_priv->dpi_panel_on2 = true;
594 else if (pipe == 0)
595 dev_priv->dpi_panel_on = true; */
596}
597
598static void mdfld_dsi_dpi_shut_down(struct mdfld_dsi_dpi_output *output,
599 int pipe)
600{
601 struct drm_device *dev = output->dev;
602
603 /*if output is on, or mode setting didn't happen, ignore this*/
604 if ((!output->panel_on) || output->first_boot) {
605 output->first_boot = 0;
606 return;
607 }
608
609 /* Wait for dpi fifo to empty */
610 mdfld_wait_for_DPI_CTRL_FIFO(dev, pipe);
611
612 /* Clear the special packet interrupt bit if set */
613 if (REG_READ(MIPI_INTR_STAT_REG(pipe)) & DSI_INTR_STATE_SPL_PKG_SENT)
614 REG_WRITE(MIPI_INTR_STAT_REG(pipe),
615 DSI_INTR_STATE_SPL_PKG_SENT);
616
617 if (REG_READ(MIPI_DPI_CONTROL_REG(pipe)) == DSI_DPI_CTRL_HS_SHUTDOWN)
618 goto shutdown_out;
619
620 REG_WRITE(MIPI_DPI_CONTROL_REG(pipe), DSI_DPI_CTRL_HS_SHUTDOWN);
621
622shutdown_out:
623 output->panel_on = 0;
624 output->first_boot = 0;
625
626 /* FIXME the following is disabled to WA the X slow start issue
627 for TMD panel
628 if (pipe == 2)
629 dev_priv->dpi_panel_on2 = false;
630 else if (pipe == 0)
631 dev_priv->dpi_panel_on = false; */
632}
633
634static void mdfld_dsi_dpi_set_power(struct drm_encoder *encoder, bool on)
635{
636 struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder);
637 struct mdfld_dsi_dpi_output *dpi_output =
638 MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
639 struct mdfld_dsi_config *dsi_config =
640 mdfld_dsi_encoder_get_config(dsi_encoder);
641 int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
642 struct drm_device *dev = dsi_config->dev;
643 struct drm_psb_private *dev_priv = dev->dev_private;
644 u32 pipeconf_reg = PIPEACONF;
645
646 if (pipe)
647 pipeconf_reg = PIPECCONF;
648
649 /*start up display island if it was shutdown*/
650 if (!gma_power_begin(dev, true))
651 return;
652
653 if (on) {
654 if (mdfld_get_panel_type(dev, pipe) == TMD_VID)
655 mdfld_dsi_dpi_turn_on(dpi_output, pipe);
656 else if (mdfld_get_panel_type(dev, pipe) == TC35876X)
657 mdfld_dsi_configure_up(dsi_encoder, pipe);
658 else {
659 /*enable mipi port*/
660 REG_WRITE(MIPI_PORT_CONTROL(pipe),
661 REG_READ(MIPI_PORT_CONTROL(pipe)) | BIT(31));
662 REG_READ(MIPI_PORT_CONTROL(pipe));
663
664 mdfld_dsi_dpi_turn_on(dpi_output, pipe);
665 mdfld_dsi_tpo_ic_init(dsi_config, pipe);
666 }
667 dev_priv->dpi_panel_on[pipe] = true;
668 } else {
669 if (mdfld_get_panel_type(dev, pipe) == TMD_VID)
670 mdfld_dsi_dpi_shut_down(dpi_output, pipe);
671 else if (mdfld_get_panel_type(dev, pipe) == TC35876X)
672 mdfld_dsi_configure_down(dsi_encoder, pipe);
673 else {
674 mdfld_dsi_dpi_shut_down(dpi_output, pipe);
675
676 /*disable mipi port*/
677 REG_WRITE(MIPI_PORT_CONTROL(pipe),
678 REG_READ(MIPI_PORT_CONTROL(pipe)) & ~BIT(31));
679 REG_READ(MIPI_PORT_CONTROL(pipe));
680 }
681 dev_priv->dpi_panel_on[pipe] = false;
682 }
683 gma_power_end(dev);
684}
685
686void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode)
687{
688 mdfld_dsi_dpi_set_power(encoder, mode == DRM_MODE_DPMS_ON);
689}
690
691bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
692 struct drm_display_mode *mode,
693 struct drm_display_mode *adjusted_mode)
694{
695 struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder);
696 struct mdfld_dsi_config *dsi_config =
697 mdfld_dsi_encoder_get_config(dsi_encoder);
698 struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
699
700 if (fixed_mode) {
701 adjusted_mode->hdisplay = fixed_mode->hdisplay;
702 adjusted_mode->hsync_start = fixed_mode->hsync_start;
703 adjusted_mode->hsync_end = fixed_mode->hsync_end;
704 adjusted_mode->htotal = fixed_mode->htotal;
705 adjusted_mode->vdisplay = fixed_mode->vdisplay;
706 adjusted_mode->vsync_start = fixed_mode->vsync_start;
707 adjusted_mode->vsync_end = fixed_mode->vsync_end;
708 adjusted_mode->vtotal = fixed_mode->vtotal;
709 adjusted_mode->clock = fixed_mode->clock;
710 drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
711 }
712 return true;
713}
714
715void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder)
716{
717 mdfld_dsi_dpi_set_power(encoder, false);
718}
719
720void mdfld_dsi_dpi_commit(struct drm_encoder *encoder)
721{
722 mdfld_dsi_dpi_set_power(encoder, true);
723}
724
725/* For TC35876X */
726/* This functionality was implemented in FW in iCDK */
727/* But removed in DV0 and later. So need to add here. */
728static void mipi_set_properties(struct mdfld_dsi_config *dsi_config, int pipe)
729{
730 struct drm_device *dev = dsi_config->dev;
731
732 REG_WRITE(MIPI_CTRL_REG(pipe), 0x00000018);
733 REG_WRITE(MIPI_INTR_EN_REG(pipe), 0xffffffff);
734 REG_WRITE(MIPI_HS_TX_TIMEOUT_REG(pipe), 0xffffff);
735 REG_WRITE(MIPI_LP_RX_TIMEOUT_REG(pipe), 0xffffff);
736 REG_WRITE(MIPI_TURN_AROUND_TIMEOUT_REG(pipe), 0x14);
737 REG_WRITE(MIPI_DEVICE_RESET_TIMER_REG(pipe), 0xff);
738 REG_WRITE(MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe), 0x25);
739 REG_WRITE(MIPI_INIT_COUNT_REG(pipe), 0xf0);
740 REG_WRITE(MIPI_EOT_DISABLE_REG(pipe), 0x00000000);
741 REG_WRITE(MIPI_LP_BYTECLK_REG(pipe), 0x00000004);
742 REG_WRITE(MIPI_DBI_BW_CTRL_REG(pipe), 0x00000820);
743 REG_WRITE(MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe), (0xa << 16) | 0x14);
744}
745
746static void mdfld_mipi_set_video_timing(struct mdfld_dsi_config *dsi_config,
747 int pipe)
748{
749 struct drm_device *dev = dsi_config->dev;
750 struct mdfld_dsi_dpi_timing dpi_timing;
751 struct drm_display_mode *mode = dsi_config->mode;
752
753 mdfld_dsi_dpi_timing_calculation(mode, &dpi_timing,
754 dsi_config->lane_count,
755 dsi_config->bpp);
756
757 REG_WRITE(MIPI_DPI_RESOLUTION_REG(pipe),
758 mode->vdisplay << 16 | mode->hdisplay);
759 REG_WRITE(MIPI_HSYNC_COUNT_REG(pipe),
760 dpi_timing.hsync_count & DSI_DPI_TIMING_MASK);
761 REG_WRITE(MIPI_HBP_COUNT_REG(pipe),
762 dpi_timing.hbp_count & DSI_DPI_TIMING_MASK);
763 REG_WRITE(MIPI_HFP_COUNT_REG(pipe),
764 dpi_timing.hfp_count & DSI_DPI_TIMING_MASK);
765 REG_WRITE(MIPI_HACTIVE_COUNT_REG(pipe),
766 dpi_timing.hactive_count & DSI_DPI_TIMING_MASK);
767 REG_WRITE(MIPI_VSYNC_COUNT_REG(pipe),
768 dpi_timing.vsync_count & DSI_DPI_TIMING_MASK);
769 REG_WRITE(MIPI_VBP_COUNT_REG(pipe),
770 dpi_timing.vbp_count & DSI_DPI_TIMING_MASK);
771 REG_WRITE(MIPI_VFP_COUNT_REG(pipe),
772 dpi_timing.vfp_count & DSI_DPI_TIMING_MASK);
773}
774
775static void mdfld_mipi_config(struct mdfld_dsi_config *dsi_config, int pipe)
776{
777 struct drm_device *dev = dsi_config->dev;
778 int lane_count = dsi_config->lane_count;
779
780 if (pipe) {
781 REG_WRITE(MIPI_PORT_CONTROL(0), 0x00000002);
782 REG_WRITE(MIPI_PORT_CONTROL(2), 0x80000000);
783 } else {
784 REG_WRITE(MIPI_PORT_CONTROL(0), 0x80010000);
785 REG_WRITE(MIPI_PORT_CONTROL(2), 0x00);
786 }
787
788 REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x150A600F);
789 REG_WRITE(MIPI_VIDEO_MODE_FORMAT_REG(pipe), 0x0000000F);
790
791 /* lane_count = 3 */
792 REG_WRITE(MIPI_DSI_FUNC_PRG_REG(pipe), 0x00000200 | lane_count);
793
794 mdfld_mipi_set_video_timing(dsi_config, pipe);
795}
796
797static void mdfld_set_pipe_timing(struct mdfld_dsi_config *dsi_config, int pipe)
798{
799 struct drm_device *dev = dsi_config->dev;
800 struct drm_display_mode *mode = dsi_config->mode;
801
802 REG_WRITE(HTOTAL_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
803 REG_WRITE(HBLANK_A, ((mode->htotal - 1) << 16) | (mode->hdisplay - 1));
804 REG_WRITE(HSYNC_A,
805 ((mode->hsync_end - 1) << 16) | (mode->hsync_start - 1));
806
807 REG_WRITE(VTOTAL_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
808 REG_WRITE(VBLANK_A, ((mode->vtotal - 1) << 16) | (mode->vdisplay - 1));
809 REG_WRITE(VSYNC_A,
810 ((mode->vsync_end - 1) << 16) | (mode->vsync_start - 1));
811
812 REG_WRITE(PIPEASRC,
813 ((mode->hdisplay - 1) << 16) | (mode->vdisplay - 1));
814}
815/* End for TC35876X */
816
817void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
818 struct drm_display_mode *mode,
819 struct drm_display_mode *adjusted_mode)
820{
821 struct mdfld_dsi_encoder *dsi_encoder = mdfld_dsi_encoder(encoder);
822 struct mdfld_dsi_dpi_output *dpi_output =
823 MDFLD_DSI_DPI_OUTPUT(dsi_encoder);
824 struct mdfld_dsi_config *dsi_config =
825 mdfld_dsi_encoder_get_config(dsi_encoder);
826 struct drm_device *dev = dsi_config->dev;
827 struct drm_psb_private *dev_priv = dev->dev_private;
828 int pipe = mdfld_dsi_encoder_get_pipe(dsi_encoder);
829
830 u32 pipeconf_reg = PIPEACONF;
831 u32 dspcntr_reg = DSPACNTR;
832
833 u32 pipeconf = dev_priv->pipeconf[pipe];
834 u32 dspcntr = dev_priv->dspcntr[pipe];
835 u32 mipi = MIPI_PORT_EN | PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
836
837 if (pipe) {
838 pipeconf_reg = PIPECCONF;
839 dspcntr_reg = DSPCCNTR;
840 } else {
841 if (mdfld_get_panel_type(dev, pipe) == TC35876X)
842 mipi &= (~0x03); /* Use all four lanes */
843 else
844 mipi |= 2;
845 }
846
847 /*start up display island if it was shutdown*/
848 if (!gma_power_begin(dev, true))
849 return;
850
851 if (mdfld_get_panel_type(dev, pipe) == TC35876X) {
852 /*
853 * The following logic is required to reset the bridge and
854 * configure. This also starts the DSI clock at 200MHz.
855 */
856 tc35876x_set_bridge_reset_state(dev, 0); /*Pull High Reset */
857 tc35876x_toshiba_bridge_panel_on(dev);
858 udelay(100);
859 /* Now start the DSI clock */
860 REG_WRITE(MRST_DPLL_A, 0x00);
861 REG_WRITE(MRST_FPA0, 0xC1);
862 REG_WRITE(MRST_DPLL_A, 0x00800000);
863 udelay(500);
864 REG_WRITE(MRST_DPLL_A, 0x80800000);
865
866 if (REG_BIT_WAIT(pipeconf_reg, 1, 29))
867 dev_err(&dev->pdev->dev, "%s: DSI PLL lock timeout\n",
868 __func__);
869
870 REG_WRITE(MIPI_DPHY_PARAM_REG(pipe), 0x2A0c6008);
871
872 mipi_set_properties(dsi_config, pipe);
873 mdfld_mipi_config(dsi_config, pipe);
874 mdfld_set_pipe_timing(dsi_config, pipe);
875
876 REG_WRITE(DSPABASE, 0x00);
877 REG_WRITE(DSPASTRIDE, (mode->hdisplay * 4));
878 REG_WRITE(DSPASIZE,
879 ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
880
881 REG_WRITE(DSPACNTR, 0x98000000);
882 REG_WRITE(DSPASURF, 0x00);
883
884 REG_WRITE(VGACNTRL, 0x80000000);
885 REG_WRITE(DEVICE_READY_REG, 0x00000001);
886
887 REG_WRITE(MIPI_PORT_CONTROL(pipe), 0x80810000);
888 } else {
889 /*set up mipi port FIXME: do at init time */
890 REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi);
891 }
892 REG_READ(MIPI_PORT_CONTROL(pipe));
893
894 if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
895 /* NOP */
896 } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) {
897 /* set up DSI controller DPI interface */
898 mdfld_dsi_dpi_controller_init(dsi_config, pipe);
899
900 /* Configure MIPI Bridge and Panel */
901 tc35876x_configure_lvds_bridge(dev);
902 dev_priv->dpi_panel_on[pipe] = true;
903 } else {
904 /*turn on DPI interface*/
905 mdfld_dsi_dpi_turn_on(dpi_output, pipe);
906 }
907
908 /*set up pipe*/
909 REG_WRITE(pipeconf_reg, pipeconf);
910 REG_READ(pipeconf_reg);
911
912 /*set up display plane*/
913 REG_WRITE(dspcntr_reg, dspcntr);
914 REG_READ(dspcntr_reg);
915
916 msleep(20); /* FIXME: this should wait for vblank */
917
918 if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
919 /* NOP */
920 } else if (mdfld_get_panel_type(dev, pipe) == TC35876X) {
921 mdfld_dsi_dpi_turn_on(dpi_output, pipe);
922 } else {
923 /* init driver ic */
924 mdfld_dsi_tpo_ic_init(dsi_config, pipe);
925 /*init backlight*/
926 mdfld_dsi_brightness_init(dsi_config, pipe);
927 }
928
929 gma_power_end(dev);
930}
931
932/*
933 * Init DSI DPI encoder.
934 * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
935 * return pointer of newly allocated DPI encoder, NULL on error
936 */
937struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
938 struct mdfld_dsi_connector *dsi_connector,
939 const struct panel_funcs *p_funcs)
940{
941 struct mdfld_dsi_dpi_output *dpi_output = NULL;
942 struct mdfld_dsi_config *dsi_config;
943 struct drm_connector *connector = NULL;
944 struct drm_encoder *encoder = NULL;
945 struct drm_display_mode *fixed_mode = NULL;
946 int pipe;
947 u32 data;
948 int ret;
949
950 pipe = dsi_connector->pipe;
951
952 if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
953 dsi_config = mdfld_dsi_get_config(dsi_connector);
954
955 /* panel hard-reset */
956 if (p_funcs->reset) {
957 ret = p_funcs->reset(pipe);
958 if (ret) {
959 DRM_ERROR("Panel %d hard-reset failed\n", pipe);
960 return NULL;
961 }
962 }
963
964 /* panel drvIC init */
965 if (p_funcs->drv_ic_init)
966 p_funcs->drv_ic_init(dsi_config, pipe);
967
968 /* panel power mode detect */
969 ret = mdfld_dsi_get_power_mode(dsi_config, &data, false);
970 if (ret) {
971 DRM_ERROR("Panel %d get power mode failed\n", pipe);
972 dsi_connector->status = connector_status_disconnected;
973 } else {
974 DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
975 dsi_connector->status = connector_status_connected;
976 }
977 }
978
979 dpi_output = kzalloc(sizeof(struct mdfld_dsi_dpi_output), GFP_KERNEL);
980 if (!dpi_output) {
981 DRM_ERROR("No memory\n");
982 return NULL;
983 }
984
985 if (dsi_connector->pipe)
986 dpi_output->panel_on = 0;
987 else
988 dpi_output->panel_on = 0;
989
990 dpi_output->dev = dev;
991 if (mdfld_get_panel_type(dev, pipe) != TC35876X)
992 dpi_output->p_funcs = p_funcs;
993 dpi_output->first_boot = 1;
994
995 /*get fixed mode*/
996 dsi_config = mdfld_dsi_get_config(dsi_connector);
997 fixed_mode = dsi_config->fixed_mode;
998
999 /*create drm encoder object*/
1000 connector = &dsi_connector->base.base;
1001 encoder = &dpi_output->base.base.base;
1002 drm_encoder_init(dev,
1003 encoder,
1004 p_funcs->encoder_funcs,
1005 DRM_MODE_ENCODER_LVDS);
1006 drm_encoder_helper_add(encoder,
1007 p_funcs->encoder_helper_funcs);
1008
1009 /*attach to given connector*/
1010 drm_mode_connector_attach_encoder(connector, encoder);
1011
1012 /*set possible crtcs and clones*/
1013 if (dsi_connector->pipe) {
1014 encoder->possible_crtcs = (1 << 2);
1015 encoder->possible_clones = (1 << 1);
1016 } else {
1017 encoder->possible_crtcs = (1 << 0);
1018 encoder->possible_clones = (1 << 0);
1019 }
1020
1021 dsi_connector->base.encoder = &dpi_output->base.base;
1022
1023 return &dpi_output->base;
1024}
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h
new file mode 100644
index 000000000000..6f762478b959
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_dpi.h
@@ -0,0 +1,79 @@
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 const struct panel_funcs *p_funcs;
52};
53
54#define MDFLD_DSI_DPI_OUTPUT(dsi_encoder)\
55 container_of(dsi_encoder, struct mdfld_dsi_dpi_output, base)
56
57/* Export functions */
58extern int mdfld_dsi_dpi_timing_calculation(struct drm_display_mode *mode,
59 struct mdfld_dsi_dpi_timing *dpi_timing,
60 int num_lane, int bpp);
61extern struct mdfld_dsi_encoder *mdfld_dsi_dpi_init(struct drm_device *dev,
62 struct mdfld_dsi_connector *dsi_connector,
63 const struct panel_funcs *p_funcs);
64
65/* MDFLD DPI helper functions */
66extern void mdfld_dsi_dpi_dpms(struct drm_encoder *encoder, int mode);
67extern bool mdfld_dsi_dpi_mode_fixup(struct drm_encoder *encoder,
68 struct drm_display_mode *mode,
69 struct drm_display_mode *adjusted_mode);
70extern void mdfld_dsi_dpi_prepare(struct drm_encoder *encoder);
71extern void mdfld_dsi_dpi_commit(struct drm_encoder *encoder);
72extern void mdfld_dsi_dpi_mode_set(struct drm_encoder *encoder,
73 struct drm_display_mode *mode,
74 struct drm_display_mode *adjusted_mode);
75extern void mdfld_dsi_dpi_turn_on(struct mdfld_dsi_dpi_output *output,
76 int pipe);
77extern void mdfld_dsi_dpi_controller_init(struct mdfld_dsi_config *dsi_config,
78 int pipe);
79#endif /*__MDFLD_DSI_DPI_H__*/
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.c b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
new file mode 100644
index 000000000000..9338c28f3999
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.c
@@ -0,0 +1,635 @@
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 <linux/module.h>
29
30#include "mdfld_dsi_output.h"
31#include "mdfld_dsi_dpi.h"
32#include "mdfld_output.h"
33#include "mdfld_dsi_pkg_sender.h"
34#include "tc35876x-dsi-lvds.h"
35#include <linux/pm_runtime.h>
36#include <asm/intel_scu_ipc.h>
37
38/* get the LABC from command line. */
39static int LABC_control = 1;
40
41#ifdef MODULE
42module_param(LABC_control, int, 0644);
43#else
44
45static int __init parse_LABC_control(char *arg)
46{
47 /* LABC control can be passed in as a cmdline parameter */
48 /* to enable this feature add LABC=1 to cmdline */
49 /* to disable this feature add LABC=0 to cmdline */
50 if (!arg)
51 return -EINVAL;
52
53 if (!strcasecmp(arg, "0"))
54 LABC_control = 0;
55 else if (!strcasecmp(arg, "1"))
56 LABC_control = 1;
57
58 return 0;
59}
60early_param("LABC", parse_LABC_control);
61#endif
62
63/**
64 * Check and see if the generic control or data buffer is empty and ready.
65 */
66void mdfld_dsi_gen_fifo_ready(struct drm_device *dev, u32 gen_fifo_stat_reg,
67 u32 fifo_stat)
68{
69 u32 GEN_BF_time_out_count;
70
71 /* Check MIPI Adatper command registers */
72 for (GEN_BF_time_out_count = 0;
73 GEN_BF_time_out_count < GEN_FB_TIME_OUT;
74 GEN_BF_time_out_count++) {
75 if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
76 break;
77 udelay(100);
78 }
79
80 if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
81 DRM_ERROR("mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x.\n",
82 gen_fifo_stat_reg);
83}
84
85/**
86 * Manage the DSI MIPI keyboard and display brightness.
87 * FIXME: this is exported to OSPM code. should work out an specific
88 * display interface to OSPM.
89 */
90
91void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
92{
93 struct mdfld_dsi_pkg_sender *sender =
94 mdfld_dsi_get_pkg_sender(dsi_config);
95 struct drm_device *dev = sender->dev;
96 struct drm_psb_private *dev_priv = dev->dev_private;
97 u32 gen_ctrl_val;
98
99 if (!sender) {
100 DRM_ERROR("No sender found\n");
101 return;
102 }
103
104 /* Set default display backlight value to 85% (0xd8)*/
105 mdfld_dsi_send_mcs_short(sender, write_display_brightness, 0xd8, 1,
106 true);
107
108 /* Set minimum brightness setting of CABC function to 20% (0x33)*/
109 mdfld_dsi_send_mcs_short(sender, write_cabc_min_bright, 0x33, 1, true);
110
111 /* Enable backlight or/and LABC */
112 gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON |
113 BACKLIGHT_ON;
114 if (LABC_control == 1)
115 gen_ctrl_val |= DISPLAY_DIMMING_ON | DISPLAY_BRIGHTNESS_AUTO
116 | GAMMA_AUTO;
117
118 if (LABC_control == 1)
119 gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
120
121 dev_priv->mipi_ctrl_display = gen_ctrl_val;
122
123 mdfld_dsi_send_mcs_short(sender, write_ctrl_display, (u8)gen_ctrl_val,
124 1, true);
125
126 mdfld_dsi_send_mcs_short(sender, write_ctrl_cabc, UI_IMAGE, 1, true);
127}
128
129void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
130{
131 struct mdfld_dsi_pkg_sender *sender;
132 struct drm_psb_private *dev_priv;
133 struct mdfld_dsi_config *dsi_config;
134 u32 gen_ctrl_val = 0;
135 int p_type = TMD_VID;
136
137 if (!dev || (pipe != 0 && pipe != 2)) {
138 DRM_ERROR("Invalid parameter\n");
139 return;
140 }
141
142 p_type = mdfld_get_panel_type(dev, 0);
143
144 dev_priv = dev->dev_private;
145
146 if (pipe)
147 dsi_config = dev_priv->dsi_configs[1];
148 else
149 dsi_config = dev_priv->dsi_configs[0];
150
151 sender = mdfld_dsi_get_pkg_sender(dsi_config);
152
153 if (!sender) {
154 DRM_ERROR("No sender found\n");
155 return;
156 }
157
158 gen_ctrl_val = (level * 0xff / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
159
160 dev_dbg(sender->dev->dev, "pipe = %d, gen_ctrl_val = %d.\n",
161 pipe, gen_ctrl_val);
162
163 if (p_type == TMD_VID) {
164 /* Set display backlight value */
165 mdfld_dsi_send_mcs_short(sender, tmd_write_display_brightness,
166 (u8)gen_ctrl_val, 1, true);
167 } else {
168 /* Set display backlight value */
169 mdfld_dsi_send_mcs_short(sender, write_display_brightness,
170 (u8)gen_ctrl_val, 1, true);
171
172 /* Enable backlight control */
173 if (level == 0)
174 gen_ctrl_val = 0;
175 else
176 gen_ctrl_val = dev_priv->mipi_ctrl_display;
177
178 mdfld_dsi_send_mcs_short(sender, write_ctrl_display,
179 (u8)gen_ctrl_val, 1, true);
180 }
181}
182
183static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
184 u8 dcs, u32 *data, bool hs)
185{
186 struct mdfld_dsi_pkg_sender *sender
187 = mdfld_dsi_get_pkg_sender(dsi_config);
188
189 if (!sender || !data) {
190 DRM_ERROR("Invalid parameter\n");
191 return -EINVAL;
192 }
193
194 return mdfld_dsi_read_mcs(sender, dcs, data, 1, hs);
195}
196
197int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config, u32 *mode,
198 bool hs)
199{
200 if (!dsi_config || !mode) {
201 DRM_ERROR("Invalid parameter\n");
202 return -EINVAL;
203 }
204
205 return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, hs);
206}
207
208int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
209 u32 *result, bool hs)
210{
211 if (!dsi_config || !result) {
212 DRM_ERROR("Invalid parameter\n");
213 return -EINVAL;
214 }
215
216 return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result, hs);
217}
218
219/*
220 * NOTE: this function was used by OSPM.
221 * TODO: will be removed later, should work out display interfaces for OSPM
222 */
223void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config, int pipe)
224{
225 if (!dsi_config || ((pipe != 0) && (pipe != 2))) {
226 DRM_ERROR("Invalid parameters\n");
227 return;
228 }
229
230 mdfld_dsi_dpi_controller_init(dsi_config, pipe);
231}
232
233static void mdfld_dsi_connector_save(struct drm_connector *connector)
234{
235}
236
237static void mdfld_dsi_connector_restore(struct drm_connector *connector)
238{
239}
240
241/* FIXME: start using the force parameter */
242static enum drm_connector_status
243mdfld_dsi_connector_detect(struct drm_connector *connector, bool force)
244{
245 struct mdfld_dsi_connector *dsi_connector
246 = mdfld_dsi_connector(connector);
247
248 dsi_connector->status = connector_status_connected;
249
250 return dsi_connector->status;
251}
252
253static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
254 struct drm_property *property,
255 uint64_t value)
256{
257 struct drm_encoder *encoder = connector->encoder;
258 struct backlight_device *psb_bd;
259
260 if (!strcmp(property->name, "scaling mode") && encoder) {
261 struct psb_intel_crtc *psb_crtc =
262 to_psb_intel_crtc(encoder->crtc);
263 bool centerechange;
264 uint64_t val;
265
266 if (!psb_crtc)
267 goto set_prop_error;
268
269 switch (value) {
270 case DRM_MODE_SCALE_FULLSCREEN:
271 break;
272 case DRM_MODE_SCALE_NO_SCALE:
273 break;
274 case DRM_MODE_SCALE_ASPECT:
275 break;
276 default:
277 goto set_prop_error;
278 }
279
280 if (drm_connector_property_get_value(connector, property, &val))
281 goto set_prop_error;
282
283 if (val == value)
284 goto set_prop_done;
285
286 if (drm_connector_property_set_value(connector,
287 property, value))
288 goto set_prop_error;
289
290 centerechange = (val == DRM_MODE_SCALE_NO_SCALE) ||
291 (value == DRM_MODE_SCALE_NO_SCALE);
292
293 if (psb_crtc->saved_mode.hdisplay != 0 &&
294 psb_crtc->saved_mode.vdisplay != 0) {
295 if (centerechange) {
296 if (!drm_crtc_helper_set_mode(encoder->crtc,
297 &psb_crtc->saved_mode,
298 encoder->crtc->x,
299 encoder->crtc->y,
300 encoder->crtc->fb))
301 goto set_prop_error;
302 } else {
303 struct drm_encoder_helper_funcs *funcs =
304 encoder->helper_private;
305 funcs->mode_set(encoder,
306 &psb_crtc->saved_mode,
307 &psb_crtc->saved_adjusted_mode);
308 }
309 }
310 } else if (!strcmp(property->name, "backlight") && encoder) {
311 if (drm_connector_property_set_value(connector, property,
312 value))
313 goto set_prop_error;
314 else {
315 psb_bd = mdfld_get_backlight_device();
316 if (psb_bd) {
317 psb_bd->props.brightness = value;
318 mdfld_set_brightness(psb_bd);
319 }
320 }
321 }
322set_prop_done:
323 return 0;
324set_prop_error:
325 return -1;
326}
327
328static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
329{
330 struct mdfld_dsi_connector *dsi_connector =
331 mdfld_dsi_connector(connector);
332 struct mdfld_dsi_pkg_sender *sender;
333
334 if (!dsi_connector)
335 return;
336 drm_sysfs_connector_remove(connector);
337 drm_connector_cleanup(connector);
338 sender = dsi_connector->pkg_sender;
339 mdfld_dsi_pkg_sender_destroy(sender);
340 kfree(dsi_connector);
341}
342
343static int mdfld_dsi_connector_get_modes(struct drm_connector *connector)
344{
345 struct mdfld_dsi_connector *dsi_connector =
346 mdfld_dsi_connector(connector);
347 struct mdfld_dsi_config *dsi_config =
348 mdfld_dsi_get_config(dsi_connector);
349 struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
350 struct drm_display_mode *dup_mode = NULL;
351 struct drm_device *dev = connector->dev;
352
353 connector->display_info.min_vfreq = 0;
354 connector->display_info.max_vfreq = 200;
355 connector->display_info.min_hfreq = 0;
356 connector->display_info.max_hfreq = 200;
357
358 if (fixed_mode) {
359 dev_dbg(dev->dev, "fixed_mode %dx%d\n",
360 fixed_mode->hdisplay, fixed_mode->vdisplay);
361 dup_mode = drm_mode_duplicate(dev, fixed_mode);
362 drm_mode_probed_add(connector, dup_mode);
363 return 1;
364 }
365 DRM_ERROR("Didn't get any modes!\n");
366 return 0;
367}
368
369static int mdfld_dsi_connector_mode_valid(struct drm_connector *connector,
370 struct drm_display_mode *mode)
371{
372 struct mdfld_dsi_connector *dsi_connector =
373 mdfld_dsi_connector(connector);
374 struct mdfld_dsi_config *dsi_config =
375 mdfld_dsi_get_config(dsi_connector);
376 struct drm_display_mode *fixed_mode = dsi_config->fixed_mode;
377
378 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
379 return MODE_NO_DBLESCAN;
380
381 if (mode->flags & DRM_MODE_FLAG_INTERLACE)
382 return MODE_NO_INTERLACE;
383
384 /**
385 * FIXME: current DC has no fitting unit, reject any mode setting
386 * request
387 * Will figure out a way to do up-scaling(pannel fitting) later.
388 **/
389 if (fixed_mode) {
390 if (mode->hdisplay != fixed_mode->hdisplay)
391 return MODE_PANEL;
392
393 if (mode->vdisplay != fixed_mode->vdisplay)
394 return MODE_PANEL;
395 }
396
397 return MODE_OK;
398}
399
400static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
401{
402 if (mode == connector->dpms)
403 return;
404
405 /*first, execute dpms*/
406
407 drm_helper_connector_dpms(connector, mode);
408}
409
410static struct drm_encoder *mdfld_dsi_connector_best_encoder(
411 struct drm_connector *connector)
412{
413 struct mdfld_dsi_connector *dsi_connector =
414 mdfld_dsi_connector(connector);
415 struct mdfld_dsi_config *dsi_config =
416 mdfld_dsi_get_config(dsi_connector);
417 return &dsi_config->encoder->base.base;
418}
419
420/*DSI connector funcs*/
421static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
422 .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
423 .save = mdfld_dsi_connector_save,
424 .restore = mdfld_dsi_connector_restore,
425 .detect = mdfld_dsi_connector_detect,
426 .fill_modes = drm_helper_probe_single_connector_modes,
427 .set_property = mdfld_dsi_connector_set_property,
428 .destroy = mdfld_dsi_connector_destroy,
429};
430
431/*DSI connector helper funcs*/
432static const struct drm_connector_helper_funcs
433 mdfld_dsi_connector_helper_funcs = {
434 .get_modes = mdfld_dsi_connector_get_modes,
435 .mode_valid = mdfld_dsi_connector_mode_valid,
436 .best_encoder = mdfld_dsi_connector_best_encoder,
437};
438
439static int mdfld_dsi_get_default_config(struct drm_device *dev,
440 struct mdfld_dsi_config *config, int pipe)
441{
442 if (!dev || !config) {
443 DRM_ERROR("Invalid parameters");
444 return -EINVAL;
445 }
446
447 config->bpp = 24;
448 if (mdfld_get_panel_type(dev, pipe) == TC35876X)
449 config->lane_count = 4;
450 else
451 config->lane_count = 2;
452 config->channel_num = 0;
453
454 if (mdfld_get_panel_type(dev, pipe) == TMD_VID)
455 config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
456 else if (mdfld_get_panel_type(dev, pipe) == TC35876X)
457 config->video_mode =
458 MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS;
459 else
460 config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
461
462 return 0;
463}
464
465int mdfld_dsi_panel_reset(int pipe)
466{
467 unsigned gpio;
468 int ret = 0;
469
470 switch (pipe) {
471 case 0:
472 gpio = 128;
473 break;
474 case 2:
475 gpio = 34;
476 break;
477 default:
478 DRM_ERROR("Invalid output\n");
479 return -EINVAL;
480 }
481
482 ret = gpio_request(gpio, "gfx");
483 if (ret) {
484 DRM_ERROR("gpio_rqueset failed\n");
485 return ret;
486 }
487
488 ret = gpio_direction_output(gpio, 1);
489 if (ret) {
490 DRM_ERROR("gpio_direction_output failed\n");
491 goto gpio_error;
492 }
493
494 gpio_get_value(128);
495
496gpio_error:
497 if (gpio_is_valid(gpio))
498 gpio_free(gpio);
499
500 return ret;
501}
502
503/*
504 * MIPI output init
505 * @dev drm device
506 * @pipe pipe number. 0 or 2
507 * @config
508 *
509 * Do the initialization of a MIPI output, including create DRM mode objects
510 * initialization of DSI output on @pipe
511 */
512void mdfld_dsi_output_init(struct drm_device *dev,
513 int pipe,
514 struct mdfld_dsi_config *config,
515 const struct panel_funcs *p_vid_funcs)
516{
517 struct mdfld_dsi_config *dsi_config;
518 struct mdfld_dsi_connector *dsi_connector;
519 struct drm_connector *connector;
520 struct mdfld_dsi_encoder *encoder;
521 struct drm_psb_private *dev_priv = dev->dev_private;
522 struct panel_info dsi_panel_info;
523 u32 width_mm, height_mm;
524
525 dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
526
527 if (!dev || ((pipe != 0) && (pipe != 2))) {
528 DRM_ERROR("Invalid parameter\n");
529 return;
530 }
531
532 /*create a new connetor*/
533 dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
534 if (!dsi_connector) {
535 DRM_ERROR("No memory");
536 return;
537 }
538
539 dsi_connector->pipe = pipe;
540
541 /*set DSI config*/
542 if (config)
543 dsi_config = config;
544 else {
545 dsi_config = kzalloc(sizeof(struct mdfld_dsi_config),
546 GFP_KERNEL);
547 if (!dsi_config) {
548 DRM_ERROR("cannot allocate memory for DSI config\n");
549 goto dsi_init_err0;
550 }
551 mdfld_dsi_get_default_config(dev, dsi_config, pipe);
552 }
553
554 dsi_connector->private = dsi_config;
555
556 dsi_config->changed = 1;
557 dsi_config->dev = dev;
558
559 dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
560 if (p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
561 goto dsi_init_err0;
562
563 width_mm = dsi_panel_info.width_mm;
564 height_mm = dsi_panel_info.height_mm;
565
566 dsi_config->mode = dsi_config->fixed_mode;
567 dsi_config->connector = dsi_connector;
568
569 if (!dsi_config->fixed_mode) {
570 DRM_ERROR("No pannel fixed mode was found\n");
571 goto dsi_init_err0;
572 }
573
574 if (pipe && dev_priv->dsi_configs[0]) {
575 dsi_config->dvr_ic_inited = 0;
576 dev_priv->dsi_configs[1] = dsi_config;
577 } else if (pipe == 0) {
578 dsi_config->dvr_ic_inited = 1;
579 dev_priv->dsi_configs[0] = dsi_config;
580 } else {
581 DRM_ERROR("Trying to init MIPI1 before MIPI0\n");
582 goto dsi_init_err0;
583 }
584
585
586 connector = &dsi_connector->base.base;
587 drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs,
588 DRM_MODE_CONNECTOR_LVDS);
589 drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
590
591 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
592 connector->display_info.width_mm = width_mm;
593 connector->display_info.height_mm = height_mm;
594 connector->interlace_allowed = false;
595 connector->doublescan_allowed = false;
596
597 /*attach properties*/
598 drm_connector_attach_property(connector,
599 dev->mode_config.scaling_mode_property,
600 DRM_MODE_SCALE_FULLSCREEN);
601 drm_connector_attach_property(connector,
602 dev_priv->backlight_property,
603 MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
604
605 /*init DSI package sender on this output*/
606 if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
607 DRM_ERROR("Package Sender initialization failed on pipe %d\n",
608 pipe);
609 goto dsi_init_err0;
610 }
611
612 encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
613 if (!encoder) {
614 DRM_ERROR("Create DPI encoder failed\n");
615 goto dsi_init_err1;
616 }
617 encoder->private = dsi_config;
618 dsi_config->encoder = encoder;
619 encoder->base.type = (pipe == 0) ? INTEL_OUTPUT_MIPI :
620 INTEL_OUTPUT_MIPI2;
621 drm_sysfs_connector_add(connector);
622 return;
623
624 /*TODO: add code to destroy outputs on error*/
625dsi_init_err1:
626 /*destroy sender*/
627 mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
628
629 drm_connector_cleanup(connector);
630
631 kfree(dsi_config->fixed_mode);
632 kfree(dsi_config);
633dsi_init_err0:
634 kfree(dsi_connector);
635}
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_output.h b/drivers/gpu/drm/gma500/mdfld_dsi_output.h
new file mode 100644
index 000000000000..2cdf666536df
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_output.h
@@ -0,0 +1,389 @@
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 <linux/version.h>
33#include <drm/drmP.h>
34#include <drm/drm.h>
35#include <drm/drm_crtc.h>
36#include <drm/drm_edid.h>
37
38#include "psb_drv.h"
39#include "psb_intel_drv.h"
40#include "psb_intel_reg.h"
41#include "mdfld_output.h"
42
43#include <asm/mrst.h>
44
45#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
46#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
47#define FLD_GET(val, start, end) (((val) & FLD_MASK(start, end)) >> (end))
48#define FLD_MOD(orig, val, start, end) \
49 (((orig) & ~FLD_MASK(start, end)) | FLD_VAL(val, start, end))
50
51#define REG_FLD_MOD(reg, val, start, end) \
52 REG_WRITE(reg, FLD_MOD(REG_READ(reg), val, start, end))
53
54static inline int REGISTER_FLD_WAIT(struct drm_device *dev, u32 reg,
55 u32 val, int start, int end)
56{
57 int t = 100000;
58
59 while (FLD_GET(REG_READ(reg), start, end) != val) {
60 if (--t == 0)
61 return 1;
62 }
63
64 return 0;
65}
66
67#define REG_FLD_WAIT(reg, val, start, end) \
68 REGISTER_FLD_WAIT(dev, reg, val, start, end)
69
70#define REG_BIT_WAIT(reg, val, bitnum) \
71 REGISTER_FLD_WAIT(dev, reg, val, bitnum, bitnum)
72
73#define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
74
75#ifdef DEBUG
76#define CHECK_PIPE(pipe) ({ \
77 const typeof(pipe) __pipe = (pipe); \
78 BUG_ON(__pipe != 0 && __pipe != 2); \
79 __pipe; })
80#else
81#define CHECK_PIPE(pipe) (pipe)
82#endif
83
84/*
85 * Actual MIPIA->MIPIC reg offset is 0x800, value 0x400 is valid for 0 and 2
86 */
87#define REG_OFFSET(pipe) (CHECK_PIPE(pipe) * 0x400)
88
89/* mdfld DSI controller registers */
90#define MIPI_DEVICE_READY_REG(pipe) (0xb000 + REG_OFFSET(pipe))
91#define MIPI_INTR_STAT_REG(pipe) (0xb004 + REG_OFFSET(pipe))
92#define MIPI_INTR_EN_REG(pipe) (0xb008 + REG_OFFSET(pipe))
93#define MIPI_DSI_FUNC_PRG_REG(pipe) (0xb00c + REG_OFFSET(pipe))
94#define MIPI_HS_TX_TIMEOUT_REG(pipe) (0xb010 + REG_OFFSET(pipe))
95#define MIPI_LP_RX_TIMEOUT_REG(pipe) (0xb014 + REG_OFFSET(pipe))
96#define MIPI_TURN_AROUND_TIMEOUT_REG(pipe) (0xb018 + REG_OFFSET(pipe))
97#define MIPI_DEVICE_RESET_TIMER_REG(pipe) (0xb01c + REG_OFFSET(pipe))
98#define MIPI_DPI_RESOLUTION_REG(pipe) (0xb020 + REG_OFFSET(pipe))
99#define MIPI_DBI_FIFO_THROTTLE_REG(pipe) (0xb024 + REG_OFFSET(pipe))
100#define MIPI_HSYNC_COUNT_REG(pipe) (0xb028 + REG_OFFSET(pipe))
101#define MIPI_HBP_COUNT_REG(pipe) (0xb02c + REG_OFFSET(pipe))
102#define MIPI_HFP_COUNT_REG(pipe) (0xb030 + REG_OFFSET(pipe))
103#define MIPI_HACTIVE_COUNT_REG(pipe) (0xb034 + REG_OFFSET(pipe))
104#define MIPI_VSYNC_COUNT_REG(pipe) (0xb038 + REG_OFFSET(pipe))
105#define MIPI_VBP_COUNT_REG(pipe) (0xb03c + REG_OFFSET(pipe))
106#define MIPI_VFP_COUNT_REG(pipe) (0xb040 + REG_OFFSET(pipe))
107#define MIPI_HIGH_LOW_SWITCH_COUNT_REG(pipe) (0xb044 + REG_OFFSET(pipe))
108#define MIPI_DPI_CONTROL_REG(pipe) (0xb048 + REG_OFFSET(pipe))
109#define MIPI_DPI_DATA_REG(pipe) (0xb04c + REG_OFFSET(pipe))
110#define MIPI_INIT_COUNT_REG(pipe) (0xb050 + REG_OFFSET(pipe))
111#define MIPI_MAX_RETURN_PACK_SIZE_REG(pipe) (0xb054 + REG_OFFSET(pipe))
112#define MIPI_VIDEO_MODE_FORMAT_REG(pipe) (0xb058 + REG_OFFSET(pipe))
113#define MIPI_EOT_DISABLE_REG(pipe) (0xb05c + REG_OFFSET(pipe))
114#define MIPI_LP_BYTECLK_REG(pipe) (0xb060 + REG_OFFSET(pipe))
115#define MIPI_LP_GEN_DATA_REG(pipe) (0xb064 + REG_OFFSET(pipe))
116#define MIPI_HS_GEN_DATA_REG(pipe) (0xb068 + REG_OFFSET(pipe))
117#define MIPI_LP_GEN_CTRL_REG(pipe) (0xb06c + REG_OFFSET(pipe))
118#define MIPI_HS_GEN_CTRL_REG(pipe) (0xb070 + REG_OFFSET(pipe))
119#define MIPI_GEN_FIFO_STAT_REG(pipe) (0xb074 + REG_OFFSET(pipe))
120#define MIPI_HS_LS_DBI_ENABLE_REG(pipe) (0xb078 + REG_OFFSET(pipe))
121#define MIPI_DPHY_PARAM_REG(pipe) (0xb080 + REG_OFFSET(pipe))
122#define MIPI_DBI_BW_CTRL_REG(pipe) (0xb084 + REG_OFFSET(pipe))
123#define MIPI_CLK_LANE_SWITCH_TIME_CNT_REG(pipe) (0xb088 + REG_OFFSET(pipe))
124
125#define MIPI_CTRL_REG(pipe) (0xb104 + REG_OFFSET(pipe))
126#define MIPI_DATA_ADD_REG(pipe) (0xb108 + REG_OFFSET(pipe))
127#define MIPI_DATA_LEN_REG(pipe) (0xb10c + REG_OFFSET(pipe))
128#define MIPI_CMD_ADD_REG(pipe) (0xb110 + REG_OFFSET(pipe))
129#define MIPI_CMD_LEN_REG(pipe) (0xb114 + REG_OFFSET(pipe))
130
131/* non-uniform reg offset */
132#define MIPI_PORT_CONTROL(pipe) (CHECK_PIPE(pipe) ? MIPI_C : MIPI)
133
134#define DSI_DEVICE_READY (0x1)
135#define DSI_POWER_STATE_ULPS_ENTER (0x2 << 1)
136#define DSI_POWER_STATE_ULPS_EXIT (0x1 << 1)
137#define DSI_POWER_STATE_ULPS_OFFSET (0x1)
138
139
140#define DSI_ONE_DATA_LANE (0x1)
141#define DSI_TWO_DATA_LANE (0x2)
142#define DSI_THREE_DATA_LANE (0X3)
143#define DSI_FOUR_DATA_LANE (0x4)
144#define DSI_DPI_VIRT_CHANNEL_OFFSET (0x3)
145#define DSI_DBI_VIRT_CHANNEL_OFFSET (0x5)
146#define DSI_DPI_COLOR_FORMAT_RGB565 (0x01 << 7)
147#define DSI_DPI_COLOR_FORMAT_RGB666 (0x02 << 7)
148#define DSI_DPI_COLOR_FORMAT_RGB666_UNPACK (0x03 << 7)
149#define DSI_DPI_COLOR_FORMAT_RGB888 (0x04 << 7)
150#define DSI_DBI_COLOR_FORMAT_OPTION2 (0x05 << 13)
151
152#define DSI_INTR_STATE_RXSOTERROR BIT(0)
153
154#define DSI_INTR_STATE_SPL_PKG_SENT BIT(30)
155#define DSI_INTR_STATE_TE BIT(31)
156
157#define DSI_HS_TX_TIMEOUT_MASK (0xffffff)
158
159#define DSI_LP_RX_TIMEOUT_MASK (0xffffff)
160
161#define DSI_TURN_AROUND_TIMEOUT_MASK (0x3f)
162
163#define DSI_RESET_TIMER_MASK (0xffff)
164
165#define DSI_DBI_FIFO_WM_HALF (0x0)
166#define DSI_DBI_FIFO_WM_QUARTER (0x1)
167#define DSI_DBI_FIFO_WM_LOW (0x2)
168
169#define DSI_DPI_TIMING_MASK (0xffff)
170
171#define DSI_INIT_TIMER_MASK (0xffff)
172
173#define DSI_DBI_RETURN_PACK_SIZE_MASK (0x3ff)
174
175#define DSI_LP_BYTECLK_MASK (0x0ffff)
176
177#define DSI_HS_CTRL_GEN_SHORT_W0 (0x03)
178#define DSI_HS_CTRL_GEN_SHORT_W1 (0x13)
179#define DSI_HS_CTRL_GEN_SHORT_W2 (0x23)
180#define DSI_HS_CTRL_GEN_R0 (0x04)
181#define DSI_HS_CTRL_GEN_R1 (0x14)
182#define DSI_HS_CTRL_GEN_R2 (0x24)
183#define DSI_HS_CTRL_GEN_LONG_W (0x29)
184#define DSI_HS_CTRL_MCS_SHORT_W0 (0x05)
185#define DSI_HS_CTRL_MCS_SHORT_W1 (0x15)
186#define DSI_HS_CTRL_MCS_R0 (0x06)
187#define DSI_HS_CTRL_MCS_LONG_W (0x39)
188#define DSI_HS_CTRL_VC_OFFSET (0x06)
189#define DSI_HS_CTRL_WC_OFFSET (0x08)
190
191#define DSI_FIFO_GEN_HS_DATA_FULL BIT(0)
192#define DSI_FIFO_GEN_HS_DATA_HALF_EMPTY BIT(1)
193#define DSI_FIFO_GEN_HS_DATA_EMPTY BIT(2)
194#define DSI_FIFO_GEN_LP_DATA_FULL BIT(8)
195#define DSI_FIFO_GEN_LP_DATA_HALF_EMPTY BIT(9)
196#define DSI_FIFO_GEN_LP_DATA_EMPTY BIT(10)
197#define DSI_FIFO_GEN_HS_CTRL_FULL BIT(16)
198#define DSI_FIFO_GEN_HS_CTRL_HALF_EMPTY BIT(17)
199#define DSI_FIFO_GEN_HS_CTRL_EMPTY BIT(18)
200#define DSI_FIFO_GEN_LP_CTRL_FULL BIT(24)
201#define DSI_FIFO_GEN_LP_CTRL_HALF_EMPTY BIT(25)
202#define DSI_FIFO_GEN_LP_CTRL_EMPTY BIT(26)
203#define DSI_FIFO_DBI_EMPTY BIT(27)
204#define DSI_FIFO_DPI_EMPTY BIT(28)
205
206#define DSI_DBI_HS_LP_SWITCH_MASK (0x1)
207
208#define DSI_HS_LP_SWITCH_COUNTER_OFFSET (0x0)
209#define DSI_LP_HS_SWITCH_COUNTER_OFFSET (0x16)
210
211#define DSI_DPI_CTRL_HS_SHUTDOWN (0x00000001)
212#define DSI_DPI_CTRL_HS_TURN_ON (0x00000002)
213
214/*dsi power modes*/
215#define DSI_POWER_MODE_DISPLAY_ON BIT(2)
216#define DSI_POWER_MODE_NORMAL_ON BIT(3)
217#define DSI_POWER_MODE_SLEEP_OUT BIT(4)
218#define DSI_POWER_MODE_PARTIAL_ON BIT(5)
219#define DSI_POWER_MODE_IDLE_ON BIT(6)
220
221enum {
222 MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE = 1,
223 MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_EVENTS = 2,
224 MDFLD_DSI_VIDEO_BURST_MODE = 3,
225};
226
227#define DSI_DPI_COMPLETE_LAST_LINE BIT(2)
228#define DSI_DPI_DISABLE_BTA BIT(3)
229
230struct mdfld_dsi_connector_state {
231 u32 mipi_ctrl_reg;
232};
233
234struct mdfld_dsi_encoder_state {
235
236};
237
238struct mdfld_dsi_connector {
239 struct psb_intel_connector base;
240
241 int pipe;
242 void *private;
243 void *pkg_sender;
244
245 /* Connection status */
246 enum drm_connector_status status;
247};
248
249struct mdfld_dsi_encoder {
250 struct psb_intel_encoder base;
251 void *private;
252};
253
254/*
255 * DSI config, consists of one DSI connector, two DSI encoders.
256 * DRM will pick up on DSI encoder basing on differents configs.
257 */
258struct mdfld_dsi_config {
259 struct drm_device *dev;
260 struct drm_display_mode *fixed_mode;
261 struct drm_display_mode *mode;
262
263 struct mdfld_dsi_connector *connector;
264 struct mdfld_dsi_encoder *encoder;
265
266 int changed;
267
268 int bpp;
269 int lane_count;
270 /*Virtual channel number for this encoder*/
271 int channel_num;
272 /*video mode configure*/
273 int video_mode;
274
275 int dvr_ic_inited;
276};
277
278static inline struct mdfld_dsi_connector *mdfld_dsi_connector(
279 struct drm_connector *connector)
280{
281 struct psb_intel_connector *psb_connector;
282
283 psb_connector = to_psb_intel_connector(connector);
284
285 return container_of(psb_connector, struct mdfld_dsi_connector, base);
286}
287
288static inline struct mdfld_dsi_encoder *mdfld_dsi_encoder(
289 struct drm_encoder *encoder)
290{
291 struct psb_intel_encoder *psb_encoder;
292
293 psb_encoder = to_psb_intel_encoder(encoder);
294
295 return container_of(psb_encoder, struct mdfld_dsi_encoder, base);
296}
297
298static inline struct mdfld_dsi_config *
299 mdfld_dsi_get_config(struct mdfld_dsi_connector *connector)
300{
301 if (!connector)
302 return NULL;
303 return (struct mdfld_dsi_config *)connector->private;
304}
305
306static inline void *mdfld_dsi_get_pkg_sender(struct mdfld_dsi_config *config)
307{
308 struct mdfld_dsi_connector *dsi_connector;
309
310 if (!config)
311 return NULL;
312
313 dsi_connector = config->connector;
314
315 if (!dsi_connector)
316 return NULL;
317
318 return dsi_connector->pkg_sender;
319}
320
321static inline struct mdfld_dsi_config *
322 mdfld_dsi_encoder_get_config(struct mdfld_dsi_encoder *encoder)
323{
324 if (!encoder)
325 return NULL;
326 return (struct mdfld_dsi_config *)encoder->private;
327}
328
329static inline struct mdfld_dsi_connector *
330 mdfld_dsi_encoder_get_connector(struct mdfld_dsi_encoder *encoder)
331{
332 struct mdfld_dsi_config *config;
333
334 if (!encoder)
335 return NULL;
336
337 config = mdfld_dsi_encoder_get_config(encoder);
338 if (!config)
339 return NULL;
340
341 return config->connector;
342}
343
344static inline void *mdfld_dsi_encoder_get_pkg_sender(
345 struct mdfld_dsi_encoder *encoder)
346{
347 struct mdfld_dsi_config *dsi_config;
348
349 dsi_config = mdfld_dsi_encoder_get_config(encoder);
350 if (!dsi_config)
351 return NULL;
352
353 return mdfld_dsi_get_pkg_sender(dsi_config);
354}
355
356static inline int mdfld_dsi_encoder_get_pipe(struct mdfld_dsi_encoder *encoder)
357{
358 struct mdfld_dsi_connector *connector;
359
360 if (!encoder)
361 return -1;
362
363 connector = mdfld_dsi_encoder_get_connector(encoder);
364 if (!connector)
365 return -1;
366 return connector->pipe;
367}
368
369/* Export functions */
370extern void mdfld_dsi_gen_fifo_ready(struct drm_device *dev,
371 u32 gen_fifo_stat_reg, u32 fifo_stat);
372extern void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config,
373 int pipe);
374extern void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe,
375 int level);
376extern void mdfld_dsi_output_init(struct drm_device *dev,
377 int pipe,
378 struct mdfld_dsi_config *config,
379 const struct panel_funcs *p_vid_funcs);
380extern void mdfld_dsi_controller_init(struct mdfld_dsi_config *dsi_config,
381 int pipe);
382
383extern int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
384 u32 *mode, bool hs);
385extern int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
386 u32 *result, bool hs);
387extern int mdfld_dsi_panel_reset(int pipe);
388
389#endif /*__MDFLD_DSI_OUTPUT_H__*/
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
new file mode 100644
index 000000000000..f193acec657e
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.c
@@ -0,0 +1,694 @@
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_dpi.h"
32
33#define MDFLD_DSI_READ_MAX_COUNT 5000
34
35enum data_type {
36 DSI_DT_GENERIC_SHORT_WRITE_0 = 0x03,
37 DSI_DT_GENERIC_SHORT_WRITE_1 = 0x13,
38 DSI_DT_GENERIC_SHORT_WRITE_2 = 0x23,
39 DSI_DT_GENERIC_READ_0 = 0x04,
40 DSI_DT_GENERIC_READ_1 = 0x14,
41 DSI_DT_GENERIC_READ_2 = 0x24,
42 DSI_DT_GENERIC_LONG_WRITE = 0x29,
43 DSI_DT_DCS_SHORT_WRITE_0 = 0x05,
44 DSI_DT_DCS_SHORT_WRITE_1 = 0x15,
45 DSI_DT_DCS_READ = 0x06,
46 DSI_DT_DCS_LONG_WRITE = 0x39,
47};
48
49enum {
50 MDFLD_DSI_PANEL_MODE_SLEEP = 0x1,
51};
52
53enum {
54 MDFLD_DSI_PKG_SENDER_FREE = 0x0,
55 MDFLD_DSI_PKG_SENDER_BUSY = 0x1,
56};
57
58static const char *const dsi_errors[] = {
59 "RX SOT Error",
60 "RX SOT Sync Error",
61 "RX EOT Sync Error",
62 "RX Escape Mode Entry Error",
63 "RX LP TX Sync Error",
64 "RX HS Receive Timeout Error",
65 "RX False Control Error",
66 "RX ECC Single Bit Error",
67 "RX ECC Multibit Error",
68 "RX Checksum Error",
69 "RX DSI Data Type Not Recognised",
70 "RX DSI VC ID Invalid",
71 "TX False Control Error",
72 "TX ECC Single Bit Error",
73 "TX ECC Multibit Error",
74 "TX Checksum Error",
75 "TX DSI Data Type Not Recognised",
76 "TX DSI VC ID invalid",
77 "High Contention",
78 "Low contention",
79 "DPI FIFO Under run",
80 "HS TX Timeout",
81 "LP RX Timeout",
82 "Turn Around ACK Timeout",
83 "ACK With No Error",
84 "RX Invalid TX Length",
85 "RX Prot Violation",
86 "HS Generic Write FIFO Full",
87 "LP Generic Write FIFO Full",
88 "Generic Read Data Avail"
89 "Special Packet Sent",
90 "Tearing Effect",
91};
92
93static inline int wait_for_gen_fifo_empty(struct mdfld_dsi_pkg_sender *sender,
94 u32 mask)
95{
96 struct drm_device *dev = sender->dev;
97 u32 gen_fifo_stat_reg = sender->mipi_gen_fifo_stat_reg;
98 int retry = 0xffff;
99
100 while (retry--) {
101 if ((mask & REG_READ(gen_fifo_stat_reg)) == mask)
102 return 0;
103 udelay(100);
104 }
105 DRM_ERROR("fifo is NOT empty 0x%08x\n", REG_READ(gen_fifo_stat_reg));
106 return -EIO;
107}
108
109static int wait_for_all_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
110{
111 return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(10) | BIT(18) |
112 BIT(26) | BIT(27) | BIT(28)));
113}
114
115static int wait_for_lp_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
116{
117 return wait_for_gen_fifo_empty(sender, (BIT(10) | BIT(26)));
118}
119
120static int wait_for_hs_fifos_empty(struct mdfld_dsi_pkg_sender *sender)
121{
122 return wait_for_gen_fifo_empty(sender, (BIT(2) | BIT(18)));
123}
124
125static int handle_dsi_error(struct mdfld_dsi_pkg_sender *sender, u32 mask)
126{
127 u32 intr_stat_reg = sender->mipi_intr_stat_reg;
128 struct drm_device *dev = sender->dev;
129
130 dev_dbg(sender->dev->dev, "Handling error 0x%08x\n", mask);
131
132 switch (mask) {
133 case BIT(0):
134 case BIT(1):
135 case BIT(2):
136 case BIT(3):
137 case BIT(4):
138 case BIT(5):
139 case BIT(6):
140 case BIT(7):
141 case BIT(8):
142 case BIT(9):
143 case BIT(10):
144 case BIT(11):
145 case BIT(12):
146 case BIT(13):
147 dev_dbg(sender->dev->dev, "No Action required\n");
148 break;
149 case BIT(14):
150 /*wait for all fifo empty*/
151 /*wait_for_all_fifos_empty(sender)*/;
152 break;
153 case BIT(15):
154 dev_dbg(sender->dev->dev, "No Action required\n");
155 break;
156 case BIT(16):
157 break;
158 case BIT(17):
159 break;
160 case BIT(18):
161 case BIT(19):
162 dev_dbg(sender->dev->dev, "High/Low contention detected\n");
163 /*wait for contention recovery time*/
164 /*mdelay(10);*/
165 /*wait for all fifo empty*/
166 if (0)
167 wait_for_all_fifos_empty(sender);
168 break;
169 case BIT(20):
170 dev_dbg(sender->dev->dev, "No Action required\n");
171 break;
172 case BIT(21):
173 /*wait for all fifo empty*/
174 /*wait_for_all_fifos_empty(sender);*/
175 break;
176 case BIT(22):
177 break;
178 case BIT(23):
179 case BIT(24):
180 case BIT(25):
181 case BIT(26):
182 case BIT(27):
183 dev_dbg(sender->dev->dev, "HS Gen fifo full\n");
184 REG_WRITE(intr_stat_reg, mask);
185 wait_for_hs_fifos_empty(sender);
186 break;
187 case BIT(28):
188 dev_dbg(sender->dev->dev, "LP Gen fifo full\n");
189 REG_WRITE(intr_stat_reg, mask);
190 wait_for_lp_fifos_empty(sender);
191 break;
192 case BIT(29):
193 case BIT(30):
194 case BIT(31):
195 dev_dbg(sender->dev->dev, "No Action required\n");
196 break;
197 }
198
199 if (mask & REG_READ(intr_stat_reg))
200 dev_dbg(sender->dev->dev,
201 "Cannot clean interrupt 0x%08x\n", mask);
202 return 0;
203}
204
205static int dsi_error_handler(struct mdfld_dsi_pkg_sender *sender)
206{
207 struct drm_device *dev = sender->dev;
208 u32 intr_stat_reg = sender->mipi_intr_stat_reg;
209 u32 mask;
210 u32 intr_stat;
211 int i;
212 int err = 0;
213
214 intr_stat = REG_READ(intr_stat_reg);
215
216 for (i = 0; i < 32; i++) {
217 mask = (0x00000001UL) << i;
218 if (intr_stat & mask) {
219 dev_dbg(sender->dev->dev, "[DSI]: %s\n", dsi_errors[i]);
220 err = handle_dsi_error(sender, mask);
221 if (err)
222 DRM_ERROR("Cannot handle error\n");
223 }
224 }
225 return err;
226}
227
228static int send_short_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
229 u8 cmd, u8 param, bool hs)
230{
231 struct drm_device *dev = sender->dev;
232 u32 ctrl_reg;
233 u32 val;
234 u8 virtual_channel = 0;
235
236 if (hs) {
237 ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
238
239 /* FIXME: wait_for_hs_fifos_empty(sender); */
240 } else {
241 ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
242
243 /* FIXME: wait_for_lp_fifos_empty(sender); */
244 }
245
246 val = FLD_VAL(param, 23, 16) | FLD_VAL(cmd, 15, 8) |
247 FLD_VAL(virtual_channel, 7, 6) | FLD_VAL(data_type, 5, 0);
248
249 REG_WRITE(ctrl_reg, val);
250
251 return 0;
252}
253
254static int send_long_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
255 u8 *data, int len, bool hs)
256{
257 struct drm_device *dev = sender->dev;
258 u32 ctrl_reg;
259 u32 data_reg;
260 u32 val;
261 u8 *p;
262 u8 b1, b2, b3, b4;
263 u8 virtual_channel = 0;
264 int i;
265
266 if (hs) {
267 ctrl_reg = sender->mipi_hs_gen_ctrl_reg;
268 data_reg = sender->mipi_hs_gen_data_reg;
269
270 /* FIXME: wait_for_hs_fifos_empty(sender); */
271 } else {
272 ctrl_reg = sender->mipi_lp_gen_ctrl_reg;
273 data_reg = sender->mipi_lp_gen_data_reg;
274
275 /* FIXME: wait_for_lp_fifos_empty(sender); */
276 }
277
278 p = data;
279 for (i = 0; i < len / 4; i++) {
280 b1 = *p++;
281 b2 = *p++;
282 b3 = *p++;
283 b4 = *p++;
284
285 REG_WRITE(data_reg, b4 << 24 | b3 << 16 | b2 << 8 | b1);
286 }
287
288 i = len % 4;
289 if (i) {
290 b1 = 0; b2 = 0; b3 = 0;
291
292 switch (i) {
293 case 3:
294 b1 = *p++;
295 b2 = *p++;
296 b3 = *p++;
297 break;
298 case 2:
299 b1 = *p++;
300 b2 = *p++;
301 break;
302 case 1:
303 b1 = *p++;
304 break;
305 }
306
307 REG_WRITE(data_reg, b3 << 16 | b2 << 8 | b1);
308 }
309
310 val = FLD_VAL(len, 23, 8) | FLD_VAL(virtual_channel, 7, 6) |
311 FLD_VAL(data_type, 5, 0);
312
313 REG_WRITE(ctrl_reg, val);
314
315 return 0;
316}
317
318static int send_pkg_prepare(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
319 u8 *data, u16 len)
320{
321 u8 cmd;
322
323 switch (data_type) {
324 case DSI_DT_DCS_SHORT_WRITE_0:
325 case DSI_DT_DCS_SHORT_WRITE_1:
326 case DSI_DT_DCS_LONG_WRITE:
327 cmd = *data;
328 break;
329 default:
330 return 0;
331 }
332
333 /*this prevents other package sending while doing msleep*/
334 sender->status = MDFLD_DSI_PKG_SENDER_BUSY;
335
336 /*wait for 120 milliseconds in case exit_sleep_mode just be sent*/
337 if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) {
338 /*TODO: replace it with msleep later*/
339 mdelay(120);
340 }
341
342 if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) {
343 /*TODO: replace it with msleep later*/
344 mdelay(120);
345 }
346 return 0;
347}
348
349static int send_pkg_done(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
350 u8 *data, u16 len)
351{
352 u8 cmd;
353
354 switch (data_type) {
355 case DSI_DT_DCS_SHORT_WRITE_0:
356 case DSI_DT_DCS_SHORT_WRITE_1:
357 case DSI_DT_DCS_LONG_WRITE:
358 cmd = *data;
359 break;
360 default:
361 return 0;
362 }
363
364 /*update panel status*/
365 if (unlikely(cmd == DCS_ENTER_SLEEP_MODE)) {
366 sender->panel_mode |= MDFLD_DSI_PANEL_MODE_SLEEP;
367 /*TODO: replace it with msleep later*/
368 mdelay(120);
369 } else if (unlikely(cmd == DCS_EXIT_SLEEP_MODE)) {
370 sender->panel_mode &= ~MDFLD_DSI_PANEL_MODE_SLEEP;
371 /*TODO: replace it with msleep later*/
372 mdelay(120);
373 } else if (unlikely(cmd == DCS_SOFT_RESET)) {
374 /*TODO: replace it with msleep later*/
375 mdelay(5);
376 }
377
378 sender->status = MDFLD_DSI_PKG_SENDER_FREE;
379
380 return 0;
381}
382
383static int send_pkg(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
384 u8 *data, u16 len, bool hs)
385{
386 int ret;
387
388 /*handle DSI error*/
389 ret = dsi_error_handler(sender);
390 if (ret) {
391 DRM_ERROR("Error handling failed\n");
392 return -EAGAIN;
393 }
394
395 /* send pkg */
396 if (sender->status == MDFLD_DSI_PKG_SENDER_BUSY) {
397 DRM_ERROR("sender is busy\n");
398 return -EAGAIN;
399 }
400
401 ret = send_pkg_prepare(sender, data_type, data, len);
402 if (ret) {
403 DRM_ERROR("send_pkg_prepare error\n");
404 return ret;
405 }
406
407 switch (data_type) {
408 case DSI_DT_GENERIC_SHORT_WRITE_0:
409 case DSI_DT_GENERIC_SHORT_WRITE_1:
410 case DSI_DT_GENERIC_SHORT_WRITE_2:
411 case DSI_DT_GENERIC_READ_0:
412 case DSI_DT_GENERIC_READ_1:
413 case DSI_DT_GENERIC_READ_2:
414 case DSI_DT_DCS_SHORT_WRITE_0:
415 case DSI_DT_DCS_SHORT_WRITE_1:
416 case DSI_DT_DCS_READ:
417 ret = send_short_pkg(sender, data_type, data[0], data[1], hs);
418 break;
419 case DSI_DT_GENERIC_LONG_WRITE:
420 case DSI_DT_DCS_LONG_WRITE:
421 ret = send_long_pkg(sender, data_type, data, len, hs);
422 break;
423 }
424
425 send_pkg_done(sender, data_type, data, len);
426
427 /*FIXME: should I query complete and fifo empty here?*/
428
429 return ret;
430}
431
432int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
433 u32 len, bool hs)
434{
435 unsigned long flags;
436
437 if (!sender || !data || !len) {
438 DRM_ERROR("Invalid parameters\n");
439 return -EINVAL;
440 }
441
442 spin_lock_irqsave(&sender->lock, flags);
443 send_pkg(sender, DSI_DT_DCS_LONG_WRITE, data, len, hs);
444 spin_unlock_irqrestore(&sender->lock, flags);
445
446 return 0;
447}
448
449int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
450 u8 param, u8 param_num, bool hs)
451{
452 u8 data[2];
453 unsigned long flags;
454 u8 data_type;
455
456 if (!sender) {
457 DRM_ERROR("Invalid parameter\n");
458 return -EINVAL;
459 }
460
461 data[0] = cmd;
462
463 if (param_num) {
464 data_type = DSI_DT_DCS_SHORT_WRITE_1;
465 data[1] = param;
466 } else {
467 data_type = DSI_DT_DCS_SHORT_WRITE_0;
468 data[1] = 0;
469 }
470
471 spin_lock_irqsave(&sender->lock, flags);
472 send_pkg(sender, data_type, data, sizeof(data), hs);
473 spin_unlock_irqrestore(&sender->lock, flags);
474
475 return 0;
476}
477
478int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
479 u8 param1, u8 param_num, bool hs)
480{
481 u8 data[2];
482 unsigned long flags;
483 u8 data_type;
484
485 if (!sender || param_num < 0 || param_num > 2) {
486 DRM_ERROR("Invalid parameter\n");
487 return -EINVAL;
488 }
489
490 switch (param_num) {
491 case 0:
492 data_type = DSI_DT_GENERIC_SHORT_WRITE_0;
493 data[0] = 0;
494 data[1] = 0;
495 break;
496 case 1:
497 data_type = DSI_DT_GENERIC_SHORT_WRITE_1;
498 data[0] = param0;
499 data[1] = 0;
500 break;
501 case 2:
502 data_type = DSI_DT_GENERIC_SHORT_WRITE_2;
503 data[0] = param0;
504 data[1] = param1;
505 break;
506 }
507
508 spin_lock_irqsave(&sender->lock, flags);
509 send_pkg(sender, data_type, data, sizeof(data), hs);
510 spin_unlock_irqrestore(&sender->lock, flags);
511
512 return 0;
513}
514
515int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
516 u32 len, bool hs)
517{
518 unsigned long flags;
519
520 if (!sender || !data || !len) {
521 DRM_ERROR("Invalid parameters\n");
522 return -EINVAL;
523 }
524
525 spin_lock_irqsave(&sender->lock, flags);
526 send_pkg(sender, DSI_DT_GENERIC_LONG_WRITE, data, len, hs);
527 spin_unlock_irqrestore(&sender->lock, flags);
528
529 return 0;
530}
531
532static int __read_panel_data(struct mdfld_dsi_pkg_sender *sender, u8 data_type,
533 u8 *data, u16 len, u32 *data_out, u16 len_out, bool hs)
534{
535 unsigned long flags;
536 struct drm_device *dev = sender->dev;
537 int i;
538 u32 gen_data_reg;
539 int retry = MDFLD_DSI_READ_MAX_COUNT;
540
541 if (!sender || !data_out || !len_out) {
542 DRM_ERROR("Invalid parameters\n");
543 return -EINVAL;
544 }
545
546 /**
547 * do reading.
548 * 0) send out generic read request
549 * 1) polling read data avail interrupt
550 * 2) read data
551 */
552 spin_lock_irqsave(&sender->lock, flags);
553
554 REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
555
556 if ((REG_READ(sender->mipi_intr_stat_reg) & BIT(29)))
557 DRM_ERROR("Can NOT clean read data valid interrupt\n");
558
559 /*send out read request*/
560 send_pkg(sender, data_type, data, len, hs);
561
562 /*polling read data avail interrupt*/
563 while (retry && !(REG_READ(sender->mipi_intr_stat_reg) & BIT(29))) {
564 udelay(100);
565 retry--;
566 }
567
568 if (!retry) {
569 spin_unlock_irqrestore(&sender->lock, flags);
570 return -ETIMEDOUT;
571 }
572
573 REG_WRITE(sender->mipi_intr_stat_reg, BIT(29));
574
575 /*read data*/
576 if (hs)
577 gen_data_reg = sender->mipi_hs_gen_data_reg;
578 else
579 gen_data_reg = sender->mipi_lp_gen_data_reg;
580
581 for (i = 0; i < len_out; i++)
582 *(data_out + i) = REG_READ(gen_data_reg);
583
584 spin_unlock_irqrestore(&sender->lock, flags);
585
586 return 0;
587}
588
589int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
590 u32 *data, u16 len, bool hs)
591{
592 if (!sender || !data || !len) {
593 DRM_ERROR("Invalid parameters\n");
594 return -EINVAL;
595 }
596
597 return __read_panel_data(sender, DSI_DT_DCS_READ, &cmd, 1,
598 data, len, hs);
599}
600
601int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
602 int pipe)
603{
604 struct mdfld_dsi_pkg_sender *pkg_sender;
605 struct mdfld_dsi_config *dsi_config =
606 mdfld_dsi_get_config(dsi_connector);
607 struct drm_device *dev = dsi_config->dev;
608 u32 mipi_val = 0;
609
610 if (!dsi_connector) {
611 DRM_ERROR("Invalid parameter\n");
612 return -EINVAL;
613 }
614
615 pkg_sender = dsi_connector->pkg_sender;
616
617 if (!pkg_sender || IS_ERR(pkg_sender)) {
618 pkg_sender = kzalloc(sizeof(struct mdfld_dsi_pkg_sender),
619 GFP_KERNEL);
620 if (!pkg_sender) {
621 DRM_ERROR("Create DSI pkg sender failed\n");
622 return -ENOMEM;
623 }
624 dsi_connector->pkg_sender = (void *)pkg_sender;
625 }
626
627 pkg_sender->dev = dev;
628 pkg_sender->dsi_connector = dsi_connector;
629 pkg_sender->pipe = pipe;
630 pkg_sender->pkg_num = 0;
631 pkg_sender->panel_mode = 0;
632 pkg_sender->status = MDFLD_DSI_PKG_SENDER_FREE;
633
634 /*init regs*/
635 if (pipe == 0) {
636 pkg_sender->dpll_reg = MRST_DPLL_A;
637 pkg_sender->dspcntr_reg = DSPACNTR;
638 pkg_sender->pipeconf_reg = PIPEACONF;
639 pkg_sender->dsplinoff_reg = DSPALINOFF;
640 pkg_sender->dspsurf_reg = DSPASURF;
641 pkg_sender->pipestat_reg = PIPEASTAT;
642 } else if (pipe == 2) {
643 pkg_sender->dpll_reg = MRST_DPLL_A;
644 pkg_sender->dspcntr_reg = DSPCCNTR;
645 pkg_sender->pipeconf_reg = PIPECCONF;
646 pkg_sender->dsplinoff_reg = DSPCLINOFF;
647 pkg_sender->dspsurf_reg = DSPCSURF;
648 pkg_sender->pipestat_reg = PIPECSTAT;
649 }
650
651 pkg_sender->mipi_intr_stat_reg = MIPI_INTR_STAT_REG(pipe);
652 pkg_sender->mipi_lp_gen_data_reg = MIPI_LP_GEN_DATA_REG(pipe);
653 pkg_sender->mipi_hs_gen_data_reg = MIPI_HS_GEN_DATA_REG(pipe);
654 pkg_sender->mipi_lp_gen_ctrl_reg = MIPI_LP_GEN_CTRL_REG(pipe);
655 pkg_sender->mipi_hs_gen_ctrl_reg = MIPI_HS_GEN_CTRL_REG(pipe);
656 pkg_sender->mipi_gen_fifo_stat_reg = MIPI_GEN_FIFO_STAT_REG(pipe);
657 pkg_sender->mipi_data_addr_reg = MIPI_DATA_ADD_REG(pipe);
658 pkg_sender->mipi_data_len_reg = MIPI_DATA_LEN_REG(pipe);
659 pkg_sender->mipi_cmd_addr_reg = MIPI_CMD_ADD_REG(pipe);
660 pkg_sender->mipi_cmd_len_reg = MIPI_CMD_LEN_REG(pipe);
661
662 /*init lock*/
663 spin_lock_init(&pkg_sender->lock);
664
665 if (mdfld_get_panel_type(dev, pipe) != TC35876X) {
666 /**
667 * For video mode, don't enable DPI timing output here,
668 * will init the DPI timing output during mode setting.
669 */
670 mipi_val = PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX;
671
672 if (pipe == 0)
673 mipi_val |= 0x2;
674
675 REG_WRITE(MIPI_PORT_CONTROL(pipe), mipi_val);
676 REG_READ(MIPI_PORT_CONTROL(pipe));
677
678 /* do dsi controller init */
679 mdfld_dsi_controller_init(dsi_config, pipe);
680 }
681
682 return 0;
683}
684
685void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender)
686{
687 if (!sender || IS_ERR(sender))
688 return;
689
690 /*free*/
691 kfree(sender);
692}
693
694
diff --git a/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h
new file mode 100644
index 000000000000..459cd7ea8b81
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_dsi_pkg_sender.h
@@ -0,0 +1,92 @@
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
33struct mdfld_dsi_pkg_sender {
34 struct drm_device *dev;
35 struct mdfld_dsi_connector *dsi_connector;
36 u32 status;
37 u32 panel_mode;
38
39 int pipe;
40
41 spinlock_t lock;
42
43 u32 pkg_num;
44
45 /* Registers */
46 u32 dpll_reg;
47 u32 dspcntr_reg;
48 u32 pipeconf_reg;
49 u32 pipestat_reg;
50 u32 dsplinoff_reg;
51 u32 dspsurf_reg;
52
53 u32 mipi_intr_stat_reg;
54 u32 mipi_lp_gen_data_reg;
55 u32 mipi_hs_gen_data_reg;
56 u32 mipi_lp_gen_ctrl_reg;
57 u32 mipi_hs_gen_ctrl_reg;
58 u32 mipi_gen_fifo_stat_reg;
59 u32 mipi_data_addr_reg;
60 u32 mipi_data_len_reg;
61 u32 mipi_cmd_addr_reg;
62 u32 mipi_cmd_len_reg;
63};
64
65/* DCS definitions */
66#define DCS_SOFT_RESET 0x01
67#define DCS_ENTER_SLEEP_MODE 0x10
68#define DCS_EXIT_SLEEP_MODE 0x11
69#define DCS_SET_DISPLAY_OFF 0x28
70#define DCS_SET_DISPLAY_ON 0x29
71#define DCS_SET_COLUMN_ADDRESS 0x2a
72#define DCS_SET_PAGE_ADDRESS 0x2b
73#define DCS_WRITE_MEM_START 0x2c
74#define DCS_SET_TEAR_OFF 0x34
75#define DCS_SET_TEAR_ON 0x35
76
77extern int mdfld_dsi_pkg_sender_init(struct mdfld_dsi_connector *dsi_connector,
78 int pipe);
79extern void mdfld_dsi_pkg_sender_destroy(struct mdfld_dsi_pkg_sender *sender);
80int mdfld_dsi_send_mcs_short(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
81 u8 param, u8 param_num, bool hs);
82int mdfld_dsi_send_mcs_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
83 u32 len, bool hs);
84int mdfld_dsi_send_gen_short(struct mdfld_dsi_pkg_sender *sender, u8 param0,
85 u8 param1, u8 param_num, bool hs);
86int mdfld_dsi_send_gen_long(struct mdfld_dsi_pkg_sender *sender, u8 *data,
87 u32 len, bool hs);
88/* Read interfaces */
89int mdfld_dsi_read_mcs(struct mdfld_dsi_pkg_sender *sender, u8 cmd,
90 u32 *data, u16 len, bool hs);
91
92#endif
diff --git a/drivers/gpu/drm/gma500/mdfld_intel_display.c b/drivers/gpu/drm/gma500/mdfld_intel_display.c
new file mode 100644
index 000000000000..55e5af5cbd3d
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_intel_display.c
@@ -0,0 +1,1192 @@
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/pm_runtime.h>
23
24#include <drm/drmP.h>
25#include "psb_intel_reg.h"
26#include "psb_intel_display.h"
27#include "framebuffer.h"
28#include "mdfld_output.h"
29#include "mdfld_dsi_output.h"
30
31/* Hardcoded currently */
32static int ksel = KSEL_CRYSTAL_19;
33
34struct psb_intel_range_t {
35 int min, max;
36};
37
38struct mrst_limit_t {
39 struct psb_intel_range_t dot, m, p1;
40};
41
42struct mrst_clock_t {
43 /* derived values */
44 int dot;
45 int m;
46 int p1;
47};
48
49#define COUNT_MAX 0x10000000
50
51void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe)
52{
53 int count, temp;
54 u32 pipeconf_reg = PIPEACONF;
55
56 switch (pipe) {
57 case 0:
58 break;
59 case 1:
60 pipeconf_reg = PIPEBCONF;
61 break;
62 case 2:
63 pipeconf_reg = PIPECCONF;
64 break;
65 default:
66 DRM_ERROR("Illegal Pipe Number.\n");
67 return;
68 }
69
70 /* FIXME JLIU7_PO */
71 psb_intel_wait_for_vblank(dev);
72 return;
73
74 /* Wait for for the pipe disable to take effect. */
75 for (count = 0; count < COUNT_MAX; count++) {
76 temp = REG_READ(pipeconf_reg);
77 if ((temp & PIPEACONF_PIPE_STATE) == 0)
78 break;
79 }
80}
81
82void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe)
83{
84 int count, temp;
85 u32 pipeconf_reg = PIPEACONF;
86
87 switch (pipe) {
88 case 0:
89 break;
90 case 1:
91 pipeconf_reg = PIPEBCONF;
92 break;
93 case 2:
94 pipeconf_reg = PIPECCONF;
95 break;
96 default:
97 DRM_ERROR("Illegal Pipe Number.\n");
98 return;
99 }
100
101 /* FIXME JLIU7_PO */
102 psb_intel_wait_for_vblank(dev);
103 return;
104
105 /* Wait for for the pipe enable to take effect. */
106 for (count = 0; count < COUNT_MAX; count++) {
107 temp = REG_READ(pipeconf_reg);
108 if ((temp & PIPEACONF_PIPE_STATE) == 1)
109 break;
110 }
111}
112
113static void psb_intel_crtc_prepare(struct drm_crtc *crtc)
114{
115 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
116 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_OFF);
117}
118
119static void psb_intel_crtc_commit(struct drm_crtc *crtc)
120{
121 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
122 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
123}
124
125static bool psb_intel_crtc_mode_fixup(struct drm_crtc *crtc,
126 struct drm_display_mode *mode,
127 struct drm_display_mode *adjusted_mode)
128{
129 return true;
130}
131
132/**
133 * Return the pipe currently connected to the panel fitter,
134 * or -1 if the panel fitter is not present or not in use
135 */
136static int psb_intel_panel_fitter_pipe(struct drm_device *dev)
137{
138 u32 pfit_control;
139
140 pfit_control = REG_READ(PFIT_CONTROL);
141
142 /* See if the panel fitter is in use */
143 if ((pfit_control & PFIT_ENABLE) == 0)
144 return -1;
145
146 /* 965 can place panel fitter on either pipe */
147 return (pfit_control >> 29) & 0x3;
148}
149
150static struct drm_device globle_dev;
151
152void mdfld__intel_plane_set_alpha(int enable)
153{
154 struct drm_device *dev = &globle_dev;
155 int dspcntr_reg = DSPACNTR;
156 u32 dspcntr;
157
158 dspcntr = REG_READ(dspcntr_reg);
159
160 if (enable) {
161 dspcntr &= ~DISPPLANE_32BPP_NO_ALPHA;
162 dspcntr |= DISPPLANE_32BPP;
163 } else {
164 dspcntr &= ~DISPPLANE_32BPP;
165 dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
166 }
167
168 REG_WRITE(dspcntr_reg, dspcntr);
169}
170
171static int check_fb(struct drm_framebuffer *fb)
172{
173 if (!fb)
174 return 0;
175
176 switch (fb->bits_per_pixel) {
177 case 8:
178 case 16:
179 case 24:
180 case 32:
181 return 0;
182 default:
183 DRM_ERROR("Unknown color depth\n");
184 return -EINVAL;
185 }
186}
187
188static int mdfld__intel_pipe_set_base(struct drm_crtc *crtc, int x, int y,
189 struct drm_framebuffer *old_fb)
190{
191 struct drm_device *dev = crtc->dev;
192 /* struct drm_i915_master_private *master_priv; */
193 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
194 struct psb_framebuffer *psbfb = to_psb_fb(crtc->fb);
195 int pipe = psb_intel_crtc->pipe;
196 unsigned long start, offset;
197 int dsplinoff = DSPALINOFF;
198 int dspsurf = DSPASURF;
199 int dspstride = DSPASTRIDE;
200 int dspcntr_reg = DSPACNTR;
201 u32 dspcntr;
202 int ret;
203
204 memcpy(&globle_dev, dev, sizeof(struct drm_device));
205
206 dev_dbg(dev->dev, "pipe = 0x%x.\n", pipe);
207
208 /* no fb bound */
209 if (!crtc->fb) {
210 dev_dbg(dev->dev, "No FB bound\n");
211 return 0;
212 }
213
214 ret = check_fb(crtc->fb);
215 if (ret)
216 return ret;
217
218 switch (pipe) {
219 case 0:
220 dsplinoff = DSPALINOFF;
221 break;
222 case 1:
223 dsplinoff = DSPBLINOFF;
224 dspsurf = DSPBSURF;
225 dspstride = DSPBSTRIDE;
226 dspcntr_reg = DSPBCNTR;
227 break;
228 case 2:
229 dsplinoff = DSPCLINOFF;
230 dspsurf = DSPCSURF;
231 dspstride = DSPCSTRIDE;
232 dspcntr_reg = DSPCCNTR;
233 break;
234 default:
235 DRM_ERROR("Illegal Pipe Number.\n");
236 return -EINVAL;
237 }
238
239 if (!gma_power_begin(dev, true))
240 return 0;
241
242 start = psbfb->gtt->offset;
243 offset = y * crtc->fb->pitches[0] + x * (crtc->fb->bits_per_pixel / 8);
244
245 REG_WRITE(dspstride, crtc->fb->pitches[0]);
246 dspcntr = REG_READ(dspcntr_reg);
247 dspcntr &= ~DISPPLANE_PIXFORMAT_MASK;
248
249 switch (crtc->fb->bits_per_pixel) {
250 case 8:
251 dspcntr |= DISPPLANE_8BPP;
252 break;
253 case 16:
254 if (crtc->fb->depth == 15)
255 dspcntr |= DISPPLANE_15_16BPP;
256 else
257 dspcntr |= DISPPLANE_16BPP;
258 break;
259 case 24:
260 case 32:
261 dspcntr |= DISPPLANE_32BPP_NO_ALPHA;
262 break;
263 }
264 REG_WRITE(dspcntr_reg, dspcntr);
265
266 dev_dbg(dev->dev, "Writing base %08lX %08lX %d %d\n",
267 start, offset, x, y);
268 REG_WRITE(dsplinoff, offset);
269 REG_READ(dsplinoff);
270 REG_WRITE(dspsurf, start);
271 REG_READ(dspsurf);
272
273 gma_power_end(dev);
274
275 return 0;
276}
277
278/*
279 * Disable the pipe, plane and pll.
280 *
281 */
282void mdfld_disable_crtc(struct drm_device *dev, int pipe)
283{
284 int dpll_reg = MRST_DPLL_A;
285 int dspcntr_reg = DSPACNTR;
286 int dspbase_reg = MRST_DSPABASE;
287 int pipeconf_reg = PIPEACONF;
288 u32 temp;
289
290 dev_dbg(dev->dev, "pipe = %d\n", pipe);
291
292
293 switch (pipe) {
294 case 0:
295 break;
296 case 1:
297 dpll_reg = MDFLD_DPLL_B;
298 dspcntr_reg = DSPBCNTR;
299 dspbase_reg = DSPBSURF;
300 pipeconf_reg = PIPEBCONF;
301 break;
302 case 2:
303 dpll_reg = MRST_DPLL_A;
304 dspcntr_reg = DSPCCNTR;
305 dspbase_reg = MDFLD_DSPCBASE;
306 pipeconf_reg = PIPECCONF;
307 break;
308 default:
309 DRM_ERROR("Illegal Pipe Number.\n");
310 return;
311 }
312
313 if (pipe != 1)
314 mdfld_dsi_gen_fifo_ready(dev, MIPI_GEN_FIFO_STAT_REG(pipe),
315 HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
316
317 /* Disable display plane */
318 temp = REG_READ(dspcntr_reg);
319 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
320 REG_WRITE(dspcntr_reg,
321 temp & ~DISPLAY_PLANE_ENABLE);
322 /* Flush the plane changes */
323 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
324 REG_READ(dspbase_reg);
325 }
326
327 /* FIXME_JLIU7 MDFLD_PO revisit */
328
329 /* Next, disable display pipes */
330 temp = REG_READ(pipeconf_reg);
331 if ((temp & PIPEACONF_ENABLE) != 0) {
332 temp &= ~PIPEACONF_ENABLE;
333 temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
334 REG_WRITE(pipeconf_reg, temp);
335 REG_READ(pipeconf_reg);
336
337 /* Wait for for the pipe disable to take effect. */
338 mdfldWaitForPipeDisable(dev, pipe);
339 }
340
341 temp = REG_READ(dpll_reg);
342 if (temp & DPLL_VCO_ENABLE) {
343 if ((pipe != 1 &&
344 !((REG_READ(PIPEACONF) | REG_READ(PIPECCONF))
345 & PIPEACONF_ENABLE)) || pipe == 1) {
346 temp &= ~(DPLL_VCO_ENABLE);
347 REG_WRITE(dpll_reg, temp);
348 REG_READ(dpll_reg);
349 /* Wait for the clocks to turn off. */
350 /* FIXME_MDFLD PO may need more delay */
351 udelay(500);
352
353 if (!(temp & MDFLD_PWR_GATE_EN)) {
354 /* gating power of DPLL */
355 REG_WRITE(dpll_reg, temp | MDFLD_PWR_GATE_EN);
356 /* FIXME_MDFLD PO - change 500 to 1 after PO */
357 udelay(5000);
358 }
359 }
360 }
361
362}
363
364/**
365 * Sets the power management mode of the pipe and plane.
366 *
367 * This code should probably grow support for turning the cursor off and back
368 * on appropriately at the same time as we're turning the pipe off/on.
369 */
370static void mdfld_crtc_dpms(struct drm_crtc *crtc, int mode)
371{
372 struct drm_device *dev = crtc->dev;
373 struct drm_psb_private *dev_priv = dev->dev_private;
374 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
375 int pipe = psb_intel_crtc->pipe;
376 int dpll_reg = MRST_DPLL_A;
377 int dspcntr_reg = DSPACNTR;
378 int dspbase_reg = MRST_DSPABASE;
379 int pipeconf_reg = PIPEACONF;
380 u32 pipestat_reg = PIPEASTAT;
381 u32 pipeconf = dev_priv->pipeconf[pipe];
382 u32 temp;
383 bool enabled;
384 int timeout = 0;
385
386 dev_dbg(dev->dev, "mode = %d, pipe = %d\n", mode, pipe);
387
388/* FIXME_JLIU7 MDFLD_PO replaced w/ the following function */
389/* mdfld_dbi_dpms (struct drm_device *dev, int pipe, bool enabled) */
390
391 switch (pipe) {
392 case 0:
393 break;
394 case 1:
395 dpll_reg = DPLL_B;
396 dspcntr_reg = DSPBCNTR;
397 dspbase_reg = MRST_DSPBBASE;
398 pipeconf_reg = PIPEBCONF;
399 dpll_reg = MDFLD_DPLL_B;
400 break;
401 case 2:
402 dpll_reg = MRST_DPLL_A;
403 dspcntr_reg = DSPCCNTR;
404 dspbase_reg = MDFLD_DSPCBASE;
405 pipeconf_reg = PIPECCONF;
406 pipestat_reg = PIPECSTAT;
407 break;
408 default:
409 DRM_ERROR("Illegal Pipe Number.\n");
410 return;
411 }
412
413 if (!gma_power_begin(dev, true))
414 return;
415
416 /* XXX: When our outputs are all unaware of DPMS modes other than off
417 * and on, we should map those modes to DRM_MODE_DPMS_OFF in the CRTC.
418 */
419 switch (mode) {
420 case DRM_MODE_DPMS_ON:
421 case DRM_MODE_DPMS_STANDBY:
422 case DRM_MODE_DPMS_SUSPEND:
423 /* Enable the DPLL */
424 temp = REG_READ(dpll_reg);
425
426 if ((temp & DPLL_VCO_ENABLE) == 0) {
427 /* When ungating power of DPLL, needs to wait 0.5us
428 before enable the VCO */
429 if (temp & MDFLD_PWR_GATE_EN) {
430 temp &= ~MDFLD_PWR_GATE_EN;
431 REG_WRITE(dpll_reg, temp);
432 /* FIXME_MDFLD PO - change 500 to 1 after PO */
433 udelay(500);
434 }
435
436 REG_WRITE(dpll_reg, temp);
437 REG_READ(dpll_reg);
438 /* FIXME_MDFLD PO - change 500 to 1 after PO */
439 udelay(500);
440
441 REG_WRITE(dpll_reg, temp | DPLL_VCO_ENABLE);
442 REG_READ(dpll_reg);
443
444 /**
445 * wait for DSI PLL to lock
446 * NOTE: only need to poll status of pipe 0 and pipe 1,
447 * since both MIPI pipes share the same PLL.
448 */
449 while ((pipe != 2) && (timeout < 20000) &&
450 !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
451 udelay(150);
452 timeout++;
453 }
454 }
455
456 /* Enable the plane */
457 temp = REG_READ(dspcntr_reg);
458 if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
459 REG_WRITE(dspcntr_reg,
460 temp | DISPLAY_PLANE_ENABLE);
461 /* Flush the plane changes */
462 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
463 }
464
465 /* Enable the pipe */
466 temp = REG_READ(pipeconf_reg);
467 if ((temp & PIPEACONF_ENABLE) == 0) {
468 REG_WRITE(pipeconf_reg, pipeconf);
469
470 /* Wait for for the pipe enable to take effect. */
471 mdfldWaitForPipeEnable(dev, pipe);
472 }
473
474 /*workaround for sighting 3741701 Random X blank display*/
475 /*perform w/a in video mode only on pipe A or C*/
476 if (pipe == 0 || pipe == 2) {
477 REG_WRITE(pipestat_reg, REG_READ(pipestat_reg));
478 msleep(100);
479 if (PIPE_VBLANK_STATUS & REG_READ(pipestat_reg))
480 dev_dbg(dev->dev, "OK");
481 else {
482 dev_dbg(dev->dev, "STUCK!!!!");
483 /*shutdown controller*/
484 temp = REG_READ(dspcntr_reg);
485 REG_WRITE(dspcntr_reg,
486 temp & ~DISPLAY_PLANE_ENABLE);
487 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
488 /*mdfld_dsi_dpi_shut_down(dev, pipe);*/
489 REG_WRITE(0xb048, 1);
490 msleep(100);
491 temp = REG_READ(pipeconf_reg);
492 temp &= ~PIPEACONF_ENABLE;
493 REG_WRITE(pipeconf_reg, temp);
494 msleep(100); /*wait for pipe disable*/
495 REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 0);
496 msleep(100);
497 REG_WRITE(0xb004, REG_READ(0xb004));
498 /* try to bring the controller back up again*/
499 REG_WRITE(MIPI_DEVICE_READY_REG(pipe), 1);
500 temp = REG_READ(dspcntr_reg);
501 REG_WRITE(dspcntr_reg,
502 temp | DISPLAY_PLANE_ENABLE);
503 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
504 /*mdfld_dsi_dpi_turn_on(dev, pipe);*/
505 REG_WRITE(0xb048, 2);
506 msleep(100);
507 temp = REG_READ(pipeconf_reg);
508 temp |= PIPEACONF_ENABLE;
509 REG_WRITE(pipeconf_reg, temp);
510 }
511 }
512
513 psb_intel_crtc_load_lut(crtc);
514
515 /* Give the overlay scaler a chance to enable
516 if it's on this pipe */
517 /* psb_intel_crtc_dpms_video(crtc, true); TODO */
518
519 break;
520 case DRM_MODE_DPMS_OFF:
521 /* Give the overlay scaler a chance to disable
522 * if it's on this pipe */
523 /* psb_intel_crtc_dpms_video(crtc, FALSE); TODO */
524 if (pipe != 1)
525 mdfld_dsi_gen_fifo_ready(dev,
526 MIPI_GEN_FIFO_STAT_REG(pipe),
527 HS_CTRL_FIFO_EMPTY | HS_DATA_FIFO_EMPTY);
528
529 /* Disable the VGA plane that we never use */
530 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
531
532 /* Disable display plane */
533 temp = REG_READ(dspcntr_reg);
534 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
535 REG_WRITE(dspcntr_reg,
536 temp & ~DISPLAY_PLANE_ENABLE);
537 /* Flush the plane changes */
538 REG_WRITE(dspbase_reg, REG_READ(dspbase_reg));
539 REG_READ(dspbase_reg);
540 }
541
542 /* Next, disable display pipes */
543 temp = REG_READ(pipeconf_reg);
544 if ((temp & PIPEACONF_ENABLE) != 0) {
545 temp &= ~PIPEACONF_ENABLE;
546 temp |= PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF;
547 REG_WRITE(pipeconf_reg, temp);
548 REG_READ(pipeconf_reg);
549
550 /* Wait for for the pipe disable to take effect. */
551 mdfldWaitForPipeDisable(dev, pipe);
552 }
553
554 temp = REG_READ(dpll_reg);
555 if (temp & DPLL_VCO_ENABLE) {
556 if ((pipe != 1 && !((REG_READ(PIPEACONF)
557 | REG_READ(PIPECCONF)) & PIPEACONF_ENABLE))
558 || pipe == 1) {
559 temp &= ~(DPLL_VCO_ENABLE);
560 REG_WRITE(dpll_reg, temp);
561 REG_READ(dpll_reg);
562 /* Wait for the clocks to turn off. */
563 /* FIXME_MDFLD PO may need more delay */
564 udelay(500);
565 }
566 }
567 break;
568 }
569 enabled = crtc->enabled && mode != DRM_MODE_DPMS_OFF;
570 gma_power_end(dev);
571}
572
573
574#define MDFLD_LIMT_DPLL_19 0
575#define MDFLD_LIMT_DPLL_25 1
576#define MDFLD_LIMT_DPLL_83 2
577#define MDFLD_LIMT_DPLL_100 3
578#define MDFLD_LIMT_DSIPLL_19 4
579#define MDFLD_LIMT_DSIPLL_25 5
580#define MDFLD_LIMT_DSIPLL_83 6
581#define MDFLD_LIMT_DSIPLL_100 7
582
583#define MDFLD_DOT_MIN 19750
584#define MDFLD_DOT_MAX 120000
585#define MDFLD_DPLL_M_MIN_19 113
586#define MDFLD_DPLL_M_MAX_19 155
587#define MDFLD_DPLL_P1_MIN_19 2
588#define MDFLD_DPLL_P1_MAX_19 10
589#define MDFLD_DPLL_M_MIN_25 101
590#define MDFLD_DPLL_M_MAX_25 130
591#define MDFLD_DPLL_P1_MIN_25 2
592#define MDFLD_DPLL_P1_MAX_25 10
593#define MDFLD_DPLL_M_MIN_83 64
594#define MDFLD_DPLL_M_MAX_83 64
595#define MDFLD_DPLL_P1_MIN_83 2
596#define MDFLD_DPLL_P1_MAX_83 2
597#define MDFLD_DPLL_M_MIN_100 64
598#define MDFLD_DPLL_M_MAX_100 64
599#define MDFLD_DPLL_P1_MIN_100 2
600#define MDFLD_DPLL_P1_MAX_100 2
601#define MDFLD_DSIPLL_M_MIN_19 131
602#define MDFLD_DSIPLL_M_MAX_19 175
603#define MDFLD_DSIPLL_P1_MIN_19 3
604#define MDFLD_DSIPLL_P1_MAX_19 8
605#define MDFLD_DSIPLL_M_MIN_25 97
606#define MDFLD_DSIPLL_M_MAX_25 140
607#define MDFLD_DSIPLL_P1_MIN_25 3
608#define MDFLD_DSIPLL_P1_MAX_25 9
609#define MDFLD_DSIPLL_M_MIN_83 33
610#define MDFLD_DSIPLL_M_MAX_83 92
611#define MDFLD_DSIPLL_P1_MIN_83 2
612#define MDFLD_DSIPLL_P1_MAX_83 3
613#define MDFLD_DSIPLL_M_MIN_100 97
614#define MDFLD_DSIPLL_M_MAX_100 140
615#define MDFLD_DSIPLL_P1_MIN_100 3
616#define MDFLD_DSIPLL_P1_MAX_100 9
617
618static const struct mrst_limit_t mdfld_limits[] = {
619 { /* MDFLD_LIMT_DPLL_19 */
620 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
621 .m = {.min = MDFLD_DPLL_M_MIN_19, .max = MDFLD_DPLL_M_MAX_19},
622 .p1 = {.min = MDFLD_DPLL_P1_MIN_19, .max = MDFLD_DPLL_P1_MAX_19},
623 },
624 { /* MDFLD_LIMT_DPLL_25 */
625 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
626 .m = {.min = MDFLD_DPLL_M_MIN_25, .max = MDFLD_DPLL_M_MAX_25},
627 .p1 = {.min = MDFLD_DPLL_P1_MIN_25, .max = MDFLD_DPLL_P1_MAX_25},
628 },
629 { /* MDFLD_LIMT_DPLL_83 */
630 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
631 .m = {.min = MDFLD_DPLL_M_MIN_83, .max = MDFLD_DPLL_M_MAX_83},
632 .p1 = {.min = MDFLD_DPLL_P1_MIN_83, .max = MDFLD_DPLL_P1_MAX_83},
633 },
634 { /* MDFLD_LIMT_DPLL_100 */
635 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
636 .m = {.min = MDFLD_DPLL_M_MIN_100, .max = MDFLD_DPLL_M_MAX_100},
637 .p1 = {.min = MDFLD_DPLL_P1_MIN_100, .max = MDFLD_DPLL_P1_MAX_100},
638 },
639 { /* MDFLD_LIMT_DSIPLL_19 */
640 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
641 .m = {.min = MDFLD_DSIPLL_M_MIN_19, .max = MDFLD_DSIPLL_M_MAX_19},
642 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_19, .max = MDFLD_DSIPLL_P1_MAX_19},
643 },
644 { /* MDFLD_LIMT_DSIPLL_25 */
645 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
646 .m = {.min = MDFLD_DSIPLL_M_MIN_25, .max = MDFLD_DSIPLL_M_MAX_25},
647 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_25, .max = MDFLD_DSIPLL_P1_MAX_25},
648 },
649 { /* MDFLD_LIMT_DSIPLL_83 */
650 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
651 .m = {.min = MDFLD_DSIPLL_M_MIN_83, .max = MDFLD_DSIPLL_M_MAX_83},
652 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_83, .max = MDFLD_DSIPLL_P1_MAX_83},
653 },
654 { /* MDFLD_LIMT_DSIPLL_100 */
655 .dot = {.min = MDFLD_DOT_MIN, .max = MDFLD_DOT_MAX},
656 .m = {.min = MDFLD_DSIPLL_M_MIN_100, .max = MDFLD_DSIPLL_M_MAX_100},
657 .p1 = {.min = MDFLD_DSIPLL_P1_MIN_100, .max = MDFLD_DSIPLL_P1_MAX_100},
658 },
659};
660
661#define MDFLD_M_MIN 21
662#define MDFLD_M_MAX 180
663static const u32 mdfld_m_converts[] = {
664/* M configuration table from 9-bit LFSR table */
665 224, 368, 440, 220, 366, 439, 219, 365, 182, 347, /* 21 - 30 */
666 173, 342, 171, 85, 298, 149, 74, 37, 18, 265, /* 31 - 40 */
667 388, 194, 353, 432, 216, 108, 310, 155, 333, 166, /* 41 - 50 */
668 83, 41, 276, 138, 325, 162, 337, 168, 340, 170, /* 51 - 60 */
669 341, 426, 469, 234, 373, 442, 221, 110, 311, 411, /* 61 - 70 */
670 461, 486, 243, 377, 188, 350, 175, 343, 427, 213, /* 71 - 80 */
671 106, 53, 282, 397, 354, 227, 113, 56, 284, 142, /* 81 - 90 */
672 71, 35, 273, 136, 324, 418, 465, 488, 500, 506, /* 91 - 100 */
673 253, 126, 63, 287, 399, 455, 483, 241, 376, 444, /* 101 - 110 */
674 478, 495, 503, 251, 381, 446, 479, 239, 375, 443, /* 111 - 120 */
675 477, 238, 119, 315, 157, 78, 295, 147, 329, 420, /* 121 - 130 */
676 210, 105, 308, 154, 77, 38, 275, 137, 68, 290, /* 131 - 140 */
677 145, 328, 164, 82, 297, 404, 458, 485, 498, 249, /* 141 - 150 */
678 380, 190, 351, 431, 471, 235, 117, 314, 413, 206, /* 151 - 160 */
679 103, 51, 25, 12, 262, 387, 193, 96, 48, 280, /* 161 - 170 */
680 396, 198, 99, 305, 152, 76, 294, 403, 457, 228, /* 171 - 180 */
681};
682
683static const struct mrst_limit_t *mdfld_limit(struct drm_crtc *crtc)
684{
685 const struct mrst_limit_t *limit = NULL;
686 struct drm_device *dev = crtc->dev;
687 struct drm_psb_private *dev_priv = dev->dev_private;
688
689 if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI)
690 || psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_MIPI2)) {
691 if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
692 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_19];
693 else if (ksel == KSEL_BYPASS_25)
694 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_25];
695 else if ((ksel == KSEL_BYPASS_83_100) &&
696 (dev_priv->core_freq == 166))
697 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_83];
698 else if ((ksel == KSEL_BYPASS_83_100) &&
699 (dev_priv->core_freq == 100 ||
700 dev_priv->core_freq == 200))
701 limit = &mdfld_limits[MDFLD_LIMT_DSIPLL_100];
702 } else if (psb_intel_pipe_has_type(crtc, INTEL_OUTPUT_HDMI)) {
703 if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19))
704 limit = &mdfld_limits[MDFLD_LIMT_DPLL_19];
705 else if (ksel == KSEL_BYPASS_25)
706 limit = &mdfld_limits[MDFLD_LIMT_DPLL_25];
707 else if ((ksel == KSEL_BYPASS_83_100) &&
708 (dev_priv->core_freq == 166))
709 limit = &mdfld_limits[MDFLD_LIMT_DPLL_83];
710 else if ((ksel == KSEL_BYPASS_83_100) &&
711 (dev_priv->core_freq == 100 ||
712 dev_priv->core_freq == 200))
713 limit = &mdfld_limits[MDFLD_LIMT_DPLL_100];
714 } else {
715 limit = NULL;
716 dev_dbg(dev->dev, "mdfld_limit Wrong display type.\n");
717 }
718
719 return limit;
720}
721
722/** Derive the pixel clock for the given refclk and divisors for 8xx chips. */
723static void mdfld_clock(int refclk, struct mrst_clock_t *clock)
724{
725 clock->dot = (refclk * clock->m) / clock->p1;
726}
727
728/**
729 * Returns a set of divisors for the desired target clock with the given refclk,
730 * or FALSE. Divisor values are the actual divisors for
731 */
732static bool
733mdfldFindBestPLL(struct drm_crtc *crtc, int target, int refclk,
734 struct mrst_clock_t *best_clock)
735{
736 struct mrst_clock_t clock;
737 const struct mrst_limit_t *limit = mdfld_limit(crtc);
738 int err = target;
739
740 memset(best_clock, 0, sizeof(*best_clock));
741
742 for (clock.m = limit->m.min; clock.m <= limit->m.max; clock.m++) {
743 for (clock.p1 = limit->p1.min; clock.p1 <= limit->p1.max;
744 clock.p1++) {
745 int this_err;
746
747 mdfld_clock(refclk, &clock);
748
749 this_err = abs(clock.dot - target);
750 if (this_err < err) {
751 *best_clock = clock;
752 err = this_err;
753 }
754 }
755 }
756 return err != target;
757}
758
759static int mdfld_crtc_mode_set(struct drm_crtc *crtc,
760 struct drm_display_mode *mode,
761 struct drm_display_mode *adjusted_mode,
762 int x, int y,
763 struct drm_framebuffer *old_fb)
764{
765 struct drm_device *dev = crtc->dev;
766 struct psb_intel_crtc *psb_intel_crtc = to_psb_intel_crtc(crtc);
767 struct drm_psb_private *dev_priv = dev->dev_private;
768 int pipe = psb_intel_crtc->pipe;
769 int fp_reg = MRST_FPA0;
770 int dpll_reg = MRST_DPLL_A;
771 int dspcntr_reg = DSPACNTR;
772 int pipeconf_reg = PIPEACONF;
773 int htot_reg = HTOTAL_A;
774 int hblank_reg = HBLANK_A;
775 int hsync_reg = HSYNC_A;
776 int vtot_reg = VTOTAL_A;
777 int vblank_reg = VBLANK_A;
778 int vsync_reg = VSYNC_A;
779 int dspsize_reg = DSPASIZE;
780 int dsppos_reg = DSPAPOS;
781 int pipesrc_reg = PIPEASRC;
782 u32 *pipeconf = &dev_priv->pipeconf[pipe];
783 u32 *dspcntr = &dev_priv->dspcntr[pipe];
784 int refclk = 0;
785 int clk_n = 0, clk_p2 = 0, clk_byte = 1, clk = 0, m_conv = 0,
786 clk_tmp = 0;
787 struct mrst_clock_t clock;
788 bool ok;
789 u32 dpll = 0, fp = 0;
790 bool is_crt = false, is_lvds = false, is_tv = false;
791 bool is_mipi = false, is_mipi2 = false, is_hdmi = false;
792 struct drm_mode_config *mode_config = &dev->mode_config;
793 struct psb_intel_encoder *psb_intel_encoder = NULL;
794 uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
795 struct drm_encoder *encoder;
796 struct drm_connector *connector;
797 int timeout = 0;
798 int ret;
799
800 dev_dbg(dev->dev, "pipe = 0x%x\n", pipe);
801
802#if 0
803 if (pipe == 1) {
804 if (!gma_power_begin(dev, true))
805 return 0;
806 android_hdmi_crtc_mode_set(crtc, mode, adjusted_mode,
807 x, y, old_fb);
808 goto mrst_crtc_mode_set_exit;
809 }
810#endif
811
812 switch (pipe) {
813 case 0:
814 break;
815 case 1:
816 fp_reg = FPB0;
817 dpll_reg = DPLL_B;
818 dspcntr_reg = DSPBCNTR;
819 pipeconf_reg = PIPEBCONF;
820 htot_reg = HTOTAL_B;
821 hblank_reg = HBLANK_B;
822 hsync_reg = HSYNC_B;
823 vtot_reg = VTOTAL_B;
824 vblank_reg = VBLANK_B;
825 vsync_reg = VSYNC_B;
826 dspsize_reg = DSPBSIZE;
827 dsppos_reg = DSPBPOS;
828 pipesrc_reg = PIPEBSRC;
829 fp_reg = MDFLD_DPLL_DIV0;
830 dpll_reg = MDFLD_DPLL_B;
831 break;
832 case 2:
833 dpll_reg = MRST_DPLL_A;
834 dspcntr_reg = DSPCCNTR;
835 pipeconf_reg = PIPECCONF;
836 htot_reg = HTOTAL_C;
837 hblank_reg = HBLANK_C;
838 hsync_reg = HSYNC_C;
839 vtot_reg = VTOTAL_C;
840 vblank_reg = VBLANK_C;
841 vsync_reg = VSYNC_C;
842 dspsize_reg = DSPCSIZE;
843 dsppos_reg = DSPCPOS;
844 pipesrc_reg = PIPECSRC;
845 break;
846 default:
847 DRM_ERROR("Illegal Pipe Number.\n");
848 return 0;
849 }
850
851 ret = check_fb(crtc->fb);
852 if (ret)
853 return ret;
854
855 dev_dbg(dev->dev, "adjusted_hdisplay = %d\n",
856 adjusted_mode->hdisplay);
857 dev_dbg(dev->dev, "adjusted_vdisplay = %d\n",
858 adjusted_mode->vdisplay);
859 dev_dbg(dev->dev, "adjusted_hsync_start = %d\n",
860 adjusted_mode->hsync_start);
861 dev_dbg(dev->dev, "adjusted_hsync_end = %d\n",
862 adjusted_mode->hsync_end);
863 dev_dbg(dev->dev, "adjusted_htotal = %d\n",
864 adjusted_mode->htotal);
865 dev_dbg(dev->dev, "adjusted_vsync_start = %d\n",
866 adjusted_mode->vsync_start);
867 dev_dbg(dev->dev, "adjusted_vsync_end = %d\n",
868 adjusted_mode->vsync_end);
869 dev_dbg(dev->dev, "adjusted_vtotal = %d\n",
870 adjusted_mode->vtotal);
871 dev_dbg(dev->dev, "adjusted_clock = %d\n",
872 adjusted_mode->clock);
873 dev_dbg(dev->dev, "hdisplay = %d\n",
874 mode->hdisplay);
875 dev_dbg(dev->dev, "vdisplay = %d\n",
876 mode->vdisplay);
877
878 if (!gma_power_begin(dev, true))
879 return 0;
880
881 memcpy(&psb_intel_crtc->saved_mode, mode,
882 sizeof(struct drm_display_mode));
883 memcpy(&psb_intel_crtc->saved_adjusted_mode, adjusted_mode,
884 sizeof(struct drm_display_mode));
885
886 list_for_each_entry(connector, &mode_config->connector_list, head) {
887 if (!connector)
888 continue;
889
890 encoder = connector->encoder;
891
892 if (!encoder)
893 continue;
894
895 if (encoder->crtc != crtc)
896 continue;
897
898 psb_intel_encoder = psb_intel_attached_encoder(connector);
899
900 switch (psb_intel_encoder->type) {
901 case INTEL_OUTPUT_LVDS:
902 is_lvds = true;
903 break;
904 case INTEL_OUTPUT_TVOUT:
905 is_tv = true;
906 break;
907 case INTEL_OUTPUT_ANALOG:
908 is_crt = true;
909 break;
910 case INTEL_OUTPUT_MIPI:
911 is_mipi = true;
912 break;
913 case INTEL_OUTPUT_MIPI2:
914 is_mipi2 = true;
915 break;
916 case INTEL_OUTPUT_HDMI:
917 is_hdmi = true;
918 break;
919 }
920 }
921
922 /* Disable the VGA plane that we never use */
923 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
924
925 /* Disable the panel fitter if it was on our pipe */
926 if (psb_intel_panel_fitter_pipe(dev) == pipe)
927 REG_WRITE(PFIT_CONTROL, 0);
928
929 /* pipesrc and dspsize control the size that is scaled from,
930 * which should always be the user's requested size.
931 */
932 if (pipe == 1) {
933 /* FIXME: To make HDMI display with 864x480 (TPO), 480x864
934 * (PYR) or 480x854 (TMD), set the sprite width/height and
935 * souce image size registers with the adjusted mode for
936 * pipe B.
937 */
938
939 /*
940 * The defined sprite rectangle must always be completely
941 * contained within the displayable area of the screen image
942 * (frame buffer).
943 */
944 REG_WRITE(dspsize_reg, ((min(mode->crtc_vdisplay, adjusted_mode->crtc_vdisplay) - 1) << 16)
945 | (min(mode->crtc_hdisplay, adjusted_mode->crtc_hdisplay) - 1));
946 /* Set the CRTC with encoder mode. */
947 REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16)
948 | (mode->crtc_vdisplay - 1));
949 } else {
950 REG_WRITE(dspsize_reg,
951 ((mode->crtc_vdisplay - 1) << 16) |
952 (mode->crtc_hdisplay - 1));
953 REG_WRITE(pipesrc_reg,
954 ((mode->crtc_hdisplay - 1) << 16) |
955 (mode->crtc_vdisplay - 1));
956 }
957
958 REG_WRITE(dsppos_reg, 0);
959
960 if (psb_intel_encoder)
961 drm_connector_property_get_value(connector,
962 dev->mode_config.scaling_mode_property, &scalingType);
963
964 if (scalingType == DRM_MODE_SCALE_NO_SCALE) {
965 /* Medfield doesn't have register support for centering so we
966 * need to mess with the h/vblank and h/vsync start and ends
967 * to get centering
968 */
969 int offsetX = 0, offsetY = 0;
970
971 offsetX = (adjusted_mode->crtc_hdisplay -
972 mode->crtc_hdisplay) / 2;
973 offsetY = (adjusted_mode->crtc_vdisplay -
974 mode->crtc_vdisplay) / 2;
975
976 REG_WRITE(htot_reg, (mode->crtc_hdisplay - 1) |
977 ((adjusted_mode->crtc_htotal - 1) << 16));
978 REG_WRITE(vtot_reg, (mode->crtc_vdisplay - 1) |
979 ((adjusted_mode->crtc_vtotal - 1) << 16));
980 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start -
981 offsetX - 1) |
982 ((adjusted_mode->crtc_hblank_end - offsetX - 1) << 16));
983 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start -
984 offsetX - 1) |
985 ((adjusted_mode->crtc_hsync_end - offsetX - 1) << 16));
986 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start -
987 offsetY - 1) |
988 ((adjusted_mode->crtc_vblank_end - offsetY - 1) << 16));
989 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start -
990 offsetY - 1) |
991 ((adjusted_mode->crtc_vsync_end - offsetY - 1) << 16));
992 } else {
993 REG_WRITE(htot_reg, (adjusted_mode->crtc_hdisplay - 1) |
994 ((adjusted_mode->crtc_htotal - 1) << 16));
995 REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) |
996 ((adjusted_mode->crtc_vtotal - 1) << 16));
997 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) |
998 ((adjusted_mode->crtc_hblank_end - 1) << 16));
999 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) |
1000 ((adjusted_mode->crtc_hsync_end - 1) << 16));
1001 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) |
1002 ((adjusted_mode->crtc_vblank_end - 1) << 16));
1003 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) |
1004 ((adjusted_mode->crtc_vsync_end - 1) << 16));
1005 }
1006
1007 /* Flush the plane changes */
1008 {
1009 struct drm_crtc_helper_funcs *crtc_funcs =
1010 crtc->helper_private;
1011 crtc_funcs->mode_set_base(crtc, x, y, old_fb);
1012 }
1013
1014 /* setup pipeconf */
1015 *pipeconf = PIPEACONF_ENABLE; /* FIXME_JLIU7 REG_READ(pipeconf_reg); */
1016
1017 /* Set up the display plane register */
1018 *dspcntr = REG_READ(dspcntr_reg);
1019 *dspcntr |= pipe << DISPPLANE_SEL_PIPE_POS;
1020 *dspcntr |= DISPLAY_PLANE_ENABLE;
1021
1022 if (is_mipi2)
1023 goto mrst_crtc_mode_set_exit;
1024 clk = adjusted_mode->clock;
1025
1026 if (is_hdmi) {
1027 if ((ksel == KSEL_CRYSTAL_19) || (ksel == KSEL_BYPASS_19)) {
1028 refclk = 19200;
1029
1030 if (is_mipi || is_mipi2)
1031 clk_n = 1, clk_p2 = 8;
1032 else if (is_hdmi)
1033 clk_n = 1, clk_p2 = 10;
1034 } else if (ksel == KSEL_BYPASS_25) {
1035 refclk = 25000;
1036
1037 if (is_mipi || is_mipi2)
1038 clk_n = 1, clk_p2 = 8;
1039 else if (is_hdmi)
1040 clk_n = 1, clk_p2 = 10;
1041 } else if ((ksel == KSEL_BYPASS_83_100) &&
1042 dev_priv->core_freq == 166) {
1043 refclk = 83000;
1044
1045 if (is_mipi || is_mipi2)
1046 clk_n = 4, clk_p2 = 8;
1047 else if (is_hdmi)
1048 clk_n = 4, clk_p2 = 10;
1049 } else if ((ksel == KSEL_BYPASS_83_100) &&
1050 (dev_priv->core_freq == 100 ||
1051 dev_priv->core_freq == 200)) {
1052 refclk = 100000;
1053 if (is_mipi || is_mipi2)
1054 clk_n = 4, clk_p2 = 8;
1055 else if (is_hdmi)
1056 clk_n = 4, clk_p2 = 10;
1057 }
1058
1059 if (is_mipi)
1060 clk_byte = dev_priv->bpp / 8;
1061 else if (is_mipi2)
1062 clk_byte = dev_priv->bpp2 / 8;
1063
1064 clk_tmp = clk * clk_n * clk_p2 * clk_byte;
1065
1066 dev_dbg(dev->dev, "clk = %d, clk_n = %d, clk_p2 = %d.\n",
1067 clk, clk_n, clk_p2);
1068 dev_dbg(dev->dev, "adjusted_mode->clock = %d, clk_tmp = %d.\n",
1069 adjusted_mode->clock, clk_tmp);
1070
1071 ok = mdfldFindBestPLL(crtc, clk_tmp, refclk, &clock);
1072
1073 if (!ok) {
1074 DRM_ERROR
1075 ("mdfldFindBestPLL fail in mdfld_crtc_mode_set.\n");
1076 } else {
1077 m_conv = mdfld_m_converts[(clock.m - MDFLD_M_MIN)];
1078
1079 dev_dbg(dev->dev, "dot clock = %d,"
1080 "m = %d, p1 = %d, m_conv = %d.\n",
1081 clock.dot, clock.m,
1082 clock.p1, m_conv);
1083 }
1084
1085 dpll = REG_READ(dpll_reg);
1086
1087 if (dpll & DPLL_VCO_ENABLE) {
1088 dpll &= ~DPLL_VCO_ENABLE;
1089 REG_WRITE(dpll_reg, dpll);
1090 REG_READ(dpll_reg);
1091
1092 /* FIXME jliu7 check the DPLL lock bit PIPEACONF[29] */
1093 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1094 udelay(500);
1095
1096 /* reset M1, N1 & P1 */
1097 REG_WRITE(fp_reg, 0);
1098 dpll &= ~MDFLD_P1_MASK;
1099 REG_WRITE(dpll_reg, dpll);
1100 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1101 udelay(500);
1102 }
1103
1104 /* When ungating power of DPLL, needs to wait 0.5us before
1105 * enable the VCO */
1106 if (dpll & MDFLD_PWR_GATE_EN) {
1107 dpll &= ~MDFLD_PWR_GATE_EN;
1108 REG_WRITE(dpll_reg, dpll);
1109 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1110 udelay(500);
1111 }
1112 dpll = 0;
1113
1114#if 0 /* FIXME revisit later */
1115 if (ksel == KSEL_CRYSTAL_19 || ksel == KSEL_BYPASS_19 ||
1116 ksel == KSEL_BYPASS_25)
1117 dpll &= ~MDFLD_INPUT_REF_SEL;
1118 else if (ksel == KSEL_BYPASS_83_100)
1119 dpll |= MDFLD_INPUT_REF_SEL;
1120#endif /* FIXME revisit later */
1121
1122 if (is_hdmi)
1123 dpll |= MDFLD_VCO_SEL;
1124
1125 fp = (clk_n / 2) << 16;
1126 fp |= m_conv;
1127
1128 /* compute bitmask from p1 value */
1129 dpll |= (1 << (clock.p1 - 2)) << 17;
1130
1131#if 0 /* 1080p30 & 720p */
1132 dpll = 0x00050000;
1133 fp = 0x000001be;
1134#endif
1135#if 0 /* 480p */
1136 dpll = 0x02010000;
1137 fp = 0x000000d2;
1138#endif
1139 } else {
1140#if 0 /*DBI_TPO_480x864*/
1141 dpll = 0x00020000;
1142 fp = 0x00000156;
1143#endif /* DBI_TPO_480x864 */ /* get from spec. */
1144
1145 dpll = 0x00800000;
1146 fp = 0x000000c1;
1147 }
1148
1149 REG_WRITE(fp_reg, fp);
1150 REG_WRITE(dpll_reg, dpll);
1151 /* FIXME_MDFLD PO - change 500 to 1 after PO */
1152 udelay(500);
1153
1154 dpll |= DPLL_VCO_ENABLE;
1155 REG_WRITE(dpll_reg, dpll);
1156 REG_READ(dpll_reg);
1157
1158 /* wait for DSI PLL to lock */
1159 while (timeout < 20000 &&
1160 !(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK)) {
1161 udelay(150);
1162 timeout++;
1163 }
1164
1165 if (is_mipi)
1166 goto mrst_crtc_mode_set_exit;
1167
1168 dev_dbg(dev->dev, "is_mipi = 0x%x\n", is_mipi);
1169
1170 REG_WRITE(pipeconf_reg, *pipeconf);
1171 REG_READ(pipeconf_reg);
1172
1173 /* Wait for for the pipe enable to take effect. */
1174 REG_WRITE(dspcntr_reg, *dspcntr);
1175 psb_intel_wait_for_vblank(dev);
1176
1177mrst_crtc_mode_set_exit:
1178
1179 gma_power_end(dev);
1180
1181 return 0;
1182}
1183
1184const struct drm_crtc_helper_funcs mdfld_helper_funcs = {
1185 .dpms = mdfld_crtc_dpms,
1186 .mode_fixup = psb_intel_crtc_mode_fixup,
1187 .mode_set = mdfld_crtc_mode_set,
1188 .mode_set_base = mdfld__intel_pipe_set_base,
1189 .prepare = psb_intel_crtc_prepare,
1190 .commit = psb_intel_crtc_commit,
1191};
1192
diff --git a/drivers/gpu/drm/gma500/mdfld_output.c b/drivers/gpu/drm/gma500/mdfld_output.c
new file mode 100644
index 000000000000..de0ce0765738
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_output.c
@@ -0,0 +1,77 @@
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_output.h"
29#include "mdfld_dsi_dpi.h"
30#include "mdfld_dsi_output.h"
31
32#include "tc35876x-dsi-lvds.h"
33
34int mdfld_get_panel_type(struct drm_device *dev, int pipe)
35{
36 struct drm_psb_private *dev_priv = dev->dev_private;
37 return dev_priv->mdfld_panel_id;
38}
39
40static void mdfld_init_panel(struct drm_device *dev, int mipi_pipe,
41 int p_type)
42{
43 switch (p_type) {
44 case TPO_VID:
45 mdfld_dsi_output_init(dev, mipi_pipe, NULL,
46 &mdfld_tpo_vid_funcs);
47 break;
48 case TC35876X:
49 tc35876x_init(dev);
50 mdfld_dsi_output_init(dev, mipi_pipe, NULL,
51 &mdfld_tc35876x_funcs);
52 break;
53 case TMD_VID:
54 mdfld_dsi_output_init(dev, mipi_pipe, NULL,
55 &mdfld_tmd_vid_funcs);
56 break;
57 case HDMI:
58/* if (dev_priv->mdfld_hdmi_present)
59 mdfld_hdmi_init(dev, &dev_priv->mode_dev); */
60 break;
61 }
62}
63
64
65int mdfld_output_init(struct drm_device *dev)
66{
67 struct drm_psb_private *dev_priv = dev->dev_private;
68
69 /* FIXME: hardcoded for now */
70 dev_priv->mdfld_panel_id = TC35876X;
71 /* MIPI panel 1 */
72 mdfld_init_panel(dev, 0, dev_priv->mdfld_panel_id);
73 /* HDMI panel */
74 mdfld_init_panel(dev, 1, HDMI);
75 return 0;
76}
77
diff --git a/drivers/gpu/drm/gma500/mdfld_output.h b/drivers/gpu/drm/gma500/mdfld_output.h
new file mode 100644
index 000000000000..ab2b27c0f037
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_output.h
@@ -0,0 +1,77 @@
1/*
2 * Copyright (c) 2010 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicensen
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * Thomas Eaton <thomas.g.eaton@intel.com>
25 * Scott Rowe <scott.m.rowe@intel.com>
26*/
27
28#ifndef MDFLD_OUTPUT_H
29#define MDFLD_OUTPUT_H
30
31#include "psb_drv.h"
32
33#define TPO_PANEL_WIDTH 84
34#define TPO_PANEL_HEIGHT 46
35#define TMD_PANEL_WIDTH 39
36#define TMD_PANEL_HEIGHT 71
37
38struct mdfld_dsi_config;
39
40enum panel_type {
41 TPO_VID,
42 TMD_VID,
43 HDMI,
44 TC35876X,
45};
46
47struct panel_info {
48 u32 width_mm;
49 u32 height_mm;
50 /* Other info */
51};
52
53struct panel_funcs {
54 const struct drm_encoder_funcs *encoder_funcs;
55 const struct drm_encoder_helper_funcs *encoder_helper_funcs;
56 struct drm_display_mode * (*get_config_mode)(struct drm_device *);
57 int (*get_panel_info)(struct drm_device *, int, struct panel_info *);
58 int (*reset)(int pipe);
59 void (*drv_ic_init)(struct mdfld_dsi_config *dsi_config, int pipe);
60};
61
62int mdfld_output_init(struct drm_device *dev);
63
64struct backlight_device *mdfld_get_backlight_device(void);
65int mdfld_set_brightness(struct backlight_device *bd);
66
67int mdfld_get_panel_type(struct drm_device *dev, int pipe);
68
69extern const struct drm_crtc_helper_funcs mdfld_helper_funcs;
70
71extern const struct panel_funcs mdfld_tmd_vid_funcs;
72extern const struct panel_funcs mdfld_tpo_vid_funcs;
73
74extern void mdfld_disable_crtc(struct drm_device *dev, int pipe);
75extern void mdfldWaitForPipeEnable(struct drm_device *dev, int pipe);
76extern void mdfldWaitForPipeDisable(struct drm_device *dev, int pipe);
77#endif
diff --git a/drivers/gpu/drm/gma500/mdfld_tmd_vid.c b/drivers/gpu/drm/gma500/mdfld_tmd_vid.c
new file mode 100644
index 000000000000..dc0c6c3d3d29
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_tmd_vid.c
@@ -0,0 +1,201 @@
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_dpi.h"
31#include "mdfld_dsi_pkg_sender.h"
32
33static struct drm_display_mode *tmd_vid_get_config_mode(struct drm_device *dev)
34{
35 struct drm_display_mode *mode;
36 struct drm_psb_private *dev_priv = dev->dev_private;
37 struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD;
38 bool use_gct = false; /*Disable GCT for now*/
39
40 mode = kzalloc(sizeof(*mode), GFP_KERNEL);
41 if (!mode)
42 return NULL;
43
44 if (use_gct) {
45 mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
46 mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
47 mode->hsync_start = mode->hdisplay + \
48 ((ti->hsync_offset_hi << 8) | \
49 ti->hsync_offset_lo);
50 mode->hsync_end = mode->hsync_start + \
51 ((ti->hsync_pulse_width_hi << 8) | \
52 ti->hsync_pulse_width_lo);
53 mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
54 ti->hblank_lo);
55 mode->vsync_start = \
56 mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
57 ti->vsync_offset_lo);
58 mode->vsync_end = \
59 mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
60 ti->vsync_pulse_width_lo);
61 mode->vtotal = mode->vdisplay + \
62 ((ti->vblank_hi << 8) | ti->vblank_lo);
63 mode->clock = ti->pixel_clock * 10;
64
65 dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
66 dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
67 dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
68 dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
69 dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
70 dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
71 dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
72 dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
73 dev_dbg(dev->dev, "clock is %d\n", mode->clock);
74 } else {
75 mode->hdisplay = 480;
76 mode->vdisplay = 854;
77 mode->hsync_start = 487;
78 mode->hsync_end = 490;
79 mode->htotal = 499;
80 mode->vsync_start = 861;
81 mode->vsync_end = 865;
82 mode->vtotal = 873;
83 mode->clock = 33264;
84 }
85
86 drm_mode_set_name(mode);
87 drm_mode_set_crtcinfo(mode, 0);
88
89 mode->type |= DRM_MODE_TYPE_PREFERRED;
90
91 return mode;
92}
93
94static int tmd_vid_get_panel_info(struct drm_device *dev,
95 int pipe,
96 struct panel_info *pi)
97{
98 if (!dev || !pi)
99 return -EINVAL;
100
101 pi->width_mm = TMD_PANEL_WIDTH;
102 pi->height_mm = TMD_PANEL_HEIGHT;
103
104 return 0;
105}
106
107/* ************************************************************************* *\
108 * FUNCTION: mdfld_init_TMD_MIPI
109 *
110 * DESCRIPTION: This function is called only by mrst_dsi_mode_set and
111 * restore_display_registers. since this function does not
112 * acquire the mutex, it is important that the calling function
113 * does!
114\* ************************************************************************* */
115
116/* FIXME: make the below data u8 instead of u32; note byte order! */
117static u32 tmd_cmd_mcap_off[] = {0x000000b2};
118static u32 tmd_cmd_enable_lane_switch[] = {0x000101ef};
119static u32 tmd_cmd_set_lane_num[] = {0x006360ef};
120static u32 tmd_cmd_pushing_clock0[] = {0x00cc2fef};
121static u32 tmd_cmd_pushing_clock1[] = {0x00dd6eef};
122static u32 tmd_cmd_set_mode[] = {0x000000b3};
123static u32 tmd_cmd_set_sync_pulse_mode[] = {0x000961ef};
124static u32 tmd_cmd_set_column[] = {0x0100002a, 0x000000df};
125static u32 tmd_cmd_set_page[] = {0x0300002b, 0x00000055};
126static u32 tmd_cmd_set_video_mode[] = {0x00000153};
127/*no auto_bl,need add in furture*/
128static u32 tmd_cmd_enable_backlight[] = {0x00005ab4};
129static u32 tmd_cmd_set_backlight_dimming[] = {0x00000ebd};
130
131static void mdfld_dsi_tmd_drv_ic_init(struct mdfld_dsi_config *dsi_config,
132 int pipe)
133{
134 struct mdfld_dsi_pkg_sender *sender
135 = mdfld_dsi_get_pkg_sender(dsi_config);
136
137 DRM_INFO("Enter mdfld init TMD MIPI display.\n");
138
139 if (!sender) {
140 DRM_ERROR("Cannot get sender\n");
141 return;
142 }
143
144 if (dsi_config->dvr_ic_inited)
145 return;
146
147 msleep(3);
148
149 /* FIXME: make the below data u8 instead of u32; note byte order! */
150
151 mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_mcap_off,
152 sizeof(tmd_cmd_mcap_off), false);
153 mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_lane_switch,
154 sizeof(tmd_cmd_enable_lane_switch), false);
155 mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_lane_num,
156 sizeof(tmd_cmd_set_lane_num), false);
157 mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock0,
158 sizeof(tmd_cmd_pushing_clock0), false);
159 mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_pushing_clock1,
160 sizeof(tmd_cmd_pushing_clock1), false);
161 mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_mode,
162 sizeof(tmd_cmd_set_mode), false);
163 mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_sync_pulse_mode,
164 sizeof(tmd_cmd_set_sync_pulse_mode), false);
165 mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_column,
166 sizeof(tmd_cmd_set_column), false);
167 mdfld_dsi_send_mcs_long(sender, (u8 *) tmd_cmd_set_page,
168 sizeof(tmd_cmd_set_page), false);
169 mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_video_mode,
170 sizeof(tmd_cmd_set_video_mode), false);
171 mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_enable_backlight,
172 sizeof(tmd_cmd_enable_backlight), false);
173 mdfld_dsi_send_gen_long(sender, (u8 *) tmd_cmd_set_backlight_dimming,
174 sizeof(tmd_cmd_set_backlight_dimming), false);
175
176 dsi_config->dvr_ic_inited = 1;
177}
178
179/*TPO DPI encoder helper funcs*/
180static const struct drm_encoder_helper_funcs
181 mdfld_tpo_dpi_encoder_helper_funcs = {
182 .dpms = mdfld_dsi_dpi_dpms,
183 .mode_fixup = mdfld_dsi_dpi_mode_fixup,
184 .prepare = mdfld_dsi_dpi_prepare,
185 .mode_set = mdfld_dsi_dpi_mode_set,
186 .commit = mdfld_dsi_dpi_commit,
187};
188
189/*TPO DPI encoder funcs*/
190static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
191 .destroy = drm_encoder_cleanup,
192};
193
194const struct panel_funcs mdfld_tmd_vid_funcs = {
195 .encoder_funcs = &mdfld_tpo_dpi_encoder_funcs,
196 .encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs,
197 .get_config_mode = &tmd_vid_get_config_mode,
198 .get_panel_info = tmd_vid_get_panel_info,
199 .reset = mdfld_dsi_panel_reset,
200 .drv_ic_init = mdfld_dsi_tmd_drv_ic_init,
201};
diff --git a/drivers/gpu/drm/gma500/mdfld_tpo_vid.c b/drivers/gpu/drm/gma500/mdfld_tpo_vid.c
new file mode 100644
index 000000000000..d8d4170725b2
--- /dev/null
+++ b/drivers/gpu/drm/gma500/mdfld_tpo_vid.c
@@ -0,0 +1,124 @@
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
30static struct drm_display_mode *tpo_vid_get_config_mode(struct drm_device *dev)
31{
32 struct drm_display_mode *mode;
33 struct drm_psb_private *dev_priv = dev->dev_private;
34 struct oaktrail_timing_info *ti = &dev_priv->gct_data.DTD;
35 bool use_gct = false;
36
37 mode = kzalloc(sizeof(*mode), GFP_KERNEL);
38 if (!mode)
39 return NULL;
40
41 if (use_gct) {
42 mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
43 mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
44 mode->hsync_start = mode->hdisplay +
45 ((ti->hsync_offset_hi << 8) |
46 ti->hsync_offset_lo);
47 mode->hsync_end = mode->hsync_start +
48 ((ti->hsync_pulse_width_hi << 8) |
49 ti->hsync_pulse_width_lo);
50 mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) |
51 ti->hblank_lo);
52 mode->vsync_start =
53 mode->vdisplay + ((ti->vsync_offset_hi << 8) |
54 ti->vsync_offset_lo);
55 mode->vsync_end =
56 mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) |
57 ti->vsync_pulse_width_lo);
58 mode->vtotal = mode->vdisplay +
59 ((ti->vblank_hi << 8) | ti->vblank_lo);
60 mode->clock = ti->pixel_clock * 10;
61
62 dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
63 dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
64 dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
65 dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
66 dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
67 dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
68 dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
69 dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
70 dev_dbg(dev->dev, "clock is %d\n", mode->clock);
71 } else {
72 mode->hdisplay = 864;
73 mode->vdisplay = 480;
74 mode->hsync_start = 873;
75 mode->hsync_end = 876;
76 mode->htotal = 887;
77 mode->vsync_start = 487;
78 mode->vsync_end = 490;
79 mode->vtotal = 499;
80 mode->clock = 33264;
81 }
82
83 drm_mode_set_name(mode);
84 drm_mode_set_crtcinfo(mode, 0);
85
86 mode->type |= DRM_MODE_TYPE_PREFERRED;
87
88 return mode;
89}
90
91static int tpo_vid_get_panel_info(struct drm_device *dev,
92 int pipe,
93 struct panel_info *pi)
94{
95 if (!dev || !pi)
96 return -EINVAL;
97
98 pi->width_mm = TPO_PANEL_WIDTH;
99 pi->height_mm = TPO_PANEL_HEIGHT;
100
101 return 0;
102}
103
104/*TPO DPI encoder helper funcs*/
105static const struct drm_encoder_helper_funcs
106 mdfld_tpo_dpi_encoder_helper_funcs = {
107 .dpms = mdfld_dsi_dpi_dpms,
108 .mode_fixup = mdfld_dsi_dpi_mode_fixup,
109 .prepare = mdfld_dsi_dpi_prepare,
110 .mode_set = mdfld_dsi_dpi_mode_set,
111 .commit = mdfld_dsi_dpi_commit,
112};
113
114/*TPO DPI encoder funcs*/
115static const struct drm_encoder_funcs mdfld_tpo_dpi_encoder_funcs = {
116 .destroy = drm_encoder_cleanup,
117};
118
119const struct panel_funcs mdfld_tpo_vid_funcs = {
120 .encoder_funcs = &mdfld_tpo_dpi_encoder_funcs,
121 .encoder_helper_funcs = &mdfld_tpo_dpi_encoder_helper_funcs,
122 .get_config_mode = &tpo_vid_get_config_mode,
123 .get_panel_info = tpo_vid_get_panel_info,
124};
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 1f57aac2cf80..fc3293049fe7 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -60,6 +60,16 @@ static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
60 /* Atom E620 */ 60 /* Atom E620 */
61 { 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops}, 61 { 0x8086, 0x4108, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &oaktrail_chip_ops},
62#endif 62#endif
63#if defined(CONFIG_DRM_MEDFIELD)
64 {0x8086, 0x0130, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
65 {0x8086, 0x0131, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
66 {0x8086, 0x0132, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
67 {0x8086, 0x0133, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
68 {0x8086, 0x0134, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
69 {0x8086, 0x0135, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
70 {0x8086, 0x0136, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
71 {0x8086, 0x0137, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &mdfld_chip_ops},
72#endif
63#if defined(CONFIG_DRM_GMA3600) 73#if defined(CONFIG_DRM_GMA3600)
64 { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 74 { 0x8086, 0x0be0, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
65 { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops}, 75 { 0x8086, 0x0be1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, (long) &cdv_chip_ops},
diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
index 3c0bf7be2738..af1c99752000 100644
--- a/drivers/gpu/drm/gma500/psb_drv.h
+++ b/drivers/gpu/drm/gma500/psb_drv.h
@@ -389,11 +389,79 @@ struct psb_state {
389 uint32_t savePWM_CONTROL_LOGIC; 389 uint32_t savePWM_CONTROL_LOGIC;
390}; 390};
391 391
392struct medfield_state {
393 uint32_t saveDPLL_A;
394 uint32_t saveFPA0;
395 uint32_t savePIPEACONF;
396 uint32_t saveHTOTAL_A;
397 uint32_t saveHBLANK_A;
398 uint32_t saveHSYNC_A;
399 uint32_t saveVTOTAL_A;
400 uint32_t saveVBLANK_A;
401 uint32_t saveVSYNC_A;
402 uint32_t savePIPEASRC;
403 uint32_t saveDSPASTRIDE;
404 uint32_t saveDSPALINOFF;
405 uint32_t saveDSPATILEOFF;
406 uint32_t saveDSPASIZE;
407 uint32_t saveDSPAPOS;
408 uint32_t saveDSPASURF;
409 uint32_t saveDSPACNTR;
410 uint32_t saveDSPASTATUS;
411 uint32_t save_palette_a[256];
412 uint32_t saveMIPI;
413
414 uint32_t saveDPLL_B;
415 uint32_t saveFPB0;
416 uint32_t savePIPEBCONF;
417 uint32_t saveHTOTAL_B;
418 uint32_t saveHBLANK_B;
419 uint32_t saveHSYNC_B;
420 uint32_t saveVTOTAL_B;
421 uint32_t saveVBLANK_B;
422 uint32_t saveVSYNC_B;
423 uint32_t savePIPEBSRC;
424 uint32_t saveDSPBSTRIDE;
425 uint32_t saveDSPBLINOFF;
426 uint32_t saveDSPBTILEOFF;
427 uint32_t saveDSPBSIZE;
428 uint32_t saveDSPBPOS;
429 uint32_t saveDSPBSURF;
430 uint32_t saveDSPBCNTR;
431 uint32_t saveDSPBSTATUS;
432 uint32_t save_palette_b[256];
433
434 uint32_t savePIPECCONF;
435 uint32_t saveHTOTAL_C;
436 uint32_t saveHBLANK_C;
437 uint32_t saveHSYNC_C;
438 uint32_t saveVTOTAL_C;
439 uint32_t saveVBLANK_C;
440 uint32_t saveVSYNC_C;
441 uint32_t savePIPECSRC;
442 uint32_t saveDSPCSTRIDE;
443 uint32_t saveDSPCLINOFF;
444 uint32_t saveDSPCTILEOFF;
445 uint32_t saveDSPCSIZE;
446 uint32_t saveDSPCPOS;
447 uint32_t saveDSPCSURF;
448 uint32_t saveDSPCCNTR;
449 uint32_t saveDSPCSTATUS;
450 uint32_t save_palette_c[256];
451 uint32_t saveMIPI_C;
452
453 uint32_t savePFIT_CONTROL;
454 uint32_t savePFIT_PGM_RATIOS;
455 uint32_t saveHDMIPHYMISCCTL;
456 uint32_t saveHDMIB_CONTROL;
457};
458
392struct psb_save_area { 459struct psb_save_area {
393 uint32_t saveBSM; 460 uint32_t saveBSM;
394 uint32_t saveVBT; 461 uint32_t saveVBT;
395 union { 462 union {
396 struct psb_state psb; 463 struct psb_state psb;
464 struct medfield_state mdfld;
397 }; 465 };
398 uint32_t saveBLC_PWM_CTL2; 466 uint32_t saveBLC_PWM_CTL2;
399 uint32_t saveBLC_PWM_CTL; 467 uint32_t saveBLC_PWM_CTL;
@@ -563,6 +631,24 @@ struct drm_psb_private {
563 631
564 /* 2D acceleration */ 632 /* 2D acceleration */
565 spinlock_t lock_2d; 633 spinlock_t lock_2d;
634
635 /*
636 * Panel brightness
637 */
638 int brightness;
639 int brightness_adjusted;
640
641 bool dsr_enable;
642 u32 dsr_fb_update;
643 bool dpi_panel_on[3];
644 void *dsi_configs[2];
645 u32 bpp;
646 u32 bpp2;
647
648 u32 pipeconf[3];
649 u32 dspcntr[3];
650
651 int mdfld_panel_id;
566}; 652};
567 653
568 654
@@ -758,6 +844,9 @@ extern const struct psb_ops psb_chip_ops;
758/* oaktrail_device.c */ 844/* oaktrail_device.c */
759extern const struct psb_ops oaktrail_chip_ops; 845extern const struct psb_ops oaktrail_chip_ops;
760 846
847/* mdlfd_device.c */
848extern const struct psb_ops mdfld_chip_ops;
849
761/* cdv_device.c */ 850/* cdv_device.c */
762extern const struct psb_ops cdv_chip_ops; 851extern const struct psb_ops cdv_chip_ops;
763 852
diff --git a/drivers/gpu/drm/gma500/psb_irq.c b/drivers/gpu/drm/gma500/psb_irq.c
index 7be802baceb5..a86fc3c4bf3a 100644
--- a/drivers/gpu/drm/gma500/psb_irq.c
+++ b/drivers/gpu/drm/gma500/psb_irq.c
@@ -27,6 +27,8 @@
27#include "psb_reg.h" 27#include "psb_reg.h"
28#include "psb_intel_reg.h" 28#include "psb_intel_reg.h"
29#include "power.h" 29#include "power.h"
30#include "psb_irq.h"
31#include "mdfld_output.h"
30 32
31/* 33/*
32 * inline functions 34 * inline functions
@@ -453,6 +455,11 @@ int psb_enable_vblank(struct drm_device *dev, int pipe)
453 uint32_t reg_val = 0; 455 uint32_t reg_val = 0;
454 uint32_t pipeconf_reg = mid_pipeconf(pipe); 456 uint32_t pipeconf_reg = mid_pipeconf(pipe);
455 457
458 /* Medfield is different - we should perhaps extract out vblank
459 and blacklight etc ops */
460 if (IS_MFLD(dev))
461 return mdfld_enable_te(dev, pipe);
462
456 if (gma_power_begin(dev, false)) { 463 if (gma_power_begin(dev, false)) {
457 reg_val = REG_READ(pipeconf_reg); 464 reg_val = REG_READ(pipeconf_reg);
458 gma_power_end(dev); 465 gma_power_end(dev);
@@ -485,6 +492,8 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
485 struct drm_psb_private *dev_priv = dev->dev_private; 492 struct drm_psb_private *dev_priv = dev->dev_private;
486 unsigned long irqflags; 493 unsigned long irqflags;
487 494
495 if (IS_MFLD(dev))
496 mdfld_disable_te(dev, pipe);
488 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags); 497 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
489 498
490 if (pipe == 0) 499 if (pipe == 0)
@@ -499,6 +508,55 @@ void psb_disable_vblank(struct drm_device *dev, int pipe)
499 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags); 508 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
500} 509}
501 510
511/*
512 * It is used to enable TE interrupt
513 */
514int mdfld_enable_te(struct drm_device *dev, int pipe)
515{
516 struct drm_psb_private *dev_priv =
517 (struct drm_psb_private *) dev->dev_private;
518 unsigned long irqflags;
519 uint32_t reg_val = 0;
520 uint32_t pipeconf_reg = mid_pipeconf(pipe);
521
522 if (gma_power_begin(dev, false)) {
523 reg_val = REG_READ(pipeconf_reg);
524 gma_power_end(dev);
525 }
526
527 if (!(reg_val & PIPEACONF_ENABLE))
528 return -EINVAL;
529
530 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
531
532 mid_enable_pipe_event(dev_priv, pipe);
533 psb_enable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
534
535 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
536
537 return 0;
538}
539
540/*
541 * It is used to disable TE interrupt
542 */
543void mdfld_disable_te(struct drm_device *dev, int pipe)
544{
545 struct drm_psb_private *dev_priv =
546 (struct drm_psb_private *) dev->dev_private;
547 unsigned long irqflags;
548
549 if (!dev_priv->dsr_enable)
550 return;
551
552 spin_lock_irqsave(&dev_priv->irqmask_lock, irqflags);
553
554 mid_disable_pipe_event(dev_priv, pipe);
555 psb_disable_pipestat(dev_priv, pipe, PIPE_TE_ENABLE);
556
557 spin_unlock_irqrestore(&dev_priv->irqmask_lock, irqflags);
558}
559
502/* Called from drm generic code, passed a 'crtc', which 560/* Called from drm generic code, passed a 'crtc', which
503 * we use as a pipe index 561 * we use as a pipe index
504 */ 562 */
diff --git a/drivers/gpu/drm/gma500/psb_irq.h b/drivers/gpu/drm/gma500/psb_irq.h
index 216fda38b57d..603045bee58a 100644
--- a/drivers/gpu/drm/gma500/psb_irq.h
+++ b/drivers/gpu/drm/gma500/psb_irq.h
@@ -42,4 +42,6 @@ int psb_enable_vblank(struct drm_device *dev, int pipe);
42void psb_disable_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); 43u32 psb_get_vblank_counter(struct drm_device *dev, int pipe);
44 44
45int mdfld_enable_te(struct drm_device *dev, int pipe);
46void mdfld_disable_te(struct drm_device *dev, int pipe);
45#endif /* _SYSIRQ_H_ */ 47#endif /* _SYSIRQ_H_ */
diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
new file mode 100644
index 000000000000..4a07ab596174
--- /dev/null
+++ b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.c
@@ -0,0 +1,829 @@
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
25#include "mdfld_dsi_dpi.h"
26#include "mdfld_output.h"
27#include "mdfld_dsi_pkg_sender.h"
28#include "tc35876x-dsi-lvds.h"
29#include <linux/i2c/tc35876x.h>
30#include <linux/kernel.h>
31#include <linux/module.h>
32#include <asm/intel_scu_ipc.h>
33
34static struct i2c_client *tc35876x_client;
35static struct i2c_client *cmi_lcd_i2c_client;
36
37#define FLD_MASK(start, end) (((1 << ((start) - (end) + 1)) - 1) << (end))
38#define FLD_VAL(val, start, end) (((val) << (end)) & FLD_MASK(start, end))
39
40/* DSI D-PHY Layer Registers */
41#define D0W_DPHYCONTTX 0x0004
42#define CLW_DPHYCONTRX 0x0020
43#define D0W_DPHYCONTRX 0x0024
44#define D1W_DPHYCONTRX 0x0028
45#define D2W_DPHYCONTRX 0x002C
46#define D3W_DPHYCONTRX 0x0030
47#define COM_DPHYCONTRX 0x0038
48#define CLW_CNTRL 0x0040
49#define D0W_CNTRL 0x0044
50#define D1W_CNTRL 0x0048
51#define D2W_CNTRL 0x004C
52#define D3W_CNTRL 0x0050
53#define DFTMODE_CNTRL 0x0054
54
55/* DSI PPI Layer Registers */
56#define PPI_STARTPPI 0x0104
57#define PPI_BUSYPPI 0x0108
58#define PPI_LINEINITCNT 0x0110
59#define PPI_LPTXTIMECNT 0x0114
60#define PPI_LANEENABLE 0x0134
61#define PPI_TX_RX_TA 0x013C
62#define PPI_CLS_ATMR 0x0140
63#define PPI_D0S_ATMR 0x0144
64#define PPI_D1S_ATMR 0x0148
65#define PPI_D2S_ATMR 0x014C
66#define PPI_D3S_ATMR 0x0150
67#define PPI_D0S_CLRSIPOCOUNT 0x0164
68#define PPI_D1S_CLRSIPOCOUNT 0x0168
69#define PPI_D2S_CLRSIPOCOUNT 0x016C
70#define PPI_D3S_CLRSIPOCOUNT 0x0170
71#define CLS_PRE 0x0180
72#define D0S_PRE 0x0184
73#define D1S_PRE 0x0188
74#define D2S_PRE 0x018C
75#define D3S_PRE 0x0190
76#define CLS_PREP 0x01A0
77#define D0S_PREP 0x01A4
78#define D1S_PREP 0x01A8
79#define D2S_PREP 0x01AC
80#define D3S_PREP 0x01B0
81#define CLS_ZERO 0x01C0
82#define D0S_ZERO 0x01C4
83#define D1S_ZERO 0x01C8
84#define D2S_ZERO 0x01CC
85#define D3S_ZERO 0x01D0
86#define PPI_CLRFLG 0x01E0
87#define PPI_CLRSIPO 0x01E4
88#define HSTIMEOUT 0x01F0
89#define HSTIMEOUTENABLE 0x01F4
90
91/* DSI Protocol Layer Registers */
92#define DSI_STARTDSI 0x0204
93#define DSI_BUSYDSI 0x0208
94#define DSI_LANEENABLE 0x0210
95#define DSI_LANESTATUS0 0x0214
96#define DSI_LANESTATUS1 0x0218
97#define DSI_INTSTATUS 0x0220
98#define DSI_INTMASK 0x0224
99#define DSI_INTCLR 0x0228
100#define DSI_LPTXTO 0x0230
101
102/* DSI General Registers */
103#define DSIERRCNT 0x0300
104
105/* DSI Application Layer Registers */
106#define APLCTRL 0x0400
107#define RDPKTLN 0x0404
108
109/* Video Path Registers */
110#define VPCTRL 0x0450
111#define HTIM1 0x0454
112#define HTIM2 0x0458
113#define VTIM1 0x045C
114#define VTIM2 0x0460
115#define VFUEN 0x0464
116
117/* LVDS Registers */
118#define LVMX0003 0x0480
119#define LVMX0407 0x0484
120#define LVMX0811 0x0488
121#define LVMX1215 0x048C
122#define LVMX1619 0x0490
123#define LVMX2023 0x0494
124#define LVMX2427 0x0498
125#define LVCFG 0x049C
126#define LVPHY0 0x04A0
127#define LVPHY1 0x04A4
128
129/* System Registers */
130#define SYSSTAT 0x0500
131#define SYSRST 0x0504
132
133/* GPIO Registers */
134/*#define GPIOC 0x0520*/
135#define GPIOO 0x0524
136#define GPIOI 0x0528
137
138/* I2C Registers */
139#define I2CTIMCTRL 0x0540
140#define I2CMADDR 0x0544
141#define WDATAQ 0x0548
142#define RDATAQ 0x054C
143
144/* Chip/Rev Registers */
145#define IDREG 0x0580
146
147/* Debug Registers */
148#define DEBUG00 0x05A0
149#define DEBUG01 0x05A4
150
151/* Panel CABC registers */
152#define PANEL_PWM_CONTROL 0x90
153#define PANEL_FREQ_DIVIDER_HI 0x91
154#define PANEL_FREQ_DIVIDER_LO 0x92
155#define PANEL_DUTY_CONTROL 0x93
156#define PANEL_MODIFY_RGB 0x94
157#define PANEL_FRAMERATE_CONTROL 0x96
158#define PANEL_PWM_MIN 0x97
159#define PANEL_PWM_REF 0x98
160#define PANEL_PWM_MAX 0x99
161#define PANEL_ALLOW_DISTORT 0x9A
162#define PANEL_BYPASS_PWMI 0x9B
163
164/* Panel color management registers */
165#define PANEL_CM_ENABLE 0x700
166#define PANEL_CM_HUE 0x701
167#define PANEL_CM_SATURATION 0x702
168#define PANEL_CM_INTENSITY 0x703
169#define PANEL_CM_BRIGHTNESS 0x704
170#define PANEL_CM_CE_ENABLE 0x705
171#define PANEL_CM_PEAK_EN 0x710
172#define PANEL_CM_GAIN 0x711
173#define PANEL_CM_HUETABLE_START 0x730
174#define PANEL_CM_HUETABLE_END 0x747 /* inclusive */
175
176/* Input muxing for registers LVMX0003...LVMX2427 */
177enum {
178 INPUT_R0, /* 0 */
179 INPUT_R1,
180 INPUT_R2,
181 INPUT_R3,
182 INPUT_R4,
183 INPUT_R5,
184 INPUT_R6,
185 INPUT_R7,
186 INPUT_G0, /* 8 */
187 INPUT_G1,
188 INPUT_G2,
189 INPUT_G3,
190 INPUT_G4,
191 INPUT_G5,
192 INPUT_G6,
193 INPUT_G7,
194 INPUT_B0, /* 16 */
195 INPUT_B1,
196 INPUT_B2,
197 INPUT_B3,
198 INPUT_B4,
199 INPUT_B5,
200 INPUT_B6,
201 INPUT_B7,
202 INPUT_HSYNC, /* 24 */
203 INPUT_VSYNC,
204 INPUT_DE,
205 LOGIC_0,
206 /* 28...31 undefined */
207};
208
209#define INPUT_MUX(lvmx03, lvmx02, lvmx01, lvmx00) \
210 (FLD_VAL(lvmx03, 29, 24) | FLD_VAL(lvmx02, 20, 16) | \
211 FLD_VAL(lvmx01, 12, 8) | FLD_VAL(lvmx00, 4, 0))
212
213/**
214 * tc35876x_regw - Write DSI-LVDS bridge register using I2C
215 * @client: struct i2c_client to use
216 * @reg: register address
217 * @value: value to write
218 *
219 * Returns 0 on success, or a negative error value.
220 */
221static int tc35876x_regw(struct i2c_client *client, u16 reg, u32 value)
222{
223 int r;
224 u8 tx_data[] = {
225 /* NOTE: Register address big-endian, data little-endian. */
226 (reg >> 8) & 0xff,
227 reg & 0xff,
228 value & 0xff,
229 (value >> 8) & 0xff,
230 (value >> 16) & 0xff,
231 (value >> 24) & 0xff,
232 };
233 struct i2c_msg msgs[] = {
234 {
235 .addr = client->addr,
236 .flags = 0,
237 .buf = tx_data,
238 .len = ARRAY_SIZE(tx_data),
239 },
240 };
241
242 r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
243 if (r < 0) {
244 dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x error %d\n",
245 __func__, reg, value, r);
246 return r;
247 }
248
249 if (r < ARRAY_SIZE(msgs)) {
250 dev_err(&client->dev, "%s: reg 0x%04x val 0x%08x msgs %d\n",
251 __func__, reg, value, r);
252 return -EAGAIN;
253 }
254
255 dev_dbg(&client->dev, "%s: reg 0x%04x val 0x%08x\n",
256 __func__, reg, value);
257
258 return 0;
259}
260
261/**
262 * tc35876x_regr - Read DSI-LVDS bridge register using I2C
263 * @client: struct i2c_client to use
264 * @reg: register address
265 * @value: pointer for storing the value
266 *
267 * Returns 0 on success, or a negative error value.
268 */
269static int tc35876x_regr(struct i2c_client *client, u16 reg, u32 *value)
270{
271 int r;
272 u8 tx_data[] = {
273 (reg >> 8) & 0xff,
274 reg & 0xff,
275 };
276 u8 rx_data[4];
277 struct i2c_msg msgs[] = {
278 {
279 .addr = client->addr,
280 .flags = 0,
281 .buf = tx_data,
282 .len = ARRAY_SIZE(tx_data),
283 },
284 {
285 .addr = client->addr,
286 .flags = I2C_M_RD,
287 .buf = rx_data,
288 .len = ARRAY_SIZE(rx_data),
289 },
290 };
291
292 r = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs));
293 if (r < 0) {
294 dev_err(&client->dev, "%s: reg 0x%04x error %d\n", __func__,
295 reg, r);
296 return r;
297 }
298
299 if (r < ARRAY_SIZE(msgs)) {
300 dev_err(&client->dev, "%s: reg 0x%04x msgs %d\n", __func__,
301 reg, r);
302 return -EAGAIN;
303 }
304
305 *value = rx_data[0] << 24 | rx_data[1] << 16 |
306 rx_data[2] << 8 | rx_data[3];
307
308 dev_dbg(&client->dev, "%s: reg 0x%04x value 0x%08x\n", __func__,
309 reg, *value);
310
311 return 0;
312}
313
314void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state)
315{
316 struct tc35876x_platform_data *pdata;
317
318 if (WARN(!tc35876x_client, "%s called before probe", __func__))
319 return;
320
321 dev_dbg(&tc35876x_client->dev, "%s: state %d\n", __func__, state);
322
323 pdata = dev_get_platdata(&tc35876x_client->dev);
324
325 if (pdata->gpio_bridge_reset == -1)
326 return;
327
328 if (state) {
329 gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
330 mdelay(10);
331 } else {
332 /* Pull MIPI Bridge reset pin to Low */
333 gpio_set_value_cansleep(pdata->gpio_bridge_reset, 0);
334 mdelay(20);
335 /* Pull MIPI Bridge reset pin to High */
336 gpio_set_value_cansleep(pdata->gpio_bridge_reset, 1);
337 mdelay(40);
338 }
339}
340
341void tc35876x_configure_lvds_bridge(struct drm_device *dev)
342{
343 struct i2c_client *i2c = tc35876x_client;
344 u32 ppi_lptxtimecnt;
345 u32 txtagocnt;
346 u32 txtasurecnt;
347 u32 id;
348
349 if (WARN(!tc35876x_client, "%s called before probe", __func__))
350 return;
351
352 dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
353
354 if (!tc35876x_regr(i2c, IDREG, &id))
355 dev_info(&tc35876x_client->dev, "tc35876x ID 0x%08x\n", id);
356 else
357 dev_err(&tc35876x_client->dev, "Cannot read ID\n");
358
359 ppi_lptxtimecnt = 4;
360 txtagocnt = (5 * ppi_lptxtimecnt - 3) / 4;
361 txtasurecnt = 3 * ppi_lptxtimecnt / 2;
362 tc35876x_regw(i2c, PPI_TX_RX_TA, FLD_VAL(txtagocnt, 26, 16) |
363 FLD_VAL(txtasurecnt, 10, 0));
364 tc35876x_regw(i2c, PPI_LPTXTIMECNT, FLD_VAL(ppi_lptxtimecnt, 10, 0));
365
366 tc35876x_regw(i2c, PPI_D0S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
367 tc35876x_regw(i2c, PPI_D1S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
368 tc35876x_regw(i2c, PPI_D2S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
369 tc35876x_regw(i2c, PPI_D3S_CLRSIPOCOUNT, FLD_VAL(1, 5, 0));
370
371 /* Enabling MIPI & PPI lanes, Enable 4 lanes */
372 tc35876x_regw(i2c, PPI_LANEENABLE,
373 BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
374 tc35876x_regw(i2c, DSI_LANEENABLE,
375 BIT(4) | BIT(3) | BIT(2) | BIT(1) | BIT(0));
376 tc35876x_regw(i2c, PPI_STARTPPI, BIT(0));
377 tc35876x_regw(i2c, DSI_STARTDSI, BIT(0));
378
379 /* Setting LVDS output frequency */
380 tc35876x_regw(i2c, LVPHY0, FLD_VAL(1, 20, 16) |
381 FLD_VAL(2, 15, 14) | FLD_VAL(6, 4, 0)); /* 0x00048006 */
382
383 /* Setting video panel control register,0x00000120 VTGen=ON ?!?!? */
384 tc35876x_regw(i2c, VPCTRL, BIT(8) | BIT(5));
385
386 /* Horizontal back porch and horizontal pulse width. 0x00280028 */
387 tc35876x_regw(i2c, HTIM1, FLD_VAL(40, 24, 16) | FLD_VAL(40, 8, 0));
388
389 /* Horizontal front porch and horizontal active video size. 0x00500500*/
390 tc35876x_regw(i2c, HTIM2, FLD_VAL(80, 24, 16) | FLD_VAL(1280, 10, 0));
391
392 /* Vertical back porch and vertical sync pulse width. 0x000e000a */
393 tc35876x_regw(i2c, VTIM1, FLD_VAL(14, 23, 16) | FLD_VAL(10, 7, 0));
394
395 /* Vertical front porch and vertical display size. 0x000e0320 */
396 tc35876x_regw(i2c, VTIM2, FLD_VAL(14, 23, 16) | FLD_VAL(800, 10, 0));
397
398 /* Set above HTIM1, HTIM2, VTIM1, and VTIM2 at next VSYNC. */
399 tc35876x_regw(i2c, VFUEN, BIT(0));
400
401 /* Soft reset LCD controller. */
402 tc35876x_regw(i2c, SYSRST, BIT(2));
403
404 /* LVDS-TX input muxing */
405 tc35876x_regw(i2c, LVMX0003,
406 INPUT_MUX(INPUT_R5, INPUT_R4, INPUT_R3, INPUT_R2));
407 tc35876x_regw(i2c, LVMX0407,
408 INPUT_MUX(INPUT_G2, INPUT_R7, INPUT_R1, INPUT_R6));
409 tc35876x_regw(i2c, LVMX0811,
410 INPUT_MUX(INPUT_G1, INPUT_G0, INPUT_G4, INPUT_G3));
411 tc35876x_regw(i2c, LVMX1215,
412 INPUT_MUX(INPUT_B2, INPUT_G7, INPUT_G6, INPUT_G5));
413 tc35876x_regw(i2c, LVMX1619,
414 INPUT_MUX(INPUT_B4, INPUT_B3, INPUT_B1, INPUT_B0));
415 tc35876x_regw(i2c, LVMX2023,
416 INPUT_MUX(LOGIC_0, INPUT_B7, INPUT_B6, INPUT_B5));
417 tc35876x_regw(i2c, LVMX2427,
418 INPUT_MUX(INPUT_R0, INPUT_DE, INPUT_VSYNC, INPUT_HSYNC));
419
420 /* Enable LVDS transmitter. */
421 tc35876x_regw(i2c, LVCFG, BIT(0));
422
423 /* Clear notifications. Don't write reserved bits. Was write 0xffffffff
424 * to 0x0288, must be in error?! */
425 tc35876x_regw(i2c, DSI_INTCLR, FLD_MASK(31, 30) | FLD_MASK(22, 0));
426}
427
428#define GPIOPWMCTRL 0x38F
429#define PWM0CLKDIV0 0x62 /* low byte */
430#define PWM0CLKDIV1 0x61 /* high byte */
431
432#define SYSTEMCLK 19200000UL /* 19.2 MHz */
433#define PWM_FREQUENCY 9600 /* Hz */
434
435/* f = baseclk / (clkdiv + 1) => clkdiv = (baseclk - f) / f */
436static inline u16 calc_clkdiv(unsigned long baseclk, unsigned int f)
437{
438 return (baseclk - f) / f;
439}
440
441static void tc35876x_brightness_init(struct drm_device *dev)
442{
443 int ret;
444 u8 pwmctrl;
445 u16 clkdiv;
446
447 /* Make sure the PWM reference is the 19.2 MHz system clock. Read first
448 * instead of setting directly to catch potential conflicts between PWM
449 * users. */
450 ret = intel_scu_ipc_ioread8(GPIOPWMCTRL, &pwmctrl);
451 if (ret || pwmctrl != 0x01) {
452 if (ret)
453 dev_err(&dev->pdev->dev, "GPIOPWMCTRL read failed\n");
454 else
455 dev_warn(&dev->pdev->dev, "GPIOPWMCTRL was not set to system clock (pwmctrl = 0x%02x)\n", pwmctrl);
456
457 ret = intel_scu_ipc_iowrite8(GPIOPWMCTRL, 0x01);
458 if (ret)
459 dev_err(&dev->pdev->dev, "GPIOPWMCTRL set failed\n");
460 }
461
462 clkdiv = calc_clkdiv(SYSTEMCLK, PWM_FREQUENCY);
463
464 ret = intel_scu_ipc_iowrite8(PWM0CLKDIV1, (clkdiv >> 8) & 0xff);
465 if (!ret)
466 ret = intel_scu_ipc_iowrite8(PWM0CLKDIV0, clkdiv & 0xff);
467
468 if (ret)
469 dev_err(&dev->pdev->dev, "PWM0CLKDIV set failed\n");
470 else
471 dev_dbg(&dev->pdev->dev, "PWM0CLKDIV set to 0x%04x (%d Hz)\n",
472 clkdiv, PWM_FREQUENCY);
473}
474
475#define PWM0DUTYCYCLE 0x67
476
477void tc35876x_brightness_control(struct drm_device *dev, int level)
478{
479 int ret;
480 u8 duty_val;
481 u8 panel_duty_val;
482
483 level = clamp(level, 0, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
484
485 /* PWM duty cycle 0x00...0x63 corresponds to 0...99% */
486 duty_val = level * 0x63 / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL;
487
488 /* I won't pretend to understand this formula. The panel spec is quite
489 * bad engrish.
490 */
491 panel_duty_val = (2 * level - 100) * 0xA9 /
492 MDFLD_DSI_BRIGHTNESS_MAX_LEVEL + 0x56;
493
494 ret = intel_scu_ipc_iowrite8(PWM0DUTYCYCLE, duty_val);
495 if (ret)
496 dev_err(&tc35876x_client->dev, "%s: ipc write fail\n",
497 __func__);
498
499 if (cmi_lcd_i2c_client) {
500 ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
501 PANEL_PWM_MAX, panel_duty_val);
502 if (ret < 0)
503 dev_err(&cmi_lcd_i2c_client->dev, "%s: i2c write failed\n",
504 __func__);
505 }
506}
507
508void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev)
509{
510 struct tc35876x_platform_data *pdata;
511
512 if (WARN(!tc35876x_client, "%s called before probe", __func__))
513 return;
514
515 dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
516
517 pdata = dev_get_platdata(&tc35876x_client->dev);
518
519 if (pdata->gpio_panel_bl_en != -1)
520 gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 0);
521
522 if (pdata->gpio_panel_vadd != -1)
523 gpio_set_value_cansleep(pdata->gpio_panel_vadd, 0);
524}
525
526void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev)
527{
528 struct tc35876x_platform_data *pdata;
529 struct drm_psb_private *dev_priv = dev->dev_private;
530
531 if (WARN(!tc35876x_client, "%s called before probe", __func__))
532 return;
533
534 dev_dbg(&tc35876x_client->dev, "%s\n", __func__);
535
536 pdata = dev_get_platdata(&tc35876x_client->dev);
537
538 if (pdata->gpio_panel_vadd != -1) {
539 gpio_set_value_cansleep(pdata->gpio_panel_vadd, 1);
540 msleep(260);
541 }
542
543 if (cmi_lcd_i2c_client) {
544 int ret;
545 dev_dbg(&cmi_lcd_i2c_client->dev, "setting TCON\n");
546 /* Bit 4 is average_saving. Setting it to 1, the brightness is
547 * referenced to the average of the frame content. 0 means
548 * reference to the maximum of frame contents. Bits 3:0 are
549 * allow_distort. When set to a nonzero value, all color values
550 * between 255-allow_distort*2 and 255 are mapped to the
551 * 255-allow_distort*2 value.
552 */
553 ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
554 PANEL_ALLOW_DISTORT, 0x10);
555 if (ret < 0)
556 dev_err(&cmi_lcd_i2c_client->dev,
557 "i2c write failed (%d)\n", ret);
558 ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
559 PANEL_BYPASS_PWMI, 0);
560 if (ret < 0)
561 dev_err(&cmi_lcd_i2c_client->dev,
562 "i2c write failed (%d)\n", ret);
563 /* Set minimum brightness value - this is tunable */
564 ret = i2c_smbus_write_byte_data(cmi_lcd_i2c_client,
565 PANEL_PWM_MIN, 0x35);
566 if (ret < 0)
567 dev_err(&cmi_lcd_i2c_client->dev,
568 "i2c write failed (%d)\n", ret);
569 }
570
571 if (pdata->gpio_panel_bl_en != -1)
572 gpio_set_value_cansleep(pdata->gpio_panel_bl_en, 1);
573
574 tc35876x_brightness_control(dev, dev_priv->brightness_adjusted);
575}
576
577static struct drm_display_mode *tc35876x_get_config_mode(struct drm_device *dev)
578{
579 struct drm_display_mode *mode;
580
581 dev_dbg(&dev->pdev->dev, "%s\n", __func__);
582
583 mode = kzalloc(sizeof(*mode), GFP_KERNEL);
584 if (!mode)
585 return NULL;
586
587 /* FIXME: do this properly. */
588 mode->hdisplay = 1280;
589 mode->vdisplay = 800;
590 mode->hsync_start = 1360;
591 mode->hsync_end = 1400;
592 mode->htotal = 1440;
593 mode->vsync_start = 814;
594 mode->vsync_end = 824;
595 mode->vtotal = 838;
596 mode->clock = 33324 << 1;
597
598 dev_info(&dev->pdev->dev, "hdisplay(w) = %d\n", mode->hdisplay);
599 dev_info(&dev->pdev->dev, "vdisplay(h) = %d\n", mode->vdisplay);
600 dev_info(&dev->pdev->dev, "HSS = %d\n", mode->hsync_start);
601 dev_info(&dev->pdev->dev, "HSE = %d\n", mode->hsync_end);
602 dev_info(&dev->pdev->dev, "htotal = %d\n", mode->htotal);
603 dev_info(&dev->pdev->dev, "VSS = %d\n", mode->vsync_start);
604 dev_info(&dev->pdev->dev, "VSE = %d\n", mode->vsync_end);
605 dev_info(&dev->pdev->dev, "vtotal = %d\n", mode->vtotal);
606 dev_info(&dev->pdev->dev, "clock = %d\n", mode->clock);
607
608 drm_mode_set_name(mode);
609 drm_mode_set_crtcinfo(mode, 0);
610
611 mode->type |= DRM_MODE_TYPE_PREFERRED;
612
613 return mode;
614}
615
616/* DV1 Active area 216.96 x 135.6 mm */
617#define DV1_PANEL_WIDTH 217
618#define DV1_PANEL_HEIGHT 136
619
620static int tc35876x_get_panel_info(struct drm_device *dev, int pipe,
621 struct panel_info *pi)
622{
623 if (!dev || !pi)
624 return -EINVAL;
625
626 pi->width_mm = DV1_PANEL_WIDTH;
627 pi->height_mm = DV1_PANEL_HEIGHT;
628
629 return 0;
630}
631
632static int tc35876x_bridge_probe(struct i2c_client *client,
633 const struct i2c_device_id *id)
634{
635 struct tc35876x_platform_data *pdata;
636
637 dev_info(&client->dev, "%s\n", __func__);
638
639 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
640 dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
641 __func__);
642 return -ENODEV;
643 }
644
645 pdata = dev_get_platdata(&client->dev);
646 if (!pdata) {
647 dev_err(&client->dev, "%s: no platform data\n", __func__);
648 return -ENODEV;
649 }
650
651 if (pdata->gpio_bridge_reset != -1) {
652 gpio_request(pdata->gpio_bridge_reset, "tc35876x bridge reset");
653 gpio_direction_output(pdata->gpio_bridge_reset, 0);
654 }
655
656 if (pdata->gpio_panel_bl_en != -1) {
657 gpio_request(pdata->gpio_panel_bl_en, "tc35876x panel bl en");
658 gpio_direction_output(pdata->gpio_panel_bl_en, 0);
659 }
660
661 if (pdata->gpio_panel_vadd != -1) {
662 gpio_request(pdata->gpio_panel_vadd, "tc35876x panel vadd");
663 gpio_direction_output(pdata->gpio_panel_vadd, 0);
664 }
665
666 tc35876x_client = client;
667
668 return 0;
669}
670
671static int tc35876x_bridge_remove(struct i2c_client *client)
672{
673 struct tc35876x_platform_data *pdata = dev_get_platdata(&client->dev);
674
675 dev_dbg(&client->dev, "%s\n", __func__);
676
677 if (pdata->gpio_bridge_reset != -1)
678 gpio_free(pdata->gpio_bridge_reset);
679
680 if (pdata->gpio_panel_bl_en != -1)
681 gpio_free(pdata->gpio_panel_bl_en);
682
683 if (pdata->gpio_panel_vadd != -1)
684 gpio_free(pdata->gpio_panel_vadd);
685
686 tc35876x_client = NULL;
687
688 return 0;
689}
690
691static const struct i2c_device_id tc35876x_bridge_id[] = {
692 { "i2c_disp_brig", 0 },
693 { }
694};
695MODULE_DEVICE_TABLE(i2c, tc35876x_bridge_id);
696
697static struct i2c_driver tc35876x_bridge_i2c_driver = {
698 .driver = {
699 .name = "i2c_disp_brig",
700 },
701 .id_table = tc35876x_bridge_id,
702 .probe = tc35876x_bridge_probe,
703 .remove = __devexit_p(tc35876x_bridge_remove),
704};
705
706/* LCD panel I2C */
707static int cmi_lcd_i2c_probe(struct i2c_client *client,
708 const struct i2c_device_id *id)
709{
710 dev_info(&client->dev, "%s\n", __func__);
711
712 if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
713 dev_err(&client->dev, "%s: i2c_check_functionality() failed\n",
714 __func__);
715 return -ENODEV;
716 }
717
718 cmi_lcd_i2c_client = client;
719
720 return 0;
721}
722
723static int cmi_lcd_i2c_remove(struct i2c_client *client)
724{
725 dev_dbg(&client->dev, "%s\n", __func__);
726
727 cmi_lcd_i2c_client = NULL;
728
729 return 0;
730}
731
732static const struct i2c_device_id cmi_lcd_i2c_id[] = {
733 { "cmi-lcd", 0 },
734 { }
735};
736MODULE_DEVICE_TABLE(i2c, cmi_lcd_i2c_id);
737
738static struct i2c_driver cmi_lcd_i2c_driver = {
739 .driver = {
740 .name = "cmi-lcd",
741 },
742 .id_table = cmi_lcd_i2c_id,
743 .probe = cmi_lcd_i2c_probe,
744 .remove = __devexit_p(cmi_lcd_i2c_remove),
745};
746
747/* HACK to create I2C device while it's not created by platform code */
748#define CMI_LCD_I2C_ADAPTER 2
749#define CMI_LCD_I2C_ADDR 0x60
750
751static int cmi_lcd_hack_create_device(void)
752{
753 struct i2c_adapter *adapter;
754 struct i2c_client *client;
755 struct i2c_board_info info = {
756 .type = "cmi-lcd",
757 .addr = CMI_LCD_I2C_ADDR,
758 };
759
760 pr_debug("%s\n", __func__);
761
762 adapter = i2c_get_adapter(CMI_LCD_I2C_ADAPTER);
763 if (!adapter) {
764 pr_err("%s: i2c_get_adapter(%d) failed\n", __func__,
765 CMI_LCD_I2C_ADAPTER);
766 return -EINVAL;
767 }
768
769 client = i2c_new_device(adapter, &info);
770 if (!client) {
771 pr_err("%s: i2c_new_device() failed\n", __func__);
772 i2c_put_adapter(adapter);
773 return -EINVAL;
774 }
775
776 return 0;
777}
778
779static const struct drm_encoder_helper_funcs tc35876x_encoder_helper_funcs = {
780 .dpms = mdfld_dsi_dpi_dpms,
781 .mode_fixup = mdfld_dsi_dpi_mode_fixup,
782 .prepare = mdfld_dsi_dpi_prepare,
783 .mode_set = mdfld_dsi_dpi_mode_set,
784 .commit = mdfld_dsi_dpi_commit,
785};
786
787static const struct drm_encoder_funcs tc35876x_encoder_funcs = {
788 .destroy = drm_encoder_cleanup,
789};
790
791const struct panel_funcs mdfld_tc35876x_funcs = {
792 .encoder_funcs = &tc35876x_encoder_funcs,
793 .encoder_helper_funcs = &tc35876x_encoder_helper_funcs,
794 .get_config_mode = tc35876x_get_config_mode,
795 .get_panel_info = tc35876x_get_panel_info,
796};
797
798void tc35876x_init(struct drm_device *dev)
799{
800 int r;
801
802 dev_dbg(&dev->pdev->dev, "%s\n", __func__);
803
804 cmi_lcd_hack_create_device();
805
806 r = i2c_add_driver(&cmi_lcd_i2c_driver);
807 if (r < 0)
808 dev_err(&dev->pdev->dev,
809 "%s: i2c_add_driver() for %s failed (%d)\n",
810 __func__, cmi_lcd_i2c_driver.driver.name, r);
811
812 r = i2c_add_driver(&tc35876x_bridge_i2c_driver);
813 if (r < 0)
814 dev_err(&dev->pdev->dev,
815 "%s: i2c_add_driver() for %s failed (%d)\n",
816 __func__, tc35876x_bridge_i2c_driver.driver.name, r);
817
818 tc35876x_brightness_init(dev);
819}
820
821void tc35876x_exit(void)
822{
823 pr_debug("%s\n", __func__);
824
825 i2c_del_driver(&tc35876x_bridge_i2c_driver);
826
827 if (cmi_lcd_i2c_client)
828 i2c_del_driver(&cmi_lcd_i2c_driver);
829}
diff --git a/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h
new file mode 100644
index 000000000000..b14b7f9e7d1e
--- /dev/null
+++ b/drivers/gpu/drm/gma500/tc35876x-dsi-lvds.h
@@ -0,0 +1,38 @@
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
25#ifndef __MDFLD_DSI_LVDS_BRIDGE_H__
26#define __MDFLD_DSI_LVDS_BRIDGE_H__
27
28void tc35876x_set_bridge_reset_state(struct drm_device *dev, int state);
29void tc35876x_configure_lvds_bridge(struct drm_device *dev);
30void tc35876x_brightness_control(struct drm_device *dev, int level);
31void tc35876x_toshiba_bridge_panel_off(struct drm_device *dev);
32void tc35876x_toshiba_bridge_panel_on(struct drm_device *dev);
33void tc35876x_init(struct drm_device *dev);
34void tc35876x_exit(void);
35
36extern const struct panel_funcs mdfld_tc35876x_funcs;
37
38#endif /*__MDFLD_DSI_LVDS_BRIDGE_H__*/