pci/zr36057.cpp: hookup interrupt routing

This commit is contained in:
angelosa 2025-02-26 09:36:59 +01:00
parent 7381cf0826
commit e12b0a4b91
4 changed files with 147 additions and 15 deletions

View File

@ -19,6 +19,7 @@ TODO:
- Hookup busmaster;
- What are i2c 0x8e >> 1 address device checks for?
\- Can't be adv7175 (0xd4 >> 1) nor adv7176 (0x54 >> 1)
- Noisy on undocumented guest ID 7 once VidCap capturing is enabled;
...
- Soft Reset & Write lock mechanisms (each register have separate macro-groups);
- GuestBus slot mechanism (relevant when multiple devices are hooked);
@ -85,6 +86,7 @@ void zr36057_device::device_add_mconfig(machine_config &config)
SAA7110A(config, m_decoder, XTAL(26'800'000));
m_decoder->sda_callback().set([this](int state) { m_decoder_sdao_state = state; });
//m_decoder->vs_callback().set(FUNC(zr36057_device::girq1_w));
//ADV7176(config, m_encoder, XTAL(27'000'000));
@ -158,6 +160,17 @@ void zr36057_device::software_reset()
m_vfe.ovl_enable = false;
m_vfe.mask_stride = 0xff;
// TODO: these also go in process_reset fn
// defaults in MPEG mode
m_jpeg.mode = false;
m_jpeg.sub_mode = 3;
m_jpeg.rtbsy_fb = m_jpeg.go_en = m_jpeg.sync_mstr = m_jpeg.fld_per_buff = false;
m_jpeg.vfifo_fb = m_jpeg.cfifo_fb = false;
m_jpeg.still_lendian = true;
m_jpeg.p_reset = true;
m_jpeg.cod_trns_en = false;
m_jpeg.active = false;
m_sync_gen.vsync_size = 6;
m_sync_gen.vtotal = 525;
m_sync_gen.hsync_start = 640;
@ -169,6 +182,9 @@ void zr36057_device::software_reset()
m_active_area.pay = 240;
m_active_area.odd = true;
m_jpeg.guest_id = 4;
m_jpeg.guest_reg = 0;
m_irq_status = m_irq_enable = 0;
m_inta_pin_enable = false;
@ -179,9 +195,6 @@ void zr36057_device::software_reset()
for (int i = 0; i < 4; i++)
m_guestbus.time[i] = 0;
m_jpeg_guest_id = 4;
m_jpeg_guest_reg = 0;
m_po.pending = false;
m_po.time_out = false;
m_po.dir = true;
@ -337,7 +350,7 @@ void zr36057_device::asr_map(address_map &map)
// Not a mistake: min_pix overlaps with the /Triton setting
m_vfe.min_pix = (m_vfe.display_config >> 24) & 0x7f;
m_vfe.triton = !!BIT(~m_vfe.display_config, 24);
LOGVFE("\tVidEn %d, MinPix %d, Triton %s Controller"
LOGVFE("\tVidEn %d, MinPix %d, Triton %s Controller\n"
, m_vfe.vid_en
, m_vfe.min_pix
, m_vfe.triton ? "Intel 'Triton' Bridge" : "Other PCI Bridge"
@ -453,6 +466,7 @@ void zr36057_device::asr_map(address_map &map)
{
m_irq_status &= ~data;
m_irq_status &= 0x7800'0000;
update_irq_status();
}
})
);
@ -474,6 +488,7 @@ void zr36057_device::asr_map(address_map &map)
, BIT(data, 28)
, BIT(data, 27)
);
update_irq_status();
}
})
);
@ -493,8 +508,71 @@ void zr36057_device::asr_map(address_map &map)
}
})
);
// map(0x100, 0x103) JPEG Mode and Control
// map(0x104, 0x107) JPEG Process Control
map(0x100, 0x103).lrw32(
NAME([this] (offs_t offset) {
LOG("JPEG Mode and Control R\n");
return (m_jpeg.mode << 31) | (m_jpeg.sub_mode << 29)
| (m_jpeg.rtbsy_fb << 6) | (m_jpeg.go_en << 5) | (m_jpeg.sync_mstr << 4)
| (m_jpeg.fld_per_buff << 3) | (m_jpeg.vfifo_fb << 2)
| (m_jpeg.cfifo_fb << 1) | (m_jpeg.still_lendian << 0);
}),
NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
LOG("JPEG Mode and Control W %08x & %08x\n", data, mem_mask);
if (ACCESSING_BITS_24_31)
{
m_jpeg.mode = !!BIT(data, 31);
// --x- (0) Still Image (1) Motion Video
// ---x (0) Decompression (1) Compression
m_jpeg.sub_mode = (data >> 29) & 3;
LOG("\tJPG %s Mode, JPGMode %d\n"
, m_jpeg.mode ? "JPEG" : "MPEG"
, m_jpeg.sub_mode
);
}
if (ACCESSING_BITS_0_7)
{
m_jpeg.rtbsy_fb = !!BIT(data, 6);
m_jpeg.go_en = !!BIT(data, 5);
m_jpeg.sync_mstr = !!BIT(data, 4);
m_jpeg.fld_per_buff = !!BIT(data, 3);
m_jpeg.vfifo_fb = !!BIT(data, 2);
m_jpeg.cfifo_fb = !!BIT(data, 1);
m_jpeg.still_lendian = !!BIT(data, 0);
LOG("\tRTBSY_FB %d, Go_en %d, SyncMstr %d, Fld_per_buff %s, VFIFO_FB %d, CFIFO_FB %d, Still_LitEndian %s\n"
, m_jpeg.rtbsy_fb
, m_jpeg.go_en
, m_jpeg.sync_mstr
, m_jpeg.fld_per_buff ? "1 (One code field)" : "0 (Two code fields, one code frame)"
, m_jpeg.vfifo_fb
, m_jpeg.cfifo_fb
, m_jpeg.still_lendian ? "Little" : "Gib"
);
if (m_jpeg.go_en)
popmessage("zr36057.cpp: go_en enabled");
}
})
);
map(0x104, 0x107).lrw32(
NAME([this] (offs_t offset) {
LOG("JPEG Process Control R\n");
return (m_jpeg.p_reset << 7) | (m_jpeg.cod_trns_en << 5) | (m_jpeg.active << 0);
}),
NAME([this] (offs_t offset, u32 data, u32 mem_mask) {
LOG("JPEG Process Control W %08x & %08x\n", data, mem_mask);
if (ACCESSING_BITS_0_7)
{
m_jpeg.p_reset = !!BIT(data, 7);
m_jpeg.cod_trns_en = !!BIT(data, 5);
m_jpeg.active = !!BIT(data, 0);
LOG("\tP_reset %d, CodTrnsEn %d, Active %d\n"
, m_jpeg.p_reset
, m_jpeg.cod_trns_en
, m_jpeg.active
);
}
})
);
map(0x108, 0x10b).lrw32(
NAME([this] (offs_t offset) {
LOGSYNC("Vertical Sync Parameters R\n");
@ -594,11 +672,11 @@ void zr36057_device::asr_map(address_map &map)
map(0x124, 0x124).lrw8(
NAME([this] (offs_t offset) {
LOG("JPEG Codec Guest ID R\n");
return (m_jpeg_guest_id << 4) | (m_jpeg_guest_reg << 0);
return (m_jpeg.guest_id << 4) | (m_jpeg.guest_reg << 0);
}),
NAME([this] (offs_t offset, u8 data) {
m_jpeg_guest_id = (data >> 4) & 7;
m_jpeg_guest_reg = (data >> 0) & 7;
m_jpeg.guest_id = (data >> 4) & 7;
m_jpeg.guest_reg = (data >> 0) & 7;
LOG("JPEG Codec Guest ID W %02x\n", data);
})
);
@ -691,3 +769,11 @@ void zr36057_device::postoffice_w(offs_t offset, u32 data, u32 mem_mask)
LOGWARN("Warning: PO access unmapped POGuestID write %d %02x\n", m_po.guest_id, m_po.guest_reg);
}
}
void zr36057_device::update_irq_status()
{
if (m_inta_pin_enable)
{
irq_pin_w(0, m_irq_status & m_irq_enable);
}
}

View File

@ -70,13 +70,27 @@ private:
u8 mask_stride;
} m_vfe;
u8 m_jpeg_guest_id, m_jpeg_guest_reg;
bool m_softreset;
u8 m_gpio_ddr, m_pci_waitstate_control;
// NOTE: these are technically external/public pins.
void girq1_w(int state) { m_irq_status |= 1 << 30; update_irq_status(); }
void girq0_w(int state) { m_irq_status |= 1 << 29; update_irq_status(); }
void cod_rep_irq_w(int state) { m_irq_status |= 1 << 28; update_irq_status(); }
void jpeg_rep_irq_w(int state) { m_irq_status |= 1 << 27; update_irq_status(); }
void update_irq_status();
u32 m_irq_status, m_irq_enable;
bool m_inta_pin_enable;
int m_decoder_sdao_state;
struct {
u8 guest_id, guest_reg;
bool mode;
u8 sub_mode;
bool rtbsy_fb, go_en, sync_mstr, fld_per_buff, vfifo_fb, cfifo_fb, still_lendian;
bool p_reset, cod_trns_en, active;
} m_jpeg;
struct {
u8 vsync_size;
@ -100,8 +114,6 @@ private:
u8 guest_id;
u8 guest_reg;
} m_po; /**< PostOffice */
int m_decoder_sdao_state;
};
DECLARE_DEVICE_TYPE(ZR36057_PCI, zr36057_device)

