drm-misc-next for 6.10:

UAPI Changes:
 
 Cross-subsystem Changes:
   - dma-buf: Warn when reserving 0 fence slots, internal API
     enhancements for heaps
 
 Core Changes:
 
 Driver Changes:
   - atmel-hlcdc: Support XLCDC in sam9x7
   - msm: Validate registers XML description against schema in CI
   - v3d: Fix build warning
   - bridges:
     - analogix_dp: Various improvements
   - panels:
     - New panel: WL-355608-A8
 -----BEGIN PGP SIGNATURE-----
 
 iJUEABMJAB0WIQTkHFbLp4ejekA/qfgnX84Zoj2+dgUCZmGY+AAKCRAnX84Zoj2+
 dqc9AX9zZrltH2ZIOVIKeMwxtVzJT45PkO1e7M1kWdtJ7LNXAty1d0XowLNErVUG
 4nXutYoBgN0n9Nw8HM39zrxpxga/axZ8UOEDr6VSxNR81Aqa5sfU/uqYS+y87aUh
 iuagVMNWdA==
 =mRtw
 -----END PGP SIGNATURE-----

Merge tag 'drm-misc-next-2024-06-06' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next

drm-misc-next for 6.10:

UAPI Changes:

Cross-subsystem Changes:
  - dma-buf: Warn when reserving 0 fence slots, internal API
    enhancements for heaps

Core Changes:

Driver Changes:
  - atmel-hlcdc: Support XLCDC in sam9x7
  - msm: Validate registers XML description against schema in CI
  - v3d: Fix build warning
  - bridges:
    - analogix_dp: Various improvements
  - panels:
    - New panel: WL-355608-A8

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Maxime Ripard <mripard@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240606-vivid-amphibian-jackrabbit-40b1d1@houat
This commit is contained in:
Dave Airlie 2024-06-21 10:31:14 +10:00
commit 6dac16124c
20 changed files with 1239 additions and 563 deletions

View File

@ -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 <ryan@testtoast.com>
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 <dt-bindings/gpio/gpio.h>
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 = <&reg_lcd>;
port {
endpoint {
remote-endpoint = <&tcon_lcd0_out_lcd>;
};
};
};
};

View File

@ -7566,7 +7566,6 @@ F: include/drm/gpu_scheduler.h
DRM PANEL DRIVERS DRM PANEL DRIVERS
M: Neil Armstrong <neil.armstrong@linaro.org> M: Neil Armstrong <neil.armstrong@linaro.org>
R: Jessica Zhang <quic_jesszhan@quicinc.com> R: Jessica Zhang <quic_jesszhan@quicinc.com>
R: Sam Ravnborg <sam@ravnborg.org>
L: dri-devel@lists.freedesktop.org L: dri-devel@lists.freedesktop.org
S: Maintained S: Maintained
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git T: git https://gitlab.freedesktop.org/drm/misc/kernel.git

View File

