Дисклеймер: Под названием HY-300 продаётся множество внешне похожих проекторов от разных производителей — с разными SoC, прошивками и аппаратными решениями. Всё описанное ниже относится к конкретному экземпляру на базе Rockchip RK3326 с прошивкой от TXCZ. У вашего HY-300 начинка может отличаться, и описанные методы могут не сработать или потребовать адаптации.


Купил портативный проектор HY-300 — один из тех бюджетных «карманных» проекторов на Android TV, которых полно на маркетплейсах. При первом включении заметил странность: на экране загрузки (статичный логотип) яркость выглядит на все 100%, но буквально через пару секунд, когда появляется boot-анимация, яркость ощутимо падает — и остаётся такой навсегда. В настройках проектора нет ни ползунка яркости, ни каких-либо параметров изображения. Вообще. Производитель просто не предусмотрел возможность настройки.

Это стало отправной точкой для исследования, которое привело нас от «а можно ли вообще подключиться?» до прямого редактирования gamma LUT в видеопроцессоре Rockchip.

Что имеем

HY-300: портативный проектор на базе SoC Rockchip RK3326 с Android TV OS. Характеристики, которые удалось вытащить:

  • SoC: Rockchip RK3326

  • ОС: Android TV (не обычный Android — это важно)

  • Разрешение: 1280x720, нативная панель 1024x600 (VOP масштабирует)

  • Производитель прошивки: TXCZ (Shenzhen TXCZ)

  • Дисплей: LVDS-панель, подключена через VOP (Video Output Processor)

  • Видеомост: RK628 (HDMI-to-MIPI CSI)

Проблема: Яркость проектора визуально ниже максимума, а в интерфейсе Android TV нет никаких настроек яркости, контраста, гаммы — ни в основных настройках, ни в скрытых, нигде. Производитель решил, что пользователю это не нужно.

Подключение: первые грабли

USB — ловушка

Первая мысль — подключить проектор к ПК через USB. У HY-300 есть USB-A порт, у ПК тоже USB-С. Взял кабель USB-A — USB-С, воткнул — проектор мгновенно вырубился.

Причина простая: оба устройства подают питание на шину (5V). Два источника питания встречаются — срабатывает защита, проектор уходит в перезагрузку.

Зарядка у проектора через круглый DC-разъём (240v всё-таки!), не USB. Micro-USB нет. Подключиться по проводу нельзя.

ADB по Wi-Fi — неожиданная удача

Остаётся ADB over WiFi. Обычно для этого нужно сначала включить Developer Options (многократно тапнуть «Build Number»). Но в Android TV нет пункта «Build Number» в привычном месте — нужно тапать «Android TV OS version». Я нашёл этот пункт, начал тапать... после 5 тапов вместо Developer Mode включился скринсейвер (часы на весь экран).

Решил попробовать наугад — вдруг ADB уже включен из коробки:

adb connect <IP проектора>:5555
adb root

ADB включен по умолчанию. Root доступен. Без каких-либо Developer Options. Спасибо, мой дорогой партия-друг TXCZ.

Что внутри: анатомия проблемы

Получив root-доступ, я начал искать механизм управления яркостью. И быстро понял, почему производитель не дал ползунок — стандартный Android-механизм яркости в этом проекторе сломан на уровне железа.

Backlight-драйвер: есть, но не работает

В device tree проектора есть узел backlight с compatible = "pwm-backlight" — стандартный PWM-драйвер подсветки Linux. Но у него отсутствует ключевое свойство pwms — драйвер не знает, к какому PWM-каналу подключена подсветка. Результат:

/sys/class/backlight/    # ПУСТО — драйвер не загружен

При этом Light HAL от Rockchip (android.hardware.lights-service.rockchip) честно пытается писать в /sys/class/backlight/backlight/brightness — но этого пути не существует. Все вызовы settings put system screen_brightness 255 уходят в пустоту.

LED — только вкл/выкл

