diff --git a/hw/xbox/smbus.h b/hw/xbox/smbus.h index 1cc25a188e..8d28198b07 100644 --- a/hw/xbox/smbus.h +++ b/hw/xbox/smbus.h @@ -29,4 +29,7 @@ void smbus_xbox_smc_init(I2CBus *smbus, int address); void smbus_cx25871_init(I2CBus *smbus, int address); void smbus_adm1032_init(I2CBus *smbus, int address); +bool xbox_smc_avpack_to_reg(const char *avpack, uint8_t *value); +void xbox_smc_append_avpack_hint(Error **errp); + #endif diff --git a/hw/xbox/smbus_xbox_smc.c b/hw/xbox/smbus_xbox_smc.c index 973b889089..cb0e244aba 100644 --- a/hw/xbox/smbus_xbox_smc.c +++ b/hw/xbox/smbus_xbox_smc.c @@ -28,6 +28,7 @@ #include "hw/i2c/i2c.h" #include "hw/i2c/smbus_slave.h" #include "qemu/config-file.h" +#include "qapi/error.h" #include "sysemu/sysemu.h" #include "smbus.h" @@ -55,10 +56,11 @@ #define SMC_REG_AVPACK 0x04 #define SMC_REG_AVPACK_SCART 0x00 #define SMC_REG_AVPACK_HDTV 0x01 -#define SMC_REG_AVPACK_VGA_SOG 0x02 +#define SMC_REG_AVPACK_VGA 0x02 +#define SMC_REG_AVPACK_RFU 0x03 #define SMC_REG_AVPACK_SVIDEO 0x04 #define SMC_REG_AVPACK_COMPOSITE 0x06 -#define SMC_REG_AVPACK_VGA 0x07 +#define SMC_REG_AVPACK_NONE 0x07 #define SMC_REG_FANMODE 0x05 #define SMC_REG_FANSPEED 0x06 #define SMC_REG_LEDMODE 0x07 @@ -86,6 +88,7 @@ typedef struct SMBusSMCDevice { SMBusDevice smbusdev; int version_string_index; uint8_t cmd; + uint8_t avpack_reg; uint8_t scratch_reg; } SMBusSMCDevice; @@ -154,8 +157,7 @@ static uint8_t smc_receive_byte(SMBusDevice *dev) smc->version_string_index++ % (sizeof(smc_version_string) - 1)]; case SMC_REG_AVPACK: - /* pretend to have a composite av pack plugged in */ - return SMC_REG_AVPACK_COMPOSITE; + return smc->avpack_reg; case SMC_REG_SCRATCH: return smc->scratch_reg; @@ -178,17 +180,62 @@ static uint8_t smc_receive_byte(SMBusDevice *dev) return 0; } +bool xbox_smc_avpack_to_reg(const char *avpack, uint8_t *value) +{ + uint8_t r; + + if (!strcmp(avpack, "composite")) { + r = SMC_REG_AVPACK_COMPOSITE; + } else if (!strcmp(avpack, "scart")) { + r = SMC_REG_AVPACK_SCART; + } else if (!strcmp(avpack, "svideo")) { + r = SMC_REG_AVPACK_SVIDEO; + } else if (!strcmp(avpack, "vga")) { + r = SMC_REG_AVPACK_VGA; + } else if (!strcmp(avpack, "rfu")) { + r = SMC_REG_AVPACK_RFU; + } else if (!strcmp(avpack, "hdtv")) { + r = SMC_REG_AVPACK_HDTV; + } else if (!strcmp(avpack, "none")) { + r = SMC_REG_AVPACK_NONE; + } else { + return false; + } + + if (value) { + *value = r; + } + return true; +} + +void xbox_smc_append_avpack_hint(Error **errp) +{ + error_append_hint(errp, "Valid options are: composite (default), scart, svideo, vga, rfu, hdtv, none\n"); +} + static void smbus_smc_realize(DeviceState *dev, Error **errp) { SMBusSMCDevice *smc = XBOX_SMC(dev); + char *avpack; smc->version_string_index = 0; + smc->avpack_reg = 0; /* Default value for Chihiro machine */ smc->scratch_reg = 0; smc->cmd = 0; if (object_property_get_bool(qdev_get_machine(), "short-animation", NULL)) { smc->scratch_reg = SMC_REG_SCRATCH_SHORT_ANIMATION; } + + avpack = object_property_get_str(qdev_get_machine(), "avpack", NULL); + if (avpack) { + if (!xbox_smc_avpack_to_reg(avpack, &smc->avpack_reg)) { + error_setg(errp, "Unsupported avpack option '%s'", avpack); + xbox_smc_append_avpack_hint(errp); + } + + g_free(avpack); + } } static void smbus_smc_class_initfn(ObjectClass *klass, void *data) diff --git a/hw/xbox/xbox.c b/hw/xbox/xbox.c index 40001d4f4b..f050f7bb94 100644 --- a/hw/xbox/xbox.c +++ b/hw/xbox/xbox.c @@ -476,6 +476,28 @@ static void machine_set_eeprom(Object *obj, const char *value, ms->eeprom = g_strdup(value); } +static char *machine_get_avpack(Object *obj, Error **errp) +{ + XboxMachineState *ms = XBOX_MACHINE(obj); + + return g_strdup(ms->avpack); +} + +static void machine_set_avpack(Object *obj, const char *value, + Error **errp) +{ + XboxMachineState *ms = XBOX_MACHINE(obj); + + if (!xbox_smc_avpack_to_reg(value, NULL)) { + error_setg(errp, "-machine avpack=%s: unsupported option", value); + xbox_smc_append_avpack_hint(errp); + return; + } + + g_free(ms->avpack); + ms->avpack = g_strdup(value); +} + static void machine_set_short_animation(Object *obj, bool value, Error **errp) { @@ -502,6 +524,12 @@ static inline void xbox_machine_initfn(Object *obj) object_property_set_description(obj, "eeprom", "Xbox EEPROM file", NULL); + object_property_add_str(obj, "avpack", machine_get_avpack, + machine_set_avpack, NULL); + object_property_set_description(obj, "avpack", + "Xbox video connector: composite (default), scart, svideo, vga, rfu, hdtv, none", NULL); + object_property_set_str(obj, "composite", "avpack", NULL); + object_property_add_bool(obj, "short-animation", machine_get_short_animation, machine_set_short_animation, NULL); diff --git a/hw/xbox/xbox.h b/hw/xbox/xbox.h index af4c0f0331..0cc27a2a77 100644 --- a/hw/xbox/xbox.h +++ b/hw/xbox/xbox.h @@ -47,6 +47,7 @@ typedef struct XboxMachineState { /*< public >*/ char *bootrom; char *eeprom; + char *avpack; bool short_animation; } XboxMachineState;