@ -50,8 +50,8 @@ static struct class *dma_heap_class;
static DEFINE_XARRAY_ALLOC(dma_heap_minors); static DEFINE_XARRAY_ALLOC(dma_heap_minors);
static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len, static int dma_heap_buffer_alloc(struct dma_heap *heap, size_t len,
unsigned int fd_flags, u32 fd_flags,
unsigned int heap_flags) u64 heap_flags)
{ {
struct dma_buf *dmabuf; struct dma_buf *dmabuf;
int fd; int fd;

View File

@ -186,6 +186,13 @@ int dma_resv_reserve_fences(struct dma_resv *obj, unsigned int num_fences)
dma_resv_assert_held(obj); 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); old = dma_resv_fences_list(obj);
if (old && old->max_fences) { if (old && old->max_fences) {
if ((old->num_fences + num_fences) <= old->max_fences) if ((old->num_fences + num_fences) <= old->max_fences)

View File

@ -30,10 +30,12 @@
* *
* @base: base CRTC state * @base: base CRTC state
* @output_mode: RGBXXX output mode * @output_mode: RGBXXX output mode
* @dpi: output DPI mode
*/ */
struct atmel_hlcdc_crtc_state { struct atmel_hlcdc_crtc_state {
struct drm_crtc_state base; struct drm_crtc_state base;
unsigned int output_mode; unsigned int output_mode;
u8 dpi;
}; };
static inline struct atmel_hlcdc_crtc_state * static inline struct atmel_hlcdc_crtc_state *
@ -164,18 +166,24 @@ static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state); state = drm_crtc_state_to_atmel_hlcdc_crtc_state(c->state);
cfg = state->output_mode << 8; cfg = state->output_mode << 8;
if (adj->flags & DRM_MODE_FLAG_NVSYNC) if (!crtc->dc->desc->is_xlcdc) {
cfg |= ATMEL_HLCDC_VSPOL; if (adj->flags & DRM_MODE_FLAG_NVSYNC)
cfg |= ATMEL_HLCDC_VSPOL;
if (adj->flags & DRM_MODE_FLAG_NHSYNC) if (adj->flags & DRM_MODE_FLAG_NHSYNC)
cfg |= ATMEL_HLCDC_HSPOL; cfg |= ATMEL_HLCDC_HSPOL;
} else {
cfg |= state->dpi << 11;
}
regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5), regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5),
ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL | ATMEL_HLCDC_HSPOL | ATMEL_HLCDC_VSPOL |
ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE | ATMEL_HLCDC_VSPDLYS | ATMEL_HLCDC_VSPDLYE |
ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY | ATMEL_HLCDC_DISPPOL | ATMEL_HLCDC_DISPDLY |
ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | 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); cfg);
clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); clk_disable_unprepare(crtc->dc->hlcdc->sys_clk);
@ -202,20 +210,37 @@ static void atmel_hlcdc_crtc_atomic_disable(struct drm_crtc *c,
pm_runtime_get_sync(dev->dev); 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); regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
(status & ATMEL_HLCDC_DISP)) !(status & ATMEL_HLCDC_DISP),
cpu_relax(); 10, 1000))
dev_warn(dev->dev, "Atmel LCDC status register DISPSTS timeout\n");
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC); regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
(status & ATMEL_HLCDC_SYNC)) !(status & ATMEL_HLCDC_SYNC),
cpu_relax(); 10, 1000))
dev_warn(dev->dev, "Atmel LCDC status register LCDSTS timeout\n");
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK); regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
(status & ATMEL_HLCDC_PIXEL_CLK)) !(status & ATMEL_HLCDC_PIXEL_CLK),
cpu_relax(); 10, 1000))
dev_warn(dev->dev, "Atmel LCDC status register CLKSTS timeout\n");
clk_disable_unprepare(crtc->dc->hlcdc->sys_clk); clk_disable_unprepare(crtc->dc->hlcdc->sys_clk);
pinctrl_pm_select_sleep_state(dev->dev); pinctrl_pm_select_sleep_state(dev->dev);
@ -241,30 +266,95 @@ static void atmel_hlcdc_crtc_atomic_enable(struct drm_crtc *c,
clk_prepare_enable(crtc->dc->hlcdc->sys_clk); clk_prepare_enable(crtc->dc->hlcdc->sys_clk);
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK); regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
!(status & ATMEL_HLCDC_PIXEL_CLK)) status & ATMEL_HLCDC_PIXEL_CLK,
cpu_relax(); 10, 1000))
dev_warn(dev->dev, "Atmel LCDC status register CLKSTS timeout\n");
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC); regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
!(status & ATMEL_HLCDC_SYNC)) status & ATMEL_HLCDC_SYNC,
cpu_relax(); 10, 1000))
dev_warn(dev->dev, "Atmel LCDC status register LCDSTS timeout\n");
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP); regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) && if (regmap_read_poll_timeout(regmap, ATMEL_HLCDC_SR, status,
!(status & ATMEL_HLCDC_DISP)) status & ATMEL_HLCDC_DISP,
cpu_relax(); 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); pm_runtime_put_sync(dev->dev);
} }
#define ATMEL_HLCDC_RGB444_OUTPUT BIT(0) #define ATMEL_HLCDC_RGB444_OUTPUT BIT(0)
#define ATMEL_HLCDC_RGB565_OUTPUT BIT(1) #define ATMEL_HLCDC_RGB565_OUTPUT BIT(1)
#define ATMEL_HLCDC_RGB666_OUTPUT BIT(2) #define ATMEL_HLCDC_RGB666_OUTPUT BIT(2)
#define ATMEL_HLCDC_RGB888_OUTPUT BIT(3) #define ATMEL_HLCDC_RGB888_OUTPUT BIT(3)
#define ATMEL_HLCDC_OUTPUT_MODE_MASK GENMASK(3, 0) #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) static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state)
{ {
@ -277,6 +367,13 @@ static int atmel_hlcdc_connector_output_mode(struct drm_connector_state *state)
encoder = state->best_encoder; encoder = state->best_encoder;
if (!encoder) if (!encoder)
encoder = connector->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)) { switch (atmel_hlcdc_encoder_get_bus_fmt(encoder)) {
case 0: case 0:
@ -317,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) 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 atmel_hlcdc_crtc_state *hstate;
struct drm_connector_state *cstate; struct drm_connector_state *cstate;
struct drm_connector *connector; struct drm_connector *connector;
@ -325,6 +422,8 @@ static int atmel_hlcdc_crtc_select_output_mode(struct drm_crtc_state *state)
int i; int i;
crtc = drm_crtc_to_atmel_hlcdc_crtc(state->crtc); 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) { for_each_new_connector_in_state(state->state, connector, cstate, i) {
unsigned int supported_fmts = 0; unsigned int supported_fmts = 0;
@ -345,7 +444,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 = drm_crtc_state_to_atmel_hlcdc_crtc_state(state);
hstate->output_mode = fls(output_fmts) - 1; 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; return 0;
} }
@ -449,6 +556,7 @@ static struct drm_crtc_state *
atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc) atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc)
{ {
struct atmel_hlcdc_crtc_state *state, *cur; struct atmel_hlcdc_crtc_state *state, *cur;
struct atmel_hlcdc_crtc *c = drm_crtc_to_atmel_hlcdc_crtc(crtc);
if (WARN_ON(!crtc->state)) if (WARN_ON(!crtc->state))
return NULL; return NULL;
@ -460,6 +568,8 @@ atmel_hlcdc_crtc_duplicate_state(struct drm_crtc *crtc)
cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state); cur = drm_crtc_state_to_atmel_hlcdc_crtc_state(crtc->state);
state->output_mode = cur->output_mode; state->output_mode = cur->output_mode;
if (c->dc->desc->is_xlcdc)
state->dpi = cur->dpi;
return &state->base; return &state->base;
} }

