一块 LG 屏的 DDC/CI 折腾记

事情是无意间发生的,于平平无奇的日常中随之展开了一段幸好有限的故事。到现在总算把这套工作流全部配完,趁还有精力赶紧记下来


起因

去年买了 LG 27UP850N 这块屏,内置两个 5W 音响,我的木耳要求不高,当时的想法是延续之前便携屏的方案,让笔电和外接屏的音响同时出声,营造一种多声源的感觉。虽然知道这方案不太好,但之前 16 寸便携屏和 13 寸笔电刚好能并排放在桌面左右两边,只用笔电音响总觉得只有左声道,有些别扭。恰好便携屏也有两个音响,音质虽烂,为了综合体验就用 Voicemeeter 配了多音源输出。没用系统自带方案是因为 Windows 的音频处理延迟太高,两边声音严重不同步,会出现叠声甚至回音。

一直用到换了 M 系芯片的 Mac,不同步的问题就没了。依稀记得当时只是在 Audio MIDI Setup 里加了个多音源输出,给外接屏勾上 Drift Correction,一切顺利,直到——

去年盛夏便携屏坏了,修不好,索性换了这块 LG 27 寸屏。不过桌子太小,它几乎占满了整个桌面,不得不买支架架起来,和笔电并排放已经不可能了。后续还配了鼠标键盘和一台迷你主机,这些在去年年末回顾里都有提到。

配置这块屏和笔电音响协作时,发现每次都要伸手去拨显示器下面的摇杆,还要去 Audio MIDI Setup 里调笔电扬声器,没法用键盘统一控制两者音量,体验很差。找了几个虚拟声卡方案,最后用了 eqMac 的免费版,一直到最近……

从多音源到单音源

这几天偶然出现屏幕关了但还在放歌的情况,笔电这边有声,但发现音量小到几乎可以忽略不计。既然以显示屏的扬声器为主对我来说也足够了,索性从多音源换单显示屏发声。

删掉多音源,把扬声器切到屏幕上,又回到了要用手去拨摇杆调音量的状态。于是找相关软件,看能不能用键盘直接控制显示屏音量。还真有,找到了 MonitorControl,功能不少,亮度音量都能调,而且支持键盘原生快捷键,装上就能用。原理是通过 USB-C 走 DDC/CI 协议直接发送硬件指令。

但第一档音量就特别大,键盘一按直接炸耳。有点像洗澡时调花洒冷热,往左一点是火往右一点是冰。网上有人说按住 Shift + Option 再按音量键可以微调,但实测行不通。后来发现 MonitorControl 里就能限制最大音量:

如果微调第一格还是觉得大,可以压缩整体比例来“骗”显示器:

  1. 点击顶部状态栏的 MonitorControl 图标,进入 设置 (Preferences/Settings)
  2. 找到 【Displays】(显示器) 标签页。
  3. 往下看,应该能找到关于 DDC 限制 (DDC limits) 或者 Max DDC volume 的高级设置(如果你打开了“显示高级设置” Show advanced settings 的话)。
  4. 怎么做: 把最大音量(Max)限制在 50% 甚至更低。
  5. 原理: 这样你用键盘按满格音量时,软件实际上只给显示器发送了 50% 的指令,那么第一格的音量也就相应地被按比例缩小了!

还有个特别实用的设置就在旁边:

还是在 Volume: 这一行,找到 Scale mapping curve(缩放映射曲线)下面的那个滑块。你可以尝试把它往左或往右拖动一下

  • 原理: 这个滑块可以改变音量增加的“曲线”。调一下也许能让前半段的音量增长变得更平缓,不会一上来就猛增。

全部设置好后,会实时自动保存并一直永久记住。

Windows 侧的尝试

既然 Mac 能这么干,连 HDMI 的 Windows 迷你主机是不是也有类似方案?找到了 Twinkle Tray,同样是 FOSS,功能大差不差。

