[Question] Is the built-in power-button beep controllable from Linux?

Started by user_2

user_2

Hi,

We want to add a low-battery warning on Photonicat 2 running Debian.

The idea is simple: when the battery drops to a low level, the device should beep a few times, and if power is not connected, our script will shut it down safely.

The device already makes a beep when the physical power button is pressed, so there is clearly some sound emitter on the board. But we cannot find how to trigger it from Linux.

What we checked:

  • ALSA is present, but only HDMI audio is exposed.
  • /sys/bus/platform/drivers/pwm-beeper exists, but no device is bound to it.
  • No pwm-beeper, gpio-beeper, buzzer, or speaker node appears in the device tree.
  • /proc/bus/input/devices shows rk805 pwrkey, but no beeper/speaker input device.
  • The PMIC is exposed as RK806/RK805-related devices, but we only see gpio_pwrctrl1/2/3, which look like power-control/DVS pins, not something safe to use as a buzzer without documentation.

Question:

Is the built-in beep controllable from Debian/Linux?

If yes, what is the correct interface?

  • GPIO?
  • PWM?
  • I2C / PMIC register?
  • EC/vendor command?
  • device-tree overlay?

We do not want to poke random GPIO/PWM/PMIC registers blindly. We just need a safe supported way to trigger the same beep that happens when the power button is pressed.

Thanks.

superlynx

Hello,

The beeper is controlled by MCU, not SoC itself. You need to send commands to MCU (to device /dev/pcat-pm-ctl).

Here is a sample code for it:

#!/usr/bin/env python3
import os

def pcat_pmu_compute_crc16(data):
    crc = 0xFFFF;

    i = 0
    for x in data:
        crc ^= data[i]
        for j in range(0, 8):
            if crc & 1:
                crc = (crc >> 1) ^ 0xA001
            else:
                crc >>= 1
        crc &= 0xFFFF
        i += 1

    return crc

def pcat_pmu_pm_dev_write_data_request(fd, command, extra_data, need_ack):
    payload = bytearray()
    payload += b"\xA5\x01\x81\x00\x00"

    if extra_data is not None and len(extra_data) > 0 and len(extra_data) <= 65532:
        extra_data_len = len(extra_data) + 3
        payload.append(extra_data_len & 0xFF)
        payload.append((extra_data_len >> 8) & 0xFF)

        payload.append(command & 0xFF)
        payload.append((command >> 8) & 0xFF)

        payload += extra_data
    else:
        payload += '\x03\x00'

        payload.append(command & 0xFF)
        payload.append((command >> 8) & 0xFF)

    if(need_ack):
        payload.append(1)
    else:
        payload.append(0)

    crc = pcat_pmu_compute_crc16(payload[1:])
    payload.append(crc & 0xFF)
    payload.append((crc >> 8) & 0xFF)

    payload.append(0x5A)

    fd.write(payload)

#Beep event 1
freq1 = 1000 # in Hz, set to 0 for silent
duration1 = 500 # in ms, must larger than 0

loop = False # Set to True for looping,

extra_data = bytearray()

extra_data.append(freq1 & 0xFF)
extra_data.append((freq1 >> 8) & 0xFF)
extra_data.append(duration1 & 0xFF)
extra_data.append((duration1 >> 8) & 0xFF)

#Beep event 2 or more, optional, maximum number of beep event is 20
#freq2 = 500
#duration2 = 500

#extra_data.append(freq2 & 0xFF)
#extra_data.append((freq2 >> 8) & 0xFF)
#extra_data.append(duration2 & 0xFF)
#extra_data.append((duration2 >> 8) & 0xFF)

if loop:
    extra_data.append(0)
else:
    extra_data.append(1)

fd = open('/dev/pcat-pm-ctl', 'wb')
pcat_pmu_pm_dev_write_data_request(fd, 163, extra_data, False)
fd.close()

Want to reply to this topic?

Sign in to participate

Don't have an account? Sign up