Skip to content

Commit cc5cc1c

Browse files
6by9popcornmix
authored andcommitted
drm/vc4: Fix interrupt masking for HVS5.
The bits in both DISPCTRL and DISPSTAT have moved between hvs4 and hvs5, and the driver wasn't taking that into account. This lead to VSTART being enabled on channel 2, which nothing then acknowledged and lead to the parent interrupt being disabled. Signed-off-by: Dave Stevenson <[email protected]>
1 parent 97195cd commit cc5cc1c

File tree

2 files changed

+71
-21
lines changed

2 files changed

+71
-21
lines changed

drivers/gpu/drm/vc4/vc4_hvs.c

Lines changed: 50 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,8 @@ static void vc4_hvs_install_dlist(struct vc4_dev *vc4, unsigned int channel)
621621
hvs->fifo[channel].pending = false;
622622

623623
reg = HVS_READ(SCALER_DISPCTRL);
624-
reg &= ~BIT(7 + (channel * (vc4->hvs->hvs5 ? 4 : 2)));
624+
reg &= ~(vc4->hvs->hvs5 ? SCALER5_DISPCTRL_DSPEIEOF(channel) :
625+
SCALER_DISPCTRL_DSPEIEOF(channel));
625626
HVS_WRITE(SCALER_DISPCTRL, reg);
626627

627628
spin_unlock_irqrestore(&hvs->hw_dlist_lock, flags);
@@ -641,7 +642,9 @@ static void vc4_hvs_schedule_dlist_update(struct vc4_dev *vc4,
641642
}
642643

643644
HVS_WRITE(SCALER_DISPCTRL,
644-
HVS_READ(SCALER_DISPCTRL) | BIT(7 + (channel * (vc4->hvs->hvs5 ? 4 : 2))));
645+
HVS_READ(SCALER_DISPCTRL) |
646+
(vc4->hvs->hvs5 ? SCALER5_DISPCTRL_DSPEIEOF(channel) :
647+
SCALER_DISPCTRL_DSPEIEOF(channel)));
645648

646649
hvs->fifo[channel].pending = true;
647650

@@ -827,7 +830,8 @@ void vc4_hvs_mask_underrun(struct drm_device *dev, int channel)
827830
struct vc4_dev *vc4 = to_vc4_dev(dev);
828831
u32 dispctrl = HVS_READ(SCALER_DISPCTRL);
829832

830-
dispctrl &= ~SCALER_DISPCTRL_DSPEISLUR(channel);
833+
dispctrl &= ~(vc4->hvs->hvs5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
834+
SCALER_DISPCTRL_DSPEISLUR(channel));
831835

832836
HVS_WRITE(SCALER_DISPCTRL, dispctrl);
833837
}
@@ -837,7 +841,8 @@ void vc4_hvs_unmask_underrun(struct drm_device *dev, int channel)
837841
struct vc4_dev *vc4 = to_vc4_dev(dev);
838842
u32 dispctrl = HVS_READ(SCALER_DISPCTRL);
839843

840-
dispctrl |= SCALER_DISPCTRL_DSPEISLUR(channel);
844+
dispctrl |= vc4->hvs->hvs5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
845+
SCALER_DISPCTRL_DSPEISLUR(channel);
841846