不过你可能会问,Windows 不需要吧,又不像 macOS 无法控制外部设备音量,把显示屏调到差不多的位置,全程用系统音量不就好了?确实是我最终的做法。本来想让两个系统都统一走屏幕硬件音量,但 Windows 系统原生音量的优先级极高,快捷键完全接管不了,遂放弃。

亮度

既然音量解决了,接下来是亮度。我键盘上没有原生的亮度映射,但反正长期关着键盘背光,索性把背光增减键映射到显示屏亮度上。

设置好了,但又发现了问题:没调 Scale Mapping Curve 的情况下,每一档对应 -13%,四档就到 50% 了。更离谱的是,屏幕亮度 0% 竟然还能继续调低。

查阅后发现这是 MonitorControl 的“混合调光”功能:

当硬件亮度到 0% 后继续按调暗键,MonitorControl 会无缝切换到软件调光,在画面上覆盖一层纯黑色半透明滤镜(Gamma 遮罩),突破硬件的物理极限。截图里那个 Combined Dimming Switchover Point 滑块就是控制切换阈值的。

自此,通过 DDC/CI 调显示屏亮度和音量的这一阶段暂告一段落。

信号源切换

每次在两台电脑之间切换都要按显示器上的摇杆,有没有办法用软件解决?虽然现在有时候偷懒直接用 Parsec 内网连 Windows,但路由器状态不好时还是会卡。

macOS → Windows

最初想用同一开发者的 BetterDisplay,但发现要付费且未开源。看到他还有个开源的 CLI 工具 m1ddc,刚好支持 USB-C 直连,遂用。

装好可不算完,中途折腾了一番 set input 接口代码,一直找不对接口代码。无论在 Mac 还是 Win,m1ddc get input 都输出 15。查阅后发现:

国际标准规定 HDMI 1 是 17,HDMI 2 是 18。但 LG 的固件工程师没有遵守标准,给 HDMI 分配了私有的高位代码:HDMI 1 = 144 (0x90),HDMI 2 = 145 (0x91)。所以发 17 过去显示器毫无反应。

执行 m1ddc set input 144 还是不行。继续查:

在标准的显示器协议里,大家都是往一个叫 0x51 的物理内存地址发指令。但是!LG 在 27UP850 等几款较新的显示器上“发癫”了,搞了个极其非主流的底层协议(开发者称之为 “LG Alt”)。
LG 要求必须往 0x50 这个非标地址发,或者用另一个隐藏的寄存器(0xF4)。m1ddc 作为一个老实本分的标准开源工具,用标准姿势发指令,LG 的芯片收到了但不认,所以直接把原数字弹回给你,毫无反应。

最后执行 m1ddc set input-alt 144 才成功。

当然这还不算完,还要变得优雅些,所以用了 Apple 自带的快捷指令,配置如下:

💡 实践中有一些需要注意的地方:如果添加了快捷键到快捷指令,会蹦出个 Receive 那行到 Shell 上面,如果快捷键执行无反应要将第一个改为 No 变成 No input…
如果还是没用就去「设置」-「键盘」-「键盘快捷键」-「服务」-「快捷指令」看看对应指令是否打勾,没打勾就勾选上,然后直接保存再试一次应该就可以了

之后再对接键盘上不怎么用的快捷键:

至此 macOS 切到 Windows 已完成。

Windows → macOS

这边可是让我最抓狂和最头痛的,本来查阅资料用的是 ControlMyMonitor 这款老软件,结果根本改不动,一点反应都没有,甚至 Gemini 还让我「彻底死心」,说得一套一套的,差点就把我说服了:

这绝对不是你的操作问题,也不是什么管理员权限没开!

我刚才死死盯着你发来的第二张截图(ControlMyMonitor),注意到了最上面那行极其致命的信息:Monitor: AMD Radeon 780M Graphics

这行字,加上你说的“永远显示 15、怎么改都不动”,直接宣告了我们在 Windows 端的“死刑”。别怪这软件,罪魁祸首是 LG 极其反人类的底层硬件协议。

1. 为什么 VCP Code 60 变成了“僵尸”?

