intel: FBC, DRRS, PSR2, Gen4-7 regs — comprehensive subsystems
fbc.rs: Frame Buffer Compression FBC_CTL enable/compression/fence programming (Gen7+) FBC_STATUS compressed buffer tracking nuke() for frontbuffer invalidation on render drrs.rs: Display Refresh Rate Switching Transitions high→low refresh rate on idle timeout DRRS_CTL with idle frame count configuration mark_active() for compositor interaction psr2.rs: Panel Self Refresh v2 Selective update via sink DPCD capability probe PSR2_MAN_TRK_CTL for partial frame update tracking DP_PSR2_SUPPORT/EN_CFG2 sink communication regs_gen4_7.rs: Pre-Gen9 FDI register definitions Gen4-7 pipe/plane/DDI registers (PIPEACONF, DSPACNTR) GMBUS at 0x5100 base (pre-PCH offset) No DDI_BUF_CTL — these platforms use FDI display mod.rs: Wired FbcState, DrrsState alongside existing PsrState
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
use std::sync::Arc;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
use log::{debug, info};
|
||||
use redox_driver_sys::memory::MmioRegion;
|
||||
|
||||
use super::info::IntelDeviceInfo;
|
||||
use crate::driver::Result;
|
||||
use crate::kms::ModeInfo;
|
||||
|
||||
const DRRS_CTL_BASE: usize = 0x46100;
|
||||
const DRRS_CTL_ENABLE: u32 = 1 << 31;
|
||||
const DRRS_CTL_IDLE_FRAMES_SHIFT: u32 = 8;
|
||||
const DRRS_CTL_IDLE_FRAMES_MASK: u32 = 0xFF;
|
||||
|
||||
const DRRS_STATUS_BASE: usize = 0x46104;
|
||||
const DRRS_STATUS_ACTIVE_LOW_RR: u32 = 1 << 31;
|
||||
const DRRS_STATUS_CURRENT_LOW_RR: u32 = 1 << 0;
|
||||
|
||||
const DRRS_IDLE_TIMEOUT_MS: u64 = 1000;
|
||||
const DRRS_IDLE_FRAMES_DEFAULT: u32 = 4;
|
||||
|
||||
pub struct DrrsState {
|
||||
mmio: Arc<MmioRegion>,
|
||||
enabled: bool,
|
||||
high_rr_mode: ModeInfo,
|
||||
low_rr_mode: Option<ModeInfo>,
|
||||
last_activity: Instant,
|
||||
pipe: u8,
|
||||
}
|
||||
|
||||
impl DrrsState {
|
||||
pub fn new(mmio: Arc<MmioRegion>, _device_info: &IntelDeviceInfo, pipe: u8) -> Self {
|
||||
Self {
|
||||
mmio,
|
||||
enabled: false,
|
||||
high_rr_mode: ModeInfo::default_1080p(),
|
||||
low_rr_mode: None,
|
||||
last_activity: Instant::now(),
|
||||
pipe,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn init(&mut self, high_mode: &ModeInfo) -> Result<()> {
|
||||
self.high_rr_mode = high_mode.clone();
|
||||
|
||||
let low_vrefresh = 48u32;
|
||||
if high_mode.vrefresh > low_vrefresh + 10 {
|
||||
let mut low = high_mode.clone();
|
||||
low.vrefresh = low_vrefresh;
|
||||
low.clock = (low.clock as u64 * low_vrefresh as u64
|
||||
/ high_mode.vrefresh as u64) as u32;
|
||||
self.low_rr_mode = Some(low);
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn enable(&mut self) -> Result<()> {
|
||||
if self.enabled {
|
||||
return Ok(());
|
||||
}
|
||||
let ctl = DRRS_CTL_BASE + self.pipe as usize * 0x1000;
|
||||
let val = DRRS_CTL_ENABLE
|
||||
| ((DRRS_IDLE_FRAMES_DEFAULT & DRRS_CTL_IDLE_FRAMES_MASK)
|
||||
<< DRRS_CTL_IDLE_FRAMES_SHIFT);
|
||||
self.mmio.write32(ctl, val);
|
||||
self.enabled = true;
|
||||
self.last_activity = Instant::now();
|
||||
info!("redox-drm-intel: DRRS enabled on pipe {}", self.pipe);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disable(&mut self) -> Result<()> {
|
||||
if !self.enabled {
|
||||
return Ok(());
|
||||
}
|
||||
let ctl = DRRS_CTL_BASE + self.pipe as usize * 0x1000;
|
||||
self.mmio.write32(ctl, 0);
|
||||
self.enabled = false;
|
||||
info!("redox-drm-intel: DRRS disabled on pipe {}", self.pipe);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn mark_active(&mut self) {
|
||||
self.last_activity = Instant::now();
|
||||
}
|
||||
|
||||
pub fn is_low_rr_active(&self) -> bool {
|
||||
if !self.enabled {
|
||||
return false;
|
||||
}
|
||||
let status = DRRS_STATUS_BASE + self.pipe as usize * 0x1000;
|
||||
let val = self.mmio.read32(status);
|
||||
val & DRRS_STATUS_CURRENT_LOW_RR != 0
|
||||
}
|
||||
|
||||
pub fn should_enter_low_rr(&self) -> bool {
|
||||
self.enabled
|
||||
&& self.low_rr_mode.is_some()
|
||||
&& self.last_activity.elapsed() > Duration::from_millis(DRRS_IDLE_TIMEOUT_MS)
|
||||
}
|
||||
|
||||
pub fn low_rr_mode(&self) -> Option<&ModeInfo> {
|
||||
self.low_rr_mode.as_ref()
|
||||
}
|
||||
|
||||
pub fn is_enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use log::{debug, info};
|
||||
use redox_driver_sys::memory::MmioRegion;
|
||||
|
||||
use super::info::IntelDeviceInfo;
|
||||
use crate::driver::Result;
|
||||
use crate::kms::ModeInfo;
|
||||
|
||||
const FBC_CTL_BASE: usize = 0x43200;
|
||||
const FBC_CTL_ENABLE: u32 = 1 << 31;
|
||||
const FBC_CTL_COMPRESSION_EN: u32 = 1 << 30;
|
||||
const FBC_CTL_INTERVAL_SHIFT: u32 = 22;
|
||||
const FBC_CTL_INTERVAL_MASK: u32 = 0x3;
|
||||
const FBC_CTL_FENCE_EN: u32 = 1 << 21;
|
||||
|
||||
const FBC_STATUS_BASE: usize = 0x43214;
|
||||
const FBC_STATUS_COMPRESSING: u32 = 1 << 31;
|
||||
const FBC_STATUS_COMPRESSED: u32 = 1 << 0;
|
||||
|
||||
const FBC_FENCE_BASE: usize = 0x43300;
|
||||
|
||||
const FBC_LL_BASE: usize = 0x43400;
|
||||
const FBC_STRIDE_OFFSET: usize = 0x4;
|
||||
const FBC_CFB_SIZE: usize = 0x8;
|
||||
|
||||
pub struct FbcState {
|
||||
mmio: Arc<MmioRegion>,
|
||||
enabled: bool,
|
||||
compressed: bool,
|
||||
compressed_size: u32,
|
||||
}
|
||||
|
||||
impl FbcState {
|
||||
pub fn new(mmio: Arc<MmioRegion>, _device_info: &IntelDeviceInfo) -> Self {
|
||||
Self {
|
||||
mmio,
|
||||
enabled: false,
|
||||
compressed: false,
|
||||
compressed_size: 0,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable(&mut self, fb_gtt_addr: u64, stride: u32, mode: &ModeInfo) -> Result<()> {
|
||||
if self.enabled {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let fb_lines = mode.vdisplay as u32;
|
||||
self.compressed_size = fb_lines.saturating_mul(stride);
|
||||
|
||||
let ctl_reg = FBC_CTL_BASE;
|
||||
let mut ctl = self.mmio.read32(ctl_reg);
|
||||
ctl &= !FBC_CTL_ENABLE;
|
||||
self.mmio.write32(ctl_reg, ctl);
|
||||
|
||||
let ll_reg = FBC_LL_BASE;
|
||||
self.mmio.write32(ll_reg, fb_gtt_addr as u32);
|
||||
self.mmio.write32(ll_reg + 4, (fb_gtt_addr >> 32) as u32);
|
||||
|
||||
self.mmio.write32(FBC_LL_BASE + FBC_STRIDE_OFFSET, stride);
|
||||
|
||||
self.mmio.write32(FBC_FENCE_BASE, 0);
|
||||
|
||||
ctl = self.mmio.read32(ctl_reg);
|
||||
ctl |= FBC_CTL_ENABLE | FBC_CTL_COMPRESSION_EN | FBC_CTL_FENCE_EN;
|
||||
ctl &= !(FBC_CTL_INTERVAL_MASK << FBC_CTL_INTERVAL_SHIFT);
|
||||
ctl |= 1 << FBC_CTL_INTERVAL_SHIFT;
|
||||
self.mmio.write32(ctl_reg, ctl);
|
||||
|
||||
let status = self.mmio.read32(FBC_STATUS_BASE);
|
||||
if status & FBC_STATUS_COMPRESSING != 0 || status & FBC_STATUS_COMPRESSED != 0 {
|
||||
self.enabled = true;
|
||||
info!(
|
||||
"redox-drm-intel: FBC enabled — {}x{} stride={} cfb={}KB status={:#x}",
|
||||
mode.hdisplay, mode.vdisplay, stride,
|
||||
self.compressed_size / 1024, status
|
||||
);
|
||||
} else {
|
||||
debug!("redox-drm-intel: FBC enable requested, status={:#x}", status);
|
||||
self.enabled = true;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disable(&mut self) -> Result<()> {
|
||||
if !self.enabled {
|
||||
return Ok(());
|
||||
}
|
||||
let ctl = self.mmio.read32(FBC_CTL_BASE);
|
||||
self.mmio.write32(FBC_CTL_BASE, ctl & !FBC_CTL_ENABLE);
|
||||
self.mmio.write32(FBC_STATUS_BASE, FBC_STATUS_COMPRESSED | FBC_STATUS_COMPRESSING);
|
||||
self.enabled = false;
|
||||
info!("redox-drm-intel: FBC disabled");
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn nuke(&self) {
|
||||
if !self.enabled {
|
||||
return;
|
||||
}
|
||||
self.mmio.write32(FBC_STATUS_BASE, FBC_STATUS_COMPRESSED);
|
||||
debug!("redox-drm-intel: FBC nuke (invalidate compressed framebuffer)");
|
||||
}
|
||||
|
||||
pub fn is_enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,9 @@ pub mod display_watermark;
|
||||
pub mod dp_aux;
|
||||
pub mod dp_link;
|
||||
pub mod execbuffer;
|
||||
pub mod drrs;
|
||||
pub mod execlists;
|
||||
pub mod fbc;
|
||||
pub mod fence;
|
||||
pub mod gamma;
|
||||
pub mod gmbus;
|
||||
@@ -30,7 +32,9 @@ pub mod info;
|
||||
pub mod lmem;
|
||||
pub mod mocs;
|
||||
pub mod panel_pps;
|
||||
pub mod psr2;
|
||||
pub mod regs;
|
||||
pub mod regs_gen4_7;
|
||||
pub mod regs_gen9;
|
||||
pub mod regs_gen12;
|
||||
pub mod regs_xe2;
|
||||
@@ -82,6 +86,8 @@ use self::regs_xe2::Xe2Regs;
|
||||
use self::backlight::Backlight;
|
||||
use self::context::ContextManager;
|
||||
use self::display_psr::PsrState;
|
||||
use self::drrs::DrrsState;
|
||||
use self::fbc::FbcState;
|
||||
use self::hangcheck::GpuHangDetector;
|
||||
use self::panel_pps::PanelPowerSequencer;
|
||||
use self::ring::{IntelRing, RingType};
|
||||
@@ -124,6 +130,8 @@ pub struct IntelDriver {
|
||||
backlight: Mutex<Backlight>,
|
||||
context_manager: Mutex<ContextManager>,
|
||||
psr: Mutex<PsrState>,
|
||||
drrs: Mutex<DrrsState>,
|
||||
fbc: Mutex<FbcState>,
|
||||
hang_detector: Mutex<GpuHangDetector>,
|
||||
panel_pps: Mutex<PanelPowerSequencer>,
|
||||
syncobj_mgr: Mutex<SyncobjManager>,
|
||||
@@ -369,6 +377,8 @@ impl IntelDriver {
|
||||
let context_manager = Mutex::new(ContextManager::new());
|
||||
|
||||
let psr = Mutex::new(PsrState::new(mmio_arc.clone(), 0));
|
||||
let drrs = Mutex::new(DrrsState::new(mmio_arc.clone(), &device_info, 0));
|
||||
let fbc = Mutex::new(FbcState::new(mmio_arc.clone(), &device_info));
|
||||
|
||||
let hang_detector = Mutex::new(GpuHangDetector::new(mmio_arc.clone(), RENDER_RING_BASE));
|
||||
|
||||
@@ -443,6 +453,8 @@ impl IntelDriver {
|
||||
backlight: Mutex::new(backlight),
|
||||
context_manager,
|
||||
psr,
|
||||
drrs,
|
||||
fbc,
|
||||
hang_detector,
|
||||
panel_pps,
|
||||
syncobj_mgr,
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use log::{debug, info};
|
||||
use redox_driver_sys::memory::MmioRegion;
|
||||
|
||||
use super::dp_aux::DpAux;
|
||||
use super::info::IntelDeviceInfo;
|
||||
use crate::driver::Result;
|
||||
|
||||
const PSR2_CTL_BASE: usize = 0x60800;
|
||||
const PSR2_CTL_ENABLE: u32 = 1 << 31;
|
||||
const PSR2_CTL_FRAME_SYNC: u32 = 1 << 14;
|
||||
const PSR2_CTL_TP2_TP3_TIME_SHIFT: u32 = 8;
|
||||
const PSR2_CTL_TP2_TP3_MASK: u32 = 0x3;
|
||||
const PSR2_CTL_IDLE_FRAMES_SHIFT: u32 = 0;
|
||||
const PSR2_CTL_IDLE_FRAMES_MASK: u32 = 0x7;
|
||||
|
||||
const PSR2_MAN_TRK_CTL_BASE: usize = 0x60810;
|
||||
const PSR2_MAN_TRK_CTL_ENABLE: u32 = 1 << 31;
|
||||
const PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE: u32 = 1 << 2;
|
||||
|
||||
const DP_PSR2_SUPPORT: u32 = 0x070;
|
||||
const DP_PSR2_CAPABILITY: u32 = 0x071;
|
||||
const DP_PSR2_ENABLE_SINK: u8 = 1 << 0;
|
||||
const DP_PSR2_Y_COORD_REQUIRED: u8 = 1 << 3;
|
||||
const DP_PSR2_SU_REGION_SCANLINE_CAP: u8 = 1 << 4;
|
||||
|
||||
const DP_PSR_EN_CFG2: u32 = 0x0171;
|
||||
const DP_PSR2_SELECTIVE_UPDATE: u8 = 1 << 0;
|
||||
|
||||
pub struct Psr2State {
|
||||
mmio: Arc<MmioRegion>,
|
||||
enabled: bool,
|
||||
selective_update: bool,
|
||||
transcoder: u8,
|
||||
}
|
||||
|
||||
impl Psr2State {
|
||||
pub fn new(mmio: Arc<MmioRegion>, _device_info: &IntelDeviceInfo, transcoder: u8) -> Self {
|
||||
Self {
|
||||
mmio,
|
||||
enabled: false,
|
||||
selective_update: false,
|
||||
transcoder,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn probe_sink_caps(&self, aux: &DpAux) -> Result<bool> {
|
||||
match aux.read_dpcd(DP_PSR2_SUPPORT, 2) {
|
||||
Ok(data) if data.len() >= 2 => {
|
||||
let supported = data[0] & 0x01 != 0;
|
||||
if supported {
|
||||
info!("redox-drm-intel: PSR2 supported by sink");
|
||||
}
|
||||
Ok(supported)
|
||||
}
|
||||
_ => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enable(&mut self, aux: Option<&DpAux>, port: u8) -> Result<()> {
|
||||
if self.enabled {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let sink_caps = aux.and_then(|a| a.read_dpcd(DP_PSR2_CAPABILITY, 2).ok());
|
||||
let y_coord_required = sink_caps.as_ref()
|
||||
.map_or(false, |d| d.len() >= 2 && d[0] & DP_PSR2_Y_COORD_REQUIRED != 0);
|
||||
let su_scanline = sink_caps.as_ref()
|
||||
.map_or(false, |d| d.len() >= 2 && d[0] & DP_PSR2_SU_REGION_SCANLINE_CAP != 0);
|
||||
|
||||
if let Some(aux) = aux {
|
||||
aux.write_dpcd(DP_PSR_EN_CFG2, &[DP_PSR2_SELECTIVE_UPDATE])?;
|
||||
aux.write_dpcd(DP_PSR2_SUPPORT, &[DP_PSR2_ENABLE_SINK])?;
|
||||
debug!("redox-drm-intel: PSR2 sink enabled on port {} (y_coord={}, su_scanline={})",
|
||||
port, y_coord_required, su_scanline);
|
||||
}
|
||||
|
||||
let ctl = PSR2_CTL_BASE + self.transcoder as usize * 0x1000;
|
||||
let val = PSR2_CTL_ENABLE
|
||||
| PSR2_CTL_FRAME_SYNC
|
||||
| (1 & PSR2_CTL_TP2_TP3_MASK) << PSR2_CTL_TP2_TP3_TIME_SHIFT
|
||||
| (4 & PSR2_CTL_IDLE_FRAMES_MASK) << PSR2_CTL_IDLE_FRAMES_SHIFT;
|
||||
self.mmio.write32(ctl, val);
|
||||
|
||||
self.enabled = true;
|
||||
self.selective_update = su_scanline;
|
||||
info!("redox-drm-intel: PSR2 enabled on transcoder {} (selective_update={})",
|
||||
self.transcoder, self.selective_update);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn disable(&mut self, aux: Option<&DpAux>) -> Result<()> {
|
||||
if !self.enabled {
|
||||
return Ok(());
|
||||
}
|
||||
let ctl = PSR2_CTL_BASE + self.transcoder as usize * 0x1000;
|
||||
self.mmio.write32(ctl, 0);
|
||||
|
||||
if let Some(aux) = aux {
|
||||
aux.write_dpcd(DP_PSR_EN_CFG2, &[0])?;
|
||||
aux.write_dpcd(DP_PSR2_SUPPORT, &[0])?;
|
||||
}
|
||||
|
||||
self.enabled = false;
|
||||
info!("redox-drm-intel: PSR2 disabled on transcoder {}", self.transcoder);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn flush(&self) {
|
||||
if !self.enabled {
|
||||
return;
|
||||
}
|
||||
let man_trk = PSR2_MAN_TRK_CTL_BASE + self.transcoder as usize * 0x1000;
|
||||
self.mmio.write32(man_trk,
|
||||
PSR2_MAN_TRK_CTL_ENABLE | PSR2_MAN_TRK_CTL_SF_PARTIAL_FRAME_UPDATE);
|
||||
debug!("redox-drm-intel: PSR2 manual tracking flush");
|
||||
}
|
||||
|
||||
pub fn is_enabled(&self) -> bool {
|
||||
self.enabled
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
use super::regs::IntelRegs;
|
||||
|
||||
pub struct Gen4_7Regs;
|
||||
|
||||
impl IntelRegs for Gen4_7Regs {
|
||||
fn forcewake_req(&self) -> usize { 0xA188 }
|
||||
fn forcewake_ack(&self) -> usize { 0x130040 }
|
||||
fn power_well_ctl(&self) -> usize { 0 }
|
||||
fn cdclk_ctl(&self) -> usize { 0x46200 }
|
||||
fn dmc_mmio_start(&self) -> usize { 0 }
|
||||
fn dmc_mmio_end(&self) -> usize { 0 }
|
||||
fn dmc_fw_base(&self) -> usize { 0 }
|
||||
fn dmc_ctrl(&self) -> usize { 0 }
|
||||
fn dmc_status(&self) -> usize { 0 }
|
||||
fn dmc_sram_base(&self) -> usize { 0 }
|
||||
fn gmbus0(&self) -> usize { 0x5100 }
|
||||
fn gmbus1(&self) -> usize { 0x5120 }
|
||||
fn gmbus2(&self) -> usize { 0x5140 }
|
||||
fn gmbus3(&self) -> usize { 0x5160 }
|
||||
fn gmbus4(&self) -> usize { 0x5180 }
|
||||
fn gmbus5(&self) -> usize { 0x51A0 }
|
||||
fn pipeconf(&self, pipe: u8) -> usize { 0x70008 + pipe as usize * 0x1000 }
|
||||
fn pipeconf_enable_mask(&self) -> u32 { 1 << 31 }
|
||||
fn htotal(&self, pipe: u8) -> usize { 0x60000 + pipe as usize * 0x1000 }
|
||||
fn hblank(&self, pipe: u8) -> usize { 0x60004 + pipe as usize * 0x1000 }
|
||||
fn hsync(&self, pipe: u8) -> usize { 0x60008 + pipe as usize * 0x1000 }
|
||||
fn vtotal(&self, pipe: u8) -> usize { 0x6000C + pipe as usize * 0x1000 }
|
||||
fn vblank(&self, pipe: u8) -> usize { 0x60010 + pipe as usize * 0x1000 }
|
||||
fn vsync(&self, pipe: u8) -> usize { 0x60014 + pipe as usize * 0x1000 }
|
||||
fn pipe_src(&self, pipe: u8) -> usize { 0x6001C + pipe as usize * 0x1000 }
|
||||
fn pipe_stride(&self) -> usize { 0x1000 }
|
||||
fn dspcntr(&self, pipe: u8) -> usize { 0x70180 + pipe as usize * 0x1000 }
|
||||
fn dspcntr_enable_mask(&self) -> u32 { 1 << 31 }
|
||||
fn dspsurf(&self, pipe: u8) -> usize { 0x7019C + pipe as usize * 0x1000 }
|
||||
fn plane_size(&self, pipe: u8) -> usize { 0x70190 + pipe as usize * 0x1000 }
|
||||
fn ps_ctrl(&self, _pipe: u8) -> usize { 0 }
|
||||
fn ps_win_pos(&self, _pipe: u8) -> usize { 0 }
|
||||
fn ps_win_size(&self, _pipe: u8) -> usize { 0 }
|
||||
fn ddi_buf_ctl(&self, _port: u8) -> usize { 0 }
|
||||
fn ddi_port_stride(&self) -> usize { 0x100 }
|
||||
fn curcntr(&self, pipe: u8) -> usize { 0x70080 + pipe as usize * 0x1000 }
|
||||
fn curbase(&self, pipe: u8) -> usize { 0x70084 + pipe as usize * 0x1000 }
|
||||
fn curpos(&self, pipe: u8) -> usize { 0x70088 + pipe as usize * 0x1000 }
|
||||
fn gfx_flsh_cntl(&self) -> usize { 0x101008 }
|
||||
fn pipestat(&self, pipe: u8) -> usize { 0x70024 + pipe as usize * 0x1000 }
|
||||
fn pipestat_vblank_mask(&self) -> u32 { 1 << 0 }
|
||||
fn pipestat_vsync_mask(&self) -> u32 { 1 << 4 }
|
||||
fn pp_status(&self) -> usize { 0xC7200 }
|
||||
fn pipeframe_reg(&self, pipe: u8) -> usize { 0x70040 + pipe as usize * 0x1000 }
|
||||
fn pipeframe_count_mask(&self) -> u32 { 0xFFFFFF }
|
||||
fn de_iir(&self) -> usize { 0x44008 }
|
||||
fn de_imr(&self) -> usize { 0x4400C }
|
||||
fn de_ier(&self) -> usize { 0x44010 }
|
||||
fn d2d_link_ctl(&self, _port: u8) -> usize { 0 }
|
||||
}
|
||||
Reference in New Issue
Block a user