echo 0 > /sys/class/leds/Lcd_power/brightness    # лампа погасла
echo 255 > /sys/class/leds/Lcd_power/brightness   # лампа зажглась
echo 128 > /sys/class/leds/Lcd_power/brightness   # то же самое, что 255

GPIO-управление. Промежуточных значений нет - только 0 (выкл) и любое другое (вкл).

PWM-каналы: один занят, остальные выключены

  • pwmchip0 (ff200000.pwm) - используется для vdd-arm (питание CPU), не для подсветки

  • ff200010.pwm — пульт дистанционного управления

  • ff200020, ff200030, ff208000-ff208030 — все disabled в device tree

Ни один PWM-канал не управляет LED-подсветкой.

PQ-система Rockchip: заниженная яркость в конфиге

Нашёл систему Picture Quality от Rockchip — библиотека libpq.so читает JSON-конфиги и применяет цветокоррекцию через DRM.

В конфиге для UI (pq_ui.json) обнаружилось:

"cscBrightness": 189   // нейтральное значение — 256. Яркость занижена на 26%!

Для сравнения, в конфиге видео (pq_play.json):

"cscBrightness": 256   // нейтральная, без занижения

То есть производитель намеренно снизил яркость UI на четверть относительно видео.

Что вообще НЕ влияло на яркость

Перечислю всё, что было испробовано, но безрезультатно:

Метод

Результат

settings put system screen_brightness 255

Значение меняется, визуально — ноль эффекта

setprop persist.vendor.brightness.main 100

Сбрасывается на 50 при каждой перезагрузке

Перезапуск vendor.light-rockchip

Сервис пишет в несуществующий путь

cmd display set-brightness 1.0

backlight=null, команда игнорируется

service call SurfaceFlinger 1015 (color matrix)

HWC полностью игнорирует матрицу

PQ-конфиг cscBrightness: 350

Минимальный эффект, fallback-пути не читаются

devmem для прямого доступа к регистрам

CONFIG_STRICT_DEVMEM блокирует MMIO

Отдельная боль — попытка отредактировать pq_ui.json на vendor-разделе. Раздел заполнен на 100% (876 КБ свободно из 272 МБ). Команда sed -i создала временный файл, которому не хватило места, и уничтожила оригинал — файл стал 0 байт. Восстановить невозможно: cp на vendor молча создаёт файлы нулевого размера из-за dm-verity.

Прорыв: testgamma и gamma LUT

Перелом наступил, когда я заглянул в логи загрузки:

01-01 00:00:42.142  init: starting service 'testgamma'...

Сервис testgamma Нашёл его определение в /vendor/etc/init/hw/init.rk30board.rc:

service testgamma  /system/bin/testgammatx.sh

Открываем скрипт:

#!/system/bin/sh
testgamma --wb_r 1.0 --wb_g 0.96 --wb_b 0.95 --contrast 58 --brightness 30 \
  --saturation 80 --hue 35 --target_gamma 1.8 --native_gamma 2.9

brightness 30 из 100. Вот она, причина. Производитель захардкодил яркость на 30% в shell-скрипте, который выполняется при каждой загрузке.

Как работает testgamma

Утилита testgamma — бинарник, который пишет gamma LUT (Look-Up Table, 256 записей формата 0x00RRGGBB) напрямую в VOP (Video Output Processor) Rockchip через DRM ioctl на /dev/dri/card0.

$ testgamma --help
--brightness   set brightness value[0, 100], default 50
--contrast     set contrast value[0, 100], default 50
--saturation   set saturation value[0, 100], default 50
--hue          set hue value[0, 100], default 50
--wb_r         set red gain of white balance, [0, 1], default 1.0
--wb_g         set green gain of white balance, [0, 1], default 1.0
--wb_b         set blue gain of white balance, [0, 1], default 1.0
--native_gamma set native gamma value, default 2.2
--target_gamma set target gamma value, default 2.2