View File

@ -58,6 +58,7 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_at91sam9n12 = {
.conflicting_output_formats = true, .conflicting_output_formats = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9n12_layers), .nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9n12_layers),
.layers = atmel_hlcdc_at91sam9n12_layers, .layers = atmel_hlcdc_at91sam9n12_layers,
.ops = &atmel_hlcdc_ops,
}; };
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_at91sam9x5_layers[] = { 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, .conflicting_output_formats = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9x5_layers), .nlayers = ARRAY_SIZE(atmel_hlcdc_at91sam9x5_layers),
.layers = atmel_hlcdc_at91sam9x5_layers, .layers = atmel_hlcdc_at91sam9x5_layers,
.ops = &atmel_hlcdc_ops,
}; };
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d3_layers[] = { 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, .conflicting_output_formats = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d3_layers), .nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d3_layers),
.layers = atmel_hlcdc_sama5d3_layers, .layers = atmel_hlcdc_sama5d3_layers,
.ops = &atmel_hlcdc_ops,
}; };
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sama5d4_layers[] = { 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, .max_hpw = 0x3ff,
.nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers), .nlayers = ARRAY_SIZE(atmel_hlcdc_sama5d4_layers),
.layers = atmel_hlcdc_sama5d4_layers, .layers = atmel_hlcdc_sama5d4_layers,
.ops = &atmel_hlcdc_ops,
}; };
static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sam9x60_layers[] = { static const struct atmel_hlcdc_layer_desc atmel_hlcdc_sam9x60_layers[] = {
@ -460,6 +464,103 @@ static const struct atmel_hlcdc_dc_desc atmel_hlcdc_dc_sam9x60 = {
.fixed_clksrc = true, .fixed_clksrc = true,
.nlayers = ARRAY_SIZE(atmel_hlcdc_sam9x60_layers), .nlayers = ARRAY_SIZE(atmel_hlcdc_sam9x60_layers),
.layers = atmel_hlcdc_sam9x60_layers, .layers = atmel_hlcdc_sam9x60_layers,
.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[] = { static const struct of_device_id atmel_hlcdc_of_match[] = {
@ -487,6 +588,10 @@ static const struct of_device_id atmel_hlcdc_of_match[] = {
.compatible = "microchip,sam9x60-hlcdc", .compatible = "microchip,sam9x60-hlcdc",
.data = &atmel_hlcdc_dc_sam9x60, .data = &atmel_hlcdc_dc_sam9x60,
}, },
{
.compatible = "microchip,sam9x75-xlcdc",
.data = &atmel_xlcdc_dc_sam9x75,
},
{ /* sentinel */ }, { /* sentinel */ },
}; };
MODULE_DEVICE_TABLE(of, atmel_hlcdc_of_match); MODULE_DEVICE_TABLE(of, atmel_hlcdc_of_match);

View File

@ -15,6 +15,7 @@
#include <drm/drm_plane.h> #include <drm/drm_plane.h>
/* LCD controller common registers */
#define ATMEL_HLCDC_LAYER_CHER 0x0 #define ATMEL_HLCDC_LAYER_CHER 0x0
#define ATMEL_HLCDC_LAYER_CHDR 0x4 #define ATMEL_HLCDC_LAYER_CHDR 0x4
#define ATMEL_HLCDC_LAYER_CHSR 0x8 #define ATMEL_HLCDC_LAYER_CHSR 0x8
@ -128,6 +129,47 @@
#define ATMEL_HLCDC_MAX_LAYERS 6 #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 * Atmel HLCDC Layer registers layout structure
* *
@ -156,6 +198,8 @@
* @disc_pos: discard area position register * @disc_pos: discard area position register
* @disc_size: discard area size register * @disc_size: discard area size register
* @csc: color space conversion 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 { struct atmel_hlcdc_layer_cfg_layout {
int xstride[ATMEL_HLCDC_LAYER_MAX_PLANES]; int xstride[ATMEL_HLCDC_LAYER_MAX_PLANES];
@ -175,6 +219,8 @@ struct atmel_hlcdc_layer_cfg_layout {
int disc_pos; int disc_pos;
int disc_size; int disc_size;
int csc; int csc;
int vxs_config;
int hxs_config;
}; };
/** /**
@ -288,6 +334,64 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *layer)
return container_of(layer, struct atmel_hlcdc_plane, 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;
extern const struct atmel_lcdc_dc_ops atmel_xlcdc_ops;
/** /**
* Atmel HLCDC Display Controller description structure. * Atmel HLCDC Display Controller description structure.
* *
@ -304,8 +408,10 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *layer)
* @conflicting_output_formats: true if RGBXXX output formats conflict with * @conflicting_output_formats: true if RGBXXX output formats conflict with
* each other. * each other.
* @fixed_clksrc: true if clock source is fixed * @fixed_clksrc: true if clock source is fixed
* @is_xlcdc: true if XLCDC IP is supported
* @layers: a layer description table describing available layers * @layers: a layer description table describing available layers
* @nlayers: layer description table size * @nlayers: layer description table size
* @ops: atmel lcdc dc ops
*/ */
struct atmel_hlcdc_dc_desc { struct atmel_hlcdc_dc_desc {
int min_width; int min_width;
@ -317,32 +423,10 @@ struct atmel_hlcdc_dc_desc {
int max_hpw; int max_hpw;
bool conflicting_output_formats; bool conflicting_output_formats;
bool fixed_clksrc; bool fixed_clksrc;
bool is_xlcdc;
const struct atmel_hlcdc_layer_desc *layers; const struct atmel_hlcdc_layer_desc *layers;
int nlayers; int nlayers;
}; const struct atmel_lcdc_dc_ops *ops;
/**
* 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;
}; };
extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats; extern struct atmel_hlcdc_formats atmel_hlcdc_plane_rgb_formats;

View File

@ -282,8 +282,9 @@ atmel_hlcdc_plane_scaler_set_phicoeff(struct atmel_hlcdc_plane *plane,
coeff_tab[i]); coeff_tab[i]);
} }
static void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane, static
struct atmel_hlcdc_plane_state *state) 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; const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
u32 xfactor, yfactor; u32 xfactor, yfactor;
@ -330,11 +331,61 @@ static void atmel_hlcdc_plane_setup_scaler(struct atmel_hlcdc_plane *plane,
yfactor)); 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 static void
atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane, atmel_hlcdc_plane_update_pos_and_size(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; const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
if (desc->layout.size) if (desc->layout.size)
atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.size, atmel_hlcdc_layer_write_cfg(&plane->layer, desc->layout.size,
@ -352,12 +403,12 @@ atmel_hlcdc_plane_update_pos_and_size(struct atmel_hlcdc_plane *plane,
ATMEL_HLCDC_LAYER_POS(state->crtc_x, ATMEL_HLCDC_LAYER_POS(state->crtc_x,
state->crtc_y)); state->crtc_y));
atmel_hlcdc_plane_setup_scaler(plane, state); dc->desc->ops->plane_setup_scaler(plane, state);
} }
static void static
atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane, void atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
struct atmel_hlcdc_plane_state *state) struct atmel_hlcdc_plane_state *state)
{ {
unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id; unsigned int cfg = ATMEL_HLCDC_LAYER_DMA_BLEN_INCR16 | state->ahb_id;
const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc;
@ -393,6 +444,40 @@ atmel_hlcdc_plane_update_general_settings(struct atmel_hlcdc_plane *plane,
cfg); 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, static void atmel_hlcdc_plane_update_format(struct atmel_hlcdc_plane *plane,
struct atmel_hlcdc_plane_state *state) struct atmel_hlcdc_plane_state *state)
{ {
@ -437,36 +522,55 @@ 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_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, 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; 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; struct drm_framebuffer *fb = state->base.fb;
u32 sr; u32 sr;
int i; 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++) { for (i = 0; i < state->nplanes; i++) {
struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i); struct drm_gem_dma_object *gem = drm_fb_dma_get_gem_obj(fb, i);
state->dscrs[i]->addr = gem->dma_addr + state->offsets[i]; state->dscrs[i]->addr = gem->dma_addr + state->offsets[i];
atmel_hlcdc_layer_write_reg(&plane->layer, dc->desc->ops->lcdc_update_buffers(plane, state, sr, i);
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);
}
if (desc->layout.xstride[i]) if (desc->layout.xstride[i])
atmel_hlcdc_layer_write_cfg(&plane->layer, atmel_hlcdc_layer_write_cfg(&plane->layer,
@ -712,11 +816,8 @@ static int atmel_hlcdc_plane_atomic_check(struct drm_plane *p,
return 0; return 0;
} }
static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p, static void atmel_hlcdc_atomic_disable(struct atmel_hlcdc_plane *plane)
struct drm_atomic_state *state)
{ {
struct atmel_hlcdc_plane *plane = drm_plane_to_atmel_hlcdc_plane(p);
/* Disable interrupts */ /* Disable interrupts */
atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IDR, atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IDR,
0xffffffff); 0xffffffff);
@ -731,31 +832,34 @@ static void atmel_hlcdc_plane_atomic_disable(struct drm_plane *p,
atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR); atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
} }
static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p, static void atmel_xlcdc_atomic_disable(struct atmel_hlcdc_plane *plane)
struct drm_atomic_state *state) {
/* 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)
{ {
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 *plane = drm_plane_to_atmel_hlcdc_plane(p);
struct atmel_hlcdc_plane_state *hstate = struct atmel_hlcdc_dc *dc = plane->base.dev->dev_private;
drm_plane_state_to_atmel_hlcdc_plane_state(new_s);
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; 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. */ /* Enable the overrun interrupts. */
atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER, atmel_hlcdc_layer_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_IER,
ATMEL_HLCDC_LAYER_OVR_IRQ(0) | ATMEL_HLCDC_LAYER_OVR_IRQ(0) |
@ -765,14 +869,129 @@ static void atmel_hlcdc_plane_atomic_update(struct drm_plane *p,
/* Apply the new config at the next SOF event. */ /* Apply the new config at the next SOF event. */
sr = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHSR); 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_write_reg(&plane->layer, ATMEL_HLCDC_LAYER_CHER,
ATMEL_HLCDC_LAYER_UPDATE | ATMEL_HLCDC_LAYER_UPDATE |
(sr & ATMEL_HLCDC_LAYER_EN ? (sr & ATMEL_HLCDC_LAYER_EN ?
ATMEL_HLCDC_LAYER_A2Q : ATMEL_HLCDC_LAYER_EN)); 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)
{
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 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]);
}
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) static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane)
{ {
const struct atmel_hlcdc_layer_desc *desc = plane->layer.desc; 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 || if (desc->type == ATMEL_HLCDC_OVERLAY_LAYER ||
desc->type == ATMEL_HLCDC_CURSOR_LAYER) { desc->type == ATMEL_HLCDC_CURSOR_LAYER) {
@ -796,31 +1015,16 @@ static int atmel_hlcdc_plane_init_properties(struct atmel_hlcdc_plane *plane)
return ret; return ret;
} }
if (desc->layout.csc) { if (desc->layout.csc)
/* dc->desc->ops->lcdc_csc_init(plane, desc);
* 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);
}
return 0; 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 = atmel_hlcdc_layer_read_reg(&plane->layer, ATMEL_HLCDC_LAYER_ISR);
u32 isr;
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 * There's not much we can do in case of overrun except informing
@ -834,6 +1038,51 @@ void atmel_hlcdc_plane_irq(struct atmel_hlcdc_plane *plane)
desc->name); 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;
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,
};
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 = { static const struct drm_plane_helper_funcs atmel_hlcdc_layer_plane_helper_funcs = {
.atomic_check = atmel_hlcdc_plane_atomic_check, .atomic_check = atmel_hlcdc_plane_atomic_check,
.atomic_update = atmel_hlcdc_plane_atomic_update, .atomic_update = atmel_hlcdc_plane_atomic_update,

View File

@ -234,28 +234,6 @@ static int analogix_dp_training_pattern_dis(struct analogix_dp_device *dp)
return ret < 0 ? ret : 0; 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) static int analogix_dp_link_start(struct analogix_dp_device *dp)
{ {
u8 buf[4]; u8 buf[4];
@ -286,10 +264,12 @@ static int analogix_dp_link_start(struct analogix_dp_device *dp)
return retval; return retval;
} }
/* Set TX pre-emphasis to minimum */ /* Set TX voltage-swing and pre-emphasis to minimum */
for (lane = 0; lane < lane_count; lane++) for (lane = 0; lane < lane_count; lane++)
analogix_dp_set_lane_lane_pre_emphasis(dp, dp->link_train.training_lane[lane] =
PRE_EMPHASIS_LEVEL_0, lane); DP_TRAIN_VOLTAGE_SWING_LEVEL_0 |
DP_TRAIN_PRE_EMPH_LEVEL_0;
analogix_dp_set_lane_link_training(dp);
/* Wait for PLL lock */ /* Wait for PLL lock */
pll_tries = 0; pll_tries = 0;
@ -384,54 +364,6 @@ static unsigned char analogix_dp_get_adjust_request_pre_emphasis(
return ((link_value >> shift) & 0xc) >> 2; 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) static void analogix_dp_reduce_link_rate(struct analogix_dp_device *dp)
{ {
analogix_dp_training_pattern_dis(dp); analogix_dp_training_pattern_dis(dp);
@ -478,11 +410,6 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
if (retval < 0) if (retval < 0)
return retval; 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) { if (analogix_dp_clock_recovery_ok(link_status, lane_count) == 0) {
/* set training pattern 2 for EQ */ /* set training pattern 2 for EQ */
analogix_dp_set_training_pattern(dp, TRAINING_PTN2); analogix_dp_set_training_pattern(dp, TRAINING_PTN2);
@ -495,38 +422,37 @@ static int analogix_dp_process_clock_recovery(struct analogix_dp_device *dp)
dev_dbg(dp->dev, "Link Training Clock Recovery success\n"); dev_dbg(dp->dev, "Link Training Clock Recovery success\n");
dp->link_train.lt_state = EQUALIZER_TRAINING; 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) == return 0;
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 || retval = drm_dp_dpcd_read(&dp->aux, DP_ADJUST_REQUEST_LANE0_1,
voltage_swing == VOLTAGE_LEVEL_3 || adjust_request, 2);
pre_emphasis == PRE_EMPHASIS_LEVEL_3) { if (retval < 0)
dev_err(dp->dev, "CR Max reached (%d,%d,%d)\n", return retval;
dp->link_train.cr_loop[lane],
voltage_swing, pre_emphasis); for (lane = 0; lane < lane_count; lane++) {
analogix_dp_reduce_link_rate(dp); training_lane = analogix_dp_get_lane_link_training(dp, lane);
return -EIO; 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;
} }
} }
analogix_dp_get_adjust_training_lane(dp, adjust_request); analogix_dp_get_adjust_training_lane(dp, adjust_request);
analogix_dp_set_lane_link_training(dp);
for (lane = 0; lane < lane_count; lane++)
analogix_dp_set_lane_link_training(dp,
dp->link_train.training_lane[lane], lane);
retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
dp->link_train.training_lane, lane_count); dp->link_train.training_lane, lane_count);
@ -538,7 +464,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) static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
{ {
int lane, lane_count, retval; int lane_count, retval;
u32 reg; u32 reg;
u8 link_align, link_status[2], adjust_request[2]; u8 link_align, link_status[2], adjust_request[2];
@ -598,9 +524,7 @@ static int analogix_dp_process_equalizer_training(struct analogix_dp_device *dp)
return -EIO; return -EIO;
} }
for (lane = 0; lane < lane_count; lane++) analogix_dp_set_lane_link_training(dp);
analogix_dp_set_lane_link_training(dp,
dp->link_train.training_lane[lane], lane);
retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET, retval = drm_dp_dpcd_write(&dp->aux, DP_TRAINING_LANE0_SET,
dp->link_train.training_lane, lane_count); dp->link_train.training_lane, lane_count);
@ -712,7 +636,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) static int analogix_dp_fast_link_train(struct analogix_dp_device *dp)
{ {
int i, ret; int ret;
u8 link_align, link_status[2]; u8 link_align, link_status[2];
enum pll_status status; enum pll_status status;
@ -720,11 +644,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_link_bandwidth(dp, dp->link_train.link_rate);
analogix_dp_set_lane_count(dp, dp->link_train.lane_count); analogix_dp_set_lane_count(dp, dp->link_train.lane_count);
analogix_dp_set_lane_link_training(dp);
for (i = 0; i < dp->link_train.lane_count; i++) {
analogix_dp_set_lane_link_training(dp,
dp->link_train.training_lane[i], i);
}
ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status, ret = readx_poll_timeout(analogix_dp_get_pll_lock_status, dp, status,
status != PLL_UNLOCKED, 120, status != PLL_UNLOCKED, 120,

View File

@ -213,26 +213,8 @@ void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,
bool enable); bool enable);
void analogix_dp_set_training_pattern(struct analogix_dp_device *dp, void analogix_dp_set_training_pattern(struct analogix_dp_device *dp,
enum pattern_set pattern); enum pattern_set pattern);
void analogix_dp_set_lane0_pre_emphasis(struct analogix_dp_device *dp, void analogix_dp_set_lane_link_training(struct analogix_dp_device *dp);
u32 level); u32 analogix_dp_get_lane_link_training(struct analogix_dp_device *dp, u8 lane);
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_reset_macro(struct analogix_dp_device *dp); void analogix_dp_reset_macro(struct analogix_dp_device *dp);
void analogix_dp_init_video(struct analogix_dp_device *dp); void analogix_dp_init_video(struct analogix_dp_device *dp);

View File

@ -557,6 +557,20 @@ void analogix_dp_get_lane_count(struct analogix_dp_device *dp, u32 *count)
*count = reg; *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, void analogix_dp_enable_enhanced_mode(struct analogix_dp_device *dp,
bool enable) 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) void analogix_dp_reset_macro(struct analogix_dp_device *dp)
{ {
u32 reg; u32 reg;
@ -1027,7 +941,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
u32 status_reg; u32 status_reg;
u8 *buffer = msg->buffer; u8 *buffer = msg->buffer;
unsigned int i; unsigned int i;
int num_transferred = 0;
int ret; int ret;
/* Buffer size of AUX CH is 16 bytes */ /* Buffer size of AUX CH is 16 bytes */
@ -1079,7 +992,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
reg = buffer[i]; reg = buffer[i];
writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + writel(reg, dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
4 * i); 4 * i);
num_transferred++;
} }
} }
@ -1127,7 +1039,6 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 + reg = readl(dp->reg_base + ANALOGIX_DP_BUF_DATA_0 +
4 * i); 4 * i);
buffer[i] = (unsigned char)reg; buffer[i] = (unsigned char)reg;
num_transferred++;
} }
} }
@ -1144,7 +1055,7 @@ ssize_t analogix_dp_transfer(struct analogix_dp_device *dp,
(msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ) (msg->request & ~DP_AUX_I2C_MOT) == DP_AUX_NATIVE_READ)
msg->reply = DP_AUX_NATIVE_REPLY_ACK; msg->reply = DP_AUX_NATIVE_REPLY_ACK;
return num_transferred > 0 ? num_transferred : -EBUSY; return msg->size;
aux_error: aux_error:
/* if aux err happen, reset aux */ /* if aux err happen, reset aux */

