Originally posted by rriveramcrus November 7, 2023
Introduction
Add a kernel device driver API for interacting with haptic driver devices.
Draft PR: #66629
Problem description
Haptic devices are integrated circuits that drive a linear resonant actuator (LRA) when an event occurs to provide the end user haptic feedback. A haptic event can be triggered via GPIO or through a control port. The haptic event sources can be simple PWM inputs, PCM inputs such as I2S/TDM, an integrated buzzer, tables of waveforms from ROM, or synthesized waveform tables in RAM.
There is currently no purpose-built API in Zephyr for interacting with haptic driver device or facilitating haptic events.
| Part Number |
Input Sources |
Feature set |
| CS40L50 and CS40L26 |
I2C/SPI, I2S |
reference clock controls, integrated boost converter controls, Data interface controls , Brownout and temperature controls, calibration interface |
| DRV2605 |
Analog, I2C, PWM |
MODE (a combination of source selection and calibration operation control) , ROM Bank Selection, Wait time between sequenced waveforms, Overdrive time offset, sustain time positive offset, sustain time negative offset, brake time offset, various ATH controls, various LRA drive controls, calibration and loop controls |
| AW869x7 |
I2C, Analog |
Calibration controls, autobrake engine controls, ROM waveform selection, various LRA drive controls, integrated boost converter controls |
The table above compare three LRA haptic driver devices from different vendors. Some overlap exists in the input sources and basic features, but advanced features are far from standardized in interface and nomenclature.
Status Quo
Zephyr OS
No known subsystem catering to haptic driver devices. The input subsystem is focused on mice, keyboards, and other HIDs.
The question of how to accomodate haptic LRA drivers has come up in the past (#22486). An embedded controller running Zephyr has various haptic feedback applications.
Linux Kernel
Haptic driver devices have been living in the Input Force Feedback subsystem as miscellaneous devices. This subsystem was not originally meant for haptic driver devices, but rather joysticks, mice, keyboards, etc.
It would not be ideal to continue this development architecture in Zephyr and serves as an opportunity to put together something better for haptic driver devices.
Proposed change

Functionally these devices are similar to audio codecs and the proposed haptic_driver_api takes inspiration from the audio_codec_api. The haptic waveform events are to be triggered through a playback state machine with three states and a corresponding handler for each state.

To begin haptic event playback the start_event handler is to be called. The device driver must begin playback of the haptic event that is presently configured. Once complete, the stop_event handler is called to stop playback of the haptic event. Haptic events in a system do have priority and the proposed API offers a preempt_event handler for preempting playback of an event. When starting or preempting an event, an event identifier is passed to the handler. This is useful for configuring the device to playback from the appropriate source,
Configuration of the device at runtime is to handled as an extension of this API.
Driver Examples
The code snippets below serve as examples of how a client of the API would interface.
<snip>
/* Zephyr device boot time data, read only */
struct cs40l26_haptics_config {
struct i2c_dt_spec i2c;
struct gpio_dt_spec gpio1;
struct gpio_dt_spec gpio2;
struct gpio_dt_spec gpio3;
};
/* Zephyr runtime data, R/W */
struct cs40l26_haptics_data {
uint32_t wf_index;
uint8_t gpio_index;
haptics_source_t configured_for;
};
<snip>
static const struct haptics_driver_api cs40l50_driver_api = {
.start_output = &cs40l26_start_output,
.stop_output = &cs40l26_stop_output,
.preempt_output = &cs40l26_preempt_output,
}
<snip>
<snip>
static int cs40l26_start_output(const struct device *dev) {
const struct cs40l26_haptics_config *cfg = dev->config;
const struct cs40l26_haptics_data *data = dev->data;
switch (data->configured_for) {
case HAPTICS_SOURCE_ROM_BANK:
return i2c_reg_write(&cfg->i2c, CS40L26_DSP_VIRTUAL1_MBOX_1, data->wf_index);
case HAPTICS_SOURCE_GPIO_BANK:
return cs40l26_set_gpios(dev);
case HAPTICS_SOURCE_I2S:
return cs40l26_i2s_en(dev);
default:
return -EINVAL;
}
return 0;
}
<snip>
```</div>
Discussed in #64942
Originally posted by rriveramcrus November 7, 2023
Introduction
Add a kernel device driver API for interacting with haptic driver devices.
Draft PR: #66629
Problem description
Haptic devices are integrated circuits that drive a linear resonant actuator (LRA) when an event occurs to provide the end user haptic feedback. A haptic event can be triggered via GPIO or through a control port. The haptic event sources can be simple PWM inputs, PCM inputs such as I2S/TDM, an integrated buzzer, tables of waveforms from ROM, or synthesized waveform tables in RAM.
There is currently no purpose-built API in Zephyr for interacting with haptic driver device or facilitating haptic events.
The table above compare three LRA haptic driver devices from different vendors. Some overlap exists in the input sources and basic features, but advanced features are far from standardized in interface and nomenclature.
Status Quo
Zephyr OS
No known subsystem catering to haptic driver devices. The input subsystem is focused on mice, keyboards, and other HIDs.
The question of how to accomodate haptic LRA drivers has come up in the past (#22486). An embedded controller running Zephyr has various haptic feedback applications.
Linux Kernel
Haptic driver devices have been living in the Input Force Feedback subsystem as miscellaneous devices. This subsystem was not originally meant for haptic driver devices, but rather joysticks, mice, keyboards, etc.
It would not be ideal to continue this development architecture in Zephyr and serves as an opportunity to put together something better for haptic driver devices.
Proposed change
Functionally these devices are similar to audio codecs and the proposed haptic_driver_api takes inspiration from the audio_codec_api. The haptic waveform events are to be triggered through a playback state machine with three states and a corresponding handler for each state.
To begin haptic event playback the start_event handler is to be called. The device driver must begin playback of the haptic event that is presently configured. Once complete, the stop_event handler is called to stop playback of the haptic event. Haptic events in a system do have priority and the proposed API offers a preempt_event handler for preempting playback of an event. When starting or preempting an event, an event identifier is passed to the handler. This is useful for configuring the device to playback from the appropriate source,
Configuration of the device at runtime is to handled as an extension of this API.
Driver Examples
The code snippets below serve as examples of how a client of the API would interface.