#include "intel_display_regs.h"
#include "intel_display_rpm.h"
#include "intel_display_types.h"
-#include "intel_pcode.h"
+#include "intel_parent.h"
static void hsw_ips_enable(const struct intel_crtc_state *crtc_state)
{
if (display->platform.broadwell) {
drm_WARN_ON(display->drm,
- intel_pcode_write(display->drm, DISPLAY_IPS_CONTROL,
- val | IPS_PCODE_CONTROL));
+ intel_parent_pcode_write(display, DISPLAY_IPS_CONTROL,
+ val | IPS_PCODE_CONTROL));
/*
* Quoting Art Runyan: "its not safe to expect any particular
* value in IPS_CTL bit 31 after enabling IPS through the
if (display->platform.broadwell) {
drm_WARN_ON(display->drm,
- intel_pcode_write(display->drm, DISPLAY_IPS_CONTROL, 0));
+ intel_parent_pcode_write(display, DISPLAY_IPS_CONTROL, 0));
/*
* Wait for PCODE to finish disabling IPS. The BSpec specified
* 42ms timeout value leads to occasional timeouts so use 100ms
#include "intel_display_utils.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
-#include "intel_pcode.h"
+#include "intel_parent.h"
#include "intel_uncore.h"
#include "skl_watermark.h"
u16 dclk;
int ret;
- ret = intel_pcode_read(display->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
- ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point),
- &val, &val2);
+ ret = intel_parent_pcode_read(display, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
+ ICL_PCODE_MEM_SS_READ_QGV_POINT_INFO(point),
+ &val, &val2);
if (ret)
return ret;
int ret;
int i;
- ret = intel_pcode_read(display->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
- ADL_PCODE_MEM_SS_READ_PSF_GV_INFO, &val, NULL);
+ ret = intel_parent_pcode_read(display, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
+ ADL_PCODE_MEM_SS_READ_PSF_GV_INFO, &val, NULL);
if (ret)
return ret;
return 0;
/* bspec says to keep retrying for at least 1 ms */
- ret = intel_pcode_request(display->drm, ICL_PCODE_SAGV_DE_MEM_SS_CONFIG,
- points_mask,
- ICL_PCODE_REP_QGV_MASK | ADLS_PCODE_REP_PSF_MASK,
- ICL_PCODE_REP_QGV_SAFE | ADLS_PCODE_REP_PSF_SAFE,
- 1);
+ ret = intel_parent_pcode_request(display, ICL_PCODE_SAGV_DE_MEM_SS_CONFIG,
+ points_mask,
+ ICL_PCODE_REP_QGV_MASK | ADLS_PCODE_REP_PSF_MASK,
+ ICL_PCODE_REP_QGV_SAFE | ADLS_PCODE_REP_PSF_SAFE,
+ 1);
if (ret < 0) {
drm_err(display->drm,
#include "intel_display_wa.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
+#include "intel_parent.h"
#include "intel_pci_config.h"
-#include "intel_pcode.h"
#include "intel_plane.h"
#include "intel_psr.h"
#include "intel_step.h"
"trying to change cdclk frequency with cdclk not enabled\n"))
return;
- ret = intel_pcode_write(display->drm, BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
+ ret = intel_parent_pcode_write(display, BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
if (ret) {
drm_err(display->drm,
"failed to inform pcode about cdclk change\n");
if (ret)
drm_err(display->drm, "Switching back to LCPLL failed\n");
- intel_pcode_write(display->drm, HSW_PCODE_DE_WRITE_FREQ_REQ,
- cdclk_config->voltage_level);
+ intel_parent_pcode_write(display, HSW_PCODE_DE_WRITE_FREQ_REQ,
+ cdclk_config->voltage_level);
intel_de_write(display, CDCLK_FREQ,
DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
drm_WARN_ON_ONCE(display->drm,
display->platform.skylake && vco == 8640000);
- ret = intel_pcode_request(display->drm, SKL_PCODE_CDCLK_CONTROL,
- SKL_CDCLK_PREPARE_FOR_CHANGE,
- SKL_CDCLK_READY_FOR_CHANGE,
- SKL_CDCLK_READY_FOR_CHANGE, 3);
+ ret = intel_parent_pcode_request(display, SKL_PCODE_CDCLK_CONTROL,
+ SKL_CDCLK_PREPARE_FOR_CHANGE,
+ SKL_CDCLK_READY_FOR_CHANGE,
+ SKL_CDCLK_READY_FOR_CHANGE, 3);
if (ret) {
drm_err(display->drm,
"Failed to inform PCU about cdclk change (%d)\n", ret);
intel_de_posting_read(display, CDCLK_CTL);
/* inform PCU of the change */
- intel_pcode_write(display->drm, SKL_PCODE_CDCLK_CONTROL,
- cdclk_config->voltage_level);
+ intel_parent_pcode_write(display, SKL_PCODE_CDCLK_CONTROL,
+ cdclk_config->voltage_level);
intel_update_cdclk(display);
}
if (DISPLAY_VER(display) >= 14 || display->platform.dg2)
; /* NOOP */
else if (DISPLAY_VER(display) >= 11)
- ret = intel_pcode_request(display->drm, SKL_PCODE_CDCLK_CONTROL,
- SKL_CDCLK_PREPARE_FOR_CHANGE,
- SKL_CDCLK_READY_FOR_CHANGE,
- SKL_CDCLK_READY_FOR_CHANGE, 3);
+ ret = intel_parent_pcode_request(display, SKL_PCODE_CDCLK_CONTROL,
+ SKL_CDCLK_PREPARE_FOR_CHANGE,
+ SKL_CDCLK_READY_FOR_CHANGE,
+ SKL_CDCLK_READY_FOR_CHANGE, 3);
else
/*
* BSpec requires us to wait up to 150usec, but that leads to
* timeouts; the 2ms used here is based on experiment.
*/
- ret = intel_pcode_write_timeout(display->drm,
- HSW_PCODE_DE_WRITE_FREQ_REQ,
- 0x80000000, 2);
+ ret = intel_parent_pcode_write_timeout(display,
+ HSW_PCODE_DE_WRITE_FREQ_REQ,
+ 0x80000000, 2);
if (ret) {
drm_err(display->drm,
* Display versions 14 and beyond
*/;
else if (DISPLAY_VER(display) >= 11 && !display->platform.dg2)
- ret = intel_pcode_write(display->drm, SKL_PCODE_CDCLK_CONTROL,
- cdclk_config->voltage_level);
+ ret = intel_parent_pcode_write(display, SKL_PCODE_CDCLK_CONTROL,
+ cdclk_config->voltage_level);
if (DISPLAY_VER(display) < 11) {
/*
* The timeout isn't specified, the 2ms used here is based on
* FIXME: Waiting for the request completion could be delayed
* until the next PCODE request based on BSpec.
*/
- ret = intel_pcode_write_timeout(display->drm,
- HSW_PCODE_DE_WRITE_FREQ_REQ,
- cdclk_config->voltage_level, 2);
+ ret = intel_parent_pcode_write_timeout(display,
+ HSW_PCODE_DE_WRITE_FREQ_REQ,
+ cdclk_config->voltage_level, 2);
}
if (ret) {
drm_err(display->drm,
if (pipe_count_update_valid)
update_mask |= DISPLAY_TO_PCODE_PIPE_COUNT_VALID;
- ret = intel_pcode_request(display->drm, SKL_PCODE_CDCLK_CONTROL,
- SKL_CDCLK_PREPARE_FOR_CHANGE |
- update_mask,
- SKL_CDCLK_READY_FOR_CHANGE,
- SKL_CDCLK_READY_FOR_CHANGE, 3);
+ ret = intel_parent_pcode_request(display, SKL_PCODE_CDCLK_CONTROL,
+ SKL_CDCLK_PREPARE_FOR_CHANGE |
+ update_mask,
+ SKL_CDCLK_READY_FOR_CHANGE,
+ SKL_CDCLK_READY_FOR_CHANGE, 3);
if (ret)
drm_err(display->drm,
"Failed to inform PCU about display config (err %d)\n",
#include "intel_mchbar_regs.h"
#include "intel_parent.h"
#include "intel_pch_refclk.h"
-#include "intel_pcode.h"
#include "intel_pmdemand.h"
#include "intel_pps_regs.h"
#include "intel_snps_phy.h"
static void hsw_write_dcomp(struct intel_display *display, u32 val)
{
if (display->platform.haswell) {
- if (intel_pcode_write(display->drm, GEN6_PCODE_WRITE_D_COMP, val))
+ if (intel_parent_pcode_write(display, GEN6_PCODE_WRITE_D_COMP, val))
drm_dbg_kms(display->drm, "Failed to write to D_COMP\n");
} else {
intel_de_write(display, D_COMP_BDW, val);
#include "intel_dpll.h"
#include "intel_hotplug.h"
#include "intel_parent.h"
-#include "intel_pcode.h"
#include "intel_pps.h"
#include "intel_psr.h"
#include "intel_tc.h"
int ret, tries = 0;
while (1) {
- ret = intel_pcode_write(display->drm, ICL_PCODE_EXIT_TCCOLD, 0);
+ ret = intel_parent_pcode_write(display, ICL_PCODE_EXIT_TCCOLD, 0);
if (ret != -EAGAIN || ++tries == 3)
break;
msleep(1);
* Spec states that we should timeout the request after 200us
* but the function below will timeout after 500us
*/
- ret = intel_pcode_read(display->drm, TGL_PCODE_TCCOLD, &low_val, &high_val);
+ ret = intel_parent_pcode_read(display, TGL_PCODE_TCCOLD, &low_val, &high_val);
if (ret == 0) {
if (block &&
(low_val & TGL_PCODE_EXIT_TCCOLD_DATA_L_EXIT_FAILED))
#include "intel_display_utils.h"
#include "intel_dram.h"
#include "intel_mchbar_regs.h"
-#include "intel_pcode.h"
+#include "intel_parent.h"
#include "intel_uncore.h"
#include "vlv_iosf_sb.h"
u32 val = 0;
int ret;
- ret = intel_pcode_read(display->drm, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
- ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL);
+ ret = intel_parent_pcode_read(display, ICL_PCODE_MEM_SUBSYSYSTEM_INFO |
+ ICL_PCODE_MEM_SS_READ_GLOBAL_INFO, &val, NULL);
if (ret)
return ret;
#include "intel_hdcp_regs.h"
#include "intel_hdcp_shim.h"
#include "intel_parent.h"
-#include "intel_pcode.h"
#include "intel_step.h"
#define USE_HDCP_GSC(__display) (DISPLAY_VER(__display) >= 14)
* Mailbox interface.
*/
if (DISPLAY_VER(display) == 9 && !display->platform.broxton) {
- ret = intel_pcode_write(display->drm, SKL_PCODE_LOAD_HDCP_KEYS, 1);
+ ret = intel_parent_pcode_write(display, SKL_PCODE_LOAD_HDCP_KEYS, 1);
if (ret) {
drm_err(display->drm,
"Failed to initiate HDCP key load (%d)\n",
display->parent->pc8->unblock(display->drm);
}
+/* pcode */
+int intel_parent_pcode_read(struct intel_display *display, u32 mbox, u32 *val, u32 *val1)
+{
+ return display->parent->pcode->read(display->drm, mbox, val, val1);
+}
+
+int intel_parent_pcode_write_timeout(struct intel_display *display, u32 mbox, u32 val, int timeout_ms)
+{
+ return display->parent->pcode->write(display->drm, mbox, val, timeout_ms);
+}
+
+int intel_parent_pcode_write(struct intel_display *display, u32 mbox, u32 val)
+{
+ return intel_parent_pcode_write_timeout(display, mbox, val, 1);
+}
+
+int intel_parent_pcode_request(struct intel_display *display, u32 mbox, u32 request,
+ u32 reply_mask, u32 reply, int timeout_base_ms)
+{
+ return display->parent->pcode->request(display->drm, mbox, request, reply_mask, reply, timeout_base_ms);
+}
+
/* rps */
bool intel_parent_rps_available(struct intel_display *display)
{
void intel_parent_pc8_block(struct intel_display *display);
void intel_parent_pc8_unblock(struct intel_display *display);
+/* pcode */
+int intel_parent_pcode_read(struct intel_display *display, u32 mbox, u32 *val, u32 *val1);
+int intel_parent_pcode_write_timeout(struct intel_display *display, u32 mbox, u32 val, int timeout_ms);
+int intel_parent_pcode_write(struct intel_display *display, u32 mbox, u32 val);
+int intel_parent_pcode_request(struct intel_display *display, u32 mbox, u32 request,
+ u32 reply_mask, u32 reply, int timeout_base_ms);
+
/* rps */
bool intel_parent_rps_available(struct intel_display *display);
void intel_parent_rps_boost_if_not_started(struct intel_display *display, struct dma_fence *fence);
#include "intel_fb.h"
#include "intel_fixed.h"
#include "intel_flipq.h"
-#include "intel_pcode.h"
+#include "intel_parent.h"
#include "intel_plane.h"
#include "intel_vblank.h"
#include "intel_wm.h"
u32 val = 0;
int ret;
- ret = intel_pcode_read(display->drm,
- GEN12_PCODE_READ_SAGV_BLOCK_TIME_US,
- &val, NULL);
+ ret = intel_parent_pcode_read(display, GEN12_PCODE_READ_SAGV_BLOCK_TIME_US,
+ &val, NULL);
if (ret) {
drm_dbg_kms(display->drm, "Couldn't read SAGV block time!\n");
return 0;
return;
drm_dbg_kms(display->drm, "Enabling SAGV\n");
- ret = intel_pcode_write(display->drm, GEN9_PCODE_SAGV_CONTROL,
- GEN9_SAGV_ENABLE);
+ ret = intel_parent_pcode_write(display, GEN9_PCODE_SAGV_CONTROL,
+ GEN9_SAGV_ENABLE);
/* We don't need to wait for SAGV when enabling */
drm_dbg_kms(display->drm, "Disabling SAGV\n");
/* bspec says to keep retrying for at least 1 ms */
- ret = intel_pcode_request(display->drm, GEN9_PCODE_SAGV_CONTROL,
- GEN9_SAGV_DISABLE,
- GEN9_SAGV_IS_DISABLED, GEN9_SAGV_IS_DISABLED, 1);
+ ret = intel_parent_pcode_request(display, GEN9_PCODE_SAGV_CONTROL,
+ GEN9_SAGV_DISABLE,
+ GEN9_SAGV_IS_DISABLED, GEN9_SAGV_IS_DISABLED, 1);
/*
* Some skl systems, pre-release machines in particular,
* don't actually have SAGV.
/* read the first set of memory latencies[0:3] */
val = 0; /* data0 to be programmed to 0 for first set */
- ret = intel_pcode_read(display->drm, GEN9_PCODE_READ_MEM_LATENCY, &val, NULL);
+ ret = intel_parent_pcode_read(display, GEN9_PCODE_READ_MEM_LATENCY, &val, NULL);
if (ret) {
drm_err(display->drm, "SKL Mailbox read error = %d\n", ret);
return;
/* read the second set of memory latencies[4:7] */
val = 1; /* data0 to be programmed to 1 for second set */
- ret = intel_pcode_read(display->drm, GEN9_PCODE_READ_MEM_LATENCY, &val, NULL);
+ ret = intel_parent_pcode_read(display, GEN9_PCODE_READ_MEM_LATENCY, &val, NULL);
if (ret) {
drm_err(display->drm, "SKL Mailbox read error = %d\n", ret);
return;
.irq = &i915_display_irq_interface,
.panic = &i915_display_panic_interface,
.pc8 = &i915_display_pc8_interface,
+ .pcode = &i915_display_pcode_interface,
.rpm = &i915_display_rpm_interface,
.rps = &i915_display_rps_interface,
.stolen = &i915_display_stolen_interface,
*/
#include <drm/drm_print.h>
+#include <drm/intel/display_parent_interface.h>
#include "i915_drv.h"
#include "i915_reg.h"
return err;
}
-/* Helpers with drm device */
-int intel_pcode_read(struct drm_device *drm, u32 mbox, u32 *val, u32 *val1)
+static int intel_pcode_read(struct drm_device *drm, u32 mbox, u32 *val, u32 *val1)
{
struct drm_i915_private *i915 = to_i915(drm);
return snb_pcode_read(&i915->uncore, mbox, val, val1);
}
-int intel_pcode_write_timeout(struct drm_device *drm, u32 mbox, u32 val, int timeout_ms)
+static int intel_pcode_write_timeout(struct drm_device *drm, u32 mbox, u32 val, int timeout_ms)
{
struct drm_i915_private *i915 = to_i915(drm);
return snb_pcode_write_timeout(&i915->uncore, mbox, val, timeout_ms);
}
-int intel_pcode_request(struct drm_device *drm, u32 mbox, u32 request,
- u32 reply_mask, u32 reply, int timeout_base_ms)
+static int intel_pcode_request(struct drm_device *drm, u32 mbox, u32 request,
+ u32 reply_mask, u32 reply, int timeout_base_ms)
{
struct drm_i915_private *i915 = to_i915(drm);
return skl_pcode_request(&i915->uncore, mbox, request, reply_mask, reply,
timeout_base_ms);
}
+
+const struct intel_display_pcode_interface i915_display_pcode_interface = {
+ .read = intel_pcode_read,
+ .write = intel_pcode_write_timeout,
+ .request = intel_pcode_request,
+};
int snb_pcode_read_p(struct intel_uncore *uncore, u32 mbcmd, u32 p1, u32 p2, u32 *val);
int snb_pcode_write_p(struct intel_uncore *uncore, u32 mbcmd, u32 p1, u32 p2, u32 val);
-/* Helpers with drm device */
-int intel_pcode_read(struct drm_device *drm, u32 mbox, u32 *val, u32 *val1);
-int intel_pcode_write_timeout(struct drm_device *drm, u32 mbox, u32 val, int timeout_ms);
-#define intel_pcode_write(drm, mbox, val) \
- intel_pcode_write_timeout((drm), (mbox), (val), 1)
-
-int intel_pcode_request(struct drm_device *drm, u32 mbox, u32 request,
- u32 reply_mask, u32 reply, int timeout_base_ms);
+extern const struct intel_display_pcode_interface i915_display_pcode_interface;
#endif /* _INTEL_PCODE_H */
display/intel_fb_bo.o \
display/intel_fbdev_fb.o \
display/xe_display.o \
+ display/xe_display_pcode.o \
display/xe_display_rpm.o \
display/xe_display_wa.o \
display/xe_dsb_buffer.o \
+++ /dev/null
-/* SPDX-License-Identifier: MIT */
-/*
- * Copyright © 2023 Intel Corporation
- */
-
-#ifndef __INTEL_PCODE_H__
-#define __INTEL_PCODE_H__
-
-#include "xe_pcode.h"
-
-#endif /* __INTEL_PCODE_H__ */
#include "intel_hotplug.h"
#include "intel_opregion.h"
#include "skl_watermark.h"
+#include "xe_display_pcode.h"
#include "xe_display_rpm.h"
#include "xe_dsb_buffer.h"
#include "xe_hdcp_gsc.h"
.initial_plane = &xe_display_initial_plane_interface,
.irq = &xe_display_irq_interface,
.panic = &xe_display_panic_interface,
+ .pcode = &xe_display_pcode_interface,
.rpm = &xe_display_rpm_interface,
.stolen = &xe_display_stolen_interface,
};
--- /dev/null
+// SPDX-License-Identifier: MIT
+/* Copyright © 2026 Intel Corporation */
+
+#include <drm/intel/display_parent_interface.h>
+
+#include "xe_device.h"
+#include "xe_pcode.h"
+
+static int xe_display_pcode_read(struct drm_device *drm, u32 mbox, u32 *val, u32 *val1)
+{
+ struct xe_device *xe = to_xe_device(drm);
+ struct xe_tile *tile = xe_device_get_root_tile(xe);
+
+ return xe_pcode_read(tile, mbox, val, val1);
+}
+
+static int xe_display_pcode_write_timeout(struct drm_device *drm, u32 mbox, u32 val, int timeout_ms)
+{
+ struct xe_device *xe = to_xe_device(drm);
+ struct xe_tile *tile = xe_device_get_root_tile(xe);
+
+ return xe_pcode_write_timeout(tile, mbox, val, timeout_ms);
+}
+
+static int xe_display_pcode_request(struct drm_device *drm, u32 mbox, u32 request,
+ u32 reply_mask, u32 reply, int timeout_base_ms)
+{
+ struct xe_device *xe = to_xe_device(drm);
+ struct xe_tile *tile = xe_device_get_root_tile(xe);
+
+ return xe_pcode_request(tile, mbox, request, reply_mask, reply, timeout_base_ms);
+}
+
+const struct intel_display_pcode_interface xe_display_pcode_interface = {
+ .read = xe_display_pcode_read,
+ .write = xe_display_pcode_write_timeout,
+ .request = xe_display_pcode_request,
+};
--- /dev/null
+/* SPDX-License-Identifier: MIT */
+/* Copyright © 2026 Intel Corporation */
+
+#ifndef __XE_DISPLAY_PCODE_H__
+#define __XE_DISPLAY_PCODE_H__
+
+extern const struct intel_display_pcode_interface xe_display_pcode_interface;
+
+#endif
return xe_pcode_ready(xe, false);
}
ALLOW_ERROR_INJECTION(xe_pcode_probe_early, ERRNO); /* See xe_pci_probe */
-
-/* Helpers with drm device. These should only be called by the display side */
-#if IS_ENABLED(CONFIG_DRM_XE_DISPLAY)
-
-int intel_pcode_read(struct drm_device *drm, u32 mbox, u32 *val, u32 *val1)
-{
- struct xe_device *xe = to_xe_device(drm);
- struct xe_tile *tile = xe_device_get_root_tile(xe);
-
- return xe_pcode_read(tile, mbox, val, val1);
-}
-
-int intel_pcode_write_timeout(struct drm_device *drm, u32 mbox, u32 val, int timeout_ms)
-{
- struct xe_device *xe = to_xe_device(drm);
- struct xe_tile *tile = xe_device_get_root_tile(xe);
-
- return xe_pcode_write_timeout(tile, mbox, val, timeout_ms);
-}
-
-int intel_pcode_request(struct drm_device *drm, u32 mbox, u32 request,
- u32 reply_mask, u32 reply, int timeout_base_ms)
-{
- struct xe_device *xe = to_xe_device(drm);
- struct xe_tile *tile = xe_device_get_root_tile(xe);
-
- return xe_pcode_request(tile, mbox, request, reply_mask, reply, timeout_base_ms);
-}
-
-#endif
| FIELD_PREP(PCODE_MB_PARAM1, param1)\
| FIELD_PREP(PCODE_MB_PARAM2, param2))
-/* Helpers with drm device */
-int intel_pcode_read(struct drm_device *drm, u32 mbox, u32 *val, u32 *val1);
-int intel_pcode_write_timeout(struct drm_device *drm, u32 mbox, u32 val, int timeout_ms);
-#define intel_pcode_write(drm, mbox, val) \
- intel_pcode_write_timeout((drm), (mbox), (val), 1)
-int intel_pcode_request(struct drm_device *drm, u32 mbox, u32 request,
- u32 reply_mask, u32 reply, int timeout_base_ms);
-
#endif
void (*unblock)(struct drm_device *drm);
};
+struct intel_display_pcode_interface {
+ int (*read)(struct drm_device *drm, u32 mbox, u32 *val, u32 *val1);
+ int (*write)(struct drm_device *drm, u32 mbox, u32 val, int timeout_ms);
+ int (*request)(struct drm_device *drm, u32 mbox, u32 request,
+ u32 reply_mask, u32 reply, int timeout_base_ms);
+};
+
struct intel_display_rpm_interface {
struct ref_tracker *(*get)(const struct drm_device *drm);
struct ref_tracker *(*get_raw)(const struct drm_device *drm);
/** @pc8: PC8 interface. Optional. */
const struct intel_display_pc8_interface *pc8;
+ /** @pcode: Pcode interface */
+ const struct intel_display_pcode_interface *pcode;
+
/** @rpm: Runtime PM functions */
const struct intel_display_rpm_interface *rpm;