View File

@ -30,12 +30,14 @@ saa7110a_device::saa7110a_device(const machine_config &mconfig, const char *tag,
: device_t(mconfig, SAA7110A, tag, owner, clock)
, i2c_hle_interface(mconfig, *this, 0x9c >> 1)
, device_memory_interface(mconfig, *this)
//, m_out_vs_cb(*this)
{
m_space_config = address_space_config("regs", ENDIANNESS_LITTLE, 8, 8, 0, address_map_constructor(FUNC(saa7110a_device::regs_map), this));
}
void saa7110a_device::device_start()
{
//m_href_timer = timer_alloc(FUNC(saa7110a_device::href_cb), this);
save_item(NAME(m_secs));
save_item(NAME(m_sstb));
save_item(NAME(m_hrmv));
@ -46,6 +48,8 @@ void saa7110a_device::device_start()
void saa7110a_device::device_reset()
{
m_secs = m_sstb = m_hrmv = m_rtse = m_vtrc = false;
//m_current_href = 0;
//m_href_timer->adjust(attotime::from_hz(15734), 0, attotime::from_hz(15734));
}
device_memory_interface::space_config_vector saa7110a_device::memory_space_config() const
@ -140,8 +144,14 @@ void saa7110a_device::regs_map(address_map &map)
map(0x2b, 0x2b).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU2B: Gain control analog #3 %02x\n", data); }));
map(0x2c, 0x2c).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU2C: Mixer control #2 %02x\n", data); }));
map(0x2d, 0x2d).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU2D: Integration value gain %02x\n", data); }));
map(0x2e, 0x2e).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU2E: Vertical blanking pulse set %02x\n", data); }));
map(0x2f, 0x2f).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU2F: Vertical blanking pulse reset %02x\n", data); }));
map(0x2e, 0x2e).lw8(NAME([this] (offs_t offset, u8 data) {
m_vbps = data;
LOG("SU2E: Vertical blanking pulse set %02x\n", data);
}));
map(0x2f, 0x2f).lw8(NAME([this] (offs_t offset, u8 data) {
m_vbpr = data;
LOG("SU2F: Vertical blanking pulse reset %02x\n", data);
}));
map(0x30, 0x30).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU30: ADCs gain control %02x\n", data); }));
map(0x31, 0x31).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU31: Mixer control #3 %02x\n", data); }));
map(0x32, 0x32).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU32: Integration value white peak %02x\n", data); }));
@ -149,3 +159,19 @@ void saa7110a_device::regs_map(address_map &map)
map(0x34, 0x34).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU34: Gain update level %02x\n", data); }));
}
//TIMER_CALLBACK_MEMBER(saa7110a_device::href_cb)
//{
// if (m_vbpr == m_vbps)
// return;
// m_current_href ++;
// if (m_current_href == m_vbps * 2)
// {
// m_out_vs_cb(1);
// }
// if (m_current_href == m_vbpr * 2)
// {
// m_out_vs_cb(0);
// }
// m_current_href %= 262;
//}
//

View File

@ -16,6 +16,8 @@ class saa7110a_device :
public:
saa7110a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
//auto vs_callback() { return m_out_vs_cb.bind(); }
protected:
// saa7110a_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
virtual void device_start() override ATTR_COLD;
@ -28,8 +30,14 @@ private:
virtual void write_data(u16 offset, u8 data) override;
address_space_config m_space_config;
// devcb_write_line m_out_vs_cb;
bool m_secs, m_sstb, m_hrmv, m_rtse, m_vtrc;
u8 m_vbps, m_vbpr;
// int m_current_href;
// TIMER_CALLBACK_MEMBER(href_cb);
// emu_timer *m_href_timer;
};
DECLARE_DEVICE_TYPE(SAA7110A, saa7110a_device)