Но есть нюанс. Параметры brightness, contrast, saturation, hue должны устанавливаться через DRM-свойства BCSH (Brightness/Contrast/Saturation/Hue) видеопроцессора. В логах видно:

brightness 0, old brightness 30, prop id 0
saturation 0, old saturation 80, prop id 0

prop id 0 — свойства не найдены. VOP Lite в RK3326 не поддерживает BCSH-свойства. Четыре из девяти параметров testgamma — пустышки. Они ни на что не влияют.

Что реально работает:

  • wb_r, wb_g, wb_b — коэффициенты white balance (0.0 — 1.0). Масштабируют каждый канал в gamma LUT. Это множитель яркости.

  • target_gamma, native_gamma — определяют форму гамма-кривой. Экспонента = target/native. Значение 1.8/2.9 = 0.62 даёт sqrt-кривую, которая поднимает тёмные тона.

Почему testgamma работает только при загрузке

testgamma запускается как init-сервис — до SurfaceFlinger. Он пишет gamma LUT в VOP через DRM, и LUT применяется. Но как только стартует SurfaceFlinger с HWC (hwcomposer.rk30board.so), он захватывает DRM-устройство и перезаписывает настройки VOP каждый кадр. Вызов testgamma в рантайме записывает LUT в регистры, но HWC тут же его затирает.

Это подтверждается экспериментом:

  • testgamma в рантайме: LUT в debugfs (/sys/kernel/debug/dri/0/ff460000.vop/gamma_lut) меняется, но визуально — никакого эффекта

  • testgamma при загрузке (через init-скрипт): визуальный эффект мгновенный и стабильный

Разблокировка записи в /system

Разделы /system и /vendor защищены dm-verity. Даже после mount -o remount,rw запись создаёт файлы нулевого размера. Решение:

adb disable-verity
# disable-verity only works for userdebug builds
# using overlayfs
# Now reboot your device for settings to take effect

adb reboot

После перезагрузки система монтирует overlayfs поверх /system и /vendor:

overlay on /system type overlay (lowerdir=/system,
  upperdir=/mnt/scratch/overlay/system/upper, ...)

Теперь mount -o remount,rw /system действительно делает раздел записываемым. Можно редактировать testgammatx.sh.

Результаты: от 10% до максимума

Систематически протестировал разные комбинации параметров. После каждого изменения — перезагрузка (другого пути нет).

wb_r/g/b

target_gamma

Результат

0.1 / 0.1 / 0.1

2.2

~10% яркости — экран еле видно

0.5 / 0.5 / 0.5

1.8

~50% яркости

1.0 / 1.0 / 1.0

1.0

Максимальная яркость, но цвета «инвертированы» — слишком агрессивная гамма-коррекция

1.0 / 1.0 / 1.0

1.6

Оптимум: максимальная яркость с нормальными цветами

1.0 / 0.96 / 0.95

1.8

Заводские настройки (~78% яркости)

Заводской скрипт снижал яркость двумя способами:

  1. White balance: зелёный и синий каналы занижены до 0.96/0.95 (потеря ~5%)

  2. Гамма-кривая: target_gamma=1.8 при native_gamma=2.9 (менее агрессивная коррекция тёмных тонов)

Оптимальный скрипт

#!/system/bin/sh
testgamma --wb_r 1.0 --wb_g 1.0 --wb_b 1.0 --contrast 58 --brightness 50 \
  --saturation 80 --hue 35 --target_gamma 1.6 --native_gamma 2.9

Изменения от заводского:

  • wb_g: 0.96 -> 1.0 (снят фильтр зелёного)

  • wb_b: 0.95 -> 1.0 (снят фильтр синего)

  • target_gamma: 1.8 -> 1.6 (усилена гамма-коррекция — тёмные тона ярче)

Пошаговая инструкция

Для владельцев HY-300 (и, возможно, других проекторов на RK3326):

1. Подключение

# Установить Android Platform Tools
# https://developer.android.com/tools/releases/platform-tools

