1 // SPDX-License-Identifier: GPL-2.0-only 2 /************************************************************************** 3 * Copyright (c) 2011, Intel Corporation. 4 * All Rights Reserved. 5 * 6 **************************************************************************/ 7 8 /* TODO 9 * - Split functions by vbt type 10 * - Make them all take drm_device 11 * - Check ioremap failures 12 */ 13 14 #include <drm/drm.h> 15 16 #include "mid_bios.h" 17 #include "psb_drv.h" 18 19 static void mid_get_fuse_settings(struct drm_device *dev) 20 { 21 struct drm_psb_private *dev_priv = dev->dev_private; 22 struct pci_dev *pci_root = 23 pci_get_domain_bus_and_slot(pci_domain_nr(dev->pdev->bus), 24 0, 0); 25 uint32_t fuse_value = 0; 26 uint32_t fuse_value_tmp = 0; 27 28 #define FB_REG06 0xD0810600 29 #define FB_MIPI_DISABLE (1 << 11) 30 #define FB_REG09 0xD0810900 31 #define FB_SKU_MASK 0x7000 32 #define FB_SKU_SHIFT 12 33 #define FB_SKU_100 0 34 #define FB_SKU_100L 1 35 #define FB_SKU_83 2 36 if (pci_root == NULL) { 37 WARN_ON(1); 38 return; 39 } 40 41 42 pci_write_config_dword(pci_root, 0xD0, FB_REG06); 43 pci_read_config_dword(pci_root, 0xD4, &fuse_value); 44 45 /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */ 46 if (IS_MRST(dev)) 47 dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE; 48 49 DRM_INFO("internal display is %s\n", 50 dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display"); 51 52 /* Prevent runtime suspend at start*/ 53 if (dev_priv->iLVDS_enable) { 54 dev_priv->is_lvds_on = true; 55 dev_priv->is_mipi_on = false; 56 } else { 57 dev_priv->is_mipi_on = true; 58 dev_priv->is_lvds_on = false; 59 } 60 61 dev_priv->video_device_fuse = fuse_value; 62 63 pci_write_config_dword(pci_root, 0xD0, FB_REG09); 64 pci_read_config_dword(pci_root, 0xD4, &fuse_value); 65 66 dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value); 67 fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT; 68 69 dev_priv->fuse_reg_value = fuse_value; 70 71 switch (fuse_value_tmp) { 72 case FB_SKU_100: 73 dev_priv->core_freq = 200; 74 break; 75 case FB_SKU_100L: 76 dev_priv->core_freq = 100; 77 break; 78 case FB_SKU_83: 79 dev_priv->core_freq = 166; 80 break; 81 default: 82 dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n", 83 fuse_value_tmp); 84 dev_priv->core_freq = 0; 85 } 86 dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq); 87 pci_dev_put(pci_root); 88 } 89 90 /* 91 * Get the revison ID, B0:D2:F0;0x08 92 */ 93 static void mid_get_pci_revID(struct drm_psb_private *dev_priv) 94 { 95 uint32_t platform_rev_id = 0; 96 int domain = pci_domain_nr(dev_priv->dev->pdev->bus); 97 struct pci_dev *pci_gfx_root = 98 pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(2, 0)); 99 100 if (pci_gfx_root == NULL) { 101 WARN_ON(1); 102 return; 103 } 104 pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); 105 dev_priv->platform_rev_id = (uint8_t) platform_rev_id; 106 pci_dev_put(pci_gfx_root); 107 dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n", 108 dev_priv->platform_rev_id); 109 } 110 111 struct mid_vbt_header { 112 u32 signature; 113 u8 revision; 114 } __packed; 115 116 /* The same for r0 and r1 */ 117 struct vbt_r0 { 118 struct mid_vbt_header vbt_header; 119 u8 size; 120 u8 checksum; 121 } __packed; 122 123 struct vbt_r10 { 124 struct mid_vbt_header vbt_header; 125 u8 checksum; 126 u16 size; 127 u8 panel_count; 128 u8 primary_panel_idx; 129 u8 secondary_panel_idx; 130 u8 __reserved[5]; 131 } __packed; 132 133 static int read_vbt_r0(u32 addr, struct vbt_r0 *vbt) 134 { 135 void __iomem *vbt_virtual; 136 137 vbt_virtual = ioremap(addr, sizeof(*vbt)); 138 if (vbt_virtual == NULL) 139 return -1; 140 141 memcpy_fromio(vbt, vbt_virtual, sizeof(*vbt)); 142 iounmap(vbt_virtual); 143 144 return 0; 145 } 146 147 static int read_vbt_r10(u32 addr, struct vbt_r10 *vbt) 148 { 149 void __iomem *vbt_virtual; 150 151 vbt_virtual = ioremap(addr, sizeof(*vbt)); 152 if (!vbt_virtual) 153 return -1; 154 155 memcpy_fromio(vbt, vbt_virtual, sizeof(*vbt)); 156 iounmap(vbt_virtual); 157 158 return 0; 159 } 160 161 static int mid_get_vbt_data_r0(struct drm_psb_private *dev_priv, u32 addr) 162 { 163 struct vbt_r0 vbt; 164 void __iomem *gct_virtual; 165 struct gct_r0 gct; 166 u8 bpi; 167 168 if (read_vbt_r0(addr, &vbt)) 169 return -1; 170 171 gct_virtual = ioremap(addr + sizeof(vbt), vbt.size - sizeof(vbt)); 172 if (!gct_virtual) 173 return -1; 174 memcpy_fromio(&gct, gct_virtual, sizeof(gct)); 175 iounmap(gct_virtual); 176 177 bpi = gct.PD.BootPanelIndex; 178 dev_priv->gct_data.bpi = bpi; 179 dev_priv->gct_data.pt = gct.PD.PanelType; 180 dev_priv->gct_data.DTD = gct.panel[bpi].DTD; 181 dev_priv->gct_data.Panel_Port_Control = 182 gct.panel[bpi].Panel_Port_Control; 183 dev_priv->gct_data.Panel_MIPI_Display_Descriptor = 184 gct.panel[bpi].Panel_MIPI_Display_Descriptor; 185 186 return 0; 187 } 188 189 static int mid_get_vbt_data_r1(struct drm_psb_private *dev_priv, u32 addr) 190 { 191 struct vbt_r0 vbt; 192 void __iomem *gct_virtual; 193 struct gct_r1 gct; 194 u8 bpi; 195 196 if (read_vbt_r0(addr, &vbt)) 197 return -1; 198 199 gct_virtual = ioremap(addr + sizeof(vbt), vbt.size - sizeof(vbt)); 200 if (!gct_virtual) 201 return -1; 202 memcpy_fromio(&gct, gct_virtual, sizeof(gct)); 203 iounmap(gct_virtual); 204 205 bpi = gct.PD.BootPanelIndex; 206 dev_priv->gct_data.bpi = bpi; 207 dev_priv->gct_data.pt = gct.PD.PanelType; 208 dev_priv->gct_data.DTD = gct.panel[bpi].DTD; 209 dev_priv->gct_data.Panel_Port_Control = 210 gct.panel[bpi].Panel_Port_Control; 211 dev_priv->gct_data.Panel_MIPI_Display_Descriptor = 212 gct.panel[bpi].Panel_MIPI_Display_Descriptor; 213 214 return 0; 215 } 216 217 static int mid_get_vbt_data_r10(struct drm_psb_private *dev_priv, u32 addr) 218 { 219 struct vbt_r10 vbt; 220 void __iomem *gct_virtual; 221 struct gct_r10 *gct; 222 struct oaktrail_timing_info *dp_ti = &dev_priv->gct_data.DTD; 223 struct gct_r10_timing_info *ti; 224 int ret = -1; 225 226 if (read_vbt_r10(addr, &vbt)) 227 return -1; 228 229 gct = kmalloc_array(vbt.panel_count, sizeof(*gct), GFP_KERNEL); 230 if (!gct) 231 return -ENOMEM; 232 233 gct_virtual = ioremap(addr + sizeof(vbt), 234 sizeof(*gct) * vbt.panel_count); 235 if (!gct_virtual) 236 goto out; 237 memcpy_fromio(gct, gct_virtual, sizeof(*gct)); 238 iounmap(gct_virtual); 239 240 dev_priv->gct_data.bpi = vbt.primary_panel_idx; 241 dev_priv->gct_data.Panel_MIPI_Display_Descriptor = 242 gct[vbt.primary_panel_idx].Panel_MIPI_Display_Descriptor; 243 244 ti = &gct[vbt.primary_panel_idx].DTD; 245 dp_ti->pixel_clock = ti->pixel_clock; 246 dp_ti->hactive_hi = ti->hactive_hi; 247 dp_ti->hactive_lo = ti->hactive_lo; 248 dp_ti->hblank_hi = ti->hblank_hi; 249 dp_ti->hblank_lo = ti->hblank_lo; 250 dp_ti->hsync_offset_hi = ti->hsync_offset_hi; 251 dp_ti->hsync_offset_lo = ti->hsync_offset_lo; 252 dp_ti->hsync_pulse_width_hi = ti->hsync_pulse_width_hi; 253 dp_ti->hsync_pulse_width_lo = ti->hsync_pulse_width_lo; 254 dp_ti->vactive_hi = ti->vactive_hi; 255 dp_ti->vactive_lo = ti->vactive_lo; 256 dp_ti->vblank_hi = ti->vblank_hi; 257 dp_ti->vblank_lo = ti->vblank_lo; 258 dp_ti->vsync_offset_hi = ti->vsync_offset_hi; 259 dp_ti->vsync_offset_lo = ti->vsync_offset_lo; 260 dp_ti->vsync_pulse_width_hi = ti->vsync_pulse_width_hi; 261 dp_ti->vsync_pulse_width_lo = ti->vsync_pulse_width_lo; 262 263 ret = 0; 264 out: 265 kfree(gct); 266 return ret; 267 } 268 269 static void mid_get_vbt_data(struct drm_psb_private *dev_priv) 270 { 271 struct drm_device *dev = dev_priv->dev; 272 u32 addr; 273 u8 __iomem *vbt_virtual; 274 struct mid_vbt_header vbt_header; 275 struct pci_dev *pci_gfx_root = 276 pci_get_domain_bus_and_slot(pci_domain_nr(dev->pdev->bus), 277 0, PCI_DEVFN(2, 0)); 278 int ret = -1; 279 280 /* Get the address of the platform config vbt */ 281 pci_read_config_dword(pci_gfx_root, 0xFC, &addr); 282 pci_dev_put(pci_gfx_root); 283 284 dev_dbg(dev->dev, "drm platform config address is %x\n", addr); 285 286 if (!addr) 287 goto out; 288 289 /* get the virtual address of the vbt */ 290 vbt_virtual = ioremap(addr, sizeof(vbt_header)); 291 if (!vbt_virtual) 292 goto out; 293 294 memcpy_fromio(&vbt_header, vbt_virtual, sizeof(vbt_header)); 295 iounmap(vbt_virtual); 296 297 if (memcmp(&vbt_header.signature, "$GCT", 4)) 298 goto out; 299 300 dev_dbg(dev->dev, "GCT revision is %02x\n", vbt_header.revision); 301 302 switch (vbt_header.revision) { 303 case 0x00: 304 ret = mid_get_vbt_data_r0(dev_priv, addr); 305 break; 306 case 0x01: 307 ret = mid_get_vbt_data_r1(dev_priv, addr); 308 break; 309 case 0x10: 310 ret = mid_get_vbt_data_r10(dev_priv, addr); 311 break; 312 default: 313 dev_err(dev->dev, "Unknown revision of GCT!\n"); 314 } 315 316 out: 317 if (ret) 318 dev_err(dev->dev, "Unable to read GCT!"); 319 else 320 dev_priv->has_gct = true; 321 } 322 323 int mid_chip_setup(struct drm_device *dev) 324 { 325 struct drm_psb_private *dev_priv = dev->dev_private; 326 mid_get_fuse_settings(dev); 327 mid_get_vbt_data(dev_priv); 328 mid_get_pci_revID(dev_priv); 329 return 0; 330 } 331