842847
HVS_WRITE(SCALER_DISPSTAT,
843848
SCALER_DISPSTAT_EUFLOW(channel));
@@ -867,7 +872,8 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
867872
for (channel = 0; channel < SCALER_CHANNELS_COUNT; channel++) {
868873
/* Interrupt masking is not always honored, so check it here. */
869874
if (status & SCALER_DISPSTAT_EUFLOW(channel) &&
870-
control & SCALER_DISPCTRL_DSPEISLUR(channel)) {
875+
control & (vc4->hvs->hvs5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
876+
SCALER_DISPCTRL_DSPEISLUR(channel))) {
871877
vc4_hvs_mask_underrun(dev, channel);
872878
vc4_hvs_report_underrun(dev);
873879

@@ -881,9 +887,14 @@ static irqreturn_t vc4_hvs_irq_handler(int irq, void *data)
881887
}
882888

883889
/* Clear every per-channel interrupt flag. */
884-
HVS_WRITE(SCALER_DISPSTAT, SCALER_DISPSTAT_IRQMASK(0) |
885-
SCALER_DISPSTAT_IRQMASK(1) |
886-
SCALER_DISPSTAT_IRQMASK(2));
890+
if (vc4->hvs->hvs5)
891+
HVS_WRITE(SCALER_DISPSTAT, SCALER5_DISPSTAT_IRQMASK(0) |
892+
SCALER5_DISPSTAT_IRQMASK(1) |
893+
SCALER5_DISPSTAT_IRQMASK(2));
894+
else
895+
HVS_WRITE(SCALER_DISPSTAT, SCALER_DISPSTAT_IRQMASK(0) |
896+
SCALER_DISPSTAT_IRQMASK(1) |
897+
SCALER_DISPSTAT_IRQMASK(2));
887898

888899
return irqret;
889900
}
@@ -979,19 +990,37 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
979990
* be unused.
980991
*/
981992
dispctrl &= ~SCALER_DISPCTRL_DSP3_MUX_MASK;
982-
dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
983-
SCALER_DISPCTRL_SLVWREIRQ |
984-
SCALER_DISPCTRL_SLVRDEIRQ |
985-
SCALER_DISPCTRL_DSPEIEOF(0) |
986-
SCALER_DISPCTRL_DSPEIEOF(1) |
987-
SCALER_DISPCTRL_DSPEIEOF(2) |
988-
SCALER_DISPCTRL_DSPEIEOLN(0) |
989-
SCALER_DISPCTRL_DSPEIEOLN(1) |
990-
SCALER_DISPCTRL_DSPEIEOLN(2) |
991-
SCALER_DISPCTRL_DSPEISLUR(0) |
992-
SCALER_DISPCTRL_DSPEISLUR(1) |
993-
SCALER_DISPCTRL_DSPEISLUR(2) |
994-
SCALER_DISPCTRL_SCLEIRQ);
993+
if (!hvs->hvs5)
994+
dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
995+
SCALER_DISPCTRL_SLVWREIRQ |
996+
SCALER_DISPCTRL_SLVRDEIRQ |
997+
SCALER_DISPCTRL_DSPEIEOF(0) |
998+
SCALER_DISPCTRL_DSPEIEOF(1) |
999+
SCALER_DISPCTRL_DSPEIEOF(2) |
1000+
SCALER_DISPCTRL_DSPEIEOLN(0) |
1001+
SCALER_DISPCTRL_DSPEIEOLN(1) |
1002+
SCALER_DISPCTRL_DSPEIEOLN(2) |
1003+
SCALER_DISPCTRL_DSPEISLUR(0) |
1004+
SCALER_DISPCTRL_DSPEISLUR(1) |
1005+
SCALER_DISPCTRL_DSPEISLUR(2) |
1006+
SCALER_DISPCTRL_SCLEIRQ);
1007+
else
1008+
dispctrl &= ~(SCALER5_DISPCTRL_DMAEIRQ |
1009+
SCALER5_DISPCTRL_SLVEIRQ |
1010+
SCALER5_DISPCTRL_DSPEIEOF(0) |
1011+
SCALER5_DISPCTRL_DSPEIEOF(1) |
1012+
SCALER5_DISPCTRL_DSPEIEOF(2) |
1013+
SCALER5_DISPCTRL_DSPEIEOLN(0) |
1014+
SCALER5_DISPCTRL_DSPEIEOLN(1) |
1015+
SCALER5_DISPCTRL_DSPEIEOLN(2) |
1016+
SCALER5_DISPCTRL_DSPEISLUR(0) |
1017+
SCALER5_DISPCTRL_DSPEISLUR(1) |
1018+
SCALER5_DISPCTRL_DSPEISLUR(2) |
1019+
SCALER5_DISPCTRL_DSPVSTART(0) |
1020+
SCALER5_DISPCTRL_DSPVSTART(1) |
1021+
SCALER5_DISPCTRL_DSPVSTART(2) |
1022+
SCALER_DISPCTRL_SCLEIRQ);
1023+
9951024
dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);
9961025

9971026
HVS_WRITE(SCALER_DISPCTRL, dispctrl);

drivers/gpu/drm/vc4/vc4_regs.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,23 @@
245245
/* Enables interrupt generation on scaler profiler interrupt. */
246246
# define SCALER_DISPCTRL_SCLEIRQ BIT(0)
247247

248+
/* Enables Display 0 short line and underrun contribution to
249+
* SCALER_DISPSTAT_IRQDISP0. Note that short frame contributions are
250+
* always enabled.
251+
*/
252+
# define SCALER5_DISPCTRL_DSPEISLUR(x) BIT(9 + ((x) * 4))
253+
/* Enables Display 0 end-of-line-N contribution to
254+
* SCALER_DISPSTAT_IRQDISP0
255+
*/
256+
# define SCALER5_DISPCTRL_DSPEIEOLN(x) BIT(8 + ((x) * 4))
257+
/* Enables Display 0 EOF contribution to SCALER_DISPSTAT_IRQDISP0 */
258+
# define SCALER5_DISPCTRL_DSPEIEOF(x) BIT(7 + ((x) * 4))
259+
/* Enables Display 0 VSTART contribution to SCALER_DISPSTAT_IRQDISP0 */
260+
# define SCALER5_DISPCTRL_DSPVSTART(x) BIT(6 + ((x) * 4))
261+
262+
# define SCALER5_DISPCTRL_SLVEIRQ BIT(5)
263+
# define SCALER5_DISPCTRL_DMAEIRQ BIT(4)
264+
248265
#define SCALER_DISPSTAT 0x00000004
249266
# define SCALER_DISPSTAT_RESP_MASK VC4_MASK(15, 14)
250267
# define SCALER_DISPSTAT_RESP_SHIFT 14
@@ -253,6 +270,8 @@
253270
# define SCALER_DISPSTAT_RESP_SLVERR 2
254271
# define SCALER_DISPSTAT_RESP_DECERR 3
255272

273+
# define SCALER5_DISPSTAT_VSTART(x) BIT(14 + ((x) * 8))
274+
256275
# define SCALER_DISPSTAT_COBLOW(x) BIT(13 + ((x) * 8))
257276
/* Set when the DISPEOLN line is done compositing. */
258277
# define SCALER_DISPSTAT_EOLN(x) BIT(12 + ((x) * 8))
@@ -274,6 +293,8 @@
274293
# define SCALER_DISPSTAT_IRQMASK(x) VC4_MASK(13 + ((x) * 8), \
275294
8 + ((x) * 8))
276295

296+
# define SCALER5_DISPSTAT_IRQMASK(x) VC4_MASK(14 + ((x) * 8), \
297+
8 + ((x) * 8))
277298
/* Set on AXI invalid DMA ID error. */
278299
# define SCALER_DISPSTAT_DMA_ERROR BIT(7)
279300
/* Set on AXI slave read decode error */

0 commit comments

Comments
 (0)