On Fri, May 18, 2018 at 09:56:20AM +0100, Brian Starkey wrote: > Hi Liviu, > > On Fri, May 18, 2018 at 09:24:21AM +0100, Liviu Dudau wrote: > > Mali DP500 behaves differently from the rest of the Mali DP IP, > > in that it does not have a one-shot mode and keeps writing the > > content of the current frame to the provided memory area until > > stopped. As a way of emulating the one-shot behaviour, we are > > going to use the CVAL interrupt that is being raised at the > > start of each frame, during prefetch phase, to act as End-of-Write > > signal, but with a twist: we are going to disable the memory > > write engine right after we're notified that it has been enabled, > > using the knowledge that the bit controlling the enabling will > > only be acted upon on the next vblank/prefetch. > > > > CVAL interrupt will fire durint the next prefetch phase every time > > the global CVAL bit gets set, so we need a state byte to track > > the memory write enabling. > > > > Signed-off-by: Liviu Dudau <liviu.dudau@xxxxxxx> > > --- > > drivers/gpu/drm/arm/malidp_hw.c | 77 +++++++++++++++++++++++++++++-- > > drivers/gpu/drm/arm/malidp_hw.h | 5 +- > > drivers/gpu/drm/arm/malidp_regs.h | 3 +- > > 3 files changed, 80 insertions(+), 5 deletions(-) > > > > diff --git a/drivers/gpu/drm/arm/malidp_hw.c b/drivers/gpu/drm/arm/malidp_hw.c > > index 455a83689d039..d9a7f19c9f219 100644 > > --- a/drivers/gpu/drm/arm/malidp_hw.c > > +++ b/drivers/gpu/drm/arm/malidp_hw.c > > @@ -22,6 +22,13 @@ > > #include "malidp_drv.h" > > #include "malidp_hw.h" > > > > +enum { > > + MW_NOT_ENABLED = 0, /* SE writeback not enabled */ > > + MW_ONESHOT, /* SE in one-shot mode for writeback */ > > + MW_START, /* SE started writeback */ > > + MW_STOP, /* SE finished writeback */ > > +}; > > + > > static const struct malidp_format_id malidp500_de_formats[] = { > > /* fourcc, layers supporting the format, internal id */ > > { DRM_FORMAT_ARGB2101010, DE_VIDEO1 | DE_GRAPHICS1 | DE_GRAPHICS2, 0 }, > > @@ -368,6 +375,50 @@ static long malidp500_se_calc_mclk(struct malidp_hw_device *hwdev, > > return ret; > > } > > > > +static int malidp500_enable_memwrite(struct malidp_hw_device *hwdev, > > + dma_addr_t *addrs, s32 *pitches, > > + int num_planes, u16 w, u16 h, u32 fmt_id) > > +{ > > + u32 base = MALIDP500_SE_MEMWRITE_BASE; > > + u32 de_base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); > > + > > + /* enable the scaling engine block */ > > + malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC); > > + > > + hwdev->mw_state = MW_START; > > + > > + malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT); > > + switch (num_planes) { > > + case 2: > > + malidp_hw_write(hwdev, lower_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_LOW); > > + malidp_hw_write(hwdev, upper_32_bits(addrs[1]), base + MALIDP_MW_P2_PTR_HIGH); > > + malidp_hw_write(hwdev, pitches[1], base + MALIDP_MW_P2_STRIDE); > > + /* fall through */ > > + case 1: > > + malidp_hw_write(hwdev, lower_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_LOW); > > + malidp_hw_write(hwdev, upper_32_bits(addrs[0]), base + MALIDP_MW_P1_PTR_HIGH); > > + malidp_hw_write(hwdev, pitches[0], base + MALIDP_MW_P1_STRIDE); > > + break; > > + default: > > + WARN(1, "Invalid number of planes"); > > + } > > + > > + malidp_hw_write(hwdev, MALIDP_DE_H_ACTIVE(w) | MALIDP_DE_V_ACTIVE(h), > > + MALIDP500_SE_MEMWRITE_OUT_SIZE); > > + malidp_hw_setbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL); > > + > > + return 0; > > +} > > + > > +static void malidp500_disable_memwrite(struct malidp_hw_device *hwdev) > > +{ > > + u32 base = malidp_get_block_base(hwdev, MALIDP_DE_BLOCK); > > + if (hwdev->mw_state == MW_START) > > + hwdev->mw_state = MW_STOP; > > + malidp_hw_clearbits(hwdev, MALIDP_SE_MEMWRITE_EN, MALIDP500_SE_CONTROL); > > + malidp_hw_clearbits(hwdev, MALIDP_SCALE_ENGINE_EN, base + MALIDP_DE_DISPLAY_FUNC); > > +} > > + > > static int malidp550_query_hw(struct malidp_hw_device *hwdev) > > { > > u32 conf = malidp_hw_read(hwdev, MALIDP550_CONFIG_ID); > > @@ -598,6 +649,8 @@ static int malidp550_enable_memwrite(struct malidp_hw_device *hwdev, > > /* enable the scaling engine block */ > > malidp_hw_setbits(hwdev, MALIDP_SCALE_ENGINE_EN, de_base + MALIDP_DE_DISPLAY_FUNC); > > > > + hwdev->mw_state = MW_ONESHOT; > > + > > malidp_hw_write(hwdev, fmt_id, base + MALIDP_MW_FORMAT); > > switch (num_planes) { > > case 2: > > @@ -676,8 +729,9 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = { > > .vsync_irq = MALIDP500_DE_IRQ_VSYNC, > > }, > > .se_irq_map = { > > - .irq_mask = MALIDP500_SE_IRQ_CONF_MODE, > > - .vsync_irq = 0, > > + .irq_mask = MALIDP500_SE_IRQ_CONF_MODE | > > + MALIDP500_SE_IRQ_CONF_VALID, > > + .vsync_irq = MALIDP500_SE_IRQ_CONF_VALID, > > }, > > .dc_irq_map = { > > .irq_mask = MALIDP500_DE_IRQ_CONF_VALID, > > @@ -696,6 +750,8 @@ const struct malidp_hw malidp_device[MALIDP_MAX_DEVICES] = { > > .rotmem_required = malidp500_rotmem_required, > > .se_set_scaling_coeffs = malidp500_se_set_scaling_coeffs, > > .se_calc_mclk = malidp500_se_calc_mclk, > > + .enable_memwrite = malidp500_enable_memwrite, > > + .disable_memwrite = malidp500_disable_memwrite, > > .features = MALIDP_DEVICE_LV_HAS_3_STRIDES, > > }, > > [MALIDP_550] = { > > @@ -934,7 +990,21 @@ static irqreturn_t malidp_se_irq(int irq, void *arg) > > mask = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_MASKIRQ); > > status = malidp_hw_read(hwdev, hw->map.se_base + MALIDP_REG_STATUS); > > status &= mask; > > - /* ToDo: status decoding and firing up of VSYNC and page flip events */ > > + > > + if (status & se->vsync_irq) { > > + switch (hwdev->mw_state) { > > + case MW_STOP: > > + case MW_ONESHOT: > > + /* disable writeback after stop or oneshot */ > > + hwdev->mw_state = MW_NOT_ENABLED; > > + break; > > + case MW_START: > > + /* writeback started, need to emulate one-shot mode */ > > + hw->disable_memwrite(hwdev); > > + hw->set_config_valid(hwdev); > > Is this serialised with incoming atomic commits? We have to make sure > we don't set CVAL while a new scene configuration is in-progress. We are not serialised with the incoming atomic commit, and we probably should. I'll have a think on how to sort this one out. > > I also think the current state tracking won't work properly for two > subsequent frames using writeback. In enable_memwrite() you change the > mw_state, but the currently ongoing job is relying on it to correctly > signal. We probably need to either block incoming commits until the > writeback is finished, or we need to enhance the state tracking to > manage multiple commits. I will go back to the drawing boards and come up with something more solid. Best regards, Liviu > > Thanks, > -Brian > > > + break; > > + } > > + } > > > > malidp_hw_clear_irq(hwdev, MALIDP_SE_BLOCK, status); > > > > @@ -964,6 +1034,7 @@ int malidp_se_irq_init(struct drm_device *drm, int irq) > > return ret; > > } > > > > + hwdev->mw_state = MW_NOT_ENABLED; > > malidp_hw_enable_irq(hwdev, MALIDP_SE_BLOCK, > > hwdev->hw->map.se_irq_map.irq_mask); > > > > diff --git a/drivers/gpu/drm/arm/malidp_hw.h b/drivers/gpu/drm/arm/malidp_hw.h > > index a242e97cf6428..c479738b81af5 100644 > > --- a/drivers/gpu/drm/arm/malidp_hw.h > > +++ b/drivers/gpu/drm/arm/malidp_hw.h > > @@ -178,7 +178,7 @@ struct malidp_hw { > > long (*se_calc_mclk)(struct malidp_hw_device *hwdev, > > struct malidp_se_config *se_config, > > struct videomode *vm); > > - /** > > + /* > > * Enable writing to memory the content of the next frame > > * @param hwdev - malidp_hw_device structure containing the HW description > > * @param addrs - array of addresses for each plane > > @@ -232,6 +232,9 @@ struct malidp_hw_device { > > /* track the device PM state */ > > bool pm_suspended; > > > > + /* track the SE memory writeback state */ > > + u8 mw_state; > > + > > /* size of memory used for rotating layers, up to two banks available */ > > u32 rotation_memory[2]; > > }; > > diff --git a/drivers/gpu/drm/arm/malidp_regs.h b/drivers/gpu/drm/arm/malidp_regs.h > > index e2b2c496225e3..93b198f3af864 100644 > > --- a/drivers/gpu/drm/arm/malidp_regs.h > > +++ b/drivers/gpu/drm/arm/malidp_regs.h > > @@ -198,7 +198,8 @@ > > #define MALIDP500_DE_LG2_PTR_BASE 0x0031c > > #define MALIDP500_SE_BASE 0x00c00 > > #define MALIDP500_SE_CONTROL 0x00c0c > > -#define MALIDP500_SE_PTR_BASE 0x00e0c > > +#define MALIDP500_SE_MEMWRITE_OUT_SIZE 0x00c2c > > +#define MALIDP500_SE_MEMWRITE_BASE 0x00e00 > > #define MALIDP500_DC_IRQ_BASE 0x00f00 > > #define MALIDP500_CONFIG_VALID 0x00f00 > > #define MALIDP500_CONFIG_ID 0x00fd4 > > -- > > 2.17.0 > > -- ==================== | I would like to | | fix the world, | | but they're not | | giving me the | \ source code! / --------------- ¯\_(ツ)_/¯ _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel