diff mbox series

[v2,2/4] xlnx_dp: Introduce a vblank signal

Message ID 20220519153829.356889-3-fkonrad@amd.com (mailing list archive)
State New, archived
Headers show
Series xlnx-zcu102: fix the display port. | expand

Commit Message

Frederic Konrad May 19, 2022, 3:38 p.m. UTC
From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>

Add a periodic timer which raises vblank at a frequency of 30Hz.

Signed-off-by: Sai Pavan Boddu <saipava@xilinx.com>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@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>
---
 hw/display/xlnx_dp.c         | 27 ++++++++++++++++++++++++---
 include/hw/display/xlnx_dp.h |  3 +++
 2 files changed, 27 insertions(+), 3 deletions(-)

Comments

Peter Maydell May 23, 2022, 1:51 p.m. UTC | #1
On Thu, 19 May 2022 at 16:39, Frederic Konrad <fkonrad@amd.com> wrote:
>
> From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
>
> Add a periodic timer which raises vblank at a frequency of 30Hz.
>
> Signed-off-by: Sai Pavan Boddu <saipava@xilinx.com>
> Signed-off-by: Edgar E. Iglesias <edgar.iglesias@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>
> ---


> @@ -107,6 +108,8 @@ struct XlnxDPState {
>       */
>      DPCDState *dpcd;
>      I2CDDCState *edid;
> +
> +    ptimer_state *vblank;
>  };

The ptimer has internal state which needs to be considered in
migration. This means you need to either include it in the device
vmstate struct (there is a VMSTATE_PTIMER macro for this), or
else set it up again in a post-load hook. Otherwise if you do
a migration or state save/load when the timer is running then
on resume the timer won't be running when it should.

Apologies for not noticing this in my first review.

-- PMM
Frederic Konrad May 24, 2022, 8:30 a.m. UTC | #2
> -----Original Message-----
> From: Peter Maydell <peter.maydell@linaro.org>
> Sent: 23 May 2022 14:52
> To: Frederic Konrad <fkonrad@amd.com>
> Cc: qemu-devel@nongnu.org; qemu-arm@nongnu.org;
> edgar.iglesias@gmail.com; alistair@alistair23.me; Sai Pavan Boddu
> <saipava@xilinx.com>; Edgar Iglesias <edgari@xilinx.com>; Sai Pavan Boddu
> <saipava@xilinx.com>; Edgar Iglesias <edgari@xilinx.com>
> Subject: Re: [PATCH v2 2/4] xlnx_dp: Introduce a vblank signal
> 
> [CAUTION: External Email]
> 
> On Thu, 19 May 2022 at 16:39, Frederic Konrad <fkonrad@amd.com> wrote:
> >
> > From: Sai Pavan Boddu <sai.pavan.boddu@xilinx.com>
> >
> > Add a periodic timer which raises vblank at a frequency of 30Hz.
> >
> > Signed-off-by: Sai Pavan Boddu <saipava@xilinx.com>
> > Signed-off-by: Edgar E. Iglesias <edgar.iglesias@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>
> > ---
> 
> 
> > @@ -107,6 +108,8 @@ struct XlnxDPState {
> >       */
> >      DPCDState *dpcd;
> >      I2CDDCState *edid;
> > +
> > +    ptimer_state *vblank;
> >  };
> 
> The ptimer has internal state which needs to be considered in
> migration. This means you need to either include it in the device
> vmstate struct (there is a VMSTATE_PTIMER macro for this), or
> else set it up again in a post-load hook. Otherwise if you do
> a migration or state save/load when the timer is running then
> on resume the timer won't be running when it should.

Ah yes indeed, I forgot about that.  Since cross version migration is not relevant
here, the VMSTATE_PTIMER would be acceptable right?

> 
> Apologies for not noticing this in my first review.

No worries, thanks for the review :).

Fred

> 
> -- PMM
diff mbox series

Patch

diff --git a/hw/display/xlnx_dp.c b/hw/display/xlnx_dp.c
index 0378570459..2686ca0f2e 100644
--- a/hw/display/xlnx_dp.c
+++ b/hw/display/xlnx_dp.c
@@ -114,6 +114,7 @@ 
 #define DP_TX_N_AUD                         (0x032C >> 2)
 #define DP_TX_AUDIO_EXT_DATA(n)             ((0x0330 + 4 * n) >> 2)
 #define DP_INT_STATUS                       (0x03A0 >> 2)
+#define DP_INT_VBLNK_START                  (1 << 13)
 #define DP_INT_MASK                         (0x03A4 >> 2)
 #define DP_INT_EN                           (0x03A8 >> 2)
 #define DP_INT_DS                           (0x03AC >> 2)
@@ -274,6 +275,10 @@  static const VMStateDescription vmstate_dp = {
     }
 };
 
+#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 uint64_t xlnx_dp_audio_read(void *opaque, hwaddr offset, unsigned size)
@@ -773,6 +778,13 @@  static void xlnx_dp_write(void *opaque, hwaddr offset, uint64_t value,
         break;
     case DP_TRANSMITTER_ENABLE:
         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;
     case DP_FORCE_SCRAMBLER_RESET:
         /*
@@ -1177,9 +1189,6 @@  static void xlnx_dp_update_display(void *opaque)
         return;
     }
 
-    s->core_registers[DP_INT_STATUS] |= (1 << 13);
-    xlnx_dp_update_irq(s);
-
     xlnx_dpdma_trigger_vsync_irq(s->dpdma);
 
     /*
@@ -1275,6 +1284,14 @@  static void xlnx_dp_finalize(Object *obj)
     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)
 {
     XlnxDPState *s = XLNX_DP(dev);
@@ -1309,6 +1326,10 @@  static void xlnx_dp_realize(DeviceState *dev, Error **errp)
                                            &as);
     AUD_set_volume_out(s->amixer_output_stream, 0, 255, 255);
     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)
diff --git a/include/hw/display/xlnx_dp.h b/include/hw/display/xlnx_dp.h
index 1ef5a89ee7..e86a87f235 100644
--- a/include/hw/display/xlnx_dp.h
+++ b/include/hw/display/xlnx_dp.h
@@ -35,6 +35,7 @@ 
 #include "hw/dma/xlnx_dpdma.h"
 #include "audio/audio.h"
 #include "qom/object.h"
+#include "hw/ptimer.h"
 
 #define AUD_CHBUF_MAX_DEPTH                 (32 * KiB)
 #define MAX_QEMU_BUFFER_SIZE                (4 * KiB)
@@ -107,6 +108,8 @@  struct XlnxDPState {
      */
     DPCDState *dpcd;
     I2CDDCState *edid;
+
+    ptimer_state *vblank;
 };
 
 #define TYPE_XLNX_DP "xlnx.v-dp"