Commit 1cbc91eb authored by Maxime Ripard's avatar Maxime Ripard

drm/vc4: Consolidate Hardware Revision Check

A new generation of controller has been introduced with the
BCM2711/RaspberryPi4. This generation needs a bunch of quirks, and over
time we've piled on a number of checks in most parts of the drivers.

All these checks are performed several times, and are not always
consistent. Let's create a single, global, variable to hold it and use
it everywhere.
Reviewed-by: default avatarMelissa Wen <mwen@igalia.com>
Signed-off-by: default avatarMaxime Ripard <maxime@cerno.tech>
Link: https://lore.kernel.org/r/20220610115149.964394-3-maxime@cerno.tech
parent cb468c7d
...@@ -256,7 +256,7 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format) ...@@ -256,7 +256,7 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format)
* Removing 1 from the FIFO full level however * Removing 1 from the FIFO full level however
* seems to completely remove that issue. * seems to completely remove that issue.
*/ */
if (!vc4->hvs->hvs5) if (!vc4->is_vc5)
return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX - 1; return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX - 1;
return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX; return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX;
...@@ -389,7 +389,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode ...@@ -389,7 +389,7 @@ static void vc4_crtc_config_pv(struct drm_crtc *crtc, struct drm_encoder *encode
if (is_dsi) if (is_dsi)
CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep); CRTC_WRITE(PV_HACT_ACT, mode->hdisplay * pixel_rep);
if (vc4->hvs->hvs5) if (vc4->is_vc5)
CRTC_WRITE(PV_MUX_CFG, CRTC_WRITE(PV_MUX_CFG,
VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP, VC4_SET_FIELD(PV_MUX_CFG_RGB_PIXEL_MUX_MODE_NO_SWAP,
PV_MUX_CFG_RGB_PIXEL_MUX_MODE)); PV_MUX_CFG_RGB_PIXEL_MUX_MODE));
...@@ -1149,7 +1149,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc, ...@@ -1149,7 +1149,7 @@ int vc4_crtc_init(struct drm_device *drm, struct vc4_crtc *vc4_crtc,
crtc_funcs, NULL); crtc_funcs, NULL);
drm_crtc_helper_add(crtc, crtc_helper_funcs); drm_crtc_helper_add(crtc, crtc_helper_funcs);
if (!vc4->hvs->hvs5) { if (!vc4->is_vc5) {
drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r)); drm_mode_crtc_set_gamma_size(crtc, ARRAY_SIZE(vc4_crtc->lut_r));
drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size); drm_crtc_enable_color_mgmt(crtc, 0, false, crtc->gamma_size);
......
...@@ -217,10 +217,13 @@ static int vc4_drm_bind(struct device *dev) ...@@ -217,10 +217,13 @@ static int vc4_drm_bind(struct device *dev)
struct vc4_dev *vc4; struct vc4_dev *vc4;
struct device_node *node; struct device_node *node;
struct drm_crtc *crtc; struct drm_crtc *crtc;
bool is_vc5;
int ret = 0; int ret = 0;
dev->coherent_dma_mask = DMA_BIT_MASK(32); dev->coherent_dma_mask = DMA_BIT_MASK(32);
is_vc5 = of_device_is_compatible(dev->of_node, "brcm,bcm2711-vc5");
/* If VC4 V3D is missing, don't advertise render nodes. */ /* If VC4 V3D is missing, don't advertise render nodes. */
node = of_find_matching_node_and_match(NULL, vc4_v3d_dt_match, NULL); node = of_find_matching_node_and_match(NULL, vc4_v3d_dt_match, NULL);
if (!node || !of_device_is_available(node)) if (!node || !of_device_is_available(node))
...@@ -230,6 +233,7 @@ static int vc4_drm_bind(struct device *dev) ...@@ -230,6 +233,7 @@ static int vc4_drm_bind(struct device *dev)
vc4 = devm_drm_dev_alloc(dev, &vc4_drm_driver, struct vc4_dev, base); vc4 = devm_drm_dev_alloc(dev, &vc4_drm_driver, struct vc4_dev, base);
if (IS_ERR(vc4)) if (IS_ERR(vc4))
return PTR_ERR(vc4); return PTR_ERR(vc4);
vc4->is_vc5 = is_vc5;
drm = &vc4->base; drm = &vc4->base;
platform_set_drvdata(pdev, drm); platform_set_drvdata(pdev, drm);
......
...@@ -74,6 +74,8 @@ struct vc4_perfmon { ...@@ -74,6 +74,8 @@ struct vc4_perfmon {
struct vc4_dev { struct vc4_dev {
struct drm_device base; struct drm_device base;
bool is_vc5;
unsigned int irq; unsigned int irq;
struct vc4_hvs *hvs; struct vc4_hvs *hvs;
...@@ -316,6 +318,7 @@ struct vc4_v3d { ...@@ -316,6 +318,7 @@ struct vc4_v3d {
}; };
struct vc4_hvs { struct vc4_hvs {
struct vc4_dev *vc4;
struct platform_device *pdev; struct platform_device *pdev;
void __iomem *regs; void __iomem *regs;
u32 __iomem *dlist; u32 __iomem *dlist;
...@@ -333,9 +336,6 @@ struct vc4_hvs { ...@@ -333,9 +336,6 @@ struct vc4_hvs {
struct drm_mm_node mitchell_netravali_filter; struct drm_mm_node mitchell_netravali_filter;
struct debugfs_regset32 regset; struct debugfs_regset32 regset;
/* HVS version 5 flag, therefore requires updated dlist structures */
bool hvs5;
}; };
struct vc4_plane { struct vc4_plane {
......
...@@ -220,10 +220,11 @@ u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo) ...@@ -220,10 +220,11 @@ u8 vc4_hvs_get_fifo_frame_count(struct vc4_hvs *hvs, unsigned int fifo)
int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output) int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output)
{ {
struct vc4_dev *vc4 = hvs->vc4;
u32 reg; u32 reg;
int ret; int ret;
if (!hvs->hvs5) if (!vc4->is_vc5)
return output; return output;
switch (output) { switch (output) {
...@@ -273,6 +274,7 @@ int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output) ...@@ -273,6 +274,7 @@ int vc4_hvs_get_fifo_from_output(struct vc4_hvs *hvs, unsigned int output)
static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,
struct drm_display_mode *mode, bool oneshot) struct drm_display_mode *mode, bool oneshot)
{ {
struct vc4_dev *vc4 = hvs->vc4;
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc); struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);
struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state); struct vc4_crtc_state *vc4_crtc_state = to_vc4_crtc_state(crtc->state);
unsigned int chan = vc4_crtc_state->assigned_channel; unsigned int chan = vc4_crtc_state->assigned_channel;
...@@ -291,7 +293,7 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, ...@@ -291,7 +293,7 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,
*/ */
dispctrl = SCALER_DISPCTRLX_ENABLE; dispctrl = SCALER_DISPCTRLX_ENABLE;
if (!hvs->hvs5) if (!vc4->is_vc5)
dispctrl |= VC4_SET_FIELD(mode->hdisplay, dispctrl |= VC4_SET_FIELD(mode->hdisplay,
SCALER_DISPCTRLX_WIDTH) | SCALER_DISPCTRLX_WIDTH) |
VC4_SET_FIELD(mode->vdisplay, VC4_SET_FIELD(mode->vdisplay,
...@@ -312,7 +314,7 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc, ...@@ -312,7 +314,7 @@ static int vc4_hvs_init_channel(struct vc4_hvs *hvs, struct drm_crtc *crtc,
HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx | HVS_WRITE(SCALER_DISPBKGNDX(chan), dispbkgndx |
SCALER_DISPBKGND_AUTOHS | SCALER_DISPBKGND_AUTOHS |
((!hvs->hvs5) ? SCALER_DISPBKGND_GAMMA : 0) | ((!vc4->is_vc5) ? SCALER_DISPBKGND_GAMMA : 0) |
(interlace ? SCALER_DISPBKGND_INTERLACE : 0)); (interlace ? SCALER_DISPBKGND_INTERLACE : 0));
/* Reload the LUT, since the SRAMs would have been disabled if /* Reload the LUT, since the SRAMs would have been disabled if
...@@ -617,11 +619,9 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) ...@@ -617,11 +619,9 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
if (!hvs) if (!hvs)
return -ENOMEM; return -ENOMEM;
hvs->vc4 = vc4;
hvs->pdev = pdev; hvs->pdev = pdev;
if (of_device_is_compatible(pdev->dev.of_node, "brcm,bcm2711-hvs"))
hvs->hvs5 = true;
hvs->regs = vc4_ioremap_regs(pdev, 0); hvs->regs = vc4_ioremap_regs(pdev, 0);
if (IS_ERR(hvs->regs)) if (IS_ERR(hvs->regs))
return PTR_ERR(hvs->regs); return PTR_ERR(hvs->regs);
...@@ -630,7 +630,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) ...@@ -630,7 +630,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
hvs->regset.regs = hvs_regs; hvs->regset.regs = hvs_regs;
hvs->regset.nregs = ARRAY_SIZE(hvs_regs); hvs->regset.nregs = ARRAY_SIZE(hvs_regs);
if (hvs->hvs5) { if (vc4->is_vc5) {
hvs->core_clk = devm_clk_get(&pdev->dev, NULL); hvs->core_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(hvs->core_clk)) { if (IS_ERR(hvs->core_clk)) {
dev_err(&pdev->dev, "Couldn't get core clock\n"); dev_err(&pdev->dev, "Couldn't get core clock\n");
...@@ -644,7 +644,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) ...@@ -644,7 +644,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
} }
} }
if (!hvs->hvs5) if (!vc4->is_vc5)
hvs->dlist = hvs->regs + SCALER_DLIST_START; hvs->dlist = hvs->regs + SCALER_DLIST_START;
else else
hvs->dlist = hvs->regs + SCALER5_DLIST_START; hvs->dlist = hvs->regs + SCALER5_DLIST_START;
...@@ -665,7 +665,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data) ...@@ -665,7 +665,7 @@ static int vc4_hvs_bind(struct device *dev, struct device *master, void *data)
* between planes when they don't overlap on the screen, but * between planes when they don't overlap on the screen, but
* for now we just allocate globally. * for now we just allocate globally.
*/ */
if (!hvs->hvs5) if (!vc4->is_vc5)
/* 48k words of 2x12-bit pixels */ /* 48k words of 2x12-bit pixels */
drm_mm_init(&hvs->lbm_mm, 0, 48 * 1024); drm_mm_init(&hvs->lbm_mm, 0, 48 * 1024);
else else
......
...@@ -393,7 +393,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -393,7 +393,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
old_hvs_state->fifo_state[channel].pending_commit = NULL; old_hvs_state->fifo_state[channel].pending_commit = NULL;
} }
if (vc4->hvs->hvs5) { if (vc4->is_vc5) {
unsigned long state_rate = max(old_hvs_state->core_clock_rate, unsigned long state_rate = max(old_hvs_state->core_clock_rate,
new_hvs_state->core_clock_rate); new_hvs_state->core_clock_rate);
unsigned long core_rate = max_t(unsigned long, unsigned long core_rate = max_t(unsigned long,
...@@ -412,7 +412,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -412,7 +412,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
vc4_ctm_commit(vc4, state); vc4_ctm_commit(vc4, state);
if (vc4->hvs->hvs5) if (vc4->is_vc5)
vc5_hvs_pv_muxing_commit(vc4, state); vc5_hvs_pv_muxing_commit(vc4, state);
else else
vc4_hvs_pv_muxing_commit(vc4, state); vc4_hvs_pv_muxing_commit(vc4, state);
...@@ -430,7 +430,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -430,7 +430,7 @@ static void vc4_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_cleanup_planes(dev, state); drm_atomic_helper_cleanup_planes(dev, state);
if (vc4->hvs->hvs5) { if (vc4->is_vc5) {
drm_dbg(dev, "Running the core clock at %lu Hz\n", drm_dbg(dev, "Running the core clock at %lu Hz\n",
new_hvs_state->core_clock_rate); new_hvs_state->core_clock_rate);
...@@ -1000,8 +1000,6 @@ static const struct drm_mode_config_funcs vc4_mode_funcs = { ...@@ -1000,8 +1000,6 @@ static const struct drm_mode_config_funcs vc4_mode_funcs = {
int vc4_kms_load(struct drm_device *dev) int vc4_kms_load(struct drm_device *dev)
{ {
struct vc4_dev *vc4 = to_vc4_dev(dev); struct vc4_dev *vc4 = to_vc4_dev(dev);
bool is_vc5 = of_device_is_compatible(dev->dev->of_node,
"brcm,bcm2711-vc5");
int ret; int ret;
/* /*
...@@ -1009,7 +1007,7 @@ int vc4_kms_load(struct drm_device *dev) ...@@ -1009,7 +1007,7 @@ int vc4_kms_load(struct drm_device *dev)
* the BCM2711, but the load tracker computations are used for * the BCM2711, but the load tracker computations are used for
* the core clock rate calculation. * the core clock rate calculation.
*/ */
if (!is_vc5) { if (!vc4->is_vc5) {
/* Start with the load tracker enabled. Can be /* Start with the load tracker enabled. Can be
* disabled through the debugfs load_tracker file. * disabled through the debugfs load_tracker file.
*/ */
...@@ -1025,7 +1023,7 @@ int vc4_kms_load(struct drm_device *dev) ...@@ -1025,7 +1023,7 @@ int vc4_kms_load(struct drm_device *dev)
return ret; return ret;
} }
if (is_vc5) { if (vc4->is_vc5) {
dev->mode_config.max_width = 7680; dev->mode_config.max_width = 7680;
dev->mode_config.max_height = 7680; dev->mode_config.max_height = 7680;
} else { } else {
......
...@@ -489,10 +489,10 @@ static u32 vc4_lbm_size(struct drm_plane_state *state) ...@@ -489,10 +489,10 @@ static u32 vc4_lbm_size(struct drm_plane_state *state)
} }
/* Align it to 64 or 128 (hvs5) bytes */ /* Align it to 64 or 128 (hvs5) bytes */
lbm = roundup(lbm, vc4->hvs->hvs5 ? 128 : 64); lbm = roundup(lbm, vc4->is_vc5 ? 128 : 64);
/* Each "word" of the LBM memory contains 2 or 4 (hvs5) pixels */ /* Each "word" of the LBM memory contains 2 or 4 (hvs5) pixels */
lbm /= vc4->hvs->hvs5 ? 4 : 2; lbm /= vc4->is_vc5 ? 4 : 2;
return lbm; return lbm;
} }
...@@ -608,7 +608,7 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state) ...@@ -608,7 +608,7 @@ static int vc4_plane_allocate_lbm(struct drm_plane_state *state)
ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm, ret = drm_mm_insert_node_generic(&vc4->hvs->lbm_mm,
&vc4_state->lbm, &vc4_state->lbm,
lbm_size, lbm_size,
vc4->hvs->hvs5 ? 64 : 32, vc4->is_vc5 ? 64 : 32,
0, 0); 0, 0);
spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags); spin_unlock_irqrestore(&vc4->hvs->mm_lock, irqflags);
...@@ -917,7 +917,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane, ...@@ -917,7 +917,7 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE && mix_plane_alpha = state->alpha != DRM_BLEND_ALPHA_OPAQUE &&
fb->format->has_alpha; fb->format->has_alpha;
if (!vc4->hvs->hvs5) { if (!vc4->is_vc5) {
/* Control word */ /* Control word */
vc4_dlist_write(vc4_state, vc4_dlist_write(vc4_state,
SCALER_CTL0_VALID | SCALER_CTL0_VALID |
...@@ -1457,14 +1457,13 @@ static const struct drm_plane_funcs vc4_plane_funcs = { ...@@ -1457,14 +1457,13 @@ static const struct drm_plane_funcs vc4_plane_funcs = {
struct drm_plane *vc4_plane_init(struct drm_device *dev, struct drm_plane *vc4_plane_init(struct drm_device *dev,
enum drm_plane_type type) enum drm_plane_type type)
{ {
struct vc4_dev *vc4 = to_vc4_dev(dev);
struct drm_plane *plane = NULL; struct drm_plane *plane = NULL;
struct vc4_plane *vc4_plane; struct vc4_plane *vc4_plane;
u32 formats[ARRAY_SIZE(hvs_formats)]; u32 formats[ARRAY_SIZE(hvs_formats)];
int num_formats = 0; int num_formats = 0;
int ret = 0; int ret = 0;
unsigned i; unsigned i;
bool hvs5 = of_device_is_compatible(dev->dev->of_node,
"brcm,bcm2711-vc5");
static const uint64_t modifiers[] = { static const uint64_t modifiers[] = {
DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED, DRM_FORMAT_MOD_BROADCOM_VC4_T_TILED,
DRM_FORMAT_MOD_BROADCOM_SAND128, DRM_FORMAT_MOD_BROADCOM_SAND128,
...@@ -1480,7 +1479,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev, ...@@ -1480,7 +1479,7 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
return ERR_PTR(-ENOMEM); return ERR_PTR(-ENOMEM);
for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) { for (i = 0; i < ARRAY_SIZE(hvs_formats); i++) {
if (!hvs_formats[i].hvs5_only || hvs5) { if (!hvs_formats[i].hvs5_only || vc4->is_vc5) {
formats[num_formats] = hvs_formats[i].drm; formats[num_formats] = hvs_formats[i].drm;
num_formats++; num_formats++;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment