1 /**************************************************************************
2 * Copyright (c) 2011, Intel Corporation.
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.
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
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.
18 **************************************************************************/
21 * - Split functions by vbt type
22 * - Make them all take drm_device
23 * - Check ioremap failures
26 #include <linux/moduleparam.h>
32 #include "mdfld_output.h"
34 static int panel_id
= GCT_DETECT
;
35 module_param_named(panel_id
, panel_id
, int, 0600);
36 MODULE_PARM_DESC(panel_id
, "Panel Identifier");
39 static void mid_get_fuse_settings(struct drm_device
*dev
)
41 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
42 struct pci_dev
*pci_root
= pci_get_bus_and_slot(0, 0);
43 uint32_t fuse_value
= 0;
44 uint32_t fuse_value_tmp
= 0;
46 #define FB_REG06 0xD0810600
47 #define FB_MIPI_DISABLE (1 << 11)
48 #define FB_REG09 0xD0810900
49 #define FB_REG09 0xD0810900
50 #define FB_SKU_MASK 0x7000
51 #define FB_SKU_SHIFT 12
55 pci_write_config_dword(pci_root
, 0xD0, FB_REG06
);
56 pci_read_config_dword(pci_root
, 0xD4, &fuse_value
);
58 /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
60 dev_priv
->iLVDS_enable
= fuse_value
& FB_MIPI_DISABLE
;
62 DRM_INFO("internal display is %s\n",
63 dev_priv
->iLVDS_enable
? "LVDS display" : "MIPI display");
65 /* Prevent runtime suspend at start*/
66 if (dev_priv
->iLVDS_enable
) {
67 dev_priv
->is_lvds_on
= true;
68 dev_priv
->is_mipi_on
= false;
70 dev_priv
->is_mipi_on
= true;
71 dev_priv
->is_lvds_on
= false;
74 dev_priv
->video_device_fuse
= fuse_value
;
76 pci_write_config_dword(pci_root
, 0xD0, FB_REG09
);
77 pci_read_config_dword(pci_root
, 0xD4, &fuse_value
);
79 dev_dbg(dev
->dev
, "SKU values is 0x%x.\n", fuse_value
);
80 fuse_value_tmp
= (fuse_value
& FB_SKU_MASK
) >> FB_SKU_SHIFT
;
82 dev_priv
->fuse_reg_value
= fuse_value
;
84 switch (fuse_value_tmp
) {
86 dev_priv
->core_freq
= 200;
89 dev_priv
->core_freq
= 100;
92 dev_priv
->core_freq
= 166;
95 dev_warn(dev
->dev
, "Invalid SKU values, SKU value = 0x%08x\n",
97 dev_priv
->core_freq
= 0;
99 dev_dbg(dev
->dev
, "LNC core clk is %dMHz.\n", dev_priv
->core_freq
);
100 pci_dev_put(pci_root
);
104 * Get the revison ID, B0:D2:F0;0x08
106 static void mid_get_pci_revID(struct drm_psb_private
*dev_priv
)
108 uint32_t platform_rev_id
= 0;
109 struct pci_dev
*pci_gfx_root
= pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
111 pci_read_config_dword(pci_gfx_root
, 0x08, &platform_rev_id
);
112 dev_priv
->platform_rev_id
= (uint8_t) platform_rev_id
;
113 pci_dev_put(pci_gfx_root
);
114 dev_dbg(dev_priv
->dev
->dev
, "platform_rev_id is %x\n",
115 dev_priv
->platform_rev_id
);
118 static void mid_get_vbt_data(struct drm_psb_private
*dev_priv
)
120 struct drm_device
*dev
= dev_priv
->dev
;
121 struct mrst_vbt
*vbt
= &dev_priv
->vbt_data
;
127 struct mrst_timing_info
*dp_ti
= &dev_priv
->gct_data
.DTD
;
128 struct gct_r10_timing_info ti
;
130 struct pci_dev
*pci_gfx_root
= pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
132 /* Get the address of the platform config vbt, B0:D2:F0;0xFC */
133 pci_read_config_dword(pci_gfx_root
, 0xFC, &addr
);
134 pci_dev_put(pci_gfx_root
);
136 dev_dbg(dev
->dev
, "drm platform config address is %x\n", addr
);
138 /* check for platform config address == 0. */
139 /* this means fw doesn't support vbt */
146 /* get the virtual address of the vbt */
147 vbt_virtual
= ioremap(addr
, sizeof(*vbt
));
149 memcpy(vbt
, vbt_virtual
, sizeof(*vbt
));
150 iounmap(vbt_virtual
); /* Free virtual address space */
152 dev_dbg(dev
->dev
, "GCT revision is %x\n", vbt
->revision
);
154 switch (vbt
->revision
) {
156 vbt
->mrst_gct
= ioremap(addr
+ sizeof(*vbt
) - 4,
157 vbt
->size
- sizeof(*vbt
) + 4);
158 pGCT
= vbt
->mrst_gct
;
159 bpi
= ((struct mrst_gct_v1
*)pGCT
)->PD
.BootPanelIndex
;
160 dev_priv
->gct_data
.bpi
= bpi
;
161 dev_priv
->gct_data
.pt
=
162 ((struct mrst_gct_v1
*)pGCT
)->PD
.PanelType
;
163 memcpy(&dev_priv
->gct_data
.DTD
,
164 &((struct mrst_gct_v1
*)pGCT
)->panel
[bpi
].DTD
,
165 sizeof(struct mrst_timing_info
));
166 dev_priv
->gct_data
.Panel_Port_Control
=
167 ((struct mrst_gct_v1
*)pGCT
)->panel
[bpi
].Panel_Port_Control
;
168 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
=
169 ((struct mrst_gct_v1
*)pGCT
)->panel
[bpi
].Panel_MIPI_Display_Descriptor
;
172 vbt
->mrst_gct
= ioremap(addr
+ sizeof(*vbt
) - 4,
173 vbt
->size
- sizeof(*vbt
) + 4);
174 pGCT
= vbt
->mrst_gct
;
175 bpi
= ((struct mrst_gct_v2
*)pGCT
)->PD
.BootPanelIndex
;
176 dev_priv
->gct_data
.bpi
= bpi
;
177 dev_priv
->gct_data
.pt
=
178 ((struct mrst_gct_v2
*)pGCT
)->PD
.PanelType
;
179 memcpy(&dev_priv
->gct_data
.DTD
,
180 &((struct mrst_gct_v2
*)pGCT
)->panel
[bpi
].DTD
,
181 sizeof(struct mrst_timing_info
));
182 dev_priv
->gct_data
.Panel_Port_Control
=
183 ((struct mrst_gct_v2
*)pGCT
)->panel
[bpi
].Panel_Port_Control
;
184 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
=
185 ((struct mrst_gct_v2
*)pGCT
)->panel
[bpi
].Panel_MIPI_Display_Descriptor
;
188 /*header definition changed from rev 01 (v2) to rev 10h. */
189 /*so, some values have changed location*/
190 new_size
= vbt
->checksum
; /*checksum contains lo size byte*/
191 /*LSB of mrst_gct contains hi size byte*/
192 new_size
|= ((0xff & (unsigned int)vbt
->mrst_gct
)) << 8;
194 vbt
->checksum
= vbt
->size
; /*size contains the checksum*/
196 vbt
->size
= 0xff; /*restrict size to 255*/
198 vbt
->size
= new_size
;
200 /* number of descriptors defined in the GCT */
201 number_desc
= ((0xff00 & (unsigned int)vbt
->mrst_gct
)) >> 8;
202 bpi
= ((0xff0000 & (unsigned int)vbt
->mrst_gct
)) >> 16;
203 vbt
->mrst_gct
= ioremap(addr
+ GCT_R10_HEADER_SIZE
,
204 GCT_R10_DISPLAY_DESC_SIZE
* number_desc
);
205 pGCT
= vbt
->mrst_gct
;
206 pGCT
= (u8
*)pGCT
+ (bpi
*GCT_R10_DISPLAY_DESC_SIZE
);
207 dev_priv
->gct_data
.bpi
= bpi
; /*save boot panel id*/
209 /*copy the GCT display timings into a temp structure*/
210 memcpy(&ti
, pGCT
, sizeof(struct gct_r10_timing_info
));
212 /*now copy the temp struct into the dev_priv->gct_data*/
213 dp_ti
->pixel_clock
= ti
.pixel_clock
;
214 dp_ti
->hactive_hi
= ti
.hactive_hi
;
215 dp_ti
->hactive_lo
= ti
.hactive_lo
;
216 dp_ti
->hblank_hi
= ti
.hblank_hi
;
217 dp_ti
->hblank_lo
= ti
.hblank_lo
;
218 dp_ti
->hsync_offset_hi
= ti
.hsync_offset_hi
;
219 dp_ti
->hsync_offset_lo
= ti
.hsync_offset_lo
;
220 dp_ti
->hsync_pulse_width_hi
= ti
.hsync_pulse_width_hi
;
221 dp_ti
->hsync_pulse_width_lo
= ti
.hsync_pulse_width_lo
;
222 dp_ti
->vactive_hi
= ti
.vactive_hi
;
223 dp_ti
->vactive_lo
= ti
.vactive_lo
;
224 dp_ti
->vblank_hi
= ti
.vblank_hi
;
225 dp_ti
->vblank_lo
= ti
.vblank_lo
;
226 dp_ti
->vsync_offset_hi
= ti
.vsync_offset_hi
;
227 dp_ti
->vsync_offset_lo
= ti
.vsync_offset_lo
;
228 dp_ti
->vsync_pulse_width_hi
= ti
.vsync_pulse_width_hi
;
229 dp_ti
->vsync_pulse_width_lo
= ti
.vsync_pulse_width_lo
;
231 /* Move the MIPI_Display_Descriptor data from GCT to dev priv */
232 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
=
233 *((u8
*)pGCT
+ 0x0d);
234 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
|=
235 (*((u8
*)pGCT
+ 0x0e)) << 8;
238 dev_err(dev
->dev
, "Unknown revision of GCT!\n");
241 if (IS_MFLD(dev_priv
->dev
)) {
242 if (panel_id
== GCT_DETECT
) {
243 if (dev_priv
->gct_data
.bpi
== 2) {
244 dev_info(dev
->dev
, "[GFX] PYR Panel Detected\n");
245 dev_priv
->panel_id
= PYR_CMD
;
247 } else if (dev_priv
->gct_data
.bpi
== 0) {
248 dev_info(dev
->dev
, "[GFX] TMD Panel Detected.\n");
249 dev_priv
->panel_id
= TMD_VID
;
252 dev_info(dev
->dev
, "[GFX] Default Panel (TPO)\n");
253 dev_priv
->panel_id
= TPO_CMD
;
257 dev_info(dev
->dev
, "[GFX] Panel Parameter Passed in through cmd line\n");
258 dev_priv
->panel_id
= panel_id
;
263 int mid_chip_setup(struct drm_device
*dev
)
265 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
266 mid_get_fuse_settings(dev
);
267 mid_get_vbt_data(dev_priv
);
268 mid_get_pci_revID(dev_priv
);