diff options
| author | 2025-02-19 11:10:47 +0100 | |
|---|---|---|
| committer | 2025-02-19 11:10:56 +0100 | |
| commit | f484388f159761b7873fba9c6205de840a9aff2a (patch) | |
| tree | c5de723b2de239e5c73f32f8030a54cbaf912814 /src | |
| parent | fb7c1fde64ccedc1bf086ab51fef4212073b8306 (diff) | |
video/saa7110.cpp: type-in OCF1 receiver writes
Diffstat (limited to 'src')
| -rw-r--r-- | src/devices/bus/pci/zr36057.cpp | 11 | ||||
| -rw-r--r-- | src/devices/video/saa7110.cpp | 125 | ||||
| -rw-r--r-- | src/devices/video/saa7110.h | 19 |
3 files changed, 138 insertions, 17 deletions
diff --git a/src/devices/bus/pci/zr36057.cpp b/src/devices/bus/pci/zr36057.cpp index dff2bf68c96..0d3964e2a0c 100644 --- a/src/devices/bus/pci/zr36057.cpp +++ b/src/devices/bus/pci/zr36057.cpp @@ -10,14 +10,17 @@ iterations. - https://www.kernel.org/doc/html/v6.13/driver-api/media/drivers/zoran.html - Currently using DC10+ configuration: ZR36067 + ZR36060 (ZR36050 + ZR36016 glued together) - SAA7110a (TV decoder, PAL B/G / NTSC M / SECAM) + adv7176 (TV encoder, Linux driver name is adv7175) + SAA7110a (TV decoder) + adv7176 (TV encoder, Linux driver name is adv7175) ZR36057 is known to have two HW quirks that are been fixed with ZR36067. TODO: -- Currently at dc10plus HW test "Error at video decoder", requires SAA7110a to continue; +- Currently at dc10plus HW test "Error at M-JPEG codec", requires ZR36060 to continue; - Hookup busmaster; -- Stub, eventually decouple AV PCI controller part from the actual client cards; +- 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); +- eventually decouple AV PCI controller part from the actual client cards; Known mix-ins: - s3virge.cpp uses SAA7110 for Scenic Highway overlay available with its S3 LPB connector; @@ -167,7 +170,7 @@ void zr36057_device::asr_map(address_map &map) if (ACCESSING_BITS_24_31) { m_softreset = !!BIT(data, 24); - // TODO: will lock all writes in config_map but this bit + // TODO: will lock all writes in asr_map but this bit // (inclusive of the "all" group?) if (!m_softreset) { diff --git a/src/devices/video/saa7110.cpp b/src/devices/video/saa7110.cpp index dda0dac2076..e4e0e9425dd 100644 --- a/src/devices/video/saa7110.cpp +++ b/src/devices/video/saa7110.cpp @@ -1,10 +1,26 @@ // license: BSD-3-Clause // copyright-holders: Angelo Salese +/************************************************************************************************** + +SAA7110/SAA7110A One Chip Front-end 1 + +TV decoder, can decode PAL B/G, NTSC M and SECAM + +TODO: +- Stub, barely enough to make i2c tests happy in ZR36057 core; +- SA configuration pin; +- How to read transmitter regs? Should be slave addresses 0x9d (SA=0) or 0x9f (SA=1), + ZR36057 doesn't seem to care for now, '60 eventually will? +- Needs an actual multimedia source to continue; + +**************************************************************************************************/ #include "emu.h" #include "saa7110.h" -#define VERBOSE (1) +#define VERBOSE (LOG_GENERAL) +//#define LOG_OUTPUT_FUNC osd_printf_info + #include "logmacro.h" DEFINE_DEVICE_TYPE(SAA7110A, saa7110a_device, "saa7110a", "SAA7110A OCF1") @@ -13,26 +29,123 @@ DEFINE_DEVICE_TYPE(SAA7110A, saa7110a_device, "saa7110a", "SAA7110A OCF1") saa7110a_device::saa7110a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, SAA7110A, tag, owner, clock) , i2c_hle_interface(mconfig, *this, 0x9c >> 1) - //, device_memory_interface(mconfig, *this) -{} + , device_memory_interface(mconfig, *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() { + save_item(NAME(m_secs)); + save_item(NAME(m_sstb)); + save_item(NAME(m_hrmv)); + save_item(NAME(m_rtse)); + save_item(NAME(m_vtrc)); } void saa7110a_device::device_reset() { + m_secs = m_sstb = m_hrmv = m_rtse = m_vtrc = false; +} +device_memory_interface::space_config_vector saa7110a_device::memory_space_config() const +{ + return space_config_vector { + std::make_pair(0, &m_space_config) + }; } u8 saa7110a_device::read_data(u16 offset) { - //printf("%02x\n", offset); - return 0xff; + // OCF1 transmitter regs + // IC version number, not necessarily device ID? + if (m_sstb == false) + { + LOG("OCF1 transmitter: read IC version number (check me)\n"); + machine().debug_break(); + return 0x01; + } + // TODO: status byte + // x--- ---- STTC horizontal time constant (0) TV time constant (1) VCR time constant + // -x-- ---- HLCK locked horizontal frequency (1) unlocked + // --x- ---- FIDT Identification bit for detected field frequency (0) 50 Hz (1) 60 Hz + // ---x ---- GLIM Gain value for active luminance limit + // ---- -x-- WIPA White peak loop activation + // ---- --x- ALTD line alternating colour burst detection (PAL/SECAM) + // ---- ---x CODE color signal has been detected + LOG("OCF1 transmitter: read status byte\n"); + return 0x00; } void saa7110a_device::write_data(u16 offset, u8 data) { - //printf("%02x %02x\n", offset, data); + // OCF1 receiver regs + space(0).write_byte(offset, data); +} + +void saa7110a_device::regs_map(address_map &map) +{ + // BMSD-SQP + BSC slave receiver + map(0x00, 0x00).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU00: Increment delay %02x\n", data); })); + map(0x01, 0x01).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU01: HSY begin 50 Hz %02x\n", data); })); + map(0x02, 0x02).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU02: HSY stop 50 Hz %02x\n", data); })); + map(0x03, 0x03).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU03: HCL begin 50 Hz %02x\n", data); })); + map(0x04, 0x04).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU04: HCL stop 50 Hz %02x\n", data); })); + map(0x05, 0x05).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU05: HSY after PHI1 50 Hz %02x\n", data); })); + map(0x06, 0x06).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU06: Luminance control %02x\n", data); })); + map(0x07, 0x07).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU07: Hue control %02x\n", data); })); + map(0x08, 0x08).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU08: Colour killer threshold QUAM (PAL/NTSC) %02x\n", data); })); + map(0x09, 0x09).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU09: Colour killer threshold SECAM %02x\n", data); })); + map(0x0a, 0x0a).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU0A: PAL switch sensitivity %02x\n", data); })); + map(0x0b, 0x0b).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU0B: SECAM switch sensitivity %02x\n", data); })); + map(0x0c, 0x0c).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU0C: Gain control chrominance %02x\n", data); })); + map(0x0d, 0x0d).lw8(NAME([this] (offs_t offset, u8 data) { + LOG("SU0D: Standard/mode control %02x\n", data); + m_secs = BIT(data, 0); + m_sstb = BIT(data, 1); + m_hrmv = BIT(data, 2); + m_rtse = BIT(data, 3); + m_vtrc = BIT(data, 7); + LOG("\tSECAM mode bit SECS = %d: %s\n", m_secs, m_secs ? "SECAM mode" : "Other standards"); + LOG("\tStatus byte select SSTB = %d\n", m_sstb); + LOG("\tHREF position select HRMV = %d: %s\n", m_hrmv, m_hrmv ? "HREF position 8 LLC2 later (SAA7191 mode)" : "HREF normal position"); + LOG("\tReal time outputs mode select RTSE = %d: %s\n", m_rtse, m_rtse ? "HL pin 39, VL pin 40" : "PLIN pin 39, ODD pin 40"); + LOG("\tTV/VCR mode select VTRC = %d: %s\n", m_vtrc, m_vtrc ? "VTR mode" : "TV mode"); + })); + map(0x0e, 0x0e).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU0E: I/O and clock control %02x\n", data); })); + map(0x0f, 0x0f).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU0F: Control #1 %02x\n", data); })); + map(0x10, 0x10).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU10: Control #2 %02x\n", data); })); + map(0x11, 0x11).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU11: Chrominance gain reference %02x\n", data); })); + map(0x12, 0x12).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU12: Chrominance saturation %02x\n", data); })); + map(0x13, 0x13).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU13: Luminance contrast %02x\n", data); })); + map(0x14, 0x14).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU14: HSY begin 60 Hz %02x\n", data); })); + map(0x15, 0x15).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU15: HSY stop 60 Hz %02x\n", data); })); + map(0x16, 0x16).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU16: HCL begin 60 Hz %02x\n", data); })); + map(0x17, 0x17).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU17: HCL stop 60 Hz %02x\n", data); })); + map(0x18, 0x18).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU18: HSY after PHI1 60 Hz %02x\n", data); })); + map(0x19, 0x19).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU19: Luminance brightness %02x\n", data); })); + + // DUAD slave receiver + map(0x20, 0x20).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU20: Analog control #1 %02x\n", data); })); + map(0x21, 0x21).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU21: Analog control #2 %02x\n", data); })); + map(0x22, 0x22).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU22: Mixer control #1 %02x\n", data); })); + map(0x23, 0x23).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU23: Clamping level control 21 %02x\n", data); })); + map(0x24, 0x24).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU24: Clamping level control 22 %02x\n", data); })); + map(0x25, 0x25).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU25: Clamping level control 31 %02x\n", data); })); + map(0x26, 0x26).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU26: Clamping level control 32 %02x\n", data); })); + map(0x27, 0x27).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU27: Gain control analog #1 %02x\n", data); })); + map(0x28, 0x28).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU28: White peak control %02x\n", data); })); + map(0x29, 0x29).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU29: Sync bottom control %02x\n", data); })); + map(0x2a, 0x2a).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU2A: Gain control analog #2 %02x\n", data); })); + 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(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); })); + map(0x33, 0x33).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU33: Mixer control #4 %02x\n", data); })); + map(0x34, 0x34).lw8(NAME([this] (offs_t offset, u8 data) { LOG("SU34: Gain update level %02x\n", data); })); } diff --git a/src/devices/video/saa7110.h b/src/devices/video/saa7110.h index d74976ba4f0..a4c5b741c9b 100644 --- a/src/devices/video/saa7110.h +++ b/src/devices/video/saa7110.h @@ -10,21 +10,26 @@ class saa7110a_device : public device_t, - public i2c_hle_interface -// public device_memory_interface + public i2c_hle_interface, + public device_memory_interface { public: saa7110a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); 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; - virtual void device_reset() override ATTR_COLD; + virtual void device_start() override ATTR_COLD; + virtual void device_reset() override ATTR_COLD; -// virtual space_config_vector memory_space_config() const override; - virtual u8 read_data(u16 offset) override; - virtual void write_data(u16 offset, u8 data) override; + virtual space_config_vector memory_space_config() const override; + void regs_map(address_map &map) ATTR_COLD; +private: + virtual u8 read_data(u16 offset) override; + virtual void write_data(u16 offset, u8 data) override; + address_space_config m_space_config; + + bool m_secs, m_sstb, m_hrmv, m_rtse, m_vtrc; }; DECLARE_DEVICE_TYPE(SAA7110A, saa7110a_device) |