View File

@ -12,6 +12,9 @@ rm -rf .git/rebase-apply
apt-get update apt-get update
apt-get install -y libssl-dev apt-get install -y libssl-dev
# for msm header validation
apt-get install -y python3-lxml
if [[ "$KERNEL_ARCH" = "arm64" ]]; then if [[ "$KERNEL_ARCH" = "arm64" ]]; then
GCC_ARCH="aarch64-linux-gnu" GCC_ARCH="aarch64-linux-gnu"
DEBIAN_ARCH="arm64" DEBIAN_ARCH="arm64"

View File

@ -106,6 +106,7 @@ build-nodebugfs:arm64:
extends: .build:arm64 extends: .build:arm64
variables: variables:
DISABLE_KCONFIGS: "DEBUG_FS" DISABLE_KCONFIGS: "DEBUG_FS"
ENABLE_KCONFIGS: "EXPERT DRM_MSM_VALIDATE_XML"
build:x86_64: build:x86_64:
extends: .build:x86_64 extends: .build:x86_64

View File

@ -433,6 +433,202 @@ static const struct nv3052c_reg fs035vg158_panel_regs[] = {
{ 0x36, 0x0a }, // bgr = 1, ss = 1, gs = 0 { 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) static inline struct nv3052c *to_nv3052c(struct drm_panel *panel)
{ {
return container_of(panel, struct nv3052c, 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 = { static const struct nv3052c_panel_info ltk035c5444t_panel_info = {
.display_modes = ltk035c5444t_modes, .display_modes = ltk035c5444t_modes,
.num_modes = ARRAY_SIZE(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), .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[] = { static const struct spi_device_id nv3052c_ids[] = {
{ "ltk035c5444t", }, { "ltk035c5444t", },
{ "fs035vg158", }, { "fs035vg158", },
{ "wl-355608-a8", },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(spi, nv3052c_ids); 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[] = { static const struct of_device_id nv3052c_of_match[] = {
{ .compatible = "leadtek,ltk035c5444t", .data = &ltk035c5444t_panel_info }, { .compatible = "leadtek,ltk035c5444t", .data = &ltk035c5444t_panel_info },
{ .compatible = "fascontek,fs035vg158", .data = &fs035vg158_panel_info }, { .compatible = "fascontek,fs035vg158", .data = &fs035vg158_panel_info },
{ .compatible = "wl-355608-a8", .data = &wl_355608_a8_panel_info },
{ /* sentinel */ } { /* sentinel */ }
}; };
MODULE_DEVICE_TABLE(of, nv3052c_of_match); MODULE_DEVICE_TABLE(of, nv3052c_of_match);
@ -719,4 +943,5 @@ module_spi_driver(nv3052c_driver);
MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>"); MODULE_AUTHOR("Paul Cercueil <paul@crapouillou.net>");
MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>"); MODULE_AUTHOR("Christophe Branchereau <cbranchereau@gmail.com>");
MODULE_AUTHOR("Ryan Walklin <ryan@testtoast.com");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");

View File

@ -299,9 +299,9 @@ static int v3d_platform_drm_probe(struct platform_device *pdev)
WARN_ON(v3d->cores > 1); /* multicore not yet implemented */ WARN_ON(v3d->cores > 1); /* multicore not yet implemented */
if (v3d->ver >= 71) 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) else if (v3d->ver >= 42)
v3d->max_counters = ARRAY_SIZE(v3d_v42_performance_counters); v3d->max_counters = V3D_V42_NUM_PERFCOUNTERS;
else else
v3d->max_counters = 0; v3d->max_counters = 0;

View File

@ -351,9 +351,6 @@ struct v3d_timestamp_query {
struct drm_syncobj *syncobj; 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 */ /* Number of perfmons required to handle all supported performance counters */
#define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_MAX_COUNTERS, \ #define V3D_MAX_PERFMONS DIV_ROUND_UP(V3D_MAX_COUNTERS, \
DRM_V3D_MAX_PERF_COUNTERS) DRM_V3D_MAX_PERF_COUNTERS)

View File

@ -9,6 +9,192 @@
#define V3D_PERFMONID_MIN 1 #define V3D_PERFMONID_MIN 1
#define V3D_PERFMONID_MAX U32_MAX #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) void v3d_perfmon_get(struct v3d_perfmon *perfmon)
{ {
if (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) if (req->counter >= v3d->max_counters)
return -EINVAL; return -EINVAL;
if (v3d->ver >= 71) { BUILD_BUG_ON(ARRAY_SIZE(v3d_v42_performance_counters) !=
WARN_ON(v3d->max_counters != ARRAY_SIZE(v3d_v71_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]; counter = &v3d_v71_performance_counters[req->counter];
} else if (v3d->ver >= 42) { else if (v3d->ver >= 42)
WARN_ON(v3d->max_counters != ARRAY_SIZE(v3d_v42_performance_counters));
counter = &v3d_v42_performance_counters[req->counter]; counter = &v3d_v42_performance_counters[req->counter];
} else { else
return -EOPNOTSUPP; return -EOPNOTSUPP;
}
strscpy(req->name, counter->name, sizeof(req->name)); strscpy(req->name, counter->name, sizeof(req->name));
strscpy(req->category, counter->category, sizeof(req->category)); strscpy(req->category, counter->category, sizeof(req->category));

View File

@ -19,190 +19,11 @@ struct v3d_perf_counter_desc {
char description[256]; 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[] = { #define V3D_V42_NUM_PERFCOUNTERS (87)
{"FEP", "FEP-valid-primitives-no-rendered-pixels", "[FEP] Valid primitives that result in no rendered pixels, for all rendered tiles"}, #define V3D_V71_NUM_PERFCOUNTERS (93)
{"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"}, /* Maximum number of performance counters supported by any version of V3D */
{"FEP", "FEP-valid-quads", "[FEP] Valid quads"}, #define V3D_MAX_COUNTERS (93)
{"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"},
};
#endif #endif

View File

@ -22,6 +22,8 @@
#define ATMEL_HLCDC_DITHER BIT(6) #define ATMEL_HLCDC_DITHER BIT(6)
#define ATMEL_HLCDC_DISPDLY BIT(7) #define ATMEL_HLCDC_DISPDLY BIT(7)
#define ATMEL_HLCDC_MODE_MASK GENMASK(9, 8) #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_PP BIT(10)
#define ATMEL_HLCDC_VSPSU BIT(12) #define ATMEL_HLCDC_VSPSU BIT(12)
#define ATMEL_HLCDC_VSPHO BIT(13) #define ATMEL_HLCDC_VSPHO BIT(13)
@ -34,6 +36,12 @@
#define ATMEL_HLCDC_IDR 0x30 #define ATMEL_HLCDC_IDR 0x30
#define ATMEL_HLCDC_IMR 0x34 #define ATMEL_HLCDC_IMR 0x34
#define ATMEL_HLCDC_ISR 0x38 #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_CLKPOL BIT(0)
#define ATMEL_HLCDC_CLKSEL BIT(2) #define ATMEL_HLCDC_CLKSEL BIT(2)
@ -48,6 +56,8 @@
#define ATMEL_HLCDC_DISP BIT(2) #define ATMEL_HLCDC_DISP BIT(2)
#define ATMEL_HLCDC_PWM BIT(3) #define ATMEL_HLCDC_PWM BIT(3)
#define ATMEL_HLCDC_SIP BIT(4) #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_SOF BIT(0)
#define ATMEL_HLCDC_SYNCDIS BIT(1) #define ATMEL_HLCDC_SYNCDIS BIT(1)

View File

@ -19,7 +19,7 @@
#define DMA_HEAP_VALID_FD_FLAGS (O_CLOEXEC | O_ACCMODE) #define DMA_HEAP_VALID_FD_FLAGS (O_CLOEXEC | O_ACCMODE)
/* Currently no heap flags */ /* 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 * struct dma_heap_allocation_data - metadata passed from userspace for