Skip to content

Commit e84da23

Browse files
mripardpelwell
authored andcommitted
drm/vc4: hvs: Support BCM2712 HVS
The HVS found in the BCM2712, while having a similar role, is very different from the one found in the previous SoCs. Indeed, the register layout is fairly different, and the DLIST format is new as well. Let's introduce the needed functions to support the new HVS. Signed-off-by: Maxime Ripard <[email protected]>
1 parent 847ec49 commit e84da23

File tree

7 files changed

+1540
-83
lines changed

7 files changed

+1540
-83
lines changed

drivers/gpu/drm/vc4/vc4_crtc.c

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -82,13 +82,22 @@ static unsigned int
8282
vc4_crtc_get_cob_allocation(struct vc4_dev *vc4, unsigned int channel)
8383
{
8484
struct vc4_hvs *hvs = vc4->hvs;
85-
u32 dispbase = HVS_READ(SCALER_DISPBASEX(channel));
85+
u32 dispbase, top, base;
86+
8687
/* Top/base are supposed to be 4-pixel aligned, but the
8788
* Raspberry Pi firmware fills the low bits (which are
8889
* presumably ignored).
8990
*/
90-
u32 top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3;
91-
u32 base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3;
91+
92+
if (vc4->gen >= VC4_GEN_6) {
93+
dispbase = HVS_READ(SCALER6_DISPX_COB(channel));
94+
top = VC4_GET_FIELD(dispbase, SCALER6_DISPX_COB_TOP) & ~3;
95+
base = VC4_GET_FIELD(dispbase, SCALER6_DISPX_COB_BASE) & ~3;
96+
} else {
97+
dispbase = HVS_READ(SCALER_DISPBASEX(channel));
98+
top = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_TOP) & ~3;
99+
base = VC4_GET_FIELD(dispbase, SCALER_DISPBASEX_BASE) & ~3;
100+
}
92101

93102
return top - base + 4;
94103
}
@@ -121,7 +130,10 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
121130
* Read vertical scanline which is currently composed for our
122131
* pixelvalve by the HVS, and also the scaler status.
123132
*/
124-
val = HVS_READ(SCALER_DISPSTATX(channel));
133+
if (vc4->gen >= VC4_GEN_6)
134+
val = HVS_READ(SCALER6_DISPX_STATUS(channel));
135+
else
136+
val = HVS_READ(SCALER_DISPSTATX(channel));
125137

126138
/* Get optional system timestamp after query. */
127139
if (etime)
@@ -130,7 +142,12 @@ static bool vc4_crtc_get_scanout_position(struct drm_crtc *crtc,
130142
/* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */
131143

132144
/* Vertical position of hvs composed scanline. */
133-
*vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE);
145+
146+
if (vc4->gen >= VC4_GEN_6)
147+
*vpos = VC4_GET_FIELD(val, SCALER6_DISPX_STATUS_YLINE);
148+
else
149+
*vpos = VC4_GET_FIELD(val, SCALER_DISPSTATX_LINE);
150+
134151
*hpos = 0;
135152

136153
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
@@ -475,8 +492,10 @@ static void require_hvs_enabled(struct drm_device *dev)
475492
struct vc4_dev *vc4 = to_vc4_dev(dev);
476493
struct vc4_hvs *hvs = vc4->hvs;
477494

478-
WARN_ON_ONCE((HVS_READ(SCALER_DISPCTRL) & SCALER_DISPCTRL_ENABLE) !=
479-
SCALER_DISPCTRL_ENABLE);
495+
if (vc4->gen >= VC4_GEN_6)
496+
WARN_ON_ONCE(!(HVS_READ(SCALER6_CONTROL) & SCALER6_CONTROL_HVS_EN));
497+
else
498+
WARN_ON_ONCE(!(HVS_READ(SCALER_DISPCTRL) & SCALER_DISPCTRL_ENABLE));
480499
}
481500