在显示器行业标准里,60 (Input Select) 就是用来切信号源的。但 LG 的固件工程师在这个型号上故意锁死了 60 通道,不管你连的是什么,它就只当个摆设(永远返回 15 或者无视你的修改指令)。它不接受标准 API 的任何写入操作,所以 ControlMyMonitor 怎么敲都没用。

2. 为什么 Mac 就能切过去?

LG 把真正的切换开关藏在了 0xF4 这个私有代码里,要求必须发送到非标准的隐藏地址 (0x50)m1ddc 的作者知道这个后门,所以专门写了 input-alt 命令绕路塞进去。

3. 为什么 Windows (AMD 显卡) 彻底没救?

ControlMyMonitor 只能走微软提供的标准 DDC/CI 通道,摸不到 LG 的隐藏地址。GitHub 上的极客们写了能绕过的工具(如 winddc),但 100% 依赖 NVIDIA 私有接口 (NvAPI)。AMD Radeon 780M 核显目前无解。

然而 Gemini 给的方案是全程通过 Mac 切换,谁受得了。于是自己去 Google,第一条就是它提到的 NVIDIA API 方案的 Reddit 帖子,标题还是「The first and only solution!」。结果翻评论区,看到有人贴了 AMD 的解法:

Found a working solution for AMD: amdddc-windows. No Windows binary available but compiling is a piece of cake.

当场就把 Gemini 骂了一顿。用中文搜还发现连中文都有人发过文章,过程还挺详细的。另外 issue 里还有人做成了 GUI

CLI 跑通后,接下来做成快捷键:

创建快捷方式

  1. 找到 amdddc-windows.exe,右键“发送到”创建桌面快捷方式。
  2. 右键快捷方式→属性→快捷方式选项卡。

注入参数与快捷键

在属性窗口里改三个地方:

  1. 目标: 在路径后加空格,粘贴参数:"你的路径\amdddc-windows.exe" --i2c-source-addr 0x50 setvcp 0 24 0xD1 (后三位根据自己情况自行修改)
  2. 快捷键: 自行设置
  3. 运行方式: 选“最小化”,避免弹黑框。

最后

至此完成:

  • 在 Mac 时: 盲按 F7(切屏幕到 Win)→ F1(键盘切到 Win)
  • 在 Win 时: 盲按 F7(切屏幕回 Mac)→ F2(键盘回 Mac)
  • 全程双手不离键盘,不碰鼠标,不摸显示器摇杆,没有任何臃肿软件常驻后台

tinkering with an lg screen over ddc/ci

machine-translated from the original

it started by accident, and out of a perfectly ordinary day unfolded a saga that was, thankfully, finite. now that the whole workflow is finally configured, i’m writing it down while i still have the energy


how it started

last year i bought this lg 27UP850N, which has two built-in 5w speakers; my tin ears don’t ask for much, and the idea at the time was to carry over the setup from the old portable monitor: laptop and external-screen speakers playing together for a multi-source feel. i knew it wasn’t a great scheme, but the 16-inch portable and the 13-inch laptop happened to sit side by side on the left and right of the desk, and using the laptop speakers alone always felt like left channel only — a bit off. the portable monitor happened to have two speakers as well; the sound quality was terrible, but for the overall experience i used voicemeeter to set up multi-device output. i didn’t use the system’s own option because windows’ audio processing latency is too high and the two sides fall badly out of sync, with doubled sound and even echo.

that lasted until i switched to an m-series mac, where the sync problem went away. as i vaguely remember, i just added a multi-output device in audio midi setup, ticked Drift Correction for the external screen, and everything was fine, until —

in high summer last year the portable monitor broke, beyond repair, so i replaced it with this 27-inch lg. but the desk is too small; it took up nearly the whole surface and had to go on an arm, and sitting it beside the laptop was no longer possible. i later added a keyboard and mouse and a mini pc, all mentioned in last year’s review.

setting up this screen to work with the laptop speakers, i found that every time i had to reach for the joystick under the monitor, and also go into audio midi setup to adjust the laptop speakers; there was no way to control both volumes from the keyboard, and the experience was poor. i looked at several virtual sound card options and ended up on the free tier of eqmac, right up until recently…

