summaryrefslogtreecommitdiffstats
path: root/resources/utilities/i945gpu/intel-regs.py
blob: f16a8d75f430e46d6d12be00670819b6d467ebf1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
# Copyright (C) 2014  Michał Masłowski  <mtjm@mtjm.eu>
#
# Licensed under copyleft-next version 0.3.0.  See
# https://gitorious.org/copyleft-next/copyleft-next/raw/master:Releases/copyleft-next-0.3.0
# for more information.

"""Get values of interesting i945 graphics parameters from a running system.

This script might show the values for GPU registers specified in
devicetree.cb on coreboot mainboard ports using i945 native VGA init
from <http://review.coreboot.org/#/c/5320/>.

Run as root.
"""


import mmap
import re
import struct
import subprocess


_MEMORY = re.compile(r"^\s+Memory\s+at\s+([0-9a-f]+)\s+\(32-bit, non-prefetchable\)\s+\[size=[0-9]+K\]$")


def get_pci_data():
    # lspci has a machine readable format, but it doesn't have the needed data.
    for devid in "8086:27a2", "8086:27a6":
        lspci = subprocess.Popen(("lspci", "-vn", "-d", devid),
                                 stdout=subprocess.PIPE,
                                 stderr=subprocess.PIPE)
        for line in lspci.communicate()[0].split("\n"):
            match = _MEMORY.match(line)
            if match is not None:
                yield int(match.group(1), 16)
                break

func0, func1 = list(get_pci_data())


def read32(fo, base, offset):
    memory = mmap.mmap(fo.fileno(), offset + 4,
                       mmap.MAP_SHARED, mmap.ACCESS_READ,
                       offset=base)
    try:
        memory.seek(offset)
        val = memory.read(4)
        return struct.unpack("=I", val)[0]
    finally:
        memory.close()

# Some i915 register names.
PORT_HOTPLUG_EN = 0x61110
BLC_PWM_CTL = 0x61254
LVDS = 0x61180

# Bits in LVDS.
LVDS_CLOCK_B_POWERUP_ALL = 3 << 4
LVDS_CLOCK_BOTH_POWERUP_ALL = 3 << 2

# Expansion of DPLL(1).
DPLL1 = ((0x06014) + (1)*((0x06018)-(0x06014)))

# Bits there.
DPLL_INTEGRATED_CLOCK_VLV = (1<<13)
DPLL_INTEGRATED_CRI_CLK_VLV = (1<<14)

if __name__ == "__main__":
    with open("/dev/mem", "rb") as mem:
        print "gpu_hotplug = 0x%08x" % read32(mem, func0, PORT_HOTPLUG_EN)
        dpll = read32(mem, func0, DPLL1)
        spread_spectrum = dpll & (DPLL_INTEGRATED_CLOCK_VLV \
                                  | DPLL_INTEGRATED_CRI_CLK_VLV)
        if spread_spectrum != 0:
            spread_spectrum = 1
        print "gpu_lvds_use_spread_spectrum_clock = %d" % spread_spectrum
        lvds = read32(mem, func0, LVDS)
        dual_channel = lvds & (LVDS_CLOCK_B_POWERUP_ALL \
                               | LVDS_CLOCK_BOTH_POWERUP_ALL)
        if dual_channel != 0:
            dual_channel = 1
        print "gpu_lvds_is_dual_channel = %d" % dual_channel
        backlight = read32(mem, func0, BLC_PWM_CTL)
        print "gpu_backlight = 0x%08x" % backlight
        # Using display clock from i945_get_display_clock_speed in
        # drivers/gpu/drm/i915/intel_display.c.  Result multiplied by
        # two to match BIOS-reported PWM frequency on my X60t.
        mod_freq = 2 * 400000000 / ((backlight >> 16) * 128.0)
        print "backlight modulation frequency = %f Hz" % mod_freq
        print "duty cycle = %d%%" % (100.0 * (backlight & 0xffff)
                                     / (backlight >> 16))