482501
static int vc4_crtc_disable(struct drm_crtc *crtc,
@@ -804,14 +823,21 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
804823
struct drm_device *dev = crtc->dev;
805824
struct vc4_dev *vc4 = to_vc4_dev(dev);
806825
struct vc4_hvs *hvs = vc4->hvs;
826+
unsigned int current_dlist;
807827
u32 chan = vc4_crtc->current_hvs_channel;
808828
unsigned long flags;
809829

810830
spin_lock_irqsave(&dev->event_lock, flags);
811831
spin_lock(&vc4_crtc->irq_lock);
832+
833+
if (vc4->gen >= VC4_GEN_6)
834+
current_dlist = VC4_GET_FIELD(HVS_READ(SCALER6_DISPX_DL(chan)),
835+
SCALER6_DISPX_DL_LACT);
836+
else
837+
current_dlist = HVS_READ(SCALER_DISPLACTX(chan));
838+
812839
if (vc4_crtc->event &&
813-
(vc4_crtc->current_dlist == HVS_READ(SCALER_DISPLACTX(chan)) ||
814-
vc4_crtc->feeds_txp)) {
840+
(vc4_crtc->current_dlist == current_dlist || vc4_crtc->feeds_txp)) {
815841
drm_crtc_send_vblank_event(crtc, vc4_crtc->event);
816842
vc4_crtc->event = NULL;
817843
drm_crtc_vblank_put(crtc);
@@ -822,7 +848,8 @@ static void vc4_crtc_handle_page_flip(struct vc4_crtc *vc4_crtc)
822848
* the CRTC and encoder already reconfigured, leading to
823849
* underruns. This can be seen when reconfiguring the CRTC.
824850
*/
825-
vc4_hvs_unmask_underrun(hvs, chan);
851+
if (vc4->gen < VC4_GEN_6)
852+
vc4_hvs_unmask_underrun(hvs, chan);
826853
}
827854
spin_unlock(&vc4_crtc->irq_lock);
828855
spin_unlock_irqrestore(&dev->event_lock, flags);

drivers/gpu/drm/vc4/vc4_drv.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,7 @@ static const struct of_device_id vc4_dma_range_matches[] = {
277277
{ .compatible = "brcm,bcm2711-hvs" },
278278
{ .compatible = "brcm,bcm2835-hvs" },
279279
{ .compatible = "brcm,bcm2711-hvs" },
280+
{ .compatible = "brcm,bcm2712-hvs" },
280281
{ .compatible = "raspberrypi,rpi-firmware-kms" },
281282
{ .compatible = "brcm,bcm2835-v3d" },
282283
{ .compatible = "brcm,cygnus-v3d" },
@@ -308,8 +309,6 @@ static int vc4_drm_bind(struct device *dev)
308309
enum vc4_gen gen;
309310
int ret = 0;
310311

311-
dev->coherent_dma_mask = DMA_BIT_MASK(32);
312-
313312
if (of_device_is_compatible(dev->of_node, "brcm,bcm2712-vc6"))
314313
gen = VC4_GEN_6;
315314
else if (of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5"))
@@ -322,6 +321,11 @@ static int vc4_drm_bind(struct device *dev)
322321
else
323322
driver = &vc4_drm_driver;
324323

324+
if (gen >= VC4_GEN_6)
325+
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(36));
326+
else
327+
dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32));
328+
325329
node = of_find_matching_node_and_match(NULL, vc4_dma_range_matches,
326330
NULL);
327331
if (node) {

drivers/gpu/drm/vc4/vc4_drv.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,8 +345,10 @@ struct vc4_hvs {
345345
unsigned int dlist_mem_size;
346346

347347
struct clk *core_clk;
348+
struct clk *disp_clk;
348349

349350
struct {
351+
unsigned int desc;
350352
unsigned int enabled: 1;
351353
} eof_irq[HVS_NUM_CHANNELS];
352354

@@ -358,6 +360,11 @@ struct vc4_hvs {
358360
struct drm_mm dlist_mm;
359361
/* Memory manager for the LBM memory used by HVS scaling. */
360362
struct drm_mm lbm_mm;
363+
364+
/* Memory manager for the UPM memory used for prefetching. */
365+
struct drm_mm upm_mm;
366+
struct ida upm_handles;
367+
361368
spinlock_t mm_lock;
362369

363370
struct list_head stale_dlist_entries;
@@ -382,6 +389,8 @@ struct vc4_hvs {
382389
bool vc5_hdmi_enable_4096by2160;
383390
};
384391

392+
#define HVS_UBM_WORD_SIZE 256
393+
385394
struct vc4_hvs_state {
386395
struct drm_private_state base;
387396
unsigned long core_clock_rate;
@@ -456,6 +465,15 @@ struct vc4_plane_state {
456465
/* Our allocation in LBM for temporary storage during scaling. */
457466
struct drm_mm_node lbm;
458467

468+
/* Our allocation in UPM for prefetching. */
469+
struct drm_mm_node upm[DRM_FORMAT_MAX_PLANES];
470+
471+
/* The Unified Pre-Fetcher Handle */
472+
unsigned int upm_handle[DRM_FORMAT_MAX_PLANES];
473+
474+
/* Number of lines to pre-fetch */
475+
unsigned int upm_buffer_lines;
476+
459477
/* Set when the plane has per-pixel alpha content or does not cover
460478
* the entire screen. This is a hint to the CRTC that it might need
461479
* to enable background color fill.

0 commit comments

Comments
 (0)