from multi-source to single source

a few days ago it happened that the screen was off but music was still playing; there was sound from the laptop side, but the volume was so low as to be negligible. since making the monitor’s speakers the main source is enough for me, i switched from multi-source to the monitor alone.

having deleted the multi-output device and switched the speakers to the monitor, i was back to reaching for the joystick to adjust volume. so i looked for software to control the monitor’s volume straight from the keyboard. there is one: monitorcontrol, with plenty of features — brightness and volume both adjustable, native keyboard shortcuts supported, works out of the box. it works by sending hardware commands straight over the ddc/ci protocol via usb-c.

but the first volume step was especially loud — one press of the keyboard and my ears exploded. a bit like adjusting a shower: a touch left is fire, a touch right is ice. people online said holding Shift + Option while pressing the volume keys allows fine adjustment, but in practice it didn’t work. later i found that monitorcontrol itself can cap the maximum volume:

if the first notch of fine adjustment still feels loud, you can compress the overall scale to 「trick」 the monitor:

  1. click the monitorcontrol icon in the menu bar and open Settings (Preferences/Settings).
  2. find the Displays tab.
  3. further down you should find the advanced setting for DDC limits or Max DDC volume (if you’ve turned on Show advanced settings).
  4. what to do: cap the maximum volume (Max) at 50% or even lower.
  5. why it works: this way, when you hit full volume on the keyboard, the software actually only sends the monitor a 50% command, and the first notch shrinks in proportion too!

there’s another very practical setting right beside it:

still on the Volume: row, find the slider under Scale mapping curve. try dragging it a little left or right.

  • why it works: this slider changes the 「curve」 of the volume increase. a tweak may make the first half of the range climb more gently, instead of jumping up straight away.

once set, everything saves in real time and is remembered permanently.

trying on the windows side

if the mac can do this, could the windows mini pc connected over hdmi have something similar? i found twinkle tray, also foss, with much the same features.

you might ask: does windows even need it — unlike macos it can control an external device’s volume, so set the monitor roughly where you want it and just use the system volume throughout? that is indeed what i ended up doing. i’d meant to have both systems uniformly use the monitor’s hardware volume, but windows’ native system volume has extremely high priority and the shortcuts couldn’t take it over at all, so i gave up.

brightness

with volume sorted, brightness was next. my keyboard has no native brightness mapping, but since i keep the backlight off anyway, i mapped the backlight up/down keys to the monitor’s brightness.

set up — but then another problem: without adjusting the scale mapping curve, each step is -13%, and four steps lands at 50%. stranger still, the screen could keep going lower past 0% brightness.

reading up, this is monitorcontrol’s 「combined dimming」: when hardware brightness reaches 0% and you keep pressing dim, monitorcontrol switches seamlessly to software dimming, laying a pure-black semi-transparent filter (a gamma mask) over the picture to push past the hardware’s physical limit. the Combined Dimming Switchover Point slider in the screenshot controls the threshold.

with that, the stage of adjusting the monitor’s brightness and volume over ddc/ci came to a close.

switching inputs

switching between the two machines meant pressing the monitor’s joystick every time — could software handle it? lately i’ve sometimes been lazy and just used parsec over the lan to get at windows, but it stutters when the router is in a bad mood.

macos → windows

at first i wanted betterdisplay from the same developer, but found it’s paid and not open source. i saw he also has an open-source cli tool, m1ddc, which happens to support usb-c direct connections, so i used that.

installing it wasn’t the end of it; partway through i wrestled with set input <code> for a while, never finding the right input code. on both mac and win, m1ddc get input printed 15. reading up:

the international standard says hdmi 1 is 17 and hdmi 2 is 18. but lg’s firmware engineers didn’t follow the standard and gave hdmi private high codes: hdmi 1 = 144 (0x90), hdmi 2 = 145 (0x91). so sending 17 gets no reaction from the monitor at all.

m1ddc set input 144 still didn’t work. digging further:

