summaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/devices/bus/pci/zr36057.cpp173
-rw-r--r--src/devices/bus/pci/zr36057.h24
-rw-r--r--src/devices/video/zr36060.cpp109
-rw-r--r--src/devices/video/zr36060.h31
-rw-r--r--src/mame/misc/magictg.cpp5
5 files changed, 321 insertions, 21 deletions
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 (<is_device_installed>)
+// map(0 | (i << 2), 3 | (i << 2)).flags(<fn>).m(m_guest[i], map);
+// else
+// map(0 | (i << 2), 3 | (i << 2)).flags(<abort_fn>);
+// }
+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<zr36060_device> m_guest;
required_device<saa7110a_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;