/drivers/staging/gma500/mid_bios.c
C | 269 lines | 199 code | 31 blank | 39 comment | 18 complexity | a716e8153caff23fb57a00fc740ab0e6 MD5 | raw file
Possible License(s): LGPL-2.0, AGPL-1.0, GPL-2.0
1/************************************************************************** 2 * Copyright (c) 2011, Intel Corporation. 3 * All Rights Reserved. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * You should have received a copy of the GNU General Public License along with 15 * this program; if not, write to the Free Software Foundation, Inc., 16 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 17 * 18 **************************************************************************/ 19 20/* TODO 21 * - Split functions by vbt type 22 * - Make them all take drm_device 23 * - Check ioremap failures 24 */ 25 26#include <drm/drmP.h> 27#include <drm/drm.h> 28#include "psb_drm.h" 29#include "psb_drv.h" 30#include "mid_bios.h" 31#include "mdfld_output.h" 32 33static int panel_id = GCT_DETECT; 34module_param_named(panel_id, panel_id, int, 0600); 35MODULE_PARM_DESC(panel_id, "Panel Identifier"); 36 37 38static void mid_get_fuse_settings(struct drm_device *dev) 39{ 40 struct drm_psb_private *dev_priv = dev->dev_private; 41 struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); 42 uint32_t fuse_value = 0; 43 uint32_t fuse_value_tmp = 0; 44 45#define FB_REG06 0xD0810600 46#define FB_MIPI_DISABLE (1 << 11) 47#define FB_REG09 0xD0810900 48#define FB_REG09 0xD0810900 49#define FB_SKU_MASK 0x7000 50#define FB_SKU_SHIFT 12 51#define FB_SKU_100 0 52#define FB_SKU_100L 1 53#define FB_SKU_83 2 54 pci_write_config_dword(pci_root, 0xD0, FB_REG06); 55 pci_read_config_dword(pci_root, 0xD4, &fuse_value); 56 57 /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */ 58 if (IS_MRST(dev)) 59 dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE; 60 61 DRM_INFO("internal display is %s\n", 62 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display"); 63 64 /* Prevent runtime suspend at start*/ 65 if (dev_priv->iLVDS_enable) { 66 dev_priv->is_lvds_on = true; 67 dev_priv->is_mipi_on = false; 68 } else { 69 dev_priv->is_mipi_on = true; 70 dev_priv->is_lvds_on = false; 71 } 72 73 dev_priv->video_device_fuse = fuse_value; 74 75 pci_write_config_dword(pci_root, 0xD0, FB_REG09); 76 pci_read_config_dword(pci_root, 0xD4, &fuse_value); 77 78 dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value); 79 fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT; 80 81 dev_priv->fuse_reg_value = fuse_value; 82 83 switch (fuse_value_tmp) { 84 case FB_SKU_100: 85 dev_priv->core_freq = 200; 86 break; 87 case FB_SKU_100L: 88 dev_priv->core_freq = 100; 89 break; 90 case FB_SKU_83: 91 dev_priv->core_freq = 166; 92 break; 93 default: 94 dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n", 95 fuse_value_tmp); 96 dev_priv->core_freq = 0; 97 } 98 dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq); 99 pci_dev_put(pci_root); 100} 101 102/* 103 * Get the revison ID, B0:D2:F0;0x08 104 */ 105static void mid_get_pci_revID(struct drm_psb_private *dev_priv) 106{ 107 uint32_t platform_rev_id = 0; 108 struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); 109 110 pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); 111 dev_priv->platform_rev_id = (uint8_t) platform_rev_id; 112 pci_dev_put(pci_gfx_root); 113 dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n", 114 dev_priv->platform_rev_id); 115} 116 117static void mid_get_vbt_data(struct drm_psb_private *dev_priv) 118{ 119 struct drm_device *dev = dev_priv->dev; 120 struct mrst_vbt *vbt = &dev_priv->vbt_data; 121 u32 addr; 122 u16 new_size; 123 u8 *vbt_virtual; 124 u8 bpi; 125 u8 number_desc = 0; 126 struct mrst_timing_info *dp_ti = &dev_priv->gct_data.DTD; 127 struct gct_r10_timing_info ti; 128 void *pGCT; 129 struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); 130 131 /* Get the address of the platform config vbt, B0:D2:F0;0xFC */ 132 pci_read_config_dword(pci_gfx_root, 0xFC, &addr); 133 pci_dev_put(pci_gfx_root); 134 135 dev_dbg(dev->dev, "drm platform config address is %x\n", addr); 136 137 /* check for platform config address == 0. */ 138 /* this means fw doesn't support vbt */ 139 140 if (addr == 0) { 141 vbt->size = 0; 142 return; 143 } 144 145 /* get the virtual address of the vbt */ 146 vbt_virtual = ioremap(addr, sizeof(*vbt)); 147 148 memcpy(vbt, vbt_virtual, sizeof(*vbt)); 149 iounmap(vbt_virtual); /* Free virtual address space */ 150 151 dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision); 152 153 switch (vbt->revision) { 154 case 0: 155 vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4, 156 vbt->size - sizeof(*vbt) + 4); 157 pGCT = vbt->mrst_gct; 158 bpi = ((struct mrst_gct_v1 *)pGCT)->PD.BootPanelIndex; 159 dev_priv->gct_data.bpi = bpi; 160 dev_priv->gct_data.pt = 161 ((struct mrst_gct_v1 *)pGCT)->PD.PanelType; 162 memcpy(&dev_priv->gct_data.DTD, 163 &((struct mrst_gct_v1 *)pGCT)->panel[bpi].DTD, 164 sizeof(struct mrst_timing_info)); 165 dev_priv->gct_data.Panel_Port_Control = 166 ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control; 167 dev_priv->gct_data.Panel_MIPI_Display_Descriptor = 168 ((struct mrst_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; 169 break; 170 case 1: 171 vbt->mrst_gct = ioremap(addr + sizeof(*vbt) - 4, 172 vbt->size - sizeof(*vbt) + 4); 173 pGCT = vbt->mrst_gct; 174 bpi = ((struct mrst_gct_v2 *)pGCT)->PD.BootPanelIndex; 175 dev_priv->gct_data.bpi = bpi; 176 dev_priv->gct_data.pt = 177 ((struct mrst_gct_v2 *)pGCT)->PD.PanelType; 178 memcpy(&dev_priv->gct_data.DTD, 179 &((struct mrst_gct_v2 *)pGCT)->panel[bpi].DTD, 180 sizeof(struct mrst_timing_info)); 181 dev_priv->gct_data.Panel_Port_Control = 182 ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control; 183 dev_priv->gct_data.Panel_MIPI_Display_Descriptor = 184 ((struct mrst_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; 185 break; 186 case 0x10: 187 /*header definition changed from rev 01 (v2) to rev 10h. */ 188 /*so, some values have changed location*/ 189 new_size = vbt->checksum; /*checksum contains lo size byte*/ 190 /*LSB of mrst_gct contains hi size byte*/ 191 new_size |= ((0xff & (unsigned int)vbt->mrst_gct)) << 8; 192 193 vbt->checksum = vbt->size; /*size contains the checksum*/ 194 if (new_size > 0xff) 195 vbt->size = 0xff; /*restrict size to 255*/ 196 else 197 vbt->size = new_size; 198 199 /* number of descriptors defined in the GCT */ 200 number_desc = ((0xff00 & (unsigned int)vbt->mrst_gct)) >> 8; 201 bpi = ((0xff0000 & (unsigned int)vbt->mrst_gct)) >> 16; 202 vbt->mrst_gct = ioremap(addr + GCT_R10_HEADER_SIZE, 203 GCT_R10_DISPLAY_DESC_SIZE * number_desc); 204 pGCT = vbt->mrst_gct; 205 pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE); 206 dev_priv->gct_data.bpi = bpi; /*save boot panel id*/ 207 208 /*copy the GCT display timings into a temp structure*/ 209 memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info)); 210 211 /*now copy the temp struct into the dev_priv->gct_data*/ 212 dp_ti->pixel_clock = ti.pixel_clock; 213 dp_ti->hactive_hi = ti.hactive_hi; 214 dp_ti->hactive_lo = ti.hactive_lo; 215 dp_ti->hblank_hi = ti.hblank_hi; 216 dp_ti->hblank_lo = ti.hblank_lo; 217 dp_ti->hsync_offset_hi = ti.hsync_offset_hi; 218 dp_ti->hsync_offset_lo = ti.hsync_offset_lo; 219 dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi; 220 dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo; 221 dp_ti->vactive_hi = ti.vactive_hi; 222 dp_ti->vactive_lo = ti.vactive_lo; 223 dp_ti->vblank_hi = ti.vblank_hi; 224 dp_ti->vblank_lo = ti.vblank_lo; 225 dp_ti->vsync_offset_hi = ti.vsync_offset_hi; 226 dp_ti->vsync_offset_lo = ti.vsync_offset_lo; 227 dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi; 228 dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo; 229 230 /* Move the MIPI_Display_Descriptor data from GCT to dev priv */ 231 dev_priv->gct_data.Panel_MIPI_Display_Descriptor = 232 *((u8 *)pGCT + 0x0d); 233 dev_priv->gct_data.Panel_MIPI_Display_Descriptor |= 234 (*((u8 *)pGCT + 0x0e)) << 8; 235 break; 236 default: 237 dev_err(dev->dev, "Unknown revision of GCT!\n"); 238 vbt->size = 0; 239 } 240 if (IS_MFLD(dev_priv->dev)) { 241 if (panel_id == GCT_DETECT) { 242 if (dev_priv->gct_data.bpi == 2) { 243 dev_info(dev->dev, "[GFX] PYR Panel Detected\n"); 244 dev_priv->panel_id = PYR_CMD; 245 panel_id = PYR_CMD; 246 } else if (dev_priv->gct_data.bpi == 0) { 247 dev_info(dev->dev, "[GFX] TMD Panel Detected.\n"); 248 dev_priv->panel_id = TMD_VID; 249 panel_id = TMD_VID; 250 } else { 251 dev_info(dev->dev, "[GFX] Default Panel (TPO)\n"); 252 dev_priv->panel_id = TPO_CMD; 253 panel_id = TPO_CMD; 254 } 255 } else { 256 dev_info(dev->dev, "[GFX] Panel Parameter Passed in through cmd line\n"); 257 dev_priv->panel_id = panel_id; 258 } 259 } 260} 261 262int mid_chip_setup(struct drm_device *dev) 263{ 264 struct drm_psb_private *dev_priv = dev->dev_private; 265 mid_get_fuse_settings(dev); 266 mid_get_vbt_data(dev_priv); 267 mid_get_pci_revID(dev_priv); 268 return 0; 269}