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
32 static void mid_get_fuse_settings(struct drm_device
*dev
)
34 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
35 struct pci_dev
*pci_root
= pci_get_bus_and_slot(0, 0);
36 uint32_t fuse_value
= 0;
37 uint32_t fuse_value_tmp
= 0;
39 #define FB_REG06 0xD0810600
40 #define FB_MIPI_DISABLE (1 << 11)
41 #define FB_REG09 0xD0810900
42 #define FB_REG09 0xD0810900
43 #define FB_SKU_MASK 0x7000
44 #define FB_SKU_SHIFT 12
48 if (pci_root
== NULL
) {
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 if (pci_gfx_root
== NULL
) {
114 pci_read_config_dword(pci_gfx_root
, 0x08, &platform_rev_id
);
115 dev_priv
->platform_rev_id
= (uint8_t) platform_rev_id
;
116 pci_dev_put(pci_gfx_root
);
117 dev_dbg(dev_priv
->dev
->dev
, "platform_rev_id is %x\n",
118 dev_priv
->platform_rev_id
);
121 static void mid_get_vbt_data(struct drm_psb_private
*dev_priv
)
123 struct drm_device
*dev
= dev_priv
->dev
;
124 struct oaktrail_vbt
*vbt
= &dev_priv
->vbt_data
;
130 struct oaktrail_timing_info
*dp_ti
= &dev_priv
->gct_data
.DTD
;
131 struct gct_r10_timing_info ti
;
133 struct pci_dev
*pci_gfx_root
= pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
135 /* Get the address of the platform config vbt, B0:D2:F0;0xFC */
136 pci_read_config_dword(pci_gfx_root
, 0xFC, &addr
);
137 pci_dev_put(pci_gfx_root
);
139 dev_dbg(dev
->dev
, "drm platform config address is %x\n", addr
);
141 /* check for platform config address == 0. */
142 /* this means fw doesn't support vbt */
149 /* get the virtual address of the vbt */
150 vbt_virtual
= ioremap(addr
, sizeof(*vbt
));
151 if (vbt_virtual
== NULL
) {
156 memcpy(vbt
, vbt_virtual
, sizeof(*vbt
));
157 iounmap(vbt_virtual
); /* Free virtual address space */
159 /* No matching signature don't process the data */
160 if (memcmp(vbt
->signature
, "$GCT", 4)) {
165 dev_dbg(dev
->dev
, "GCT revision is %x\n", vbt
->revision
);
167 switch (vbt
->revision
) {
169 vbt
->oaktrail_gct
= ioremap(addr
+ sizeof(*vbt
) - 4,
170 vbt
->size
- sizeof(*vbt
) + 4);
171 pGCT
= vbt
->oaktrail_gct
;
172 bpi
= ((struct oaktrail_gct_v1
*)pGCT
)->PD
.BootPanelIndex
;
173 dev_priv
->gct_data
.bpi
= bpi
;
174 dev_priv
->gct_data
.pt
=
175 ((struct oaktrail_gct_v1
*)pGCT
)->PD
.PanelType
;
176 memcpy(&dev_priv
->gct_data
.DTD
,
177 &((struct oaktrail_gct_v1
*)pGCT
)->panel
[bpi
].DTD
,
178 sizeof(struct oaktrail_timing_info
));
179 dev_priv
->gct_data
.Panel_Port_Control
=
180 ((struct oaktrail_gct_v1
*)pGCT
)->panel
[bpi
].Panel_Port_Control
;
181 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
=
182 ((struct oaktrail_gct_v1
*)pGCT
)->panel
[bpi
].Panel_MIPI_Display_Descriptor
;
185 vbt
->oaktrail_gct
= ioremap(addr
+ sizeof(*vbt
) - 4,
186 vbt
->size
- sizeof(*vbt
) + 4);
187 pGCT
= vbt
->oaktrail_gct
;
188 bpi
= ((struct oaktrail_gct_v2
*)pGCT
)->PD
.BootPanelIndex
;
189 dev_priv
->gct_data
.bpi
= bpi
;
190 dev_priv
->gct_data
.pt
=
191 ((struct oaktrail_gct_v2
*)pGCT
)->PD
.PanelType
;
192 memcpy(&dev_priv
->gct_data
.DTD
,
193 &((struct oaktrail_gct_v2
*)pGCT
)->panel
[bpi
].DTD
,
194 sizeof(struct oaktrail_timing_info
));
195 dev_priv
->gct_data
.Panel_Port_Control
=
196 ((struct oaktrail_gct_v2
*)pGCT
)->panel
[bpi
].Panel_Port_Control
;
197 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
=
198 ((struct oaktrail_gct_v2
*)pGCT
)->panel
[bpi
].Panel_MIPI_Display_Descriptor
;
201 /*header definition changed from rev 01 (v2) to rev 10h. */
202 /*so, some values have changed location*/
203 new_size
= vbt
->checksum
; /*checksum contains lo size byte*/
204 /*LSB of oaktrail_gct contains hi size byte*/
205 new_size
|= ((0xff & (unsigned int)(long)vbt
->oaktrail_gct
)) << 8;
207 vbt
->checksum
= vbt
->size
; /*size contains the checksum*/
209 vbt
->size
= 0xff; /*restrict size to 255*/
211 vbt
->size
= new_size
;
213 /* number of descriptors defined in the GCT */
214 number_desc
= ((0xff00 & (unsigned int)(long)vbt
->oaktrail_gct
)) >> 8;
215 bpi
= ((0xff0000 & (unsigned int)(long)vbt
->oaktrail_gct
)) >> 16;
216 vbt
->oaktrail_gct
= ioremap(addr
+ GCT_R10_HEADER_SIZE
,
217 GCT_R10_DISPLAY_DESC_SIZE
* number_desc
);
218 pGCT
= vbt
->oaktrail_gct
;
219 pGCT
= (u8
*)pGCT
+ (bpi
*GCT_R10_DISPLAY_DESC_SIZE
);
220 dev_priv
->gct_data
.bpi
= bpi
; /*save boot panel id*/
222 /*copy the GCT display timings into a temp structure*/
223 memcpy(&ti
, pGCT
, sizeof(struct gct_r10_timing_info
));
225 /*now copy the temp struct into the dev_priv->gct_data*/
226 dp_ti
->pixel_clock
= ti
.pixel_clock
;
227 dp_ti
->hactive_hi
= ti
.hactive_hi
;
228 dp_ti
->hactive_lo
= ti
.hactive_lo
;
229 dp_ti
->hblank_hi
= ti
.hblank_hi
;
230 dp_ti
->hblank_lo
= ti
.hblank_lo
;
231 dp_ti
->hsync_offset_hi
= ti
.hsync_offset_hi
;
232 dp_ti
->hsync_offset_lo
= ti
.hsync_offset_lo
;
233 dp_ti
->hsync_pulse_width_hi
= ti
.hsync_pulse_width_hi
;
234 dp_ti
->hsync_pulse_width_lo
= ti
.hsync_pulse_width_lo
;
235 dp_ti
->vactive_hi
= ti
.vactive_hi
;
236 dp_ti
->vactive_lo
= ti
.vactive_lo
;
237 dp_ti
->vblank_hi
= ti
.vblank_hi
;
238 dp_ti
->vblank_lo
= ti
.vblank_lo
;
239 dp_ti
->vsync_offset_hi
= ti
.vsync_offset_hi
;
240 dp_ti
->vsync_offset_lo
= ti
.vsync_offset_lo
;
241 dp_ti
->vsync_pulse_width_hi
= ti
.vsync_pulse_width_hi
;
242 dp_ti
->vsync_pulse_width_lo
= ti
.vsync_pulse_width_lo
;
244 /* Move the MIPI_Display_Descriptor data from GCT to dev priv */
245 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
=
246 *((u8
*)pGCT
+ 0x0d);
247 dev_priv
->gct_data
.Panel_MIPI_Display_Descriptor
|=
248 (*((u8
*)pGCT
+ 0x0e)) << 8;
251 dev_err(dev
->dev
, "Unknown revision of GCT!\n");
256 int mid_chip_setup(struct drm_device
*dev
)
258 struct drm_psb_private
*dev_priv
= dev
->dev_private
;
259 mid_get_fuse_settings(dev
);
260 mid_get_vbt_data(dev_priv
);
261 mid_get_pci_revID(dev_priv
);