Unrud / init-headphone

Manage the headphone amplifier found in some Clevo laptops
GNU General Public License v3.0
56 stars 7 forks source link

init-headphone

Manage the headphone amplifier found in some Clevo laptops. Can initialize the device if headphones are not working after suspend.

There are packages for Arch Linux, Fedora and Ubuntu

Installation

To install just run:

./autogen.sh
./configure
make
make install

If systemd is available, a unit file that starts the program automatically gets installed. To enable it run:

systemctl enable init-headphone

If you are not using systemd, take a look at the etc/ folder. It includes example configuration for pm-utils and upstart to start the program automatically.

On older Linux versions you might have to add the kernel parameter acpi_enforce_resources=lax to make the i2c driver work.

Usage

init-headphone --help
usage: init-headphone [-h] [--version] [-v] [command]

Manage the headphone amplifier found in some Clevo laptops

positional arguments:
  command        see the list of available commands below, init is the default
                 if the argument is omitted

optional arguments:
  -h, --help     show this help message and exit
  --version      show program's version number and exit
  -v, --verbose  increase output verbosity

available commands:
  init           initialize amplifier (with effect1)
  effect0        no change
  effect1        bass boost
  effect2
  effect3
  effect4        boost everything
  effect5
  effect6
  mute           turn output off
  unmute         turn output on
  recovery

Troubleshoot

Information about the Windows driver

The Windows driver consists of a kernel space component SvThANSP.sys and a user space component hp.dll. The kernel driver is simple and only supports a few commands that allow access to I/O ports. hp.dll uses DeviceIoControl to communicates via the device file \\.\SvANSPDo with the driver. It talks directly to the SMBus controller.

hp.dll exports the functions InitHeadphone(), Set_Mute(bool) and Set_effect(int) to control the headphone amplifier which is connected to the SMBus.

If you are interested in analyzing or running the Windows driver on Linux (with Wine) take a look at: https://github.com/Unrud/init-headphone-tools

Supported dwIoControlCodes for DeviceIoControl

0x9C402494: Enumerate PCI device

lpInBuffer amd lpOutBuffer look something like:

struct {
    int bus,
    int device,
    int func,
    int pcireg,
    int result,
    int unused
}

The driver reads a word from the register pcireg of the PCI device specified by bus, device and func. The result is returned in result. If the register doesn't exist, the returned result is 0xffff. It's used to find the SMBus controller by hp.dll.

0x9C4024D0: Read byte

lpInBuffer amd lpOutBuffer look something like:

struct {
    int address,
    int data_read,
    int data_write
}

The driver reads one byte from address. The result is returned in data_read.

0x9C4024C4: Write byte

lpInBuffer amd lpOutBuffer are the same as above.

The driver writes one byte data_write to address.

SMBus controller

A detailed description of the controller is available in the chipset datasheet.

The important registers are:

Supported models

This list is subject to change. If the headphone jack is not working after suspend, the model is probably supported.

x is used as wildcard