From aa71584b323acf62f42844e4f1b4d472b7958a0b Mon Sep 17 00:00:00 2001 From: Manikandan Muralidharan Date: Wed, 24 Apr 2024 11:03:44 +0530 Subject: [PATCH 01/18] drm: atmel-hlcdc: add driver ops to differentiate HLCDC and XLCDC IP Add LCD IP specific ops in driver data to differentiate HLCDC and XLCDC code within the atmel-hlcdc driver files. XLCDC in SAM9X7 has different sets of registers and additional configuration bits when compared to previous HLCDC IP. Read/write operation on the controller register and functionality is now separated using the LCD IP specific ops. Signed-off-by: Manikandan Muralidharan Acked-by: Sam Ravnborg Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20240424053351.589830-2-manikandan.m@microchip.com --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 5 + drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h | 83 +++++--- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 189 +++++++++++------- 3 files changed, 183 insertions(+), 94 deletions(-) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index 84c54e8622d1..b09df821cbc0 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -58,6 +58,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9n12 = { .conflicting_output_formats = true, .nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9n12_layers), .layers = atmel_hlcdc_at91sam9n12_layers, + .ops = &atmel_hlcdc_ops, }; static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { @@ -151,6 +152,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9x5 = { .conflicting_output_formats = true, .nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9x5_layers), .layers = atmel_hlcdc_at91sam9x5_layers, + .ops = &atmel_hlcdc_ops, }; static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { @@ -269,6 +271,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d3 = { .conflicting_output_formats = true, .nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d3_layers), .layers = atmel_hlcdc_sama5d3_layers, + .ops = &atmel_hlcdc_ops, }; static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { @@ -364,6 +367,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sama5d4 = { .max_hpw = 0x3ff, .nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers), .layers = atmel_hlcdc_sama5d4_layers, + .ops = &atmel_hlcdc_ops, }; static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sam9x60_layers[] = { @@ -460,6 +464,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sam9x60 = { .fixed_clksrc = true, .nlayers = ARRAY_SIZE(atmel_hlcdc_sam9x60_layers), .layers = atmel_hlcdc_sam9x60_layers, + .ops = &atmel_hlcdc_ops, }; static const struct of_device_id atmel_hlcdc_of_match[] = { diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index 5b5c774e0edf..d0ecf0f58cce 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -288,6 +288,63 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *layer) return container_of(layer, struct atmel_hlcdc_plane, layer); } +/** + * struct atmel_hlcdc_dc - Atmel HLCDC Display Controller. + * @desc: HLCDC Display Controller description + * @dscrpool: DMA coherent pool used to allocate DMA descriptors + * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device + * @crtc: CRTC provided by the display controller + * @layers: active HLCDC layers + * @suspend: used to store the HLCDC state when entering suspend + * @suspend.imr: used to read/write LCDC Interrupt Mask Register + * @suspend.state: Atomic commit structure + */ +struct atmel_hlcdc_dc { + const struct atmel_hlcdc_dc_desc *desc; + struct dma_pool *dscrpool; + struct atmel_hlcdc *hlcdc; + struct drm_crtc *crtc; + struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS]; + struct { + u32 imr; + struct drm_atomic_state *state; + } suspend; +}; + +struct atmel_hlcdc_plane_state; + +/** + * struct atmel_lcdc_dc_ops - describes atmel_lcdc ops group + * to differentiate HLCDC and XLCDC IP code support + * @plane_setup_scaler: update the vertical and horizontal scaling factors + * @update_lcdc_buffers: update the each LCDC layers DMA registers + * @lcdc_atomic_disable: disable LCDC interrupts and layers + * @lcdc_update_general_settings: update each LCDC layers general + * configuration register + * @lcdc_atomic_update: enable the LCDC layers and interrupts + * @lcdc_csc_init: update the color space conversion co-efficient of + * High-end overlay register + * @lcdc_irq_dbg: to raise alert incase of interrupt overrun in any LCDC layer + */ +struct atmel_lcdc_dc_ops { + void (*plane_setup_scaler)(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state); + void (*lcdc_update_buffers)(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state, + u32 sr, int i); + void (*lcdc_atomic_disable)(struct atmel_hlcdc_plane *plane); + void (*lcdc_update_general_settings)(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state); + void (*lcdc_atomic_update)(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_dc *dc); + void (*lcdc_csc_init)(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc); + void (*lcdc_irq_dbg)(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc); +}; + +extern const struct atmel_lcdc_dc_ops atmel_hlcdc_ops; + /** * Atmel HLCDC Display Controller description structure. * @@ -306,6 +363,7 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *layer) * @fixed_clksrc: true if clock source is fixed * @layers: a layer description table describing available layers * @nlayers: layer description table size + * @ops: atmel lcdc dc ops */ struct atmel_hlcdc_dc_desc { int min_width; @@ -319,30 +377,7 @@ struct atmel_hlcdc_dc_desc { bool fixed_clksrc; const struct atmel_hlcdc_layer_desc *layers; int nlayers; -}; - -/** - * Atmel HLCDC Display Controller. - * - * @desc: HLCDC Display Controller description - * @dscrpool: DMA coherent pool used to allocate DMA descriptors - * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device - * @fbdev: framebuffer device attached to the Display Controller - * @crtc: CRTC provided by the display controller - * @planes: instantiated planes - * @layers: active HLCDC layers - * @suspend: used to store the HLCDC state when entering suspend - */ -struct atmel_hlcdc_dc { - const struct atmel_hlcdc_dc_desc *desc; - struct dma_pool *dscrpool; - struct atmel_hlcdc *hlcdc; - struct drm_crtc *crtc; - struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS]; - struct { - u32 imr; - struct drm_atomic_state *state; - } suspend; + const struct atmel_lcdc_dc_ops *ops; }; extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index daa508504f47..9db66df8b0e4 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -282,8 +282,9 @@ atmel_hlcdc_plane_scaler_set_phicoeff(struct atmel_hlcdc_plane *plane, coeff_tab[i]); } -static void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, - struct atmel_hlcdc_plane_state *state) +static +void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state) { const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; u32 xfactor, yfactor; @@ -335,6 +336,7 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane, struct atmel_hlcdc_plane_state *state) { const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; if (desc->layout.size) atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.size, @@ -352,12 +354,12 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane, ATMEL_HLCDC_LAYER_POS(state->crtc_x, state->crtc_y)); - atmel_hlcdc_plane_setup_scaler(plane, state); + dc->desc->ops->plane_setup_scaler(plane, state); } -static void -atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, - struct atmel_hlcdc_plane_state *state) +static +void atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state) { unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id; const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; @@ -437,10 +439,33 @@ static void atmel_hlcdc_plane_update_clut(struct atmel_hlcdc_plane *plane, } } +static void atmel_hlcdc_update_buffers(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state, + u32 sr, int i) +{ + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_HLCDC_LAYER_PLANE_HEAD(i), + state->dscrs[i]->self); + + if (sr & ATMEL_HLCDC_LAYER_EN) + return; + + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_HLCDC_LAYER_PLANE_ADDR(i), + state->dscrs[i]->addr); + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_HLCDC_LAYER_PLANE_CTRL(i), + state->dscrs[i]->ctrl); + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_HLCDC_LAYER_PLANE_NEXT(i), + state->dscrs[i]->self); +} + static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, - struct atmel_hlcdc_plane_state *state) + struct atmel_hlcdc_plane_state *state) { const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; struct drm_framebuffer *fb = state->base.fb; u32 sr; int i; @@ -452,21 +477,7 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, state->dscrs[i]->addr = gem->dma_addr + state->offsets[i]; - atmel_hlcdc_layer_write_reg(&plane->layer, - ATMEL_HLCDC_LAYER_PLANE_HEAD(i), - state->dscrs[i]->self); - - if (!(sr & ATMEL_HLCDC_LAYER_EN)) { - atmel_hlcdc_layer_write_reg(&plane->layer, - ATMEL_HLCDC_LAYER_PLANE_ADDR(i), - state->dscrs[i]->addr); - atmel_hlcdc_layer_write_reg(&plane->layer, - ATMEL_HLCDC_LAYER_PLANE_CTRL(i), - state->dscrs[i]->ctrl); - atmel_hlcdc_layer_write_reg(&plane->layer, - ATMEL_HLCDC_LAYER_PLANE_NEXT(i), - state->dscrs[i]->self); - } + dc->desc->ops->lcdc_update_buffers(plane, state, sr, i); if (desc->layout.xstride[i]) atmel_hlcdc_layer_write_cfg(&plane->layer, @@ -712,11 +723,8 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p, return 0; } -static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, - struct drm_atomic_state *state) +static void atmel_hlcdc_atomic_disable(struct atmel_hlcdc_plane *plane) { - struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); - /* Disable interrupts */ atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IDR, 0xffffffff); @@ -731,31 +739,20 @@ static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); } -static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, - struct drm_atomic_state *state) +static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, + struct drm_atomic_state *state) { - struct drm_plane_state *new_s = drm_atomic_get_new_plane_state(state, - p); struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); - struct atmel_hlcdc_plane_state *hstate = - drm_plane_state_to_atmel_hlcdc_plane_state(new_s); + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; + + dc->desc->ops->lcdc_atomic_disable(plane); +} + +static void atmel_hlcdc_atomic_update(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_dc *dc) +{ u32 sr; - if (!new_s->crtc || !new_s->fb) - return; - - if (!hstate->base.visible) { - atmel_hlcdc_plane_atomic_disable(p, state); - return; - } - - atmel_hlcdc_plane_update_pos_and_size(plane, hstate); - atmel_hlcdc_plane_update_general_settings(plane, hstate); - atmel_hlcdc_plane_update_format(plane, hstate); - atmel_hlcdc_plane_update_clut(plane, hstate); - atmel_hlcdc_plane_update_buffers(plane, hstate); - atmel_hlcdc_plane_update_disc_area(plane, hstate); - /* Enable the overrun interrupts. */ atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER, ATMEL_HLCDC_LAYER_OVR_IRQ(0) | @@ -765,14 +762,63 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, /* Apply the new config at the next SOF event. */ sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER, - ATMEL_HLCDC_LAYER_UPDATE | - (sr & ATMEL_HLCDC_LAYER_EN ? - ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN)); + ATMEL_HLCDC_LAYER_UPDATE | + (sr & ATMEL_HLCDC_LAYER_EN ? + ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN)); +} + +static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, + struct drm_atomic_state *state) +{ + struct drm_plane_state *new_s = drm_atomic_get_new_plane_state(state, + p); + struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p); + struct atmel_hlcdc_plane_state *hstate = + drm_plane_state_to_atmel_hlcdc_plane_state(new_s); + struct atmel_hlcdc_dc *dc = p->dev->dev_private; + + if (!new_s->crtc || !new_s->fb) + return; + + if (!hstate->base.visible) { + atmel_hlcdc_plane_atomic_disable(p, state); + return; + } + + atmel_hlcdc_plane_update_pos_and_size(plane, hstate); + dc->desc->ops->lcdc_update_general_settings(plane, hstate); + atmel_hlcdc_plane_update_format(plane, hstate); + atmel_hlcdc_plane_update_clut(plane, hstate); + atmel_hlcdc_plane_update_buffers(plane, hstate); + atmel_hlcdc_plane_update_disc_area(plane, hstate); + + dc->desc->ops->lcdc_atomic_update(plane, dc); +} + +static void atmel_hlcdc_csc_init(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc) +{ + /* + * TODO: declare a "yuv-to-rgb-conv-factors" property to let + * userspace modify these factors (using a BLOB property ?). + */ + static const u32 hlcdc_csc_coeffs[] = { + 0x4c900091, + 0x7a5f5090, + 0x40040890 + }; + + for (int i = 0; i < ARRAY_SIZE(hlcdc_csc_coeffs); i++) { + atmel_hlcdc_layer_write_cfg(&plane->layer, + desc->layout.csc + i, + hlcdc_csc_coeffs[i]); + } } static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane) { const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; if (desc->type == ATMEL_HLCDC_OVERLAY_LAYER || desc->type == ATMEL_HLCDC_CURSOR_LAYER) { @@ -796,31 +842,16 @@ static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane) return ret; } - if (desc->layout.csc) { - /* - * TODO: decare a "yuv-to-rgb-conv-factors" property to let - * userspace modify these factors (using a BLOB property ?). - */ - atmel_hlcdc_layer_write_cfg(&plane->layer, - desc->layout.csc, - 0x4c900091); - atmel_hlcdc_layer_write_cfg(&plane->layer, - desc->layout.csc + 1, - 0x7a5f5090); - atmel_hlcdc_layer_write_cfg(&plane->layer, - desc->layout.csc + 2, - 0x40040890); - } + if (desc->layout.csc) + dc->desc->ops->lcdc_csc_init(plane, desc); return 0; } -void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane) +static void atmel_hlcdc_irq_dbg(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc) { - const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; - u32 isr; - - isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); + u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); /* * There's not much we can do in case of overrun except informing @@ -834,6 +865,24 @@ void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane) desc->name); } +void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane) +{ + const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private; + + dc->desc->ops->lcdc_irq_dbg(plane, desc); +} + +const struct atmel_lcdc_dc_ops atmel_hlcdc_ops = { + .plane_setup_scaler = atmel_hlcdc_plane_setup_scaler, + .lcdc_update_buffers = atmel_hlcdc_update_buffers, + .lcdc_atomic_disable = atmel_hlcdc_atomic_disable, + .lcdc_update_general_settings = atmel_hlcdc_plane_update_general_settings, + .lcdc_atomic_update = atmel_hlcdc_atomic_update, + .lcdc_csc_init = atmel_hlcdc_csc_init, + .lcdc_irq_dbg = atmel_hlcdc_irq_dbg, +}; + static const struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = { .atomic_check = atmel_hlcdc_plane_atomic_check, .atomic_update = atmel_hlcdc_plane_atomic_update, From 73fc975318e0ab3385c5b3372c7b296ae58c8d6b Mon Sep 17 00:00:00 2001 From: Durai Manickam KR Date: Wed, 24 Apr 2024 11:03:45 +0530 Subject: [PATCH 02/18] drm: atmel-hlcdc: Define XLCDC specific registers The register address of the XLCDC IP used in SAM9X7 SoC family are different from the previous HLCDC. Defining those address space with valid macros. Signed-off-by: Durai Manickam KR [manikandan.m@microchip.com: Remove unused macro definitions] Signed-off-by: Manikandan Muralidharan Acked-by: Lee Jones Acked-by: Sam Ravnborg Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20240424053351.589830-3-manikandan.m@microchip.com --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h | 42 ++++++++++++++++++++ include/linux/mfd/atmel-hlcdc.h | 10 +++++ 2 files changed, 52 insertions(+) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index d0ecf0f58cce..c32e5c8809d7 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -15,6 +15,7 @@ #include +/* LCD controller common registers */ #define ATMEL_HLCDC_LAYER_CHER 0x0 #define ATMEL_HLCDC_LAYER_CHDR 0x4 #define ATMEL_HLCDC_LAYER_CHSR 0x8 @@ -128,6 +129,47 @@ #define ATMEL_HLCDC_MAX_LAYERS 6 +/* XLCDC controller specific registers */ +#define ATMEL_XLCDC_LAYER_ENR 0x10 +#define ATMEL_XLCDC_LAYER_EN BIT(0) + +#define ATMEL_XLCDC_LAYER_IER 0x0 +#define ATMEL_XLCDC_LAYER_IDR 0x4 +#define ATMEL_XLCDC_LAYER_ISR 0xc +#define ATMEL_XLCDC_LAYER_OVR_IRQ(p) BIT(2 + (8 * (p))) + +#define ATMEL_XLCDC_LAYER_PLANE_ADDR(p) (((p) * 0x4) + 0x18) + +#define ATMEL_XLCDC_LAYER_DMA_CFG 0 + +#define ATMEL_XLCDC_LAYER_DMA BIT(0) +#define ATMEL_XLCDC_LAYER_REP BIT(1) +#define ATMEL_XLCDC_LAYER_DISCEN BIT(4) + +#define ATMEL_XLCDC_LAYER_SFACTC_A0_MULT_AS (4 << 6) +#define ATMEL_XLCDC_LAYER_SFACTA_ONE BIT(9) +#define ATMEL_XLCDC_LAYER_DFACTC_M_A0_MULT_AS (6 << 11) +#define ATMEL_XLCDC_LAYER_DFACTA_ONE BIT(14) + +#define ATMEL_XLCDC_LAYER_A0_SHIFT 16 +#define ATMEL_XLCDC_LAYER_A0(x) \ + ((x) << ATMEL_XLCDC_LAYER_A0_SHIFT) + +#define ATMEL_XLCDC_LAYER_VSCALER_LUMA_ENABLE BIT(0) +#define ATMEL_XLCDC_LAYER_VSCALER_CHROMA_ENABLE BIT(1) +#define ATMEL_XLCDC_LAYER_HSCALER_LUMA_ENABLE BIT(4) +#define ATMEL_XLCDC_LAYER_HSCALER_CHROMA_ENABLE BIT(5) + +#define ATMEL_XLCDC_LAYER_VXSYCFG_ONE BIT(0) +#define ATMEL_XLCDC_LAYER_VXSYTAP2_ENABLE BIT(4) +#define ATMEL_XLCDC_LAYER_VXSCCFG_ONE BIT(16) +#define ATMEL_XLCDC_LAYER_VXSCTAP2_ENABLE BIT(20) + +#define ATMEL_XLCDC_LAYER_HXSYCFG_ONE BIT(0) +#define ATMEL_XLCDC_LAYER_HXSYTAP2_ENABLE BIT(4) +#define ATMEL_XLCDC_LAYER_HXSCCFG_ONE BIT(16) +#define ATMEL_XLCDC_LAYER_HXSCTAP2_ENABLE BIT(20) + /** * Atmel HLCDC Layer registers layout structure * diff --git a/include/linux/mfd/atmel-hlcdc.h b/include/linux/mfd/atmel-hlcdc.h index a186119a49b5..80d675a03b39 100644 --- a/include/linux/mfd/atmel-hlcdc.h +++ b/include/linux/mfd/atmel-hlcdc.h @@ -22,6 +22,8 @@ #define ATMEL_HLCDC_DITHER BIT(6) #define ATMEL_HLCDC_DISPDLY BIT(7) #define ATMEL_HLCDC_MODE_MASK GENMASK(9, 8) +#define ATMEL_XLCDC_MODE_MASK GENMASK(10, 8) +#define ATMEL_XLCDC_DPI BIT(11) #define ATMEL_HLCDC_PP BIT(10) #define ATMEL_HLCDC_VSPSU BIT(12) #define ATMEL_HLCDC_VSPHO BIT(13) @@ -34,6 +36,12 @@ #define ATMEL_HLCDC_IDR 0x30 #define ATMEL_HLCDC_IMR 0x34 #define ATMEL_HLCDC_ISR 0x38 +#define ATMEL_XLCDC_ATTRE 0x3c + +#define ATMEL_XLCDC_BASE_UPDATE BIT(0) +#define ATMEL_XLCDC_OVR1_UPDATE BIT(1) +#define ATMEL_XLCDC_OVR3_UPDATE BIT(2) +#define ATMEL_XLCDC_HEO_UPDATE BIT(3) #define ATMEL_HLCDC_CLKPOL BIT(0) #define ATMEL_HLCDC_CLKSEL BIT(2) @@ -48,6 +56,8 @@ #define ATMEL_HLCDC_DISP BIT(2) #define ATMEL_HLCDC_PWM BIT(3) #define ATMEL_HLCDC_SIP BIT(4) +#define ATMEL_XLCDC_SD BIT(5) +#define ATMEL_XLCDC_CM BIT(6) #define ATMEL_HLCDC_SOF BIT(0) #define ATMEL_HLCDC_SYNCDIS BIT(1) From f5a5f04b6019b9b61a1d744ea80376c1365218af Mon Sep 17 00:00:00 2001 From: Manikandan Muralidharan Date: Wed, 24 Apr 2024 11:03:46 +0530 Subject: [PATCH 03/18] drm: atmel_hlcdc: replace regmap_read with regmap_read_poll_timeout Replace regmap_read with regmap_read_poll_timeout to neatly handle retries Signed-off-by: Manikandan Muralidharan Acked-by: Dharma Balasubiramani Reviewed-by: Hari Prasath Gujulan Elango Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20240424053351.589830-4-manikandan.m@microchip.com --- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 44 +++++++++++-------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index cc5cf4c2faf7..b229692a27ca 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -203,19 +203,22 @@ static void atmel_hlcdc_crtc_atomic_disable(struct drm_crtc *c, pm_runtime_get_sync(dev->dev); regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - (status & ATMEL_HLCDC_DISP)) - cpu_relax(); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + !(status & ATMEL_HLCDC_DISP), + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register DISPSTS timeout\n"); regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - (status & ATMEL_HLCDC_SYNC)) - cpu_relax(); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + !(status & ATMEL_HLCDC_SYNC), + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register LCDSTS timeout\n"); regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - (status & ATMEL_HLCDC_PIXEL_CLK)) - cpu_relax(); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + !(status & ATMEL_HLCDC_PIXEL_CLK), + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register CLKSTS timeout\n"); clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); pinctrl_pm_select_sleep_state(dev->dev); @@ -241,20 +244,23 @@ static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c, clk_prepare_enable(crtc->dc->hlcdc->sys_clk); regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - !(status & ATMEL_HLCDC_PIXEL_CLK)) - cpu_relax(); - + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + status & ATMEL_HLCDC_PIXEL_CLK, + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register CLKSTS timeout\n"); regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - !(status & ATMEL_HLCDC_SYNC)) - cpu_relax(); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + status & ATMEL_HLCDC_SYNC, + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register LCDSTS timeout\n"); regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP); - while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && - !(status & ATMEL_HLCDC_DISP)) - cpu_relax(); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + status & ATMEL_HLCDC_DISP, + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register DISPSTS timeout\n"); + pm_runtime_put_sync(dev->dev); From d498771b0b830140a70cb8118ee0ee522be94f39 Mon Sep 17 00:00:00 2001 From: Manikandan Muralidharan Date: Wed, 24 Apr 2024 11:03:47 +0530 Subject: [PATCH 04/18] drm: atmel_hlcdc: Add support for XLCDC using IP specific driver ops Add XLCDC specific driver ops and is_xlcdc flag to separate the functionality and to access the controller registers. HEO scaling, window resampling, Alpha blending, YUV-to-RGB conversion in XLCDC is derived and handled using additional configuration bits and registers. Writing one to the Enable fields of each layer in LCD_ATTRE is required to reflect the values set in Configuration, FBA, Enable registers of each layer. Signed-off-by: Manikandan Muralidharan Co-developed-by: Hari Prasath Gujulan Elango Signed-off-by: Hari Prasath Gujulan Elango Co-developed-by: Durai Manickam KR Signed-off-by: Durai Manickam KR Acked-by: Sam Ravnborg Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20240424053351.589830-5-manikandan.m@microchip.com --- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 37 +++- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h | 3 + .../gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 182 +++++++++++++++++- 3 files changed, 217 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index b229692a27ca..98a98b5fca85 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -164,11 +164,13 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state); cfg = state->output_mode << 8; - if (adj->flags & DRM_MODE_FLAG_NVSYNC) - cfg |= ATMEL_HLCDC_VSPOL; + if (!crtc->dc->desc->is_xlcdc) { + if (adj->flags & DRM_MODE_FLAG_NVSYNC) + cfg |= ATMEL_HLCDC_VSPOL; - if (adj->flags & DRM_MODE_FLAG_NHSYNC) - cfg |= ATMEL_HLCDC_HSPOL; + if (adj->flags & DRM_MODE_FLAG_NHSYNC) + cfg |= ATMEL_HLCDC_HSPOL; + } regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5), ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL | @@ -202,6 +204,20 @@ static void atmel_hlcdc_crtc_atomic_disable(struct drm_crtc *c, pm_runtime_get_sync(dev->dev); + if (crtc->dc->desc->is_xlcdc) { + regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_XLCDC_CM); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + !(status & ATMEL_XLCDC_CM), + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register CMSTS timeout\n"); + + regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_XLCDC_SD); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + status & ATMEL_XLCDC_SD, + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register SDSTS timeout\n"); + } + regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP); if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, !(status & ATMEL_HLCDC_DISP), @@ -261,6 +277,19 @@ static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c, 10, 1000)) dev_warn(dev->dev, "Atmel LCDC status register DISPSTS timeout\n"); + if (crtc->dc->desc->is_xlcdc) { + regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_XLCDC_CM); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + status & ATMEL_XLCDC_CM, + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register CMSTS timeout\n"); + + regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_XLCDC_SD); + if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status, + !(status & ATMEL_XLCDC_SD), + 10, 1000)) + dev_warn(dev->dev, "Atmel LCDC status register SDSTS timeout\n"); + } pm_runtime_put_sync(dev->dev); diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index c32e5c8809d7..1153d402f810 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -386,6 +386,7 @@ struct atmel_lcdc_dc_ops { }; extern const struct atmel_lcdc_dc_ops atmel_hlcdc_ops; +extern const struct atmel_lcdc_dc_ops atmel_xlcdc_ops; /** * Atmel HLCDC Display Controller description structure. @@ -403,6 +404,7 @@ extern const struct atmel_lcdc_dc_ops atmel_hlcdc_ops; * @conflicting_output_formats: true if RGBXXX output formats conflict with * each other. * @fixed_clksrc: true if clock source is fixed + * @is_xlcdc: true if XLCDC IP is supported * @layers: a layer description table describing available layers * @nlayers: layer description table size * @ops: atmel lcdc dc ops @@ -417,6 +419,7 @@ struct atmel_hlcdc_dc_desc { int max_hpw; bool conflicting_output_formats; bool fixed_clksrc; + bool is_xlcdc; const struct atmel_hlcdc_layer_desc *layers; int nlayers; const struct atmel_lcdc_dc_ops *ops; diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index 9db66df8b0e4..f60367dc6d9d 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -331,6 +331,55 @@ void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, yfactor)); } +static +void atmel_xlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state) +{ + const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + u32 xfactor, yfactor; + + if (!desc->layout.scaler_config) + return; + + if (state->crtc_w == state->src_w && state->crtc_h == state->src_h) { + atmel_hlcdc_layer_write_cfg(&plane->layer, + desc->layout.scaler_config, 0); + return; + } + + /* xfactor = round[(2^20 * XMEMSIZE)/XSIZE)] */ + xfactor = (u32)(((1 << 20) * state->src_w) / state->crtc_w); + + /* yfactor = round[(2^20 * YMEMSIZE)/YSIZE)] */ + yfactor = (u32)(((1 << 20) * state->src_h) / state->crtc_h); + + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config, + ATMEL_XLCDC_LAYER_VSCALER_LUMA_ENABLE | + ATMEL_XLCDC_LAYER_VSCALER_CHROMA_ENABLE | + ATMEL_XLCDC_LAYER_HSCALER_LUMA_ENABLE | + ATMEL_XLCDC_LAYER_HSCALER_CHROMA_ENABLE); + + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 1, + yfactor); + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 3, + xfactor); + + /* + * With YCbCr 4:2:2 and YCbYcr 4:2:0 window resampling, configuration + * register LCDC_HEOCFG25.VXSCFACT and LCDC_HEOCFG27.HXSCFACT is half + * the value of yfactor and xfactor. + */ + if (state->base.fb->format->format == DRM_FORMAT_YUV420) { + yfactor /= 2; + xfactor /= 2; + } + + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 2, + yfactor); + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.scaler_config + 4, + xfactor); +} + static void atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane, struct atmel_hlcdc_plane_state *state) @@ -395,6 +444,40 @@ void atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, cfg); } +static +void atmel_xlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state) +{ + const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; + const struct drm_format_info *format = state->base.fb->format; + unsigned int cfg; + + atmel_hlcdc_layer_write_cfg(&plane->layer, ATMEL_XLCDC_LAYER_DMA_CFG, + ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id); + + cfg = ATMEL_XLCDC_LAYER_DMA | ATMEL_XLCDC_LAYER_REP; + + if (plane->base.type != DRM_PLANE_TYPE_PRIMARY) { + /* + * Alpha Blending bits specific to SAM9X7 SoC + */ + cfg |= ATMEL_XLCDC_LAYER_SFACTC_A0_MULT_AS | + ATMEL_XLCDC_LAYER_SFACTA_ONE | + ATMEL_XLCDC_LAYER_DFACTC_M_A0_MULT_AS | + ATMEL_XLCDC_LAYER_DFACTA_ONE; + if (format->has_alpha) + cfg |= ATMEL_XLCDC_LAYER_A0(0xff); + else + cfg |= ATMEL_XLCDC_LAYER_A0(state->base.alpha); + } + + if (state->disc_h && state->disc_w) + cfg |= ATMEL_XLCDC_LAYER_DISCEN; + + atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.general_config, + cfg); +} + static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane, struct atmel_hlcdc_plane_state *state) { @@ -461,6 +544,15 @@ static void atmel_hlcdc_update_buffers(struct atmel_hlcdc_plane *plane, state->dscrs[i]->self); } +static void atmel_xlcdc_update_buffers(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_plane_state *state, + u32 sr, int i) +{ + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_XLCDC_LAYER_PLANE_ADDR(i), + state->dscrs[i]->addr); +} + static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, struct atmel_hlcdc_plane_state *state) { @@ -470,7 +562,8 @@ static void atmel_hlcdc_plane_update_buffers(struct atmel_hlcdc_plane *plane, u32 sr; int i; - sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); + if (!dc->desc->is_xlcdc) + sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); for (i = 0; i < state->nplanes; i++) { struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i); @@ -739,6 +832,20 @@ static void atmel_hlcdc_atomic_disable(struct atmel_hlcdc_plane *plane) atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); } +static void atmel_xlcdc_atomic_disable(struct atmel_hlcdc_plane *plane) +{ + /* Disable interrupts */ + atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_IDR, + 0xffffffff); + + /* Disable the layer */ + atmel_hlcdc_layer_write_reg(&plane->layer, + ATMEL_XLCDC_LAYER_ENR, 0); + + /* Clear all pending interrupts */ + atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_XLCDC_LAYER_ISR); +} + static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, struct drm_atomic_state *state) { @@ -767,6 +874,28 @@ static void atmel_hlcdc_atomic_update(struct atmel_hlcdc_plane *plane, ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN)); } +static void atmel_xlcdc_atomic_update(struct atmel_hlcdc_plane *plane, + struct atmel_hlcdc_dc *dc) +{ + /* Enable the overrun interrupts. */ + atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_IER, + ATMEL_XLCDC_LAYER_OVR_IRQ(0) | + ATMEL_XLCDC_LAYER_OVR_IRQ(1) | + ATMEL_XLCDC_LAYER_OVR_IRQ(2)); + + atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_XLCDC_LAYER_ENR, + ATMEL_XLCDC_LAYER_EN); + + /* + * Updating XLCDC_xxxCFGx, XLCDC_xxxFBA and XLCDC_xxxEN, + * (where xxx indicates each layer) requires writing one to the + * Update Attribute field for each layer in LCDC_ATTRE register for SAM9X7. + */ + regmap_write(dc->hlcdc->regmap, ATMEL_XLCDC_ATTRE, ATMEL_XLCDC_BASE_UPDATE | + ATMEL_XLCDC_OVR1_UPDATE | ATMEL_XLCDC_OVR3_UPDATE | + ATMEL_XLCDC_HEO_UPDATE); +} + static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, struct drm_atomic_state *state) { @@ -815,6 +944,30 @@ static void atmel_hlcdc_csc_init(struct atmel_hlcdc_plane *plane, } } +static void atmel_xlcdc_csc_init(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc) +{ + /* + * yuv-to-rgb-conv-factors are now defined from LCDC_HEOCFG16 to + * LCDC_HEOCFG21 registers in SAM9X7. + */ + static const u32 xlcdc_csc_coeffs[] = { + 0x00000488, + 0x00000648, + 0x1EA00480, + 0x00001D28, + 0x08100480, + 0x00000000, + 0x00000007 + }; + + for (int i = 0; i < ARRAY_SIZE(xlcdc_csc_coeffs); i++) { + atmel_hlcdc_layer_write_cfg(&plane->layer, + desc->layout.csc + i, + xlcdc_csc_coeffs[i]); + } +} + static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane) { const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; @@ -865,6 +1018,23 @@ static void atmel_hlcdc_irq_dbg(struct atmel_hlcdc_plane *plane, desc->name); } +static void atmel_xlcdc_irq_dbg(struct atmel_hlcdc_plane *plane, + const struct atmel_hlcdc_layer_desc *desc) +{ + u32 isr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_XLCDC_LAYER_ISR); + + /* + * There's not much we can do in case of overrun except informing + * the user. However, we are in interrupt context here, hence the + * use of dev_dbg(). + */ + if (isr & + (ATMEL_XLCDC_LAYER_OVR_IRQ(0) | ATMEL_XLCDC_LAYER_OVR_IRQ(1) | + ATMEL_XLCDC_LAYER_OVR_IRQ(2))) + dev_dbg(plane->base.dev->dev, "overrun on plane %s\n", + desc->name); +} + void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane) { const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; @@ -883,6 +1053,16 @@ const struct atmel_lcdc_dc_ops atmel_hlcdc_ops = { .lcdc_irq_dbg = atmel_hlcdc_irq_dbg, }; +const struct atmel_lcdc_dc_ops atmel_xlcdc_ops = { + .plane_setup_scaler = atmel_xlcdc_plane_setup_scaler, + .lcdc_update_buffers = atmel_xlcdc_update_buffers, + .lcdc_atomic_disable = atmel_xlcdc_atomic_disable, + .lcdc_update_general_settings = atmel_xlcdc_plane_update_general_settings, + .lcdc_atomic_update = atmel_xlcdc_atomic_update, + .lcdc_csc_init = atmel_xlcdc_csc_init, + .lcdc_irq_dbg = atmel_xlcdc_irq_dbg, +}; + static const struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = { .atomic_check = atmel_hlcdc_plane_atomic_check, .atomic_update = atmel_hlcdc_plane_atomic_update, From 0af86604e34188e1a7263dac739f2b8faa6e892c Mon Sep 17 00:00:00 2001 From: Manikandan Muralidharan Date: Wed, 24 Apr 2024 11:03:48 +0530 Subject: [PATCH 05/18] drm: atmel-hlcdc: add DPI mode support for XLCDC Add support for Display Pixel Interface (DPI) Compatible Mode support in atmel-hlcdc driver for XLCDC IP along with legacy pixel mapping. DPI mode BIT is configured in LCDC_CFG5 register. Signed-off-by: Manikandan Muralidharan [durai.manickamkr@microchip.com: update DPI mode bit using is_xlcdc flag] Signed-off-by: Durai Manickam KR Acked-by: Sam Ravnborg Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20240424053351.589830-6-manikandan.m@microchip.com --- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index 98a98b5fca85..fdd3a6bc0f79 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -30,10 +30,12 @@ * * @base: base CRTC state * @output_mode: RGBXXX output mode + * @dpi: output DPI mode */ struct atmel_hlcdc_crtc_state { struct drm_crtc_state base; unsigned int output_mode; + u8 dpi; }; static inline struct atmel_hlcdc_crtc_state * @@ -170,6 +172,8 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) if (adj->flags & DRM_MODE_FLAG_NHSYNC) cfg |= ATMEL_HLCDC_HSPOL; + } else { + cfg |= state->dpi << 11; } regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5), @@ -177,7 +181,9 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c) ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE | ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY | ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | - ATMEL_HLCDC_GUARDTIME_MASK | ATMEL_HLCDC_MODE_MASK, + ATMEL_HLCDC_GUARDTIME_MASK | + (crtc->dc->desc->is_xlcdc ? ATMEL_XLCDC_MODE_MASK | + ATMEL_XLCDC_DPI : ATMEL_HLCDC_MODE_MASK), cfg); clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); @@ -380,7 +386,15 @@ static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) hstate = drm_crtc_state_to_atmel_hlcdc_crtc_state(state); hstate->output_mode = fls(output_fmts) - 1; - + if (crtc->dc->desc->is_xlcdc) { + /* check if MIPI DPI bit needs to be set */ + if (fls(output_fmts) > 3) { + hstate->output_mode -= 4; + hstate->dpi = 1; + } else { + hstate->dpi = 0; + } + } return 0; } @@ -484,6 +498,7 @@ static struct drm_crtc_state * atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc) { struct atmel_hlcdc_crtc_state *state, *cur; + struct atmel_hlcdc_crtc *c = drm_crtc_to_atmel_hlcdc_crtc(crtc); if (WARN_ON(!crtc->state)) return NULL; @@ -495,6 +510,8 @@ atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc) cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); state->output_mode = cur->output_mode; + if (c->dc->desc->is_xlcdc) + state->dpi = cur->dpi; return &state->base; } From 391acbc6899791a963716e7be4ffe5e682bd7acf Mon Sep 17 00:00:00 2001 From: Manikandan Muralidharan Date: Wed, 24 Apr 2024 11:03:49 +0530 Subject: [PATCH 06/18] drm: atmel-hlcdc: add vertical and horizontal scaling support for XLCDC Update the vertical and horizontal scaler registers of XLCDC IP with Bilinear and Bicubic co-efficients taps for Chroma and Luma componenets of the Pixel. Signed-off-by: Manikandan Muralidharan Acked-by: Sam Ravnborg Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20240424053351.589830-7-manikandan.m@microchip.com --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h | 4 ++++ .../gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c | 20 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h index 1153d402f810..e1a0bb24b511 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h @@ -198,6 +198,8 @@ * @disc_pos: discard area position register * @disc_size: discard area size register * @csc: color space conversion register + * @vxs_config: vertical scalar filter taps control register + * @hxs_config: horizontal scalar filter taps control register */ struct atmel_hlcdc_layer_cfg_layout { int xstride[ATMEL_HLCDC_LAYER_MAX_PLANES]; @@ -217,6 +219,8 @@ struct atmel_hlcdc_layer_cfg_layout { int disc_pos; int disc_size; int csc; + int vxs_config; + int hxs_config; }; /** diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c index f60367dc6d9d..4a7ba0918eca 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_plane.c @@ -966,6 +966,26 @@ static void atmel_xlcdc_csc_init(struct atmel_hlcdc_plane *plane, desc->layout.csc + i, xlcdc_csc_coeffs[i]); } + + if (desc->layout.vxs_config && desc->layout.hxs_config) { + /* + * Updating vxs.config and hxs.config fixes the + * Green Color Issue in SAM9X7 EGT Video Player App + */ + atmel_hlcdc_layer_write_cfg(&plane->layer, + desc->layout.vxs_config, + ATMEL_XLCDC_LAYER_VXSYCFG_ONE | + ATMEL_XLCDC_LAYER_VXSYTAP2_ENABLE | + ATMEL_XLCDC_LAYER_VXSCCFG_ONE | + ATMEL_XLCDC_LAYER_VXSCTAP2_ENABLE); + + atmel_hlcdc_layer_write_cfg(&plane->layer, + desc->layout.hxs_config, + ATMEL_XLCDC_LAYER_HXSYCFG_ONE | + ATMEL_XLCDC_LAYER_HXSYTAP2_ENABLE | + ATMEL_XLCDC_LAYER_HXSCCFG_ONE | + ATMEL_XLCDC_LAYER_HXSCTAP2_ENABLE); + } } static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane) From d0e78f535cbcda9a4574e8d329d099cebda64df4 Mon Sep 17 00:00:00 2001 From: Manikandan Muralidharan Date: Wed, 24 Apr 2024 11:03:50 +0530 Subject: [PATCH 07/18] drm: atmel-hlcdc: add support for DSI output formats Add support for the following DPI mode if the encoder type is DSI as per the XLCDC IP datasheet: - 16BPPCFG1 - 16BPPCFG2 - 16BPPCFG3 - 18BPPCFG1 - 18BPPCFG2 - 24BPP Signed-off-by: Manikandan Muralidharan [durai.manickamkr@microchip.com: update output format using is_xlcdc flag] Signed-off-by: Durai Manickam KR Acked-by: Sam Ravnborg Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20240424053351.589830-8-manikandan.m@microchip.com --- .../gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c | 70 +++++++++++++++++-- 1 file changed, 64 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c index fdd3a6bc0f79..0f7ffb3ced20 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c @@ -301,11 +301,60 @@ static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c, } -#define ATMEL_HLCDC_RGB444_OUTPUT BIT(0) -#define ATMEL_HLCDC_RGB565_OUTPUT BIT(1) -#define ATMEL_HLCDC_RGB666_OUTPUT BIT(2) -#define ATMEL_HLCDC_RGB888_OUTPUT BIT(3) -#define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0) +#define ATMEL_HLCDC_RGB444_OUTPUT BIT(0) +#define ATMEL_HLCDC_RGB565_OUTPUT BIT(1) +#define ATMEL_HLCDC_RGB666_OUTPUT BIT(2) +#define ATMEL_HLCDC_RGB888_OUTPUT BIT(3) +#define ATMEL_HLCDC_DPI_RGB565C1_OUTPUT BIT(4) +#define ATMEL_HLCDC_DPI_RGB565C2_OUTPUT BIT(5) +#define ATMEL_HLCDC_DPI_RGB565C3_OUTPUT BIT(6) +#define ATMEL_HLCDC_DPI_RGB666C1_OUTPUT BIT(7) +#define ATMEL_HLCDC_DPI_RGB666C2_OUTPUT BIT(8) +#define ATMEL_HLCDC_DPI_RGB888_OUTPUT BIT(9) +#define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0) +#define ATMEL_XLCDC_OUTPUT_MODE_MASK GENMASK(9, 0) + +static int atmel_xlcdc_connector_output_dsi(struct drm_encoder *encoder, + struct drm_display_info *info) +{ + int j; + unsigned int supported_fmts = 0; + + switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) { + case 0: + break; + case MEDIA_BUS_FMT_RGB565_1X16: + return ATMEL_HLCDC_DPI_RGB565C1_OUTPUT; + case MEDIA_BUS_FMT_RGB666_1X18: + return ATMEL_HLCDC_DPI_RGB666C1_OUTPUT; + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: + return ATMEL_HLCDC_DPI_RGB666C2_OUTPUT; + case MEDIA_BUS_FMT_RGB888_1X24: + return ATMEL_HLCDC_DPI_RGB888_OUTPUT; + default: + return -EINVAL; + } + + for (j = 0; j < info->num_bus_formats; j++) { + switch (info->bus_formats[j]) { + case MEDIA_BUS_FMT_RGB565_1X16: + supported_fmts |= ATMEL_HLCDC_DPI_RGB565C1_OUTPUT; + break; + case MEDIA_BUS_FMT_RGB666_1X18: + supported_fmts |= ATMEL_HLCDC_DPI_RGB666C1_OUTPUT; + break; + case MEDIA_BUS_FMT_RGB666_1X24_CPADHI: + supported_fmts |= ATMEL_HLCDC_DPI_RGB666C2_OUTPUT; + break; + case MEDIA_BUS_FMT_RGB888_1X24: + supported_fmts |= ATMEL_HLCDC_DPI_RGB888_OUTPUT; + break; + default: + break; + } + } + return supported_fmts; +} static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state) { @@ -318,6 +367,13 @@ static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state) encoder = state->best_encoder; if (!encoder) encoder = connector->encoder; + /* + * atmel-hlcdc to support DSI formats with DSI video pipeline + * when DRM_MODE_ENCODER_DSI type is set by + * connector driver component. + */ + if (encoder->encoder_type == DRM_MODE_ENCODER_DSI) + return atmel_xlcdc_connector_output_dsi(encoder, info); switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) { case 0: @@ -358,7 +414,7 @@ static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state) static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) { - unsigned int output_fmts = ATMEL_HLCDC_OUTPUT_MODE_MASK; + unsigned int output_fmts; struct atmel_hlcdc_crtc_state *hstate; struct drm_connector_state *cstate; struct drm_connector *connector; @@ -366,6 +422,8 @@ static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state) int i; crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc); + output_fmts = crtc->dc->desc->is_xlcdc ? ATMEL_XLCDC_OUTPUT_MODE_MASK : + ATMEL_HLCDC_OUTPUT_MODE_MASK; for_each_new_connector_in_state(state->state, connector, cstate, i) { unsigned int supported_fmts = 0; From 86266829ea755f737762ebda614c59b136c8feac Mon Sep 17 00:00:00 2001 From: Manikandan Muralidharan Date: Wed, 24 Apr 2024 11:03:51 +0530 Subject: [PATCH 08/18] drm: atmel-hlcdc: add LCD controller layer definition for sam9x75 Add the LCD controller layer definition and descriptor structure for sam9x75 for the following layers: - Base Layer - Overlay1 Layer - Overlay2 Layer - High End Overlay Signed-off-by: Manikandan Muralidharan Acked-by: Sam Ravnborg Signed-off-by: Sam Ravnborg Link: https://patchwork.freedesktop.org/patch/msgid/20240424053351.589830-9-manikandan.m@microchip.com --- drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c | 100 +++++++++++++++++++ 1 file changed, 100 insertions(+) diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c index b09df821cbc0..9ce429f889ca 100644 --- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c +++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c @@ -467,6 +467,102 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sam9x60 = { .ops = &atmel_hlcdc_ops, }; +static const struct atmel_hlcdc_layer_desc atmel_xlcdc_sam9x75_layers[] = { + { + .name = "base", + .formats = &atmel_hlcdc_plane_rgb_formats, + .regs_offset = 0x60, + .id = 0, + .type = ATMEL_HLCDC_BASE_LAYER, + .cfgs_offset = 0x1c, + .layout = { + .xstride = { 2 }, + .default_color = 3, + .general_config = 4, + .disc_pos = 5, + .disc_size = 6, + }, + .clut_offset = 0x700, + }, + { + .name = "overlay1", + .formats = &atmel_hlcdc_plane_rgb_formats, + .regs_offset = 0x160, + .id = 1, + .type = ATMEL_HLCDC_OVERLAY_LAYER, + .cfgs_offset = 0x1c, + .layout = { + .pos = 2, + .size = 3, + .xstride = { 4 }, + .pstride = { 5 }, + .default_color = 6, + .chroma_key = 7, + .chroma_key_mask = 8, + .general_config = 9, + }, + .clut_offset = 0xb00, + }, + { + .name = "overlay2", + .formats = &atmel_hlcdc_plane_rgb_formats, + .regs_offset = 0x260, + .id = 2, + .type = ATMEL_HLCDC_OVERLAY_LAYER, + .cfgs_offset = 0x1c, + .layout = { + .pos = 2, + .size = 3, + .xstride = { 4 }, + .pstride = { 5 }, + .default_color = 6, + .chroma_key = 7, + .chroma_key_mask = 8, + .general_config = 9, + }, + .clut_offset = 0xf00, + }, + { + .name = "high-end-overlay", + .formats = &atmel_hlcdc_plane_rgb_and_yuv_formats, + .regs_offset = 0x360, + .id = 3, + .type = ATMEL_HLCDC_OVERLAY_LAYER, + .cfgs_offset = 0x30, + .layout = { + .pos = 2, + .size = 3, + .memsize = 4, + .xstride = { 5, 7 }, + .pstride = { 6, 8 }, + .default_color = 9, + .chroma_key = 10, + .chroma_key_mask = 11, + .general_config = 12, + .csc = 16, + .scaler_config = 23, + .vxs_config = 30, + .hxs_config = 31, + }, + .clut_offset = 0x1300, + }, +}; + +static const struct atmel_hlcdc_dc_desc atmel_xlcdc_dc_sam9x75 = { + .min_width = 0, + .min_height = 0, + .max_width = 2048, + .max_height = 2048, + .max_spw = 0x3ff, + .max_vpw = 0x3ff, + .max_hpw = 0x3ff, + .fixed_clksrc = true, + .is_xlcdc = true, + .nlayers = ARRAY_SIZE(atmel_xlcdc_sam9x75_layers), + .layers = atmel_xlcdc_sam9x75_layers, + .ops = &atmel_xlcdc_ops, +}; + static const struct of_device_id atmel_hlcdc_of_match[] = { { .compatible = "atmel,at91sam9n12-hlcdc", @@ -492,6 +588,10 @@ static const struct of_device_id atmel_hlcdc_of_match[] = { .compatible = "microchip,sam9x60-hlcdc", .data = &atmel_hlcdc_dc_sam9x60, }, + { + .compatible = "microchip,sam9x75-xlcdc", + .data = &atmel_xlcdc_dc_sam9x75, + }, { /* sentinel */ }, }; MODULE_DEVICE_TABLE(of, atmel_hlcdc_of_match); From c4e3267868e1debb3d87d21a36efc8a2255298e2 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Fri, 3 May 2024 21:15:04 +0300 Subject: [PATCH 09/18] drm/ci: validate drm/msm XML register files against schema In order to validate drm/msm register definition files against schema, reuse the nodebugfs build step. The validation entry is guarded by the EXPERT Kconfig option and we don't want to enable that option for all the builds. Reviewed-by: Abhinav Kumar Acked-by: Helen Koike Link: https://patchwork.freedesktop.org/patch/msgid/20240503-fd-fix-lxml-v2-2-f80a60ce21a1@linaro.org Signed-off-by: Dmitry Baryshkov --- drivers/gpu/drm/ci/build.sh | 3 +++ drivers/gpu/drm/ci/build.yml | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/gpu/drm/ci/build.sh b/drivers/gpu/drm/ci/build.sh index 106f2d40d222..28a495c0c39c 100644 --- a/drivers/gpu/drm/ci/build.sh +++ b/drivers/gpu/drm/ci/build.sh @@ -12,6 +12,9 @@ rm -rf .git/rebase-apply apt-get update apt-get install -y libssl-dev +# for msm header validation +apt-get install -y python3-lxml + if [[ "$KERNEL_ARCH" = "arm64" ]]; then GCC_ARCH="aarch64-linux-gnu" DEBIAN_ARCH="arm64" diff --git a/drivers/gpu/drm/ci/build.yml b/drivers/gpu/drm/ci/build.yml index 17ab38304885..9c198239033d 100644 --- a/drivers/gpu/drm/ci/build.yml +++ b/drivers/gpu/drm/ci/build.yml @@ -106,6 +106,7 @@ build-nodebugfs:arm64: extends: .build:arm64 variables: DISABLE_KCONFIGS: "DEBUG_FS" + ENABLE_KCONFIGS: "EXPERT DRM_MSM_VALIDATE_XML" build:x86_64: extends: .build:x86_64 From c9402efe492bb46ccbf94fedc4783eb8f8747567 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Christian=20K=C3=B6nig?= Date: Wed, 29 May 2024 10:43:22 +0200 Subject: [PATCH 10/18] dma-buf: add a warning when drv try to reserve 0 fence slots MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When dma_resv_reserve_fences() is called with num_fences=0 it usually means that a driver or other component messed up its calculation how many fences are needed. Warn in that situation. When no fence are needed the function shouldn't be called in the first place. Signed-off-by: Christian König Link: https://patchwork.freedesktop.org/patch/msgid/20240529084322.2284-1-christian.koenig@amd.com Reviewed-by: Matthew Auld --- drivers/dma-buf/dma-resv.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/dma-buf/dma-resv.c b/drivers/dma-buf/dma-resv.c index e2869fb31140..5f8d010516f0 100644 --- a/drivers/dma-buf/dma-resv.c +++ b/drivers/dma-buf/dma-resv.c @@ -186,6 +186,13 @@ int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences) dma_resv_assert_held(obj); + /* Driver and component code should never call this function with + * num_fences=0. If they do it usually points to bugs when calculating + * the number of needed fences dynamically. + */ + if (WARN_ON(!num_fences)) + return -EINVAL; + old = dma_resv_fences_list(obj); if (old && old->max_fences) { if ((old->num_fences + num_fences) <= old->max_fences) From 4a534428ef8df2e3ca91a8341702f6127fb42867 Mon Sep 17 00:00:00 2001 From: Sam Ravnborg Date: Thu, 30 May 2024 23:14:02 +0200 Subject: [PATCH 11/18] MAINTAINERS: drm: Drop sam as panel reviewer Drop myself as reviewer of panel patches, to reflect the reality. Signed-off-by: Sam Ravnborg Cc: Neil Armstrong Acked-by: Neil Armstrong Link: https://lore.kernel.org/r/20240530211402.GA1660596@ravnborg.org Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240530211402.GA1660596@ravnborg.org --- MAINTAINERS | 1 - 1 file changed, 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index ac285040578e..38978699bef5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7567,7 +7567,6 @@ F: include/drm/gpu_scheduler.h DRM PANEL DRIVERS M: Neil Armstrong R: Jessica Zhang -R: Sam Ravnborg L: dri-devel@lists.freedesktop.org S: Maintained T: git https://gitlab.freedesktop.org/drm/misc/kernel.git From 45b888a8980ae9a09fbf2f50b0ffb7505a834533 Mon Sep 17 00:00:00 2001 From: Ryan Walklin Date: Fri, 31 May 2024 09:12:14 +1200 Subject: [PATCH 12/18] dt-bindings: display: panel: Add WL-355608-A8 panel The WL-355608-A8 is a 3.5" 640x480@60Hz RGB LCD display used in a number of handheld gaming devices made by Anbernic. By consensus a vendor prefix is not provided as the panel OEM is unknown. Add a device tree binding for the panel. Signed-off-by: Ryan Walklin Reviewed-by: Conor Dooley Link: https://lore.kernel.org/r/20240530211415.44201-3-ryan@testtoast.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240530211415.44201-3-ryan@testtoast.com --- .../bindings/display/panel/wl-355608-a8.yaml | 60 +++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 Documentation/devicetree/bindings/display/panel/wl-355608-a8.yaml diff --git a/Documentation/devicetree/bindings/display/panel/wl-355608-a8.yaml b/Documentation/devicetree/bindings/display/panel/wl-355608-a8.yaml new file mode 100644 index 000000000000..e552d01b52b9 --- /dev/null +++ b/Documentation/devicetree/bindings/display/panel/wl-355608-a8.yaml @@ -0,0 +1,60 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/display/panel/wl-355608-a8.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: WL-355608-A8 3.5" (640x480 pixels) 24-bit IPS LCD panel + +maintainers: + - Ryan Walklin + +allOf: + - $ref: panel-common.yaml# + - $ref: /schemas/spi/spi-peripheral-props.yaml# + +properties: + compatible: + const: wl-355608-a8 + + reg: + maxItems: 1 + + spi-3wire: true + +required: + - compatible + - reg + - port + - power-supply + - reset-gpios + +unevaluatedProperties: false + +examples: + - | + #include + + spi { + #address-cells = <1>; + #size-cells = <0>; + + panel@0 { + compatible = "wl-355608-a8"; + reg = <0>; + + spi-3wire; + spi-max-frequency = <3125000>; + + reset-gpios = <&pio 8 14 GPIO_ACTIVE_LOW>; // PI14 + + backlight = <&backlight>; + power-supply = <®_lcd>; + + port { + endpoint { + remote-endpoint = <&tcon_lcd0_out_lcd>; + }; + }; + }; + }; From 62ea2eeba7bf11f4b04e080475de93c2f8ee0f92 Mon Sep 17 00:00:00 2001 From: Ryan Walklin Date: Fri, 31 May 2024 09:12:15 +1200 Subject: [PATCH 13/18] drm: panel: nv3052c: Add WL-355608-A8 panel The WL-355608-A8 is a 3.5" 640x480@60Hz RGB LCD display from an unknown OEM used in a number of handheld gaming devices made by Anbernic. Limited information is available online however the panel timing values (below) have been obtained from the vendor BSP. The panel appears to integrate a NV3052C LCD driver (or clone). Available devices address it in SPI/RGB mode, with the timing signals generated from the device SoC (Allwinner H700) and passed through. Add a panel definition and display mode to the existing NV3502C driver. It was assumed during bringup that the initialisation sequence was the same as the existing Fascontek FS035VG158 panel, proved working during experimentation, however subsequent dumping of the init sequence with a logic analyser confirms one small change to VCOM_ADJ3 from 0x4a to 0x44, therefore a separate set of registers is also added. Timings: | Active | FP | Sync | BP | Total -----------|--------|------|------|------|------- Horizontal | 640 | 64 | 20 | 46 | 770 Vertical | 480 | 21 | 4 | 15 | 520 Signed-off-by: Ryan Walklin Co-developed-by: Hironori KIKUCHI Signed-off-by: Hironori KIKUCHI Reviewed-by: John Watts Reviewed-by: Neil Armstrong Acked-by: Jessica Zhang Link: https://lore.kernel.org/r/20240530211415.44201-4-ryan@testtoast.com Signed-off-by: Neil Armstrong Link: https://patchwork.freedesktop.org/patch/msgid/20240530211415.44201-4-ryan@testtoast.com --- .../gpu/drm/panel/panel-newvision-nv3052c.c | 225 ++++++++++++++++++ 1 file changed, 225 insertions(+) diff --git a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c index 1aab0c9ae52f..e986d9823528 100644 --- a/drivers/gpu/drm/panel/panel-newvision-nv3052c.c +++ b/drivers/gpu/drm/panel/panel-newvision-nv3052c.c @@ -433,6 +433,202 @@ static const struct nv3052c_reg fs035vg158_panel_regs[] = { { 0x36, 0x0a }, // bgr = 1, ss = 1, gs = 0 }; + +static const struct nv3052c_reg wl_355608_a8_panel_regs[] = { + // EXTC Command set enable, select page 1 + { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x01 }, + // Mostly unknown registers + { 0xe3, 0x00 }, + { 0x40, 0x00 }, + { 0x03, 0x40 }, + { 0x04, 0x00 }, + { 0x05, 0x03 }, + { 0x08, 0x00 }, + { 0x09, 0x07 }, + { 0x0a, 0x01 }, + { 0x0b, 0x32 }, + { 0x0c, 0x32 }, + { 0x0d, 0x0b }, + { 0x0e, 0x00 }, + { 0x23, 0xa0 }, + { 0x24, 0x0c }, + { 0x25, 0x06 }, + { 0x26, 0x14 }, + { 0x27, 0x14 }, + { 0x38, 0xcc }, // VCOM_ADJ1 + { 0x39, 0xd7 }, // VCOM_ADJ2 + { 0x3a, 0x44 }, // VCOM_ADJ3 + { 0x28, 0x40 }, + { 0x29, 0x01 }, + { 0x2a, 0xdf }, + { 0x49, 0x3c }, + { 0x91, 0x77 }, // EXTPW_CTRL2 + { 0x92, 0x77 }, // EXTPW_CTRL3 + { 0xa0, 0x55 }, + { 0xa1, 0x50 }, + { 0xa4, 0x9c }, + { 0xa7, 0x02 }, + { 0xa8, 0x01 }, + { 0xa9, 0x01 }, + { 0xaa, 0xfc }, + { 0xab, 0x28 }, + { 0xac, 0x06 }, + { 0xad, 0x06 }, + { 0xae, 0x06 }, + { 0xaf, 0x03 }, + { 0xb0, 0x08 }, + { 0xb1, 0x26 }, + { 0xb2, 0x28 }, + { 0xb3, 0x28 }, + { 0xb4, 0x33 }, + { 0xb5, 0x08 }, + { 0xb6, 0x26 }, + { 0xb7, 0x08 }, + { 0xb8, 0x26 }, + { 0xf0, 0x00 }, + { 0xf6, 0xc0 }, + // EXTC Command set enable, select page 2 + { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x02 }, + // Set gray scale voltage to adjust gamma + { 0xb0, 0x0b }, // PGAMVR0 + { 0xb1, 0x16 }, // PGAMVR1 + { 0xb2, 0x17 }, // PGAMVR2 + { 0xb3, 0x2c }, // PGAMVR3 + { 0xb4, 0x32 }, // PGAMVR4 + { 0xb5, 0x3b }, // PGAMVR5 + { 0xb6, 0x29 }, // PGAMPR0 + { 0xb7, 0x40 }, // PGAMPR1 + { 0xb8, 0x0d }, // PGAMPK0 + { 0xb9, 0x05 }, // PGAMPK1 + { 0xba, 0x12 }, // PGAMPK2 + { 0xbb, 0x10 }, // PGAMPK3 + { 0xbc, 0x12 }, // PGAMPK4 + { 0xbd, 0x15 }, // PGAMPK5 + { 0xbe, 0x19 }, // PGAMPK6 + { 0xbf, 0x0e }, // PGAMPK7 + { 0xc0, 0x16 }, // PGAMPK8 + { 0xc1, 0x0a }, // PGAMPK9 + // Set gray scale voltage to adjust gamma + { 0xd0, 0x0c }, // NGAMVR0 + { 0xd1, 0x17 }, // NGAMVR0 + { 0xd2, 0x14 }, // NGAMVR1 + { 0xd3, 0x2e }, // NGAMVR2 + { 0xd4, 0x32 }, // NGAMVR3 + { 0xd5, 0x3c }, // NGAMVR4 + { 0xd6, 0x22 }, // NGAMPR0 + { 0xd7, 0x3d }, // NGAMPR1 + { 0xd8, 0x0d }, // NGAMPK0 + { 0xd9, 0x07 }, // NGAMPK1 + { 0xda, 0x13 }, // NGAMPK2 + { 0xdb, 0x13 }, // NGAMPK3 + { 0xdc, 0x11 }, // NGAMPK4 + { 0xdd, 0x15 }, // NGAMPK5 + { 0xde, 0x19 }, // NGAMPK6 + { 0xdf, 0x10 }, // NGAMPK7 + { 0xe0, 0x17 }, // NGAMPK8 + { 0xe1, 0x0a }, // NGAMPK9 + // EXTC Command set enable, select page 3 + { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x03 }, + // Set various timing settings + { 0x00, 0x2a }, // GIP_VST_1 + { 0x01, 0x2a }, // GIP_VST_2 + { 0x02, 0x2a }, // GIP_VST_3 + { 0x03, 0x2a }, // GIP_VST_4 + { 0x04, 0x61 }, // GIP_VST_5 + { 0x05, 0x80 }, // GIP_VST_6 + { 0x06, 0xc7 }, // GIP_VST_7 + { 0x07, 0x01 }, // GIP_VST_8 + { 0x08, 0x03 }, // GIP_VST_9 + { 0x09, 0x04 }, // GIP_VST_10 + { 0x70, 0x22 }, // GIP_ECLK1 + { 0x71, 0x80 }, // GIP_ECLK2 + { 0x30, 0x2a }, // GIP_CLK_1 + { 0x31, 0x2a }, // GIP_CLK_2 + { 0x32, 0x2a }, // GIP_CLK_3 + { 0x33, 0x2a }, // GIP_CLK_4 + { 0x34, 0x61 }, // GIP_CLK_5 + { 0x35, 0xc5 }, // GIP_CLK_6 + { 0x36, 0x80 }, // GIP_CLK_7 + { 0x37, 0x23 }, // GIP_CLK_8 + { 0x40, 0x03 }, // GIP_CLKA_1 + { 0x41, 0x04 }, // GIP_CLKA_2 + { 0x42, 0x05 }, // GIP_CLKA_3 + { 0x43, 0x06 }, // GIP_CLKA_4 + { 0x44, 0x11 }, // GIP_CLKA_5 + { 0x45, 0xe8 }, // GIP_CLKA_6 + { 0x46, 0xe9 }, // GIP_CLKA_7 + { 0x47, 0x11 }, // GIP_CLKA_8 + { 0x48, 0xea }, // GIP_CLKA_9 + { 0x49, 0xeb }, // GIP_CLKA_10 + { 0x50, 0x07 }, // GIP_CLKB_1 + { 0x51, 0x08 }, // GIP_CLKB_2 + { 0x52, 0x09 }, // GIP_CLKB_3 + { 0x53, 0x0a }, // GIP_CLKB_4 + { 0x54, 0x11 }, // GIP_CLKB_5 + { 0x55, 0xec }, // GIP_CLKB_6 + { 0x56, 0xed }, // GIP_CLKB_7 + { 0x57, 0x11 }, // GIP_CLKB_8 + { 0x58, 0xef }, // GIP_CLKB_9 + { 0x59, 0xf0 }, // GIP_CLKB_10 + // Map internal GOA signals to GOA output pad + { 0xb1, 0x01 }, // PANELD2U2 + { 0xb4, 0x15 }, // PANELD2U5 + { 0xb5, 0x16 }, // PANELD2U6 + { 0xb6, 0x09 }, // PANELD2U7 + { 0xb7, 0x0f }, // PANELD2U8 + { 0xb8, 0x0d }, // PANELD2U9 + { 0xb9, 0x0b }, // PANELD2U10 + { 0xba, 0x00 }, // PANELD2U11 + { 0xc7, 0x02 }, // PANELD2U24 + { 0xca, 0x17 }, // PANELD2U27 + { 0xcb, 0x18 }, // PANELD2U28 + { 0xcc, 0x0a }, // PANELD2U29 + { 0xcd, 0x10 }, // PANELD2U30 + { 0xce, 0x0e }, // PANELD2U31 + { 0xcf, 0x0c }, // PANELD2U32 + { 0xd0, 0x00 }, // PANELD2U33 + // Map internal GOA signals to GOA output pad + { 0x81, 0x00 }, // PANELU2D2 + { 0x84, 0x15 }, // PANELU2D5 + { 0x85, 0x16 }, // PANELU2D6 + { 0x86, 0x10 }, // PANELU2D7 + { 0x87, 0x0a }, // PANELU2D8 + { 0x88, 0x0c }, // PANELU2D9 + { 0x89, 0x0e }, // PANELU2D10 + { 0x8a, 0x02 }, // PANELU2D11 + { 0x97, 0x00 }, // PANELU2D24 + { 0x9a, 0x17 }, // PANELU2D27 + { 0x9b, 0x18 }, // PANELU2D28 + { 0x9c, 0x0f }, // PANELU2D29 + { 0x9d, 0x09 }, // PANELU2D30 + { 0x9e, 0x0b }, // PANELU2D31 + { 0x9f, 0x0d }, // PANELU2D32 + { 0xa0, 0x01 }, // PANELU2D33 + // EXTC Command set enable, select page 2 + { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x02 }, + // Unknown registers + { 0x01, 0x01 }, + { 0x02, 0xda }, + { 0x03, 0xba }, + { 0x04, 0xa8 }, + { 0x05, 0x9a }, + { 0x06, 0x70 }, + { 0x07, 0xff }, + { 0x08, 0x91 }, + { 0x09, 0x90 }, + { 0x0a, 0xff }, + { 0x0b, 0x8f }, + { 0x0c, 0x60 }, + { 0x0d, 0x58 }, + { 0x0e, 0x48 }, + { 0x0f, 0x38 }, + { 0x10, 0x2b }, + // EXTC Command set enable, select page 0 + { 0xff, 0x30 }, { 0xff, 0x52 }, { 0xff, 0x00 }, + // Display Access Control + { 0x36, 0x0a }, // bgr = 1, ss = 1, gs = 0 +}; + static inline struct nv3052c *to_nv3052c(struct drm_panel *panel) { return container_of(panel, struct nv3052c, panel); @@ -670,6 +866,21 @@ static const struct drm_display_mode fs035vg158_modes[] = { }, }; +static const struct drm_display_mode wl_355608_a8_mode[] = { + { + .clock = 24000, + .hdisplay = 640, + .hsync_start = 640 + 64, + .hsync_end = 640 + 64 + 20, + .htotal = 640 + 64 + 20 + 46, + .vdisplay = 480, + .vsync_start = 480 + 21, + .vsync_end = 480 + 21 + 4, + .vtotal = 480 + 21 + 4 + 15, + .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC, + }, +}; + static const struct nv3052c_panel_info ltk035c5444t_panel_info = { .display_modes = ltk035c5444t_modes, .num_modes = ARRAY_SIZE(ltk035c5444t_modes), @@ -692,9 +903,21 @@ static const struct nv3052c_panel_info fs035vg158_panel_info = { .panel_regs_len = ARRAY_SIZE(fs035vg158_panel_regs), }; +static const struct nv3052c_panel_info wl_355608_a8_panel_info = { + .display_modes = wl_355608_a8_mode, + .num_modes = ARRAY_SIZE(wl_355608_a8_mode), + .width_mm = 150, + .height_mm = 94, + .bus_format = MEDIA_BUS_FMT_RGB888_1X24, + .bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_NEGEDGE, + .panel_regs = wl_355608_a8_panel_regs, + .panel_regs_len = ARRAY_SIZE(wl_355608_a8_panel_regs), +}; + static const struct spi_device_id nv3052c_ids[] = { { "ltk035c5444t", }, { "fs035vg158", }, + { "wl-355608-a8", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(spi, nv3052c_ids); @@ -702,6 +925,7 @@ MODULE_DEVICE_TABLE(spi, nv3052c_ids); static const struct of_device_id nv3052c_of_match[] = { { .compatible = "leadtek,ltk035c5444t", .data = <k035c5444t_panel_info }, { .compatible = "fascontek,fs035vg158", .data = &fs035vg158_panel_info }, + { .compatible = "wl-355608-a8", .data = &wl_355608_a8_panel_info }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, nv3052c_of_match); @@ -719,4 +943,5 @@ module_spi_driver(nv3052c_driver); MODULE_AUTHOR("Paul Cercueil "); MODULE_AUTHOR("Christophe Branchereau "); +MODULE_AUTHOR("Ryan Walklin Date: Mon, 18 Mar 2024 21:39:23 +0100 Subject: [PATCH 14/18] drm/bridge: analogix_dp: properly handle zero sized AUX transactions Address only transactions without any data are valid and should not be flagged as short transactions. Simply return the message size when no transaction errors occured. CC: stable@vger.kernel.org Signed-off-by: Lucas Stach Reviewed-by: Robert Foss Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20240318203925.2837689-1-l.stach@pengutronix.de --- drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 6a4f20fccf84..7b0bc9704eac 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -1027,7 +1027,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, u32 status_reg; u8 *buffer = msg->buffer; unsigned int i; - int num_transferred = 0; int ret; /* Buffer size of AUX CH is 16 bytes */ @@ -1079,7 +1078,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, reg = buffer[i]; writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + 4 * i); - num_transferred++; } } @@ -1127,7 +1125,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + 4 * i); buffer[i] = (unsigned char)reg; - num_transferred++; } } @@ -1144,7 +1141,7 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp, (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ) msg->reply = DP_AUX_NATIVE_REPLY_ACK; - return num_transferred > 0 ? num_transferred : -EBUSY; + return msg->size; aux_error: /* if aux err happen, reset aux */ From 3747c9818954368020c6de7602e7a8869213f053 Mon Sep 17 00:00:00 2001 From: Wyon Bi Date: Mon, 18 Mar 2024 21:39:24 +0100 Subject: [PATCH 15/18] drm/bridge: analogix_dp: simplify analogix_dp_{set/get}_lane_link_training helpers There is no need for separate functions for each lane, as we can deduct the register offset to read/write from the lane index. Signed-off-by: Wyon Bi Signed-off-by: Lucas Stach Reviewed-by: Robert Foss Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20240318203925.2837689-2-l.stach@pengutronix.de --- .../drm/bridge/analogix/analogix_dp_core.c | 97 ++------------- .../drm/bridge/analogix/analogix_dp_core.h | 22 +--- .../gpu/drm/bridge/analogix/analogix_dp_reg.c | 114 +++--------------- 3 files changed, 26 insertions(+), 207 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 9360b63ad37c..89d7c30e393f 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -234,28 +234,6 @@ static int analogix_dp_training_pattern_dis(struct analogix_dp_device *dp) return ret < 0 ? ret : 0; } -static void -analogix_dp_set_lane_lane_pre_emphasis(struct analogix_dp_device *dp, - int pre_emphasis, int lane) -{ - switch (lane) { - case 0: - analogix_dp_set_lane0_pre_emphasis(dp, pre_emphasis); - break; - case 1: - analogix_dp_set_lane1_pre_emphasis(dp, pre_emphasis); - break; - - case 2: - analogix_dp_set_lane2_pre_emphasis(dp, pre_emphasis); - break; - - case 3: - analogix_dp_set_lane3_pre_emphasis(dp, pre_emphasis); - break; - } -} - static int analogix_dp_link_start(struct analogix_dp_device *dp) { u8 buf[4]; @@ -286,10 +264,12 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp) return retval; } - /* Set TX pre-emphasis to minimum */ + /* Set TX voltage-swing and pre-emphasis to minimum */ for (lane = 0; lane < lane_count; lane++) - analogix_dp_set_lane_lane_pre_emphasis(dp, - PRE_EMPHASIS_LEVEL_0, lane); + dp->link_train.training_lane[lane] = + DP_TRAIN_VOLTAGE_SWING_LEVEL_0 | + DP_TRAIN_PRE_EMPH_LEVEL_0; + analogix_dp_set_lane_link_training(dp); /* Wait for PLL lock */ pll_tries = 0; @@ -384,54 +364,6 @@ static unsigned char analogix_dp_get_adjust_request_pre_emphasis( return ((link_value >> shift) & 0xc) >> 2; } -static void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp, - u8 training_lane_set, int lane) -{ - switch (lane) { - case 0: - analogix_dp_set_lane0_link_training(dp, training_lane_set); - break; - case 1: - analogix_dp_set_lane1_link_training(dp, training_lane_set); - break; - - case 2: - analogix_dp_set_lane2_link_training(dp, training_lane_set); - break; - - case 3: - analogix_dp_set_lane3_link_training(dp, training_lane_set); - break; - } -} - -static unsigned int -analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, - int lane) -{ - u32 reg; - - switch (lane) { - case 0: - reg = analogix_dp_get_lane0_link_training(dp); - break; - case 1: - reg = analogix_dp_get_lane1_link_training(dp); - break; - case 2: - reg = analogix_dp_get_lane2_link_training(dp); - break; - case 3: - reg = analogix_dp_get_lane3_link_training(dp); - break; - default: - WARN_ON(1); - return 0; - } - - return reg; -} - static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp) { analogix_dp_training_pattern_dis(dp); @@ -523,10 +455,7 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) } analogix_dp_get_adjust_training_lane(dp, adjust_request); - - for (lane = 0; lane < lane_count; lane++) - analogix_dp_set_lane_link_training(dp, - dp->link_train.training_lane[lane], lane); + analogix_dp_set_lane_link_training(dp); retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, dp->link_train.training_lane, lane_count); @@ -538,7 +467,7 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) { - int lane, lane_count, retval; + int lane_count, retval; u32 reg; u8 link_align, link_status[2], adjust_request[2]; @@ -598,9 +527,7 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp) return -EIO; } - for (lane = 0; lane < lane_count; lane++) - analogix_dp_set_lane_link_training(dp, - dp->link_train.training_lane[lane], lane); + analogix_dp_set_lane_link_training(dp); retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, dp->link_train.training_lane, lane_count); @@ -712,7 +639,7 @@ static int analogix_dp_full_link_train(struct analogix_dp_device *dp, static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) { - int i, ret; + int ret; u8 link_align, link_status[2]; enum pll_status status; @@ -720,11 +647,7 @@ static int analogix_dp_fast_link_train(struct analogix_dp_device *dp) analogix_dp_set_link_bandwidth(dp, dp->link_train.link_rate); analogix_dp_set_lane_count(dp, dp->link_train.lane_count); - - for (i = 0; i < dp->link_train.lane_count; i++) { - analogix_dp_set_lane_link_training(dp, - dp->link_train.training_lane[i], i); - } + analogix_dp_set_lane_link_training(dp); ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status, status != PLL_UNLOCKED, 120, diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h index 433f2d7efa0c..382b2f068ab9 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.h @@ -213,26 +213,8 @@ void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, bool enable); void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, enum pattern_set pattern); -void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, - u32 level); -void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, - u32 level); -void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, - u32 level); -void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, - u32 level); -void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, - u32 training_lane); -void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, - u32 training_lane); -void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, - u32 training_lane); -void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, - u32 training_lane); -u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp); -u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp); -u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp); -u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp); +void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp); +u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane); void analogix_dp_reset_macro(struct analogix_dp_device *dp); void analogix_dp_init_video(struct analogix_dp_device *dp); diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c index 7b0bc9704eac..d267cf05cbca 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_reg.c @@ -557,6 +557,20 @@ void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count) *count = reg; } +void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp) +{ + u8 lane; + + for (lane = 0; lane < dp->link_train.lane_count; lane++) + writel(dp->link_train.training_lane[lane], + dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane); +} + +u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane) +{ + return readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL + 4 * lane); +} + void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp, bool enable) { @@ -606,106 +620,6 @@ void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, } } -void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, - u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane1_pre_emphasis(struct analogix_dp_device *dp, - u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane2_pre_emphasis(struct analogix_dp_device *dp, - u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane3_pre_emphasis(struct analogix_dp_device *dp, - u32 level) -{ - u32 reg; - - reg = readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); - reg &= ~PRE_EMPHASIS_SET_MASK; - reg |= level << PRE_EMPHASIS_SET_SHIFT; - writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane0_link_training(struct analogix_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane1_link_training(struct analogix_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane2_link_training(struct analogix_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); -} - -void analogix_dp_set_lane3_link_training(struct analogix_dp_device *dp, - u32 training_lane) -{ - u32 reg; - - reg = training_lane; - writel(reg, dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); -} - -u32 analogix_dp_get_lane0_link_training(struct analogix_dp_device *dp) -{ - return readl(dp->reg_base + ANALOGIX_DP_LN0_LINK_TRAINING_CTL); -} - -u32 analogix_dp_get_lane1_link_training(struct analogix_dp_device *dp) -{ - return readl(dp->reg_base + ANALOGIX_DP_LN1_LINK_TRAINING_CTL); -} - -u32 analogix_dp_get_lane2_link_training(struct analogix_dp_device *dp) -{ - return readl(dp->reg_base + ANALOGIX_DP_LN2_LINK_TRAINING_CTL); -} - -u32 analogix_dp_get_lane3_link_training(struct analogix_dp_device *dp) -{ - return readl(dp->reg_base + ANALOGIX_DP_LN3_LINK_TRAINING_CTL); -} - void analogix_dp_reset_macro(struct analogix_dp_device *dp) { u32 reg; From 35e7a72a67190a3846cfe2f87add4ed1229b2248 Mon Sep 17 00:00:00 2001 From: Lucas Stach Date: Mon, 18 Mar 2024 21:39:25 +0100 Subject: [PATCH 16/18] drm/bridge: analogix_dp: don't adjust further when clock recovery succeeded Take a early return from the clock recovery training when the sink reports CR_DONE for all lanes. There is no point in trying to adjust the link parameters further. Signed-off-by: Lucas Stach Reviewed-by: Robert Foss Signed-off-by: Robert Foss Link: https://patchwork.freedesktop.org/patch/msgid/20240318203925.2837689-3-l.stach@pengutronix.de --- .../drm/bridge/analogix/analogix_dp_core.c | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c index 89d7c30e393f..b5dbff21c187 100644 --- a/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c +++ b/drivers/gpu/drm/bridge/analogix/analogix_dp_core.c @@ -410,11 +410,6 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) if (retval < 0) return retval; - retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1, - adjust_request, 2); - if (retval < 0) - return retval; - if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) { /* set training pattern 2 for EQ */ analogix_dp_set_training_pattern(dp, TRAINING_PTN2); @@ -427,30 +422,32 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp) dev_dbg(dp->dev, "Link Training Clock Recovery success\n"); dp->link_train.lt_state = EQUALIZER_TRAINING; - } else { - for (lane = 0; lane < lane_count; lane++) { - training_lane = analogix_dp_get_lane_link_training( - dp, lane); - voltage_swing = analogix_dp_get_adjust_request_voltage( - adjust_request, lane); - pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis( - adjust_request, lane); - if (DPCD_VOLTAGE_SWING_GET(training_lane) == - voltage_swing && - DPCD_PRE_EMPHASIS_GET(training_lane) == - pre_emphasis) - dp->link_train.cr_loop[lane]++; + return 0; + } - if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP || - voltage_swing == VOLTAGE_LEVEL_3 || - pre_emphasis == PRE_EMPHASIS_LEVEL_3) { - dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", - dp->link_train.cr_loop[lane], - voltage_swing, pre_emphasis); - analogix_dp_reduce_link_rate(dp); - return -EIO; - } + retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1, + adjust_request, 2); + if (retval < 0) + return retval; + + for (lane = 0; lane < lane_count; lane++) { + training_lane = analogix_dp_get_lane_link_training(dp, lane); + voltage_swing = analogix_dp_get_adjust_request_voltage(adjust_request, lane); + pre_emphasis = analogix_dp_get_adjust_request_pre_emphasis(adjust_request, lane); + + if (DPCD_VOLTAGE_SWING_GET(training_lane) == voltage_swing && + DPCD_PRE_EMPHASIS_GET(training_lane) == pre_emphasis) + dp->link_train.cr_loop[lane]++; + + if (dp->link_train.cr_loop[lane] == MAX_CR_LOOP || + voltage_swing == VOLTAGE_LEVEL_3 || + pre_emphasis == PRE_EMPHASIS_LEVEL_3) { + dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", + dp->link_train.cr_loop[lane], + voltage_swing, pre_emphasis); + analogix_dp_reduce_link_rate(dp); + return -EIO; } } From 9c3951ec27b947ea419b48294ff7342fd15005dc Mon Sep 17 00:00:00 2001 From: Tvrtko Ursulin Date: Tue, 4 Jun 2024 17:02:10 +0100 Subject: [PATCH 17/18] drm/v3d: Fix perfmon build error/warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Move static const array into the source file to fix the "defined but not used" errors. The fix is perhaps not the prettiest due hand crafting the array sizes in v3d_performance_counters.h, but I did add some build time asserts to validate the counts look sensible, so hopefully it is good enough for a quick fix. Signed-off-by: Tvrtko Ursulin Fixes: 3cbcbe016c31 ("drm/v3d: Add Performance Counters descriptions for V3D 4.2 and 7.1") Reported-by: kernel test robot Closes: https://lore.kernel.org/oe-kbuild-all/202405211137.hueFkLKG-lkp@intel.com/Cc: Maíra Canal Cc: Iago Toral Quiroga Cc: Jani Nikula Cc: Ashutosh Dixit Reviewed-by: Iago Toral Quiroga Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20240604160210.24073-1-tursulin@igalia.com --- drivers/gpu/drm/v3d/v3d_drv.c | 4 +- drivers/gpu/drm/v3d/v3d_drv.h | 3 - drivers/gpu/drm/v3d/v3d_perfmon.c | 204 +++++++++++++++++- .../gpu/drm/v3d/v3d_performance_counters.h | 189 +--------------- 4 files changed, 205 insertions(+), 195 deletions(-) diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c index f7477488b1cc..a47f00b443d3 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.c +++ b/drivers/gpu/drm/v3d/v3d_drv.c @@ -299,9 +299,9 @@ static int v3d_platform_drm_probe(struct platform_device *pdev) WARN_ON(v3d->cores > 1); /* multicore not yet implemented */ if (v3d->ver >= 71) - v3d->max_counters = ARRAY_SIZE(v3d_v71_performance_counters); + v3d->max_counters = V3D_V71_NUM_PERFCOUNTERS; else if (v3d->ver >= 42) - v3d->max_counters = ARRAY_SIZE(v3d_v42_performance_counters); + v3d->max_counters = V3D_V42_NUM_PERFCOUNTERS; else v3d->max_counters = 0; diff --git a/drivers/gpu/drm/v3d/v3d_drv.h b/drivers/gpu/drm/v3d/v3d_drv.h index 556cbb400ba0..099b962bdfde 100644 --- a/drivers/gpu/drm/v3d/v3d_drv.h +++ b/drivers/gpu/drm/v3d/v3d_drv.h @@ -351,9 +351,6 @@ struct v3d_timestamp_query { struct drm_syncobj *syncobj; }; -/* Maximum number of performance counters supported by any version of V3D */ -#define V3D_MAX_COUNTERS ARRAY_SIZE(v3d_v71_performance_counters) - /* Number of perfmons required to handle all supported performance counters */ #define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_MAX_COUNTERS, \ DRM_V3D_MAX_PERF_COUNTERS) diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c index 73e2bb8bdb7f..b7d0b02e1a95 100644 --- a/drivers/gpu/drm/v3d/v3d_perfmon.c +++ b/drivers/gpu/drm/v3d/v3d_perfmon.c @@ -9,6 +9,192 @@ #define V3D_PERFMONID_MIN 1 #define V3D_PERFMONID_MAX U32_MAX +static const struct v3d_perf_counter_desc v3d_v42_performance_counters[] = { + {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"}, + {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"}, + {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"}, + {"FEP", "FEP-valid-quads", "[FEP] Valid quads"}, + {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"}, + {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"}, + {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"}, + {"TLB", "TLB-quads-with-zero-coverage", "[TLB] Quads with all pixels having zero coverage"}, + {"TLB", "TLB-quads-with-non-zero-coverage", "[TLB] Quads with any pixels having non-zero coverage"}, + {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"}, + {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"}, + {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"}, + {"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"}, + {"QPU", "QPU-total-idle-clk-cycles", "[QPU] Total idle clock cycles for all QPUs"}, + {"QPU", "QPU-total-active-clk-cycles-vertex-coord-shading", "[QPU] Total active clock cycles for all QPUs doing vertex/coordinate/user shading (counts only when QPU is not stalled)"}, + {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"}, + {"QPU", "QPU-total-clk-cycles-executing-valid-instr", "[QPU] Total clock cycles for all QPUs executing valid instructions"}, + {"QPU", "QPU-total-clk-cycles-waiting-TMU", "[QPU] Total clock cycles for all QPUs stalled waiting for TMUs only (counter won't increment if QPU also stalling for another reason)"}, + {"QPU", "QPU-total-clk-cycles-waiting-scoreboard", "[QPU] Total clock cycles for all QPUs stalled waiting for Scoreboard only (counter won't increment if QPU also stalling for another reason)"}, + {"QPU", "QPU-total-clk-cycles-waiting-varyings", "[QPU] Total clock cycles for all QPUs stalled waiting for Varyings only (counter won't increment if QPU also stalling for another reason)"}, + {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"}, + {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"}, + {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"}, + {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"}, + {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"}, + {"TMU", "TMU-total-text-cache-miss", "[TMU] Total texture cache misses (number of fetches from memory/L2cache)"}, + {"VPM", "VPM-total-clk-cycles-VDW-stalled", "[VPM] Total clock cycles VDW is stalled waiting for VPM access"}, + {"VPM", "VPM-total-clk-cycles-VCD-stalled", "[VPM] Total clock cycles VCD is stalled waiting for VPM access"}, + {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"}, + {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"}, + {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"}, + {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"}, + {"CORE", "cycle-count", "[CORE] Cycle counter"}, + {"QPU", "QPU-total-clk-cycles-waiting-vertex-coord-shading", "[QPU] Total stalled clock cycles for all QPUs doing vertex/coordinate/user shading"}, + {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"}, + {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"}, + {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"}, + {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"}, + {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"}, + {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"}, + {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"}, + {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"}, + {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"}, + {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"}, + {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"}, + {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"}, + {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"}, + {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"}, + {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"}, + {"TMU", "TMU-total-config-access", "[TMU] Total config accesses"}, + {"L2T", "L2T-no-id-stalled", "[L2T] No ID stall"}, + {"L2T", "L2T-command-queue-stalled", "[L2T] Command queue full stall"}, + {"L2T", "L2T-TMU-writes", "[L2T] TMU write accesses"}, + {"TMU", "TMU-active-cycles", "[TMU] Active cycles"}, + {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"}, + {"CLE", "CLE-thread-active-cycles", "[CLE] Bin or render thread active cycles"}, + {"L2T", "L2T-TMU-reads", "[L2T] TMU read accesses"}, + {"L2T", "L2T-CLE-reads", "[L2T] CLE read accesses"}, + {"L2T", "L2T-VCD-reads", "[L2T] VCD read accesses"}, + {"L2T", "L2T-TMU-config-reads", "[L2T] TMU CFG read accesses"}, + {"L2T", "L2T-SLC0-reads", "[L2T] SLC0 read accesses"}, + {"L2T", "L2T-SLC1-reads", "[L2T] SLC1 read accesses"}, + {"L2T", "L2T-SLC2-reads", "[L2T] SLC2 read accesses"}, + {"L2T", "L2T-TMU-write-miss", "[L2T] TMU write misses"}, + {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"}, + {"L2T", "L2T-CLE-read-miss", "[L2T] CLE read misses"}, + {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"}, + {"L2T", "L2T-TMU-config-read-miss", "[L2T] TMU CFG read misses"}, + {"L2T", "L2T-SLC0-read-miss", "[L2T] SLC0 read misses"}, + {"L2T", "L2T-SLC1-read-miss", "[L2T] SLC1 read misses"}, + {"L2T", "L2T-SLC2-read-miss", "[L2T] SLC2 read misses"}, + {"CORE", "core-memory-writes", "[CORE] Total memory writes"}, + {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"}, + {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"}, + {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"}, + {"CORE", "core-memory-reads", "[CORE] Total memory reads"}, + {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"}, + {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"}, + {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"}, + {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"}, + {"GMP", "GMP-memory-reads", "[GMP] Total memory reads"}, + {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"}, + {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"}, + {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"}, + {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"}, + {"TMU", "TMU-MRU-hits", "[TMU] Total MRU hits"}, + {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"}, +}; + +static const struct v3d_perf_counter_desc v3d_v71_performance_counters[] = { + {"CORE", "cycle-count", "[CORE] Cycle counter"}, + {"CORE", "core-active", "[CORE] Bin/Render/Compute active cycles"}, + {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"}, + {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"}, + {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"}, + {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"}, + {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"}, + {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"}, + {"FEP", "FEP-valid-quads", "[FEP] Valid quads"}, + {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"}, + {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"}, + {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"}, + {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"}, + {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"}, + {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"}, + {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"}, + {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"}, + {"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"}, + {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"}, + {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"}, + {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"}, + {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"}, + {"TMU", "TMU-active-cycles", "[TMU] Active cycles"}, + {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"}, + {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"}, + {"TMU", "TMU-cache-x4-active-cycles", "[TMU] Cache active cycles for x4 access"}, + {"TMU", "TMU-cache-x4-stalled-cycles", "[TMU] Cache stalled cycles for x4 access"}, + {"TMU", "TMU-total-text-quads-x4-access", "[TMU] Total texture cache x4 access"}, + {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"}, + {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"}, + {"L2T", "L2T-local", "[L2T] Local mode access"}, + {"L2T", "L2T-writeback", "[L2T] Writeback"}, + {"L2T", "L2T-zero", "[L2T] Zero"}, + {"L2T", "L2T-merge", "[L2T] Merge"}, + {"L2T", "L2T-fill", "[L2T] Fill"}, + {"L2T", "L2T-stalls-no-wid", "[L2T] Stalls because no WID available"}, + {"L2T", "L2T-stalls-no-rid", "[L2T] Stalls because no RID available"}, + {"L2T", "L2T-stalls-queue-full", "[L2T] Stalls because internal queue full"}, + {"L2T", "L2T-stalls-wrightback", "[L2T] Stalls because writeback in flight"}, + {"L2T", "L2T-stalls-mem", "[L2T] Stalls because AXI blocks read"}, + {"L2T", "L2T-stalls-fill", "[L2T] Stalls because fill pending for victim cache-line"}, + {"L2T", "L2T-hitq", "[L2T] Sent request via hit queue"}, + {"L2T", "L2T-hitq-full", "[L2T] Sent request via main queue because hit queue is full"}, + {"L2T", "L2T-stalls-read-data", "[L2T] Stalls because waiting for data from SDRAM"}, + {"L2T", "L2T-TMU-read-hits", "[L2T] TMU read hits"}, + {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"}, + {"L2T", "L2T-VCD-read-hits", "[L2T] VCD read hits"}, + {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"}, + {"L2T", "L2T-SLC-read-hits", "[L2T] SLC read hits (all slices)"}, + {"L2T", "L2T-SLC-read-miss", "[L2T] SLC read misses (all slices)"}, + {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"}, + {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"}, + {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"}, + {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"}, + {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"}, + {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"}, + {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"}, + {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"}, + {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"}, + {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"}, + {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"}, + {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"}, + {"CORE", "core-memory-writes", "[CORE] Total memory writes"}, + {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"}, + {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"}, + {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"}, + {"CORE", "core-memory-reads", "[CORE] Total memory reads"}, + {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"}, + {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"}, + {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"}, + {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"}, + {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"}, + {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"}, + {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"}, + {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"}, + {"AXI", "AXI-read-trans", "[AXI] Read transaction count"}, + {"AXI", "AXI-write-trans", "[AXI] Write transaction count"}, + {"AXI", "AXI-read-wait-cycles", "[AXI] Read total wait cycles"}, + {"AXI", "AXI-write-wait-cycles", "[AXI] Write total wait cycles"}, + {"AXI", "AXI-max-outstanding-reads", "[AXI] Maximum outstanding read transactions"}, + {"AXI", "AXI-max-outstanding-writes", "[AXI] Maximum outstanding write transactions"}, + {"QPU", "QPU-wait-bubble", "[QPU] Pipeline bubble in qcycles due all threads waiting"}, + {"QPU", "QPU-ic-miss-bubble", "[QPU] Pipeline bubble in qcycles due instruction-cache miss"}, + {"QPU", "QPU-active", "[QPU] Executed shader instruction"}, + {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"}, + {"QPU", "QPU-stalls", "[QPU] Stalled qcycles executing shader instruction"}, + {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"}, + {"QPU", "QPU-stalls-TMU", "[QPU] Stalled qcycles waiting for TMU"}, + {"QPU", "QPU-stalls-TLB", "[QPU] Stalled qcycles waiting for TLB"}, + {"QPU", "QPU-stalls-VPM", "[QPU] Stalled qcycles waiting for VPM"}, + {"QPU", "QPU-stalls-uniforms", "[QPU] Stalled qcycles waiting for uniforms"}, + {"QPU", "QPU-stalls-SFU", "[QPU] Stalled qcycles waiting for SFU"}, + {"QPU", "QPU-stalls-other", "[QPU] Stalled qcycles waiting for any other reason (vary/W/Z)"}, +}; + void v3d_perfmon_get(struct v3d_perfmon *perfmon) { if (perfmon) @@ -234,15 +420,21 @@ int v3d_perfmon_get_counter_ioctl(struct drm_device *dev, void *data, if (req->counter >= v3d->max_counters) return -EINVAL; - if (v3d->ver >= 71) { - WARN_ON(v3d->max_counters != ARRAY_SIZE(v3d_v71_performance_counters)); + BUILD_BUG_ON(ARRAY_SIZE(v3d_v42_performance_counters) != + V3D_V42_NUM_PERFCOUNTERS); + BUILD_BUG_ON(ARRAY_SIZE(v3d_v71_performance_counters) != + V3D_V71_NUM_PERFCOUNTERS); + BUILD_BUG_ON(V3D_MAX_COUNTERS < V3D_V42_NUM_PERFCOUNTERS); + BUILD_BUG_ON(V3D_MAX_COUNTERS < V3D_V71_NUM_PERFCOUNTERS); + BUILD_BUG_ON((V3D_MAX_COUNTERS != V3D_V42_NUM_PERFCOUNTERS) && + (V3D_MAX_COUNTERS != V3D_V71_NUM_PERFCOUNTERS)); + + if (v3d->ver >= 71) counter = &v3d_v71_performance_counters[req->counter]; - } else if (v3d->ver >= 42) { - WARN_ON(v3d->max_counters != ARRAY_SIZE(v3d_v42_performance_counters)); + else if (v3d->ver >= 42) counter = &v3d_v42_performance_counters[req->counter]; - } else { + else return -EOPNOTSUPP; - } strscpy(req->name, counter->name, sizeof(req->name)); strscpy(req->category, counter->category, sizeof(req->category)); diff --git a/drivers/gpu/drm/v3d/v3d_performance_counters.h b/drivers/gpu/drm/v3d/v3d_performance_counters.h index 72822205ebdc..131b2909522a 100644 --- a/drivers/gpu/drm/v3d/v3d_performance_counters.h +++ b/drivers/gpu/drm/v3d/v3d_performance_counters.h @@ -19,190 +19,11 @@ struct v3d_perf_counter_desc { char description[256]; }; -static const struct v3d_perf_counter_desc v3d_v71_performance_counters[] = { - {"CORE", "cycle-count", "[CORE] Cycle counter"}, - {"CORE", "core-active", "[CORE] Bin/Render/Compute active cycles"}, - {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"}, - {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"}, - {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"}, - {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"}, - {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"}, - {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"}, - {"FEP", "FEP-valid-quads", "[FEP] Valid quads"}, - {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"}, - {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"}, - {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"}, - {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"}, - {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"}, - {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"}, - {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"}, - {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"}, - {"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"}, - {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"}, - {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"}, - {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"}, - {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"}, - {"TMU", "TMU-active-cycles", "[TMU] Active cycles"}, - {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"}, - {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"}, - {"TMU", "TMU-cache-x4-active-cycles", "[TMU] Cache active cycles for x4 access"}, - {"TMU", "TMU-cache-x4-stalled-cycles", "[TMU] Cache stalled cycles for x4 access"}, - {"TMU", "TMU-total-text-quads-x4-access", "[TMU] Total texture cache x4 access"}, - {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"}, - {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"}, - {"L2T", "L2T-local", "[L2T] Local mode access"}, - {"L2T", "L2T-writeback", "[L2T] Writeback"}, - {"L2T", "L2T-zero", "[L2T] Zero"}, - {"L2T", "L2T-merge", "[L2T] Merge"}, - {"L2T", "L2T-fill", "[L2T] Fill"}, - {"L2T", "L2T-stalls-no-wid", "[L2T] Stalls because no WID available"}, - {"L2T", "L2T-stalls-no-rid", "[L2T] Stalls because no RID available"}, - {"L2T", "L2T-stalls-queue-full", "[L2T] Stalls because internal queue full"}, - {"L2T", "L2T-stalls-wrightback", "[L2T] Stalls because writeback in flight"}, - {"L2T", "L2T-stalls-mem", "[L2T] Stalls because AXI blocks read"}, - {"L2T", "L2T-stalls-fill", "[L2T] Stalls because fill pending for victim cache-line"}, - {"L2T", "L2T-hitq", "[L2T] Sent request via hit queue"}, - {"L2T", "L2T-hitq-full", "[L2T] Sent request via main queue because hit queue is full"}, - {"L2T", "L2T-stalls-read-data", "[L2T] Stalls because waiting for data from SDRAM"}, - {"L2T", "L2T-TMU-read-hits", "[L2T] TMU read hits"}, - {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"}, - {"L2T", "L2T-VCD-read-hits", "[L2T] VCD read hits"}, - {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"}, - {"L2T", "L2T-SLC-read-hits", "[L2T] SLC read hits (all slices)"}, - {"L2T", "L2T-SLC-read-miss", "[L2T] SLC read misses (all slices)"}, - {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"}, - {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"}, - {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"}, - {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"}, - {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"}, - {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"}, - {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"}, - {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"}, - {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"}, - {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"}, - {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"}, - {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"}, - {"CORE", "core-memory-writes", "[CORE] Total memory writes"}, - {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"}, - {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"}, - {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"}, - {"CORE", "core-memory-reads", "[CORE] Total memory reads"}, - {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"}, - {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"}, - {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"}, - {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"}, - {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"}, - {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"}, - {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"}, - {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"}, - {"AXI", "AXI-read-trans", "[AXI] Read transaction count"}, - {"AXI", "AXI-write-trans", "[AXI] Write transaction count"}, - {"AXI", "AXI-read-wait-cycles", "[AXI] Read total wait cycles"}, - {"AXI", "AXI-write-wait-cycles", "[AXI] Write total wait cycles"}, - {"AXI", "AXI-max-outstanding-reads", "[AXI] Maximum outstanding read transactions"}, - {"AXI", "AXI-max-outstanding-writes", "[AXI] Maximum outstanding write transactions"}, - {"QPU", "QPU-wait-bubble", "[QPU] Pipeline bubble in qcycles due all threads waiting"}, - {"QPU", "QPU-ic-miss-bubble", "[QPU] Pipeline bubble in qcycles due instruction-cache miss"}, - {"QPU", "QPU-active", "[QPU] Executed shader instruction"}, - {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"}, - {"QPU", "QPU-stalls", "[QPU] Stalled qcycles executing shader instruction"}, - {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"}, - {"QPU", "QPU-stalls-TMU", "[QPU] Stalled qcycles waiting for TMU"}, - {"QPU", "QPU-stalls-TLB", "[QPU] Stalled qcycles waiting for TLB"}, - {"QPU", "QPU-stalls-VPM", "[QPU] Stalled qcycles waiting for VPM"}, - {"QPU", "QPU-stalls-uniforms", "[QPU] Stalled qcycles waiting for uniforms"}, - {"QPU", "QPU-stalls-SFU", "[QPU] Stalled qcycles waiting for SFU"}, - {"QPU", "QPU-stalls-other", "[QPU] Stalled qcycles waiting for any other reason (vary/W/Z)"}, -}; -static const struct v3d_perf_counter_desc v3d_v42_performance_counters[] = { - {"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"}, - {"FEP", "FEP-valid-primitives-rendered-pixels", "[FEP] Valid primitives for all rendered tiles (primitives may be counted in more than one tile)"}, - {"FEP", "FEP-clipped-quads", "[FEP] Early-Z/Near/Far clipped quads"}, - {"FEP", "FEP-valid-quads", "[FEP] Valid quads"}, - {"TLB", "TLB-quads-not-passing-stencil-test", "[TLB] Quads with no pixels passing the stencil test"}, - {"TLB", "TLB-quads-not-passing-z-and-stencil-test", "[TLB] Quads with no pixels passing the Z and stencil tests"}, - {"TLB", "TLB-quads-passing-z-and-stencil-test", "[TLB] Quads with any pixels passing the Z and stencil tests"}, - {"TLB", "TLB-quads-with-zero-coverage", "[TLB] Quads with all pixels having zero coverage"}, - {"TLB", "TLB-quads-with-non-zero-coverage", "[TLB] Quads with any pixels having non-zero coverage"}, - {"TLB", "TLB-quads-written-to-color-buffer", "[TLB] Quads with valid pixels written to colour buffer"}, - {"PTB", "PTB-primitives-discarded-outside-viewport", "[PTB] Primitives discarded by being outside the viewport"}, - {"PTB", "PTB-primitives-need-clipping", "[PTB] Primitives that need clipping"}, - {"PTB", "PTB-primitives-discarded-reversed", "[PTB] Primitives that are discarded because they are reversed"}, - {"QPU", "QPU-total-idle-clk-cycles", "[QPU] Total idle clock cycles for all QPUs"}, - {"QPU", "QPU-total-active-clk-cycles-vertex-coord-shading", "[QPU] Total active clock cycles for all QPUs doing vertex/coordinate/user shading (counts only when QPU is not stalled)"}, - {"QPU", "QPU-total-active-clk-cycles-fragment-shading", "[QPU] Total active clock cycles for all QPUs doing fragment shading (counts only when QPU is not stalled)"}, - {"QPU", "QPU-total-clk-cycles-executing-valid-instr", "[QPU] Total clock cycles for all QPUs executing valid instructions"}, - {"QPU", "QPU-total-clk-cycles-waiting-TMU", "[QPU] Total clock cycles for all QPUs stalled waiting for TMUs only (counter won't increment if QPU also stalling for another reason)"}, - {"QPU", "QPU-total-clk-cycles-waiting-scoreboard", "[QPU] Total clock cycles for all QPUs stalled waiting for Scoreboard only (counter won't increment if QPU also stalling for another reason)"}, - {"QPU", "QPU-total-clk-cycles-waiting-varyings", "[QPU] Total clock cycles for all QPUs stalled waiting for Varyings only (counter won't increment if QPU also stalling for another reason)"}, - {"QPU", "QPU-total-instr-cache-hit", "[QPU] Total instruction cache hits for all slices"}, - {"QPU", "QPU-total-instr-cache-miss", "[QPU] Total instruction cache misses for all slices"}, - {"QPU", "QPU-total-uniform-cache-hit", "[QPU] Total uniforms cache hits for all slices"}, - {"QPU", "QPU-total-uniform-cache-miss", "[QPU] Total uniforms cache misses for all slices"}, - {"TMU", "TMU-total-text-quads-access", "[TMU] Total texture cache accesses"}, - {"TMU", "TMU-total-text-cache-miss", "[TMU] Total texture cache misses (number of fetches from memory/L2cache)"}, - {"VPM", "VPM-total-clk-cycles-VDW-stalled", "[VPM] Total clock cycles VDW is stalled waiting for VPM access"}, - {"VPM", "VPM-total-clk-cycles-VCD-stalled", "[VPM] Total clock cycles VCD is stalled waiting for VPM access"}, - {"CLE", "CLE-bin-thread-active-cycles", "[CLE] Bin thread active cycles"}, - {"CLE", "CLE-render-thread-active-cycles", "[CLE] Render thread active cycles"}, - {"L2T", "L2T-total-cache-hit", "[L2T] Total Level 2 cache hits"}, - {"L2T", "L2T-total-cache-miss", "[L2T] Total Level 2 cache misses"}, - {"CORE", "cycle-count", "[CORE] Cycle counter"}, - {"QPU", "QPU-total-clk-cycles-waiting-vertex-coord-shading", "[QPU] Total stalled clock cycles for all QPUs doing vertex/coordinate/user shading"}, - {"QPU", "QPU-total-clk-cycles-waiting-fragment-shading", "[QPU] Total stalled clock cycles for all QPUs doing fragment shading"}, - {"PTB", "PTB-primitives-binned", "[PTB] Total primitives binned"}, - {"AXI", "AXI-writes-seen-watch-0", "[AXI] Writes seen by watch 0"}, - {"AXI", "AXI-reads-seen-watch-0", "[AXI] Reads seen by watch 0"}, - {"AXI", "AXI-writes-stalled-seen-watch-0", "[AXI] Write stalls seen by watch 0"}, - {"AXI", "AXI-reads-stalled-seen-watch-0", "[AXI] Read stalls seen by watch 0"}, - {"AXI", "AXI-write-bytes-seen-watch-0", "[AXI] Total bytes written seen by watch 0"}, - {"AXI", "AXI-read-bytes-seen-watch-0", "[AXI] Total bytes read seen by watch 0"}, - {"AXI", "AXI-writes-seen-watch-1", "[AXI] Writes seen by watch 1"}, - {"AXI", "AXI-reads-seen-watch-1", "[AXI] Reads seen by watch 1"}, - {"AXI", "AXI-writes-stalled-seen-watch-1", "[AXI] Write stalls seen by watch 1"}, - {"AXI", "AXI-reads-stalled-seen-watch-1", "[AXI] Read stalls seen by watch 1"}, - {"AXI", "AXI-write-bytes-seen-watch-1", "[AXI] Total bytes written seen by watch 1"}, - {"AXI", "AXI-read-bytes-seen-watch-1", "[AXI] Total bytes read seen by watch 1"}, - {"TLB", "TLB-partial-quads-written-to-color-buffer", "[TLB] Partial quads written to the colour buffer"}, - {"TMU", "TMU-total-config-access", "[TMU] Total config accesses"}, - {"L2T", "L2T-no-id-stalled", "[L2T] No ID stall"}, - {"L2T", "L2T-command-queue-stalled", "[L2T] Command queue full stall"}, - {"L2T", "L2T-TMU-writes", "[L2T] TMU write accesses"}, - {"TMU", "TMU-active-cycles", "[TMU] Active cycles"}, - {"TMU", "TMU-stalled-cycles", "[TMU] Stalled cycles"}, - {"CLE", "CLE-thread-active-cycles", "[CLE] Bin or render thread active cycles"}, - {"L2T", "L2T-TMU-reads", "[L2T] TMU read accesses"}, - {"L2T", "L2T-CLE-reads", "[L2T] CLE read accesses"}, - {"L2T", "L2T-VCD-reads", "[L2T] VCD read accesses"}, - {"L2T", "L2T-TMU-config-reads", "[L2T] TMU CFG read accesses"}, - {"L2T", "L2T-SLC0-reads", "[L2T] SLC0 read accesses"}, - {"L2T", "L2T-SLC1-reads", "[L2T] SLC1 read accesses"}, - {"L2T", "L2T-SLC2-reads", "[L2T] SLC2 read accesses"}, - {"L2T", "L2T-TMU-write-miss", "[L2T] TMU write misses"}, - {"L2T", "L2T-TMU-read-miss", "[L2T] TMU read misses"}, - {"L2T", "L2T-CLE-read-miss", "[L2T] CLE read misses"}, - {"L2T", "L2T-VCD-read-miss", "[L2T] VCD read misses"}, - {"L2T", "L2T-TMU-config-read-miss", "[L2T] TMU CFG read misses"}, - {"L2T", "L2T-SLC0-read-miss", "[L2T] SLC0 read misses"}, - {"L2T", "L2T-SLC1-read-miss", "[L2T] SLC1 read misses"}, - {"L2T", "L2T-SLC2-read-miss", "[L2T] SLC2 read misses"}, - {"CORE", "core-memory-writes", "[CORE] Total memory writes"}, - {"L2T", "L2T-memory-writes", "[L2T] Total memory writes"}, - {"PTB", "PTB-memory-writes", "[PTB] Total memory writes"}, - {"TLB", "TLB-memory-writes", "[TLB] Total memory writes"}, - {"CORE", "core-memory-reads", "[CORE] Total memory reads"}, - {"L2T", "L2T-memory-reads", "[L2T] Total memory reads"}, - {"PTB", "PTB-memory-reads", "[PTB] Total memory reads"}, - {"PSE", "PSE-memory-reads", "[PSE] Total memory reads"}, - {"TLB", "TLB-memory-reads", "[TLB] Total memory reads"}, - {"GMP", "GMP-memory-reads", "[GMP] Total memory reads"}, - {"PTB", "PTB-memory-words-writes", "[PTB] Total memory words written"}, - {"TLB", "TLB-memory-words-writes", "[TLB] Total memory words written"}, - {"PSE", "PSE-memory-words-reads", "[PSE] Total memory words read"}, - {"TLB", "TLB-memory-words-reads", "[TLB] Total memory words read"}, - {"TMU", "TMU-MRU-hits", "[TMU] Total MRU hits"}, - {"CORE", "compute-active-cycles", "[CORE] Compute active cycles"}, -}; +#define V3D_V42_NUM_PERFCOUNTERS (87) +#define V3D_V71_NUM_PERFCOUNTERS (93) + +/* Maximum number of performance counters supported by any version of V3D */ +#define V3D_MAX_COUNTERS (93) #endif From 310ec03841a36e3f45fb528f0dfdfe5b9e84b037 Mon Sep 17 00:00:00 2001 From: Barry Song Date: Wed, 5 Jun 2024 13:26:05 +1200 Subject: [PATCH 18/18] dma-buf: align fd_flags and heap_flags with dma_heap_allocation_data dma_heap_allocation_data defines the UAPI as follows: struct dma_heap_allocation_data { __u64 len; __u32 fd; __u32 fd_flags; __u64 heap_flags; }; However, dma_heap_buffer_alloc() casts both fd_flags and heap_flags into unsigned int. We're inconsistent with types in the non UAPI arguments. This patch fixes it. Signed-off-by: Barry Song Acked-by: John Stultz Signed-off-by: Sumit Semwal Link: https://patchwork.freedesktop.org/patch/msgid/20240605012605.5341-1-21cnbao@gmail.com --- drivers/dma-buf/dma-heap.c | 4 ++-- include/uapi/linux/dma-heap.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/dma-buf/dma-heap.c b/drivers/dma-buf/dma-heap.c index 84ae708fafe7..2298ca5e112e 100644 --- a/drivers/dma-buf/dma-heap.c +++ b/drivers/dma-buf/dma-heap.c @@ -50,8 +50,8 @@ static struct class *dma_heap_class; static DEFINE_XARRAY_ALLOC(dma_heap_minors); static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, - unsigned int fd_flags, - unsigned int heap_flags) + u32 fd_flags, + u64 heap_flags) { struct dma_buf *dmabuf; int fd; diff --git a/include/uapi/linux/dma-heap.h b/include/uapi/linux/dma-heap.h index 6f84fa08e074..a4cf716a49fa 100644 --- a/include/uapi/linux/dma-heap.h +++ b/include/uapi/linux/dma-heap.h @@ -19,7 +19,7 @@ #define DMA_HEAP_VALID_FD_FLAGS (O_CLOEXEC | O_ACCMODE) /* Currently no heap flags */ -#define DMA_HEAP_VALID_HEAP_FLAGS (0) +#define DMA_HEAP_VALID_HEAP_FLAGS (0ULL) /** * struct dma_heap_allocation_data - metadata passed from userspace for