diff --git a/scripts/src/video.lua b/scripts/src/video.lua index cbeb2153db7..b7bb3aa3d20 100644 --- a/scripts/src/video.lua +++ b/scripts/src/video.lua @@ -1697,6 +1697,18 @@ if (VIDEOS["X1_001"]~=null) then } end +-------------------------------------------------- +-- +--@src/devices/video/zr36060.h,VIDEOS["ZR36060"] = true +-------------------------------------------------- + +if (VIDEOS["ZR36060"]~=null) then + files { + MAME_DIR .. "src/devices/video/zr36060.cpp", + MAME_DIR .. "src/devices/video/zr36060.h", + } +end + -------------------------------------------------- -- --@src/devices/video/zr36110.h,VIDEOS["ZR36110"] = true diff --git a/src/devices/bus/pci/zr36057.cpp b/src/devices/bus/pci/zr36057.cpp index 0d3964e2a0c..57fbf9f056e 100644 --- a/src/devices/bus/pci/zr36057.cpp +++ b/src/devices/bus/pci/zr36057.cpp @@ -14,12 +14,13 @@ iterations. ZR36057 is known to have two HW quirks that are been fixed with ZR36067. TODO: -- Currently at dc10plus HW test "Error at M-JPEG codec", requires ZR36060 to continue; +- Enough to pass board functions in dc10plus HW test, requires VSYNC signal from ZR36060 to continue; - Hookup busmaster; - What are i2c 0x8e >> 1 address device checks for? \- Can't be adv7175 (0xd4 >> 1) nor adv7176 (0x54 >> 1) ... - Soft Reset & Write lock mechanisms (each register have separate macro-groups); +- GuestBus slot mechanism (relevant when multiple devices are hooked); - eventually decouple AV PCI controller part from the actual client cards; Known mix-ins: @@ -37,13 +38,14 @@ Known mix-ins: #include "zr36057.h" #define LOG_WARN (1U << 1) +#define LOG_PO (1U << 2) // PostOffice interactions -#define VERBOSE (LOG_GENERAL | LOG_WARN) +#define VERBOSE (LOG_GENERAL | LOG_WARN | LOG_PO) //#define LOG_OUTPUT_FUNC osd_printf_info #include "logmacro.h" #define LOGWARN(...) LOGMASKED(LOG_WARN, __VA_ARGS__) - +#define LOGPO(...) LOGMASKED(LOG_PO, __VA_ARGS__) DEFINE_DEVICE_TYPE(ZR36057_PCI, zr36057_device, "zr36057", "Zoran ZR36057-based Enhanced Multimedia Controller") //DEFINE_DEVICE_TYPE(ZR36067_PCI, zr36067_device, "zr36067", "Zoran ZR36067-based AV Controller") @@ -51,6 +53,7 @@ DEFINE_DEVICE_TYPE(ZR36057_PCI, zr36057_device, "zr36057", "Zoran ZR36057-ba zr36057_device::zr36057_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock) : pci_card_device(mconfig, type, tag, owner, clock) + , m_guest(*this, "guest") , m_decoder(*this, "decoder") { // ZR36057PQC Video cutting chipset @@ -73,11 +76,13 @@ zr36057_device::zr36057_device(const machine_config &mconfig, const char *tag, d void zr36057_device::device_add_mconfig(machine_config &config) { - // 27'000'000 xtal near ZR36060 + ZR36060(config, m_guest, XTAL(27'000'000)); SAA7110A(config, m_decoder, XTAL(26'800'000)); m_decoder->sda_callback().set([this](int state) { m_decoder_sdao_state = state; }); + //ADV7176(config, m_encoder, XTAL(27'000'000)); + // S-Video input/output // composite video input/output @@ -116,8 +121,11 @@ void zr36057_device::device_reset() void zr36057_device::software_reset() { LOG("SoftReset\n"); - m_video_frontend.horizontal_config = (0 << 30) | (0x001 << 10) | (0x3ff << 0); - m_video_frontend.vertical_config = (0 << 30) | (0x001 << 10) | (0x3ff << 0); + m_vfe.hspol = m_vfe.vspol = 0; + m_vfe.hstart = m_vfe.vstart = 0x001; + m_vfe.hend = m_vfe.vend = 0x3ff; + m_vfe.horizontal_config = (m_vfe.hspol << 30) | (m_vfe.hstart << 10) | (m_vfe.hend << 0); + m_vfe.vertical_config = (m_vfe.vspol << 30) | (m_vfe.vstart << 10) | (m_vfe.vend << 0); m_pci_waitstate_control = 0; m_gpio_ddr = 0xff; // all inputs @@ -125,6 +133,15 @@ void zr36057_device::software_reset() // m_gpio_data = 0xf0; 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; + m_po.guest_id = 0; + m_po.guest_reg = 0; } void zr36057_device::config_map(address_map &map) @@ -134,33 +151,46 @@ void zr36057_device::config_map(address_map &map) map(0x3f, 0x3f).lr8(NAME([] () { return 0x10; })); } -// Application Specific Register +// Application Specific Register(s) void zr36057_device::asr_map(address_map &map) { map(0x000, 0x003).lrw32( NAME([this] (offs_t offset) { // NOTE: wants to read-back here, throws "Bus Master ASIC error" otherwise (?) LOG("Video Front End Horizontal Configuration R\n"); - return m_video_frontend.horizontal_config; + return m_vfe.horizontal_config; }), NAME([this] (offs_t offset, u32 data, u32 mem_mask) { - COMBINE_DATA(&m_video_frontend.horizontal_config); + COMBINE_DATA(&m_vfe.horizontal_config); LOG("Video Front End Horizontal Configuration W %08x & %08x\n", data, mem_mask); + m_vfe.hspol = BIT(m_vfe.horizontal_config, 30); + m_vfe.hstart = (m_vfe.horizontal_config >> 10) & 0x3ff; + m_vfe.hend = (m_vfe.horizontal_config >> 0) & 0x3ff; + LOG("\tVSPOL %d VSTART %d VEND %d\n", m_vfe.hspol, m_vfe.hstart, m_vfe.hend); }) ); map(0x004, 0x007).lrw32( NAME([this] (offs_t offset) { LOG("Video Front End Vertical Configuration R\n"); - return m_video_frontend.vertical_config; + return m_vfe.vertical_config; }), NAME([this] (offs_t offset, u32 data, u32 mem_mask) { - COMBINE_DATA(&m_video_frontend.vertical_config); + COMBINE_DATA(&m_vfe.vertical_config); LOG("Video Front End Vertical Configuration %08x & %08\n", data, mem_mask); + m_vfe.vspol = BIT(m_vfe.vertical_config, 30); + m_vfe.vstart = (m_vfe.vertical_config >> 10) & 0x3ff; + m_vfe.vend = (m_vfe.vertical_config >> 0) & 0x3ff; + LOG("\tVSPOL %d VSTART %d VEND %d\n", m_vfe.vspol, m_vfe.vstart, m_vfe.vend); }) ); - - // ... - +// map(0x008, 0x00b) VFE Config, Video Scaler and Pixel Format +// map(0x00c, 0x00f) Video Display Top +// map(0x010, 0x013) Video Display Bottom +// map(0x014, 0x017) Video Display Stride, Status and Frame Grab +// map(0x018, 0x01b) Video Display Configuration +// map(0x01c, 0x01f) Masking Map Top +// map(0x020, 0x023) Masking Map Bottom +// map(0x024, 0x027) Overlay Control map(0x028, 0x02b).lrw32( NAME([this] (offs_t offset) { return (m_softreset << 24) | (m_pci_waitstate_control << 16) | m_gpio_ddr; @@ -191,6 +221,7 @@ void zr36057_device::asr_map(address_map &map) // The doc claims 0xf0 default for GPIO, but win98 driver will throw "subvendor ID failed" // while testing various ID combinations here + // This should come from GDAT pin at strapping time return (0x7e << 24) | (m_guestbus.time[3] << 12) | (m_guestbus.time[2] << 8) | (m_guestbus.time[1] << 4) | (m_guestbus.time[0] << 0); }), NAME([this] (offs_t offset, u32 data, u32 mem_mask) { @@ -212,7 +243,11 @@ void zr36057_device::asr_map(address_map &map) } }) ); - +// map(0x030, 0x033) MPEG Code Source Address +// map(0x034, 0x037) MPEG Code Transfer Control +// map(0x038, 0x03b) MPEG Code Memory Pointer +// map(0x03c, 0x03f) Interrupt Status +// map(0x040, 0x043) Interrupt Control map(0x044, 0x047).lrw32( NAME([this] (offs_t offset) { LOG("I2C R\n"); @@ -229,4 +264,112 @@ void zr36057_device::asr_map(address_map &map) } }) ); +// map(0x100, 0x103) JPEG Mode and Control +// map(0x104, 0x107) JPEG Process Control +// map(0x108, 0x10b) Vertical Sync Parameters (as sync master) +// map(0x10c, 0x10f) Horizontal Sync Parameters (as sync master) +// map(0x110, 0x113) Field Horizontal Active Portion +// map(0x114, 0x117) Field Vertical Active Portion +// map(0x118, 0x11b) Field Process Parameters +// map(0x11c, 0x11f) JPEG Code Base Address +// map(0x120, 0x123) JPEG Code FIFO Threshold + 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); + }), + NAME([this] (offs_t offset, u8 data) { + m_jpeg_guest_id = (data >> 4) & 7; + m_jpeg_guest_reg = (data >> 0) & 7; + LOG("JPEG Codec Guest ID W %02x\n", data); + }) + ); + map(0x12c, 0x12f).lrw32( + NAME([this] (offs_t offset) { + LOG("GuestBus Control (II) R\n"); + + return (0 << 16) | (m_guestbus.time[7] << 12) | (m_guestbus.time[6] << 8) | (m_guestbus.time[5] << 4) | (m_guestbus.time[4] << 0); + }), + NAME([this] (offs_t offset, u32 data, u32 mem_mask) { + LOG("GuestBus Control (II) W %08x & %08x\n", data, mem_mask); + + if (ACCESSING_BITS_8_15) + { + m_guestbus.time[7] = (data >> 12) & 0xf; + m_guestbus.time[6] = (data >> 8) & 0xf; + } + + if (ACCESSING_BITS_0_7) + { + m_guestbus.time[5] = (data >> 4) & 0xf; + m_guestbus.time[4] = (data >> 0) & 0xf; + } + }) + ); + + map(0x200, 0x2ff).rw(FUNC(zr36057_device::postoffice_r), FUNC(zr36057_device::postoffice_w)); +// map(0x300, 0x303) Still Transfer +} + +// TODO: PostOffice accesses thru GuestBus are dictated with PCI clock cycles, asynchronous +// We pretend they are synchronous as a starting point, and one port only (which may matter later +// with CODE transfers). A time out happens 64 PCI cycles later in ZR36067, '120 halves that threshold. +// This should eventually be expressed in a osd_work_queue, with guestbus address_space roughly as: +// for (int i = 0; i < 8; i++) +// { +// if () +// map(0 | (i << 2), 3 | (i << 2)).flags().m(m_guest[i], map); +// else +// map(0 | (i << 2), 3 | (i << 2)).flags(); +// } +u32 zr36057_device::postoffice_r(offs_t offset) +{ + //LOGPO("PO R %d %d\n", m_po.guest_id, m_po.guest_reg); + u8 res = 0; + if (m_po.guest_id == 0) + { + if (m_po.dir == false) + res = m_guest->read(m_po.guest_reg); + } + else if (!machine().side_effects_disabled()) + { + m_po.time_out = true; + LOGWARN("Warning: PO access unmapped POGuestID read %d %02x\n", m_po.guest_id, m_po.guest_reg); + } + + return (m_po.pending << 25) + | (m_po.time_out << 24) + | (m_po.dir << 23) + | (m_po.guest_id << 20) + | (m_po.guest_reg << 16) + | res; +} + +void zr36057_device::postoffice_w(offs_t offset, u32 data, u32 mem_mask) +{ + // clear a previously set time out flag + if (BIT(data, 24)) + m_po.time_out = false; + m_po.dir = !!(BIT(data, 23)); + m_po.guest_id = (data >> 20) & 7; + m_po.guest_reg = (data >> 16) & 7; + LOGPO("PO W [%08x] %08x & %08x PODir %s POGuestID %d POGuestReg %d POData %02x\n" + , offset << 2 + , data + , mem_mask + , m_po.dir ? "Write" : "Read" + , m_po.guest_id + , m_po.guest_reg + , data & 0xff + ); + if (m_po.guest_id == 0) + { + if (m_po.dir == true) + m_guest->write(m_po.guest_reg, data & 0xff); + } + else + { + m_po.time_out = true; + LOGWARN("Warning: PO access unmapped POGuestID write %d %02x\n", m_po.guest_id, m_po.guest_reg); + } } diff --git a/src/devices/bus/pci/zr36057.h b/src/devices/bus/pci/zr36057.h index 94b3b436633..71ced398967 100644 --- a/src/devices/bus/pci/zr36057.h +++ b/src/devices/bus/pci/zr36057.h @@ -8,6 +8,7 @@ #include "pci_slot.h" #include "video/saa7110.h" +#include "video/zr36060.h" class zr36057_device : public pci_card_device { @@ -25,29 +26,42 @@ protected: // virtual const tiny_rom_entry *device_rom_region() const override ATTR_COLD; -// virtual void map_extra(uint64_t memory_window_start, uint64_t memory_window_end, uint64_t memory_offset, address_space *memory_space, -// uint64_t io_window_start, uint64_t io_window_end, uint64_t io_offset, address_space *io_space) override; - virtual void config_map(address_map &map) override ATTR_COLD; private: + required_device m_guest; required_device m_decoder; void asr_map(address_map &map) ATTR_COLD; void software_reset(); + u32 postoffice_r(offs_t offset); + void postoffice_w(offs_t offset, u32 data, u32 mem_mask); + // Video Front End struct { u32 horizontal_config; u32 vertical_config; - } m_video_frontend; + int hspol, vspol; + u16 hstart, hend, vstart, vend; + } m_vfe; + + u8 m_jpeg_guest_id, m_jpeg_guest_reg; bool m_softreset; u8 m_gpio_ddr, m_pci_waitstate_control; struct { - u8 time[4]; + u8 time[8]; } m_guestbus; + struct { + bool dir; /**< true: Write, false: Read */ + bool time_out; + bool pending; + u8 guest_id; + u8 guest_reg; + } m_po; /**< PostOffice */ + int m_decoder_sdao_state; }; diff --git a/src/devices/video/zr36060.cpp b/src/devices/video/zr36060.cpp new file mode 100644 index 00000000000..35db120b5ea --- /dev/null +++ b/src/devices/video/zr36060.cpp @@ -0,0 +1,109 @@ +// license:BSD-3-Clause +// copyright-holders: Angelo Salese + +#include "emu.h" +#include "zr36060.h" + +#define VERBOSE (LOG_GENERAL) +#include "logmacro.h" + +DEFINE_DEVICE_TYPE(ZR36060, zr36060_device, "zr36060", "Zoran ZR36060 Integrated JPEG codec") + +zr36060_device::zr36060_device(const machine_config &mconfig, char const *tag, device_t *owner, u32 clock) + : device_t(mconfig, ZR36060, tag, owner, clock) + , device_memory_interface(mconfig, *this) +{ + m_space_config = address_space_config("regs", ENDIANNESS_BIG, 8, 10, 0, address_map_constructor(FUNC(zr36060_device::regs_map), this)); + +} + +device_memory_interface::space_config_vector zr36060_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(0, &m_space_config) + }; +} + + +void zr36060_device::device_start() +{ +} + +void zr36060_device::device_reset() +{ +} + +void zr36060_device::regs_map(address_map &map) +{ +// map(0x000, 0x000) LOAD Parameters +// map(0x001, 0x001) Code FIFO Status (r/o) +// map(0x002, 0x002) Code Interface +// map(0x003, 0x003) Codec Mode + +// map(0x005, 0x005) Maximum Block Code +// map(0x006, 0x006) Markers Enable +// map(0x007, 0x007) Interrupt Mask +// map(0x008, 0x008) Interrupt Status (r/o) +// map(0x009, 0x00c) Target Net Code Volume +// map(0x00d, 0x010) Target Data Code Volume +// map(0x011, 0x012) Scale Factor +// map(0x013, 0x015) Allocation Factor +// map(0x016, 0x019) Accumulated Code Volume +// map(0x01a, 0x01d) Accumulated Total Activity +// map(0x01e, 0x021) Accumulated Truncated Bits + map(0x022, 0x022).lr8(NAME([this] (offs_t offset) { LOG("Read Device ID\n"); return 0x33; })); + map(0x023, 0x023).lr8(NAME([this] (offs_t offset) { LOG("Read Revision ID\n"); return 0x01; })); +// map(0x024, 0x025) Test Control + +// map(0x030, 0x030) Video Control +// map(0x031, 0x031) Video Polarity +// map(0x032, 0x032) Scaling +// map(0x033, 0x035) Background Color +// map(0x036, 0x041) Sync Generator +// map(0x042, 0x049) Active Area +// map(0x04a, 0x051) SUBIMG Window + + map(0x060, 0x3ff).ram(); // JPEG Markers Array +} + +/************************************** + * + * Host I/F + * + *************************************/ + +u8 zr36060_device::read(offs_t offset) +{ + switch(offset & 3) + { + case 0: + LOG("CODE FIFO read\n"); + return 0; + case 1: + return (m_address >> 8) & 3; + case 2: + return m_address & 0xff; + case 3: + return space(0).read_byte(m_address); + } + return 0; +} + +void zr36060_device::write(offs_t offset, u8 data) +{ + switch(offset & 3) + { + case 0: + LOG("CODE FIFO write %02x\n", data); + break; + case 1: + m_address = (data << 8) | (m_address & 0xff); + break; + case 2: + m_address = (data & 0xff) | (m_address & 0x300); + break; + case 3: + space(0).write_byte(m_address, data); + break; + } +} diff --git a/src/devices/video/zr36060.h b/src/devices/video/zr36060.h new file mode 100644 index 00000000000..86e3877b915 --- /dev/null +++ b/src/devices/video/zr36060.h @@ -0,0 +1,31 @@ +// license:BSD-3-Clause +// copyright-holders: Angelo Salese + +#ifndef MAME_VIDEO_ZR36060_H +#define MAME_VIDEO_ZR36060_H + +#pragma once + +class zr36060_device : public device_t, public device_memory_interface +{ +public: + zr36060_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + + u8 read(offs_t offset); + void write(offs_t offset, u8 data); + +protected: + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; + + virtual space_config_vector memory_space_config() const override; +private: + void regs_map(address_map &map); + + u16 m_address; + address_space_config m_space_config; +}; + +DECLARE_DEVICE_TYPE(ZR36060, zr36060_device) + +#endif // MAME_VIDEO_ZR36060_H diff --git a/src/mame/misc/magictg.cpp b/src/mame/misc/magictg.cpp index d02c76b27fc..7112bbdc002 100644 --- a/src/mame/misc/magictg.cpp +++ b/src/mame/misc/magictg.cpp @@ -501,7 +501,7 @@ uint32_t magictg_state::zr36120_r(offs_t offset) } else { - /* Post office */ + // PostOffice reads res = 0;//mame_rand(machine);//m_zr36120.as_regs[0x48/4]; } logerror("PINKEYE_R[%x]\n", offset); @@ -529,6 +529,9 @@ void magictg_state::zr36120_w(offs_t offset, uint32_t data) } else { + // PostOffice writes + // - Takes 32 PCI clocks for time out to happen compared to 64 in ZR36067 + // - Has 4 guests instead of 8 uint32_t guest = (data >> 20) & 3; uint32_t g_data = data & 0xff; uint32_t g_reg = (data >> 16) & 7;