mirror of https://github.com/xemu-project/xemu.git
xlnx_dp: Introduce a vblank signal
Add a periodic timer which raises vblank at a frequency of 30Hz. Note that this is a migration compatibility break for the xlnx-zcu102 board type. Signed-off-by: Sai Pavan Boddu <saipava@xilinx.com> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Signed-off-by: Frederic Konrad <fkonrad@amd.com> Acked-by: Alistair Francis <alistair.francis@wdc.com> Message-id: 20220601172353.3220232-3-fkonrad@xilinx.com Changes by fkonrad: - Switched to transaction-based ptimer API. - Added the DP_INT_VBLNK_START macro. Signed-off-by: Frederic Konrad <fkonrad@amd.com> [PMM: bump vmstate version, add commit message note about compat break] Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
d2008b3355
commit
759ae1b47e
|
@ -114,6 +114,7 @@
|
||||||
#define DP_TX_N_AUD (0x032C >> 2)
|
#define DP_TX_N_AUD (0x032C >> 2)
|
||||||
#define DP_TX_AUDIO_EXT_DATA(n) ((0x0330 + 4 * n) >> 2)
|
#define DP_TX_AUDIO_EXT_DATA(n) ((0x0330 + 4 * n) >> 2)
|
||||||
#define DP_INT_STATUS (0x03A0 >> 2)
|
#define DP_INT_STATUS (0x03A0 >> 2)
|
||||||
|
#define DP_INT_VBLNK_START (1 << 13)
|
||||||
#define DP_INT_MASK (0x03A4 >> 2)
|
#define DP_INT_MASK (0x03A4 >> 2)
|
||||||
#define DP_INT_EN (0x03A8 >> 2)
|
#define DP_INT_EN (0x03A8 >> 2)
|
||||||
#define DP_INT_DS (0x03AC >> 2)
|
#define DP_INT_DS (0x03AC >> 2)
|
||||||
|
@ -260,7 +261,7 @@ typedef enum DPVideoFmt DPVideoFmt;
|
||||||
|
|
||||||
static const VMStateDescription vmstate_dp = {
|
static const VMStateDescription vmstate_dp = {
|
||||||
.name = TYPE_XLNX_DP,
|
.name = TYPE_XLNX_DP,
|
||||||
.version_id = 1,
|
.version_id = 2,
|
||||||
.fields = (VMStateField[]){
|
.fields = (VMStateField[]){
|
||||||
VMSTATE_UINT32_ARRAY(core_registers, XlnxDPState,
|
VMSTATE_UINT32_ARRAY(core_registers, XlnxDPState,
|
||||||
DP_CORE_REG_ARRAY_SIZE),
|
DP_CORE_REG_ARRAY_SIZE),
|
||||||
|
@ -270,10 +271,15 @@ static const VMStateDescription vmstate_dp = {
|
||||||
DP_VBLEND_REG_ARRAY_SIZE),
|
DP_VBLEND_REG_ARRAY_SIZE),
|
||||||
VMSTATE_UINT32_ARRAY(audio_registers, XlnxDPState,
|
VMSTATE_UINT32_ARRAY(audio_registers, XlnxDPState,
|
||||||
DP_AUDIO_REG_ARRAY_SIZE),
|
DP_AUDIO_REG_ARRAY_SIZE),
|
||||||
|
VMSTATE_PTIMER(vblank, XlnxDPState),
|
||||||
VMSTATE_END_OF_LIST()
|
VMSTATE_END_OF_LIST()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define DP_VBLANK_PTIMER_POLICY (PTIMER_POLICY_WRAP_AFTER_ONE_PERIOD | \
|
||||||
|
PTIMER_POLICY_CONTINUOUS_TRIGGER | \
|
||||||
|
PTIMER_POLICY_NO_IMMEDIATE_TRIGGER)
|
||||||
|
|
||||||
static void xlnx_dp_update_irq(XlnxDPState *s);
|
static void xlnx_dp_update_irq(XlnxDPState *s);
|
||||||
|
|
||||||
static uint64_t xlnx_dp_audio_read(void *opaque, hwaddr offset, unsigned size)
|
static uint64_t xlnx_dp_audio_read(void *opaque, hwaddr offset, unsigned size)
|
||||||
|
@ -773,6 +779,13 @@ static void xlnx_dp_write(void *opaque, hwaddr offset, uint64_t value,
|
||||||
break;
|
break;
|
||||||
case DP_TRANSMITTER_ENABLE:
|
case DP_TRANSMITTER_ENABLE:
|
||||||
s->core_registers[offset] = value & 0x01;
|
s->core_registers[offset] = value & 0x01;
|
||||||
|
ptimer_transaction_begin(s->vblank);
|
||||||
|
if (value & 0x1) {
|
||||||
|
ptimer_run(s->vblank, 0);
|
||||||
|
} else {
|
||||||
|
ptimer_stop(s->vblank);
|
||||||
|
}
|
||||||
|
ptimer_transaction_commit(s->vblank);
|
||||||
break;
|
break;
|
||||||
case DP_FORCE_SCRAMBLER_RESET:
|
case DP_FORCE_SCRAMBLER_RESET:
|
||||||
/*
|
/*
|
||||||
|
@ -1177,9 +1190,6 @@ static void xlnx_dp_update_display(void *opaque)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
s->core_registers[DP_INT_STATUS] |= (1 << 13);
|
|
||||||
xlnx_dp_update_irq(s);
|
|
||||||
|
|
||||||
xlnx_dpdma_trigger_vsync_irq(s->dpdma);
|
xlnx_dpdma_trigger_vsync_irq(s->dpdma);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1275,6 +1285,14 @@ static void xlnx_dp_finalize(Object *obj)
|
||||||
fifo8_destroy(&s->rx_fifo);
|
fifo8_destroy(&s->rx_fifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void vblank_hit(void *opaque)
|
||||||
|
{
|
||||||
|
XlnxDPState *s = XLNX_DP(opaque);
|
||||||
|
|
||||||
|
s->core_registers[DP_INT_STATUS] |= DP_INT_VBLNK_START;
|
||||||
|
xlnx_dp_update_irq(s);
|
||||||
|
}
|
||||||
|
|
||||||
static void xlnx_dp_realize(DeviceState *dev, Error **errp)
|
static void xlnx_dp_realize(DeviceState *dev, Error **errp)
|
||||||
{
|
{
|
||||||
XlnxDPState *s = XLNX_DP(dev);
|
XlnxDPState *s = XLNX_DP(dev);
|
||||||
|
@ -1309,6 +1327,10 @@ static void xlnx_dp_realize(DeviceState *dev, Error **errp)
|
||||||
&as);
|
&as);
|
||||||
AUD_set_volume_out(s->amixer_output_stream, 0, 255, 255);
|
AUD_set_volume_out(s->amixer_output_stream, 0, 255, 255);
|
||||||
xlnx_dp_audio_activate(s);
|
xlnx_dp_audio_activate(s);
|
||||||
|
s->vblank = ptimer_init(vblank_hit, s, DP_VBLANK_PTIMER_POLICY);
|
||||||
|
ptimer_transaction_begin(s->vblank);
|
||||||
|
ptimer_set_freq(s->vblank, 30);
|
||||||
|
ptimer_transaction_commit(s->vblank);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xlnx_dp_reset(DeviceState *dev)
|
static void xlnx_dp_reset(DeviceState *dev)
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include "hw/dma/xlnx_dpdma.h"
|
#include "hw/dma/xlnx_dpdma.h"
|
||||||
#include "audio/audio.h"
|
#include "audio/audio.h"
|
||||||
#include "qom/object.h"
|
#include "qom/object.h"
|
||||||
|
#include "hw/ptimer.h"
|
||||||
|
|
||||||
#define AUD_CHBUF_MAX_DEPTH (32 * KiB)
|
#define AUD_CHBUF_MAX_DEPTH (32 * KiB)
|
||||||
#define MAX_QEMU_BUFFER_SIZE (4 * KiB)
|
#define MAX_QEMU_BUFFER_SIZE (4 * KiB)
|
||||||
|
@ -107,6 +108,8 @@ struct XlnxDPState {
|
||||||
*/
|
*/
|
||||||
DPCDState *dpcd;
|
DPCDState *dpcd;
|
||||||
I2CDDCState *edid;
|
I2CDDCState *edid;
|
||||||
|
|
||||||
|
ptimer_state *vblank;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TYPE_XLNX_DP "xlnx.v-dp"
|
#define TYPE_XLNX_DP "xlnx.v-dp"
|
||||||
|
|
Loading…
Reference in New Issue