adb connect <IP проектора>:5555
adb root

2. Отключение dm-verity (однократно)

adb disable-verity
adb reboot
# Дождаться полной загрузки
adb connect <IP>:5555
adb root

3. Установка максимальной яркости

adb shell mount -o remount,rw /system

adb shell "echo '#!/system/bin/sh
testgamma --wb_r 1.0 --wb_g 1.0 --wb_b 1.0 --contrast 58 --brightness 50 \
  --saturation 80 --hue 35 --target_gamma 1.6 --native_gamma 2.9' \
  > /system/bin/testgammatx.sh"

adb reboot

4. Откат к заводским настройкам

adb shell mount -o remount,rw /system

adb shell "echo '#!/system/bin/sh
testgamma --wb_r 1.0 --wb_g 0.96 --wb_b 0.95 --contrast 58 --brightness 30 \
  --saturation 80 --hue 35 --target_gamma 1.8 --native_gamma 2.9' \
  > /system/bin/testgammatx.sh"

adb reboot

Что мы узнали о скрытых возможностях настройки

Исследование вскрыло целый пласт настроек, о которых производитель молчит:

Gamma LUT (testgamma) — полный контроль над гамма-кривой дисплея. Можно настраивать баланс белого по каналам, гамма-коррекцию, и даже создавать произвольные цветовые профили. Утилита поддерживает 9 параметров, из которых 5 реально работают на этом железе.

PQ-система Rockchip — система постобработки изображения с конфигами в JSON. Отдельные профили для UI и видео, поддержка CSC (Color Space Conversion) с настройкой яркости, контраста, насыщенности, тона и гамма-таблиц.

Режимы PQ — свойство persist.vendor.tvinput.rkpq.mode переключает профили в реальном времени (но mode=1 вызывает зелёный экран из-за несовместимого профиля).

DRM/VOP debugfs — полный доступ к состоянию видеопроцессора через /sys/kernel/debug/dri/0/. Можно читать текущую gamma LUT, состояние плейнов, режимы дисплея.

I2C-устройства — на шине I2C-0 обнаружены g-сенсоры (для автоповорота), акселерометр MSA311 и видеомост RK628. Видеомост потенциально может иметь свои настройки яркости/контраста для HDMI-входа.

Два уровня яркости

В итоге мы выяснили, что яркость проектора складывается из двух независимых компонент:

  1. Аппаратная яркость LED — ток через светодиод, управляемый драйвером на плате. Падает на этапе boot-анимации (bootloader или kernel). Из Android софтварно не управляется — ни через PWM (сломан в device tree), ни через GPIO (только вкл/выкл), ни через I2C (LED-драйвер не на шине).

  2. Программная яркость (gamma LUT) — таблица из 256 значений в видеопроцессоре VOP, преобразующая каждый пиксель перед выводом на панель. Полностью контролируемая через testgamma. Именно здесь производитель занизил яркость.

Мы не можем выжать больше фотонов из LED, но можем убрать программное занижение и получить максимум от того, что есть. Разница между заводскими настройками и оптимальными — заметна невооружённым глазом.

Выводы

  1. Бюджетные Android-проекторы могут идти с заниженной программной яркостью — производители перестраховываются с тепловым режимом и ресурсом LED, жертвуя пользовательским опытом.

  2. Отсутствие настроек в интерфейсе не означает отсутствие возможности настройки. Если есть ADB и root — можно добраться до всего.

  3. sed -i на полном разделе — это rm. Всегда проверяйте свободное место перед in-place редактированием.

  4. dm-verity на Android можно обойти через adb disable-verity + overlayfs — это даёт полный доступ к /system и /vendor без перепрошивки.

  5. Если вы видите prop id 0 в логах DRM — свойство не поддерживается вашим видеопроцессором, и никакие значения параметра не помогут.

Проектор стал заметно ярче. Война за яркость выиграна — по крайней мере, в рамках того, что позволяет софт.