@@ -17,15 +17,146 @@ Options:
1717 -m, --model [value] Specify the model code of the phone
1818 -k, --ksu [Y/n] Include KernelSU
1919 -r, --recovery [y/N] Compile kernel for an Android Recovery
20+ -g, --gpu-max [value] Set GPU max MHz (ex: 806) using forOC tables
2021EOF
2122}
2223
24+ apply_gpu_tables ()
25+ {
26+ local max_khz=" $1 "
27+ local src_dtsi=" $PWD /forOC/exynos9820-mali_tables.dtsi"
28+ local dst_dtsi=" $PWD /arch/arm64/boot/dts/exynos/exynos9820-mali_tables.dtsi"
29+ local src_cal=" $PWD /forOC/g3d_dvfs_table.h"
30+ local dst_cal=" $PWD /drivers/soc/samsung/cal-if/g3d_dvfs_table.h"
31+
32+ if [ ! -f " $src_dtsi " ] || [ ! -f " $src_cal " ]; then
33+ echo " GPU table sources not found under forOC; skipping GPU table update."
34+ return 1
35+ fi
36+
37+ if ! command -v python3 > /dev/null 2>&1 ; then
38+ echo " python3 not found; cannot update GPU tables."
39+ return 1
40+ fi
41+
42+ python3 - " $max_khz " " $src_dtsi " " $dst_dtsi " " $src_cal " " $dst_cal " << 'PY '
43+ import re
44+ import sys
45+ from pathlib import Path
46+
47+ max_khz = int(sys.argv[1])
48+ src_dtsi = Path(sys.argv[2])
49+ dst_dtsi = Path(sys.argv[3])
50+ src_cal = Path(sys.argv[4])
51+ dst_cal = Path(sys.argv[5])
52+
53+ def parse_table(lines, key):
54+ start = next(i for i, l in enumerate(lines) if key in l)
55+ end = next(i for i in range(start + 1, len(lines)) if ">;" in lines[i])
56+ entries = []
57+ indent = None
58+ for line in lines[start + 1:end + 1]:
59+ stripped = line.strip()
60+ if not stripped or stripped.startswith("/*"):
61+ continue
62+ cleaned = re.sub(r">;\s*$", "", stripped)
63+ cleaned = re.sub(r">\s*$", "", cleaned)
64+ parts = cleaned.split()
65+ if not parts or not parts[0].isdigit():
66+ continue
67+ freq = int(parts[0])
68+ if indent is None:
69+ indent = line[:len(line) - len(line.lstrip())]
70+ entries.append((freq, cleaned))
71+ if indent is None:
72+ indent = "\t"
73+ return start, end, entries, indent
74+
75+ def update_size_line(line, row, cols):
76+ return re.sub(r"<\s*\d+\s+%d\s*>" % cols, f"<{row} {cols}>", line)
77+
78+ def update_clock_line(line, value):
79+ return re.sub(r"<\s*\d+\s*>", f"<{value}>", line)
80+
81+ def write_dtsi():
82+ lines = src_dtsi.read_text().splitlines(True)
83+ start, end, entries, indent = parse_table(lines, "gpu_dvfs_table = <")
84+ filtered = [e for e in entries if e[0] <= max_khz]
85+ if not any(e[0] == max_khz for e in filtered):
86+ raise SystemExit(f"GPU max {max_khz} not found in DVFS table")
87+ dvfs_block = []
88+ for idx, (_, cleaned) in enumerate(filtered):
89+ suffix = " >;\n" if idx == len(filtered) - 1 else "\n"
90+ dvfs_block.append(f"{indent}{cleaned}{suffix}")
91+ lines[start + 1:end + 1] = dvfs_block
92+
93+ start, end, entries, indent = parse_table(lines, "gpu_cl_pmqos_table = <")
94+ filtered_cl = [e for e in entries if e[0] <= max_khz]
95+ if not any(e[0] == max_khz for e in filtered_cl):
96+ raise SystemExit(f"GPU max {max_khz} not found in PMQoS table")
97+ cl_block = []
98+ for idx, (_, cleaned) in enumerate(filtered_cl):
99+ suffix = " >;\n" if idx == len(filtered_cl) - 1 else "\n"
100+ cl_block.append(f"{indent}{cleaned}{suffix}")
101+ lines[start + 1:end + 1] = cl_block
102+
103+ for i, line in enumerate(lines):
104+ if line.strip().startswith("gpu_dvfs_table_size"):
105+ lines[i] = update_size_line(line, len(filtered), 8)
106+ elif line.strip().startswith("gpu_cl_pmqos_table_size"):
107+ lines[i] = update_size_line(line, len(filtered_cl), 5)
108+ elif line.strip().startswith("gpu_max_clock_limit"):
109+ lines[i] = update_clock_line(line, max_khz)
110+ elif line.strip().startswith("gpu_max_clock"):
111+ lines[i] = update_clock_line(line, max_khz)
112+
113+ dst_dtsi.write_text("".join(lines))
114+
115+ def write_cal():
116+ lines = src_cal.read_text().splitlines(True)
117+ start = next(i for i, l in enumerate(lines)
118+ if "G3D_DVFS_TABLE_ENTRY_LIST" in l)
119+ i = start + 1
120+ entries = []
121+ indent = None
122+ while i < len(lines):
123+ line = lines[i]
124+ if line.strip().startswith("#endif") or not line.strip():
125+ break
126+ m = re.search(r"\bX\((\d+),", line)
127+ if m:
128+ if indent is None:
129+ indent = line[:len(line) - len(line.lstrip())]
130+ entries.append((int(m.group(1)), line))
131+ i += 1
132+ if indent is None:
133+ indent = "\t"
134+ filtered = [(f, l) for (f, l) in entries if f <= max_khz]
135+ if not any(f == max_khz for f, _ in filtered):
136+ raise SystemExit(f"GPU max {max_khz} not found in CAL table")
137+ new_list = []
138+ for idx, (_, line) in enumerate(filtered):
139+ core = line.rstrip().rstrip("\\").rstrip()
140+ suffix = "\n" if idx == len(filtered) - 1 else " \\\n"
141+ new_list.append(f"{indent}{core}{suffix}")
142+ lines[start + 1:i] = new_list
143+ dst_cal.write_text("".join(lines))
144+
145+ write_dtsi()
146+ write_cal()
147+ PY
148+ }
149+
23150while [[ $# -gt 0 ]]; do
24151 case " $1 " in
25152 --model|-m)
26153 MODEL=" $2 "
27154 shift 2
28155 ;;
156+ --gpu-max|-g)
157+ GPU_MAX=" $2 "
158+ shift 2
159+ ;;
29160 --ksu|-k)
30161 KSU_OPTION=" $2 "
31162 shift 2
@@ -148,6 +279,25 @@ if [[ "$KSU_OPTION" == "y" ]]; then
148279 KSU=ksu.config
149280fi
150281
282+ if [ -n " $GPU_MAX " ]; then
283+ if ! [[ " $GPU_MAX " =~ ^[0-9]+$ ]]; then
284+ echo " Invalid GPU max value: $GPU_MAX "
285+ exit 1
286+ fi
287+
288+ if [ " $SOC " != " exynos9820" ]; then
289+ echo " GPU max override is only supported on exynos9820; skipping."
290+ else
291+ if [ " $GPU_MAX " -lt 10000 ]; then
292+ GPU_MAX_KHZ=$(( GPU_MAX * 1000 ))
293+ else
294+ GPU_MAX_KHZ=$GPU_MAX
295+ fi
296+ echo " Applying GPU max: ${GPU_MAX_KHZ} kHz (from forOC tables)"
297+ apply_gpu_tables " $GPU_MAX_KHZ " || abort
298+ fi
299+ fi
300+
151301rm -rf build/out/$MODEL
152302mkdir -p build/out/$MODEL /zip/files
153303mkdir -p build/out/$MODEL /zip/META-INF/com/google/android
0 commit comments