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
31 #include "mdfld_output.h"
33 static int panel_id
= GCT_DETECT
;
34 module_param_named(panel_id
, panel_id
, int, 0600);
35 MODULE_PARM_DESC(panel_id
, "Panel Identifier");
38 static void mid_get_fuse_settings(struct drm_device
*dev
)
40 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
41 struct pci_dev
*pci_root
= pci_get_bus_and_slot(0, 0);
42 uint32_t fuse_value
= 0;
43 uint32_t fuse_value_tmp
= 0;
45 #define FB_REG06 0xD0810600
46 #define FB_MIPI_DISABLE (1 << 11)
47 #define FB_REG09 0xD0810900
48 #define FB_REG09 0xD0810900
49 #define FB_SKU_MASK 0x7000
50 #define FB_SKU_SHIFT 12
54 pci_write_config_dword(pci_root
, 0xD0, FB_REG06
);
55 pci_read_config_dword(pci_root
, 0xD4, &fuse_value
);
57 /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */
59 dev_priv
->iLVDS_enable
= fuse_value
& FB_MIPI_DISABLE
;
61 DRM_INFO("internal display is %s\n",
62 dev_priv
->iLVDS_enable
? "LVDS display" : "MIPI display");
64 /* Prevent runtime suspend at start*/
65 if (dev_priv
->iLVDS_enable
) {
66 dev_priv
->is_lvds_on
= true;
67 dev_priv
->is_mipi_on
= false;
69 dev_priv
->is_mipi_on
= true;
70 dev_priv
->is_lvds_on
= false;
73 dev_priv
->video_device_fuse
= fuse_value
;
75 pci_write_config_dword(pci_root
, 0xD0, FB_REG09
);
76 pci_read_config_dword(pci_root
, 0xD4, &fuse_value
);
78 dev_dbg(dev
->dev
, "SKU values is 0x%x.\n", fuse_value
);
79 fuse_value_tmp
= (fuse_value
& FB_SKU_MASK
) >> FB_SKU_SHIFT
;
81 dev_priv
->fuse_reg_value
= fuse_value
;
83 switch (fuse_value_tmp
) {
85 dev_priv
->core_freq
= 200;
88 dev_priv
->core_freq
= 100;
91 dev_priv
->core_freq
= 166;
94 dev_warn(dev
->dev
, "Invalid SKU values, SKU value = 0x%08x\n",
96 dev_priv
->core_freq
= 0;
98 dev_dbg(dev
->dev
, "LNC core clk is %dMHz.\n", dev_priv
->core_freq
);
99 pci_dev_put(pci_root
);
103 * Get the revison ID, B0:D2:F0;0x08
105 static void mid_get_pci_revID(struct drm_psb_private
*dev_priv
)
107 uint32_t platform_rev_id
= 0;
108 struct pci_dev
*pci_gfx_root
= pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
110 pci_read_config_dword(pci_gfx_root
, 0x08, &platform_rev_id
);
111 dev_priv
->platform_rev_id
= (uint8_t) platform_rev_id
;
112 pci_dev_put(pci_gfx_root
);
113 dev_dbg(dev_priv
->dev
->dev
, "platform_rev_id is %x\n",
114 dev_priv
->platform_rev_id
);
117 static void mid_get_vbt_data(struct drm_psb_private
*dev_priv
)
119 struct drm_device
*dev
= dev_priv
->dev
;
120 struct mrst_vbt
*vbt
= &dev_priv
->vbt_data
;
126 struct mrst_timing_info
*dp_ti
= &dev_priv
->gct_data
.DTD
;
127 struct gct_r10_timing_info ti
;
129 struct pci_dev
*pci_gfx_root
= pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
131 /* Get the address of the platform config vbt, B0:D2:F0;0xFC */
132 pci_read_config_dword(pci_gfx_root
, 0xFC, &addr
);
133 pci_dev_put(pci_gfx_root
);
135 dev_dbg(dev
->dev
, "drm platform config address is %x\n", addr
);
137 /* check for platform config address == 0. */
138 /* this means fw doesn't support vbt */
145 /* get the virtual address of the vbt */
146 vbt_virtual
= ioremap(addr
, sizeof(*vbt
));
148 memcpy(vbt
, vbt_virtual
, sizeof(*vbt
));
149 iounmap(vbt_virtual
); /* Free virtual address space */
151 dev_dbg(dev
->dev
, "GCT revision is %x\n", vbt
->revision
);
153 switch (vbt
->revision
) {
155 vbt
->mrst_gct
= ioremap(addr
+ sizeof(*vbt
) - 4,
156 vbt
->size
- sizeof(*vbt
) + 4);
157 pGCT
= vbt
->mrst_gct
;
158 bpi
= ((struct mrst_gct_v1
*)pGCT
)->PD
.BootPanelIndex
;
159 dev_priv
->gct_data
.bpi
= bpi
;
160 dev_priv
->gct_data
.pt
=
161 ((struct mrst_gct_v1
*)pGCT
)->PD
.PanelType
;
162 memcpy(&dev_priv
->gct_data
.DTD
,
163 &((struct mrst_gct_v1
*)pGCT
)->panel
[bpi
].DTD
,
164 sizeof(struct mrst_timing_info
));
165 dev_priv
->gct_data
.Panel_Port_Control
=
166 ((struct mrst_gct_v1
*)pGCT
)->panel
[bpi
].Panel_Port_Control
;
167 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
=
168 ((struct mrst_gct_v1
*)pGCT
)->panel
[bpi
].Panel_MIPI_Display_Descriptor
;
171 vbt
->mrst_gct
= ioremap(addr
+ sizeof(*vbt
) - 4,
172 vbt
->size
- sizeof(*vbt
) + 4);
173 pGCT
= vbt
->mrst_gct
;
174 bpi
= ((struct mrst_gct_v2
*)pGCT
)->PD
.BootPanelIndex
;
175 dev_priv
->gct_data
.bpi
= bpi
;
176 dev_priv
->gct_data
.pt
=
177 ((struct mrst_gct_v2
*)pGCT
)->PD
.PanelType
;
178 memcpy(&dev_priv
->gct_data
.DTD
,
179 &((struct mrst_gct_v2
*)pGCT
)->panel
[bpi
].DTD
,
180 sizeof(struct mrst_timing_info
));
181 dev_priv
->gct_data
.Panel_Port_Control
=
182 ((struct mrst_gct_v2
*)pGCT
)->panel
[bpi
].Panel_Port_Control
;
183 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
=
184 ((struct mrst_gct_v2
*)pGCT
)->panel
[bpi
].Panel_MIPI_Display_Descriptor
;
187 /*header definition changed from rev 01 (v2) to rev 10h. */
188 /*so, some values have changed location*/
189 new_size
= vbt
->checksum
; /*checksum contains lo size byte*/
190 /*LSB of mrst_gct contains hi size byte*/
191 new_size
|= ((0xff & (unsigned int)vbt
->mrst_gct
)) << 8;
193 vbt
->checksum
= vbt
->size
; /*size contains the checksum*/
195 vbt
->size
= 0xff; /*restrict size to 255*/
197 vbt
->size
= new_size
;
199 /* number of descriptors defined in the GCT */
200 number_desc
= ((0xff00 & (unsigned int)vbt
->mrst_gct
)) >> 8;
201 bpi
= ((0xff0000 & (unsigned int)vbt
->mrst_gct
)) >> 16;
202 vbt
->mrst_gct
= ioremap(addr
+ GCT_R10_HEADER_SIZE
,
203 GCT_R10_DISPLAY_DESC_SIZE
* number_desc
);
204 pGCT
= vbt
->mrst_gct
;
205 pGCT
= (u8
*)pGCT
+ (bpi
*GCT_R10_DISPLAY_DESC_SIZE
);
206 dev_priv
->gct_data
.bpi
= bpi
; /*save boot panel id*/
208 /*copy the GCT display timings into a temp structure*/
209 memcpy(&ti
, pGCT
, sizeof(struct gct_r10_timing_info
));
211 /*now copy the temp struct into the dev_priv->gct_data*/
212 dp_ti
->pixel_clock
= ti
.pixel_clock
;
213 dp_ti
->hactive_hi
= ti
.hactive_hi
;
214 dp_ti
->hactive_lo
= ti
.hactive_lo
;
215 dp_ti
->hblank_hi
= ti
.hblank_hi
;
216 dp_ti
->hblank_lo
= ti
.hblank_lo
;
217 dp_ti
->hsync_offset_hi
= ti
.hsync_offset_hi
;
218 dp_ti
->hsync_offset_lo
= ti
.hsync_offset_lo
;
219 dp_ti
->hsync_pulse_width_hi
= ti
.hsync_pulse_width_hi
;
220 dp_ti
->hsync_pulse_width_lo
= ti
.hsync_pulse_width_lo
;
221 dp_ti
->vactive_hi
= ti
.vactive_hi
;
222 dp_ti
->vactive_lo
= ti
.vactive_lo
;
223 dp_ti
->vblank_hi
= ti
.vblank_hi
;
224 dp_ti
->vblank_lo
= ti
.vblank_lo
;
225 dp_ti
->vsync_offset_hi
= ti
.vsync_offset_hi
;
226 dp_ti
->vsync_offset_lo
= ti
.vsync_offset_lo
;
227 dp_ti
->vsync_pulse_width_hi
= ti
.vsync_pulse_width_hi
;
228 dp_ti
->vsync_pulse_width_lo
= ti
.vsync_pulse_width_lo
;
230 /* Move the MIPI_Display_Descriptor data from GCT to dev priv */
231 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
=
232 *((u8
*)pGCT
+ 0x0d);
233 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
|=
234 (*((u8
*)pGCT
+ 0x0e)) << 8;
237 dev_err(dev
->dev
, "Unknown revision of GCT!\n");
240 if (IS_MFLD(dev_priv
->dev
)) {
241 if (panel_id
== GCT_DETECT
) {
242 if (dev_priv
->gct_data
.bpi
== 2) {
243 dev_info(dev
->dev
, "[GFX] PYR Panel Detected\n");
244 dev_priv
->panel_id
= PYR_CMD
;
246 } else if (dev_priv
->gct_data
.bpi
== 0) {
247 dev_info(dev
->dev
, "[GFX] TMD Panel Detected.\n");
248 dev_priv
->panel_id
= TMD_VID
;
251 dev_info(dev
->dev
, "[GFX] Default Panel (TPO)\n");
252 dev_priv
->panel_id
= TPO_CMD
;
256 dev_info(dev
->dev
, "[GFX] Panel Parameter Passed in through cmd line\n");
257 dev_priv
->panel_id
= panel_id
;
262 int mid_chip_setup(struct drm_device
*dev
)
264 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
265 mid_get_fuse_settings(dev
);
266 mid_get_vbt_data(dev_priv
);
267 mid_get_pci_revID(dev_priv
);