intel-regs.py 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. #!/usr/bin/env python2
  2. # -*- coding: utf-8 -*-
  3. # Copyright (C) 2014 Michał Masłowski <mtjm@mtjm.eu>
  4. #
  5. # Licensed under copyleft-next version 0.3.0. See
  6. # https://gitorious.org/copyleft-next/copyleft-next/raw/master:Releases/copyleft-next-0.3.0
  7. # for more information.
  8. """Get values of interesting i945 graphics parameters from a running system.
  9. This script might show the values for GPU registers specified in
  10. devicetree.cb on coreboot mainboard ports using i945 native VGA init
  11. from <http://review.coreboot.org/#/c/5320/>.
  12. Run as root.
  13. """
  14. import mmap
  15. import re
  16. import struct
  17. import subprocess
  18. _MEMORY = re.compile(r"^\s+Memory\s+at\s+([0-9a-f]+)\s+\(32-bit, non-prefetchable\)\s+\[size=[0-9]+K\]$")
  19. def get_pci_data():
  20. # lspci has a machine readable format, but it doesn't have the needed data.
  21. for devid in ("8086:27a2",):
  22. lspci = subprocess.Popen(("lspci", "-vn", "-d", devid),
  23. stdout=subprocess.PIPE,
  24. stderr=subprocess.PIPE)
  25. address = None
  26. memory = None
  27. for line in lspci.communicate()[0].split("\n"):
  28. if line and line[0] == "0":
  29. address = line.split()[0]
  30. match = _MEMORY.match(line)
  31. if match is not None:
  32. memory = int(match.group(1), 16)
  33. break
  34. yield (address, memory)
  35. def config_byte(address, offset):
  36. """Return byte at specified offset in PCI config space of device
  37. identified by address."""
  38. with open("/sys/bus/pci/devices/0000:%s/config" % address, "rb") as f:
  39. f.seek(offset)
  40. return struct.unpack("=B", f.read(1))
  41. addr0, func0 = list(get_pci_data())[0]
  42. def read32(fo, base, offset):
  43. memory = mmap.mmap(fo.fileno(), offset + 4,
  44. mmap.MAP_SHARED, mmap.ACCESS_READ,
  45. offset=base)
  46. try:
  47. memory.seek(offset)
  48. val = memory.read(4)
  49. return struct.unpack("=I", val)[0]
  50. finally:
  51. memory.close()
  52. # Some i915 register names.
  53. PORT_HOTPLUG_EN = 0x61110
  54. BLC_PWM_CTL = 0x61254
  55. LVDS = 0x61180
  56. # Bits in LVDS.
  57. LVDS_CLOCK_B_POWERUP_ALL = 3 << 4
  58. LVDS_CLOCK_BOTH_POWERUP_ALL = 3 << 2
  59. # Expansion of DPLL(1).
  60. DPLL1 = ((0x06014) + (1)*((0x06018)-(0x06014)))
  61. # Bits there.
  62. DPLL_INTEGRATED_CLOCK_VLV = (1<<13)
  63. DPLL_INTEGRATED_CRI_CLK_VLV = (1<<14)
  64. if __name__ == "__main__":
  65. with open("/dev/mem", "rb") as mem:
  66. print "gpu_hotplug = 0x%08x" % read32(mem, func0, PORT_HOTPLUG_EN)
  67. dpll = read32(mem, func0, DPLL1)
  68. spread_spectrum = dpll & (DPLL_INTEGRATED_CLOCK_VLV \
  69. | DPLL_INTEGRATED_CRI_CLK_VLV)
  70. if spread_spectrum != 0:
  71. spread_spectrum = 1
  72. print "gpu_lvds_use_spread_spectrum_clock = %d" % spread_spectrum
  73. lvds = read32(mem, func0, LVDS)
  74. dual_channel = lvds & (LVDS_CLOCK_B_POWERUP_ALL \
  75. | LVDS_CLOCK_BOTH_POWERUP_ALL)
  76. if dual_channel != 0:
  77. dual_channel = 1
  78. print "gpu_lvds_is_dual_channel = %d" % dual_channel
  79. backlight = read32(mem, func0, BLC_PWM_CTL)
  80. print "gpu_backlight = 0x%08x" % backlight
  81. # Using display clock from i945_get_display_clock_speed in
  82. # drivers/gpu/drm/i915/intel_display.c. Result multiplied by
  83. # two to match BIOS-reported PWM frequency on my X60t.
  84. mod_freq = 2 * 400000000 / ((backlight >> 16) * 128.0)
  85. print "backlight modulation frequency = %f Hz" % mod_freq
  86. print "duty cycle = %d%%" % (100.0 * (backlight & 0xffff)
  87. / (backlight >> 16))
  88. print "legacy backlight brightness = 0x%02x" % config_byte(addr0, 0xf4)