Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 50 additions & 21 deletions drivers/gpu/drm/vc4/vc4_hvs.c
Original file line number Diff line number Diff line change
Expand Up @@ -621,7 +621,8 @@ static void vc4_hvs_install_dlist(struct vc4_dev *vc4, unsigned int channel)
hvs->fifo[channel].pending = false;

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

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

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

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

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

dispctrl &= ~SCALER_DISPCTRL_DSPEISLUR(channel);
dispctrl &= ~(vc4->hvs->hvs5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
SCALER_DISPCTRL_DSPEISLUR(channel));

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

dispctrl |= SCALER_DISPCTRL_DSPEISLUR(channel);
dispctrl |= vc4->hvs->hvs5 ? SCALER5_DISPCTRL_DSPEISLUR(channel) :
SCALER_DISPCTRL_DSPEISLUR(channel);

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

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

/* Clear every per-channel interrupt flag. */
HVS_WRITE(SCALER_DISPSTAT, SCALER_DISPSTAT_IRQMASK(0) |
SCALER_DISPSTAT_IRQMASK(1) |
SCALER_DISPSTAT_IRQMASK(2));
if (vc4->hvs->hvs5)
HVS_WRITE(SCALER_DISPSTAT, SCALER5_DISPSTAT_IRQMASK(0) |
SCALER5_DISPSTAT_IRQMASK(1) |
SCALER5_DISPSTAT_IRQMASK(2));
else
HVS_WRITE(SCALER_DISPSTAT, SCALER_DISPSTAT_IRQMASK(0) |
SCALER_DISPSTAT_IRQMASK(1) |
SCALER_DISPSTAT_IRQMASK(2));

return irqret;
}
Expand Down Expand Up @@ -979,19 +990,37 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
* be unused.
*/
dispctrl &= ~SCALER_DISPCTRL_DSP3_MUX_MASK;
dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
SCALER_DISPCTRL_SLVWREIRQ |
SCALER_DISPCTRL_SLVRDEIRQ |
SCALER_DISPCTRL_DSPEIEOF(0) |
SCALER_DISPCTRL_DSPEIEOF(1) |
SCALER_DISPCTRL_DSPEIEOF(2) |
SCALER_DISPCTRL_DSPEIEOLN(0) |
SCALER_DISPCTRL_DSPEIEOLN(1) |
SCALER_DISPCTRL_DSPEIEOLN(2) |
SCALER_DISPCTRL_DSPEISLUR(0) |
SCALER_DISPCTRL_DSPEISLUR(1) |
SCALER_DISPCTRL_DSPEISLUR(2) |
SCALER_DISPCTRL_SCLEIRQ);
if (!hvs->hvs5)
dispctrl &= ~(SCALER_DISPCTRL_DMAEIRQ |
SCALER_DISPCTRL_SLVWREIRQ |
SCALER_DISPCTRL_SLVRDEIRQ |
SCALER_DISPCTRL_DSPEIEOF(0) |
SCALER_DISPCTRL_DSPEIEOF(1) |
SCALER_DISPCTRL_DSPEIEOF(2) |
SCALER_DISPCTRL_DSPEIEOLN(0) |
SCALER_DISPCTRL_DSPEIEOLN(1) |
SCALER_DISPCTRL_DSPEIEOLN(2) |
SCALER_DISPCTRL_DSPEISLUR(0) |
SCALER_DISPCTRL_DSPEISLUR(1) |
SCALER_DISPCTRL_DSPEISLUR(2) |
SCALER_DISPCTRL_SCLEIRQ);
else
dispctrl &= ~(SCALER5_DISPCTRL_DMAEIRQ |
SCALER5_DISPCTRL_SLVEIRQ |
SCALER5_DISPCTRL_DSPEIEOF(0) |
SCALER5_DISPCTRL_DSPEIEOF(1) |
SCALER5_DISPCTRL_DSPEIEOF(2) |
SCALER5_DISPCTRL_DSPEIEOLN(0) |
SCALER5_DISPCTRL_DSPEIEOLN(1) |
SCALER5_DISPCTRL_DSPEIEOLN(2) |
SCALER5_DISPCTRL_DSPEISLUR(0) |
SCALER5_DISPCTRL_DSPEISLUR(1) |
SCALER5_DISPCTRL_DSPEISLUR(2) |
SCALER5_DISPCTRL_DSPVSTART(0) |
SCALER5_DISPCTRL_DSPVSTART(1) |
SCALER5_DISPCTRL_DSPVSTART(2) |
SCALER_DISPCTRL_SCLEIRQ);

dispctrl |= VC4_SET_FIELD(2, SCALER_DISPCTRL_DSP3_MUX);

HVS_WRITE(SCALER_DISPCTRL, dispctrl);
Expand Down
62 changes: 49 additions & 13 deletions drivers/gpu/drm/vc4/vc4_plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -665,6 +665,48 @@ static const u32 colorspace_coeffs[2][DRM_COLOR_ENCODING_MAX][3] = {
}
};

static u32 vc4_hvs4_get_alpha_blend_mode(struct drm_plane_state *state)
{
if (!state->fb->format->has_alpha)
return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_FIXED,
SCALER_POS2_ALPHA_MODE);

switch (state->pixel_blend_mode) {
case DRM_MODE_BLEND_PIXEL_NONE:
return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_FIXED,
SCALER_POS2_ALPHA_MODE);
default:
case DRM_MODE_BLEND_PREMULTI:
return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_PIPELINE,
SCALER_POS2_ALPHA_MODE) |
SCALER_POS2_ALPHA_PREMULT;
case DRM_MODE_BLEND_COVERAGE:
return VC4_SET_FIELD(SCALER_POS2_ALPHA_MODE_PIPELINE,
SCALER_POS2_ALPHA_MODE);
}
}