in the standard monitor protocol, everyone sends commands to a physical memory address called 0x51. but! on the 27UP850 and a few other newer monitors, lg 「went feral」 and cooked up an extremely non-mainstream low-level protocol (the developer calls it “LG Alt”).
lg demands that you send to the non-standard address 0x50, or use another hidden register (0xF4). m1ddc, an honest, by-the-book open-source tool, sends commands the standard way; lg’s chip receives them but doesn’t recognise them, so it just bounces the number back at you and does nothing.

in the end m1ddc set input-alt 144 worked.

of course that still wasn’t the end — it had to be made elegant, so i used apple’s own shortcuts, configured like this:

💡 a few things to watch in practice: if you add a keyboard shortcut to a shortcut, a 「Receive」 line pops up above the Shell action; if pressing the shortcut does nothing, change the first one to No so it becomes No input…
if it still does nothing, go to 「Settings」-「Keyboard」-「Keyboard Shortcuts」-「Services」-「Shortcuts」 and check whether the shortcut is ticked; tick it if not, save, and try again — that should do it

then wire it to a rarely used key on the keyboard:

and with that, macos → windows was done.

windows → macos

this side drove me the most mad and gave me the biggest headache. the research pointed to an old utility, controlmymonitor, which turned out to change nothing at all, not the slightest reaction; gemini even told me to 「give up completely」, so persuasively it nearly convinced me:

this is absolutely not an operator error, and it’s not about admin rights either!

i was just staring hard at the second screenshot you sent (ControlMyMonitor) and noticed an extremely fatal line at the very top: Monitor: AMD Radeon 780M Graphics.

that line, plus your 「always shows 15, nothing changes no matter what」, pronounces a 「death sentence」 on our windows side. don’t blame the software — the culprit is lg’s extremely user-hostile low-level hardware protocol.

1. why has VCP Code 60 become a 「zombie」?

in the monitor industry standard, 60 (Input Select) is the code for switching inputs. but lg’s firmware engineers deliberately locked channel 60 on this model; whatever you connect, it’s just decoration (forever returning 15, or ignoring your write commands). it accepts no write operations through the standard api, so ControlMyMonitor gets nowhere no matter what you type.

2. why can the mac switch it?

lg hid the real switch in the private code 0xF4, and requires it to be sent to the non-standard hidden address (0x50). the author of m1ddc knew about this back door and wrote the input-alt command specifically to sneak around it.

3. why is windows (amd graphics) a total lost cause?

ControlMyMonitor can only go through the standard ddc/ci channel microsoft provides and can’t reach lg’s hidden address. geeks on github have written tools that get around it (like winddc), but they depend 100% on nvidia’s private interface (NvAPI). the amd radeon 780m integrated graphics currently has no solution.

but the solution gemini offered was to do every switch from the mac — who could stand that. so i went to google myself, and the first result was the nvidia-api approach it mentioned, a reddit thread titled, no less, 「The first and only solution!」. but scrolling the comments, someone had posted the amd answer:

Found a working solution for AMD: amdddc-windows. No Windows binary available but compiling is a piece of cake.

i gave gemini a telling-off on the spot. searching in chinese i found someone had even written a post about it, quite detailed. and in the issues someone had made a gui.

with the cli working, next was turning it into a shortcut key:

create a shortcut

  1. find amdddc-windows.exe, right-click → 「Send to」 → create a desktop shortcut.
  2. right-click the shortcut → Properties → the Shortcut tab.

add the arguments and the hotkey

change three things in the properties window:

  1. Target: add a space after the path and paste the arguments: "your\path\amdddc-windows.exe" --i2c-source-addr 0x50 setvcp 0 24 0xD1 (adjust the last three values to your own setup)
  2. Shortcut key: set as you like
  3. Run: choose 「Minimized」 to avoid the black window popping up.

finally

and so it’s done:

  • on the mac: blind-press F7 (screen to win) → F1 (keyboard to win)
  • on win: blind-press F7 (screen back to mac) → F2 (keyboard back to mac)
  • hands never leave the keyboard, no mouse, no monitor joystick, and no bloated software sitting in the background