static u32 vc4_hvs5_get_alpha_blend_mode(struct drm_plane_state *state)
{
if (!state->fb->format->has_alpha)
return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_FIXED,
SCALER5_CTL2_ALPHA_MODE);

switch (state->pixel_blend_mode) {
case DRM_MODE_BLEND_PIXEL_NONE:
return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_FIXED,
SCALER5_CTL2_ALPHA_MODE);
default:
case DRM_MODE_BLEND_PREMULTI:
return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_PIPELINE,
SCALER5_CTL2_ALPHA_MODE) |
SCALER5_CTL2_ALPHA_PREMULT;
case DRM_MODE_BLEND_COVERAGE:
return VC4_SET_FIELD(SCALER5_CTL2_ALPHA_MODE_PIPELINE,
SCALER5_CTL2_ALPHA_MODE);
}
}

/* Writes out a full display list for an active plane to the plane's
* private dlist state.
*/
Expand Down Expand Up @@ -926,13 +968,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
/* Position Word 2: Source Image Size, Alpha */
vc4_state->pos2_offset = vc4_state->dlist_count;
vc4_dlist_write(vc4_state,
VC4_SET_FIELD(fb->format->has_alpha ?
SCALER_POS2_ALPHA_MODE_PIPELINE :
SCALER_POS2_ALPHA_MODE_FIXED,
SCALER_POS2_ALPHA_MODE) |
(mix_plane_alpha ? SCALER_POS2_ALPHA_MIX : 0) |
(fb->format->has_alpha ?
SCALER_POS2_ALPHA_PREMULT : 0) |
vc4_hvs4_get_alpha_blend_mode(state) |
VC4_SET_FIELD(vc4_state->src_w[0],
SCALER_POS2_WIDTH) |
VC4_SET_FIELD(vc4_state->src_h[0],
Expand Down Expand Up @@ -977,14 +1014,9 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
vc4_dlist_write(vc4_state,
VC4_SET_FIELD(state->alpha >> 4,
SCALER5_CTL2_ALPHA) |
(fb->format->has_alpha ?
SCALER5_CTL2_ALPHA_PREMULT : 0) |
vc4_hvs5_get_alpha_blend_mode(state) |
(mix_plane_alpha ?
SCALER5_CTL2_ALPHA_MIX : 0) |
VC4_SET_FIELD(fb->format->has_alpha ?
SCALER5_CTL2_ALPHA_MODE_PIPELINE :
SCALER5_CTL2_ALPHA_MODE_FIXED,
SCALER5_CTL2_ALPHA_MODE)
SCALER5_CTL2_ALPHA_MIX : 0)
);

/* Position Word 1: Scaled Image Dimensions. */
Expand Down Expand Up @@ -1489,6 +1521,10 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
drm_plane_helper_add(plane, &vc4_plane_helper_funcs);

drm_plane_create_alpha_property(plane);
drm_plane_create_blend_mode_property(plane,
BIT(DRM_MODE_BLEND_PIXEL_NONE) |
BIT(DRM_MODE_BLEND_PREMULTI) |
BIT(DRM_MODE_BLEND_COVERAGE));
drm_plane_create_rotation_property(plane, DRM_MODE_ROTATE_0,
DRM_MODE_ROTATE_0 |
DRM_MODE_ROTATE_180 |
Expand Down
21 changes: 21 additions & 0 deletions drivers/gpu/drm/vc4/vc4_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,23 @@
/* Enables interrupt generation on scaler profiler interrupt. */
# define SCALER_DISPCTRL_SCLEIRQ BIT(0)

/* Enables Display 0 short line and underrun contribution to
* SCALER_DISPSTAT_IRQDISP0. Note that short frame contributions are
* always enabled.
*/
# define SCALER5_DISPCTRL_DSPEISLUR(x) BIT(9 + ((x) * 4))
/* Enables Display 0 end-of-line-N contribution to
* SCALER_DISPSTAT_IRQDISP0
*/
# define SCALER5_DISPCTRL_DSPEIEOLN(x) BIT(8 + ((x) * 4))
/* Enables Display 0 EOF contribution to SCALER_DISPSTAT_IRQDISP0 */
# define SCALER5_DISPCTRL_DSPEIEOF(x) BIT(7 + ((x) * 4))
/* Enables Display 0 VSTART contribution to SCALER_DISPSTAT_IRQDISP0 */
# define SCALER5_DISPCTRL_DSPVSTART(x) BIT(6 + ((x) * 4))

# define SCALER5_DISPCTRL_SLVEIRQ BIT(5)
# define SCALER5_DISPCTRL_DMAEIRQ BIT(4)

#define SCALER_DISPSTAT 0x00000004
# define SCALER_DISPSTAT_RESP_MASK VC4_MASK(15, 14)
# define SCALER_DISPSTAT_RESP_SHIFT 14
Expand All @@ -253,6 +270,8 @@
# define SCALER_DISPSTAT_RESP_SLVERR 2
# define SCALER_DISPSTAT_RESP_DECERR 3

# define SCALER5_DISPSTAT_VSTART(x) BIT(14 + ((x) * 8))

# define SCALER_DISPSTAT_COBLOW(x) BIT(13 + ((x) * 8))
/* Set when the DISPEOLN line is done compositing. */
# define SCALER_DISPSTAT_EOLN(x) BIT(12 + ((x) * 8))
Expand All @@ -274,6 +293,8 @@
# define SCALER_DISPSTAT_IRQMASK(x) VC4_MASK(13 + ((x) * 8), \
8 + ((x) * 8))

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