Skip to content
2 changes: 1 addition & 1 deletion drivers/gpu/drm/drm_atomic.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ static void drm_atomic_crtc_print_state(struct drm_printer *p,
drm_printf(p, "\tactive_changed=%d\n", state->active_changed);
drm_printf(p, "\tconnectors_changed=%d\n", state->connectors_changed);
drm_printf(p, "\tcolor_mgmt_changed=%d\n", state->color_mgmt_changed);
drm_printf(p, "\tplane_mask=%x\n", state->plane_mask);
drm_printf(p, "\tplane_mask=%llx\n", state->plane_mask);
drm_printf(p, "\tconnector_mask=%x\n", state->connector_mask);
drm_printf(p, "\tencoder_mask=%x\n", state->encoder_mask);
drm_printf(p, "\tmode: " DRM_MODE_FMT "\n", DRM_MODE_ARG(&state->mode));
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/drm_atomic_uapi.c
Original file line number Diff line number Diff line change
Expand Up @@ -811,6 +811,8 @@ static int drm_atomic_connector_set_property(struct drm_connector *connector,
state->max_requested_bpc = val;
} else if (property == connector->privacy_screen_sw_state_property) {
state->privacy_screen_sw_state = val;
} else if (property == connector->rotation_property) {
state->rotation = val;
} else if (connector->funcs->atomic_set_property) {
return connector->funcs->atomic_set_property(connector,
state, property, val);
Expand Down Expand Up @@ -900,6 +902,8 @@ drm_atomic_connector_get_property(struct drm_connector *connector,
*val = state->max_requested_bpc;
} else if (property == connector->privacy_screen_sw_state_property) {
*val = state->privacy_screen_sw_state;
} else if (property == connector->rotation_property) {
*val = state->rotation;
} else if (connector->funcs->atomic_get_property) {
return connector->funcs->atomic_get_property(connector,
state, property, val);
Expand Down
51 changes: 42 additions & 9 deletions drivers/gpu/drm/drm_blend.c
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,16 @@
}
EXPORT_SYMBOL(drm_plane_create_alpha_property);

static const struct drm_prop_enum_list drm_rotate_props[] = {
{ __builtin_ffs(DRM_MODE_ROTATE_0) - 1, "rotate-0" },
{ __builtin_ffs(DRM_MODE_ROTATE_90) - 1, "rotate-90" },
{ __builtin_ffs(DRM_MODE_ROTATE_180) - 1, "rotate-180" },
{ __builtin_ffs(DRM_MODE_ROTATE_270) - 1, "rotate-270" },
{ __builtin_ffs(DRM_MODE_REFLECT_X) - 1, "reflect-x" },
{ __builtin_ffs(DRM_MODE_REFLECT_Y) - 1, "reflect-y" },
{ __builtin_ffs(DRM_MODE_TRANSPOSE) - 1, "transpose" },
};

/**
* drm_plane_create_rotation_property - create a new rotation property
* @plane: drm plane
Expand All @@ -254,7 +264,7 @@
* DRM_MODE_ROTATE_0:
* "rotate-0"
* DRM_MODE_ROTATE_90:
* "rotate-90"

Check failure on line 267 in drivers/gpu/drm/drm_blend.c

View workflow job for this annotation

GitHub Actions / checkpatch review

WARNING: please, no space before tabs
* DRM_MODE_ROTATE_180:
* "rotate-180"
* DRM_MODE_ROTATE_270:
Expand All @@ -263,6 +273,8 @@
* "reflect-x"
* DRM_MODE_REFLECT_Y:
* "reflect-y"
* DRM_MODE_TRANSPOSE:
* "transpose"
*
* Rotation is the specified amount in degrees in counter clockwise direction,
* the X and Y axis are within the source rectangle, i.e. the X/Y axis before
Expand All @@ -273,22 +285,15 @@
unsigned int rotation,
unsigned int supported_rotations)
{
static const struct drm_prop_enum_list props[] = {
{ __builtin_ffs(DRM_MODE_ROTATE_0) - 1, "rotate-0" },
{ __builtin_ffs(DRM_MODE_ROTATE_90) - 1, "rotate-90" },
{ __builtin_ffs(DRM_MODE_ROTATE_180) - 1, "rotate-180" },
{ __builtin_ffs(DRM_MODE_ROTATE_270) - 1, "rotate-270" },
{ __builtin_ffs(DRM_MODE_REFLECT_X) - 1, "reflect-x" },
{ __builtin_ffs(DRM_MODE_REFLECT_Y) - 1, "reflect-y" },
};
struct drm_property *prop;

WARN_ON((supported_rotations & DRM_MODE_ROTATE_MASK) == 0);
WARN_ON(!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK));
WARN_ON(rotation & ~supported_rotations);

prop = drm_property_create_bitmask(plane->dev, 0, "rotation",
props, ARRAY_SIZE(props),
drm_rotate_props,
ARRAY_SIZE(drm_rotate_props),
supported_rotations);
if (!prop)
return -ENOMEM;
Expand All @@ -304,6 +309,34 @@
}
EXPORT_SYMBOL(drm_plane_create_rotation_property);

int drm_connector_create_rotation_property(struct drm_connector *conn,
unsigned int rotation,
unsigned int supported_rotations)
{
struct drm_property *prop;

WARN_ON((supported_rotations & DRM_MODE_ROTATE_MASK) == 0);
WARN_ON(!is_power_of_2(rotation & DRM_MODE_ROTATE_MASK));
WARN_ON(rotation & ~supported_rotations);

prop = drm_property_create_bitmask(conn->dev, 0, "rotation",
drm_rotate_props,
ARRAY_SIZE(drm_rotate_props),
supported_rotations);
if (!prop)
return -ENOMEM;

drm_object_attach_property(&conn->base, prop, rotation);

if (conn->state)
conn->state->rotation = rotation;

conn->rotation_property = prop;

return 0;
}
EXPORT_SYMBOL(drm_connector_create_rotation_property);

/**
* drm_rotation_simplify() - Try to simplify the rotation
* @rotation: Rotation to be simplified
Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/drm_connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -361,7 +361,8 @@ static int __drm_connector_init(struct drm_device *dev,

drm_object_attach_property(&connector->base,
config->non_desktop_property,
0);
(connector_type != DRM_MODE_CONNECTOR_VIRTUAL &&
connector_type != DRM_MODE_CONNECTOR_WRITEBACK) ? 0 : 1);
drm_object_attach_property(&connector->base,
config->tile_property,
0);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/drm_framebuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -959,7 +959,7 @@ static int atomic_remove_fb(struct drm_framebuffer *fb)
struct drm_connector *conn __maybe_unused;
struct drm_connector_state *conn_state;
int i, ret;
unsigned plane_mask;
u64 plane_mask;
bool disable_crtcs = false;

retry_disable:
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/drm_mode_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ void drm_mode_config_validate(struct drm_device *dev)
struct drm_encoder *encoder;
struct drm_crtc *crtc;
struct drm_plane *plane;
u32 primary_with_crtc = 0, cursor_with_crtc = 0;
u64 primary_with_crtc = 0, cursor_with_crtc = 0;
unsigned int num_primary = 0;

if (!drm_core_check_feature(dev, DRIVER_MODESET))
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/drm_plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ static int __drm_universal_plane_init(struct drm_device *dev,
int ret;

/* plane index is used with 32bit bitmasks */
if (WARN_ON(config->num_total_plane >= 32))
if (WARN_ON(config->num_total_plane >= 64))
return -EINVAL;

/*
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ static int ipu_crtc_atomic_check(struct drm_crtc *crtc,
{
struct drm_crtc_state *crtc_state = drm_atomic_get_new_crtc_state(state,
crtc);
u32 primary_plane_mask = drm_plane_mask(crtc->primary);
u64 primary_plane_mask = drm_plane_mask(crtc->primary);

if (crtc_state->active && (primary_plane_mask & crtc_state->plane_mask) == 0)
return -EINVAL;
Expand Down
59 changes: 50 additions & 9 deletions drivers/gpu/drm/vc4/vc4_plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,11 @@ static enum vc4_scaling_mode vc4_get_scaling_mode(u32 src, u32 dst)
{
if (dst == src >> 16)
return VC4_SCALING_NONE;
if (3 * dst >= 2 * (src >> 16))

if (src <= (1 << 16))
/* Source rectangle <= 1 pixel can use TPZ for resize/upscale */
return VC4_SCALING_TPZ;
else if (3 * dst >= 2 * (src >> 16))
return VC4_SCALING_PPF;
else
return VC4_SCALING_TPZ;
Expand Down Expand Up @@ -592,12 +596,17 @@ static void vc4_write_tpz(struct vc4_plane_state *vc4_state, u32 src, u32 dst)

WARN_ON_ONCE(vc4->gen > VC4_GEN_6);

scale = src / dst;
if ((dst << 16) < src) {
scale = src / dst;

/* The specs note that while the reciprocal would be defined
* as (1<<32)/scale, ~0 is close enough.
*/
recip = ~0 / scale;
/* The specs note that while the reciprocal would be defined
* as (1<<32)/scale, ~0 is close enough.
*/
recip = ~0 / scale;
} else {
scale = (1 << 16) + 1;
recip = (1 << 16) - 1;
}

vc4_dlist_write(vc4_state,
/*
Expand Down Expand Up @@ -1291,7 +1300,8 @@ static int vc4_plane_mode_set(struct drm_plane *plane,
width = vc4_state->src_w[0] >> 16;
height = vc4_state->src_h[0] >> 16;

if (!width || !height || !vc4_state->crtc_w || !vc4_state->crtc_h) {
if (!vc4_state->src_w[0] || !vc4_state->src_h[0] ||
!vc4_state->crtc_w || !vc4_state->crtc_h) {
/* 0 source size probably means the plane is offscreen */
vc4_state->dlist_initialized = 1;
return 0;
Expand Down Expand Up @@ -1829,7 +1839,8 @@ static int vc6_plane_mode_set(struct drm_plane *plane,
width = vc4_state->src_w[0] >> 16;
height = vc4_state->src_h[0] >> 16;

if (!width || !height || !vc4_state->crtc_w || !vc4_state->crtc_h) {
if (!vc4_state->src_w[0] || !vc4_state->src_h[0] ||
!vc4_state->crtc_w || !vc4_state->crtc_h) {
/* 0 source size probably means the plane is offscreen.
* 0 destination size is a redundant plane.
*/
Expand Down Expand Up @@ -2647,12 +2658,27 @@ struct drm_plane *vc4_plane_init(struct drm_device *dev,
}

#define VC4_NUM_OVERLAY_PLANES 16
#define VC4_NUM_TXP_OVERLAY_PLANES 32

int vc4_plane_create_additional_planes(struct drm_device *drm)
{
struct drm_plane *cursor_plane;
struct drm_crtc *crtc;
unsigned int i;
struct drm_crtc *txp_crtc;
uint32_t non_txp_crtc_mask;

drm_for_each_crtc(crtc, drm) {
struct vc4_crtc *vc4_crtc = to_vc4_crtc(crtc);

if (vc4_crtc->feeds_txp) {
txp_crtc = crtc;
break;
}
}

non_txp_crtc_mask = GENMASK(drm->mode_config.num_crtc - 1, 0) -
drm_crtc_mask(txp_crtc);

/* Set up some arbitrary number of planes. We're not limited
* by a set number of physical registers, just the space in
Expand All @@ -2666,7 +2692,22 @@ int vc4_plane_create_additional_planes(struct drm_device *drm)
for (i = 0; i < VC4_NUM_OVERLAY_PLANES; i++) {
struct drm_plane *plane =
vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
GENMASK(drm->mode_config.num_crtc - 1, 0));
non_txp_crtc_mask);

if (IS_ERR(plane))
continue;

/* Create zpos property. Max of all the overlays + 1 primary +
* 1 cursor plane on a crtc.
*/
drm_plane_create_zpos_property(plane, i + 1, 1,
VC4_NUM_OVERLAY_PLANES + 1);
}

for (i = 0; i < VC4_NUM_TXP_OVERLAY_PLANES; i++) {
struct drm_plane *plane =
vc4_plane_init(drm, DRM_PLANE_TYPE_OVERLAY,
drm_crtc_mask(txp_crtc));

if (IS_ERR(plane))
continue;
Expand Down
21 changes: 17 additions & 4 deletions drivers/gpu/drm/vc4/vc4_txp.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_blend.h>
#include <drm/drm_drv.h>
#include <drm/drm_edid.h>
#include <drm/drm_fb_dma_helper.h>
Expand Down Expand Up @@ -259,10 +260,15 @@ static int vc4_txp_connector_atomic_check(struct drm_connector *conn,
crtc_state = drm_atomic_get_new_crtc_state(state, conn_state->crtc);

fb = conn_state->writeback_job->fb;
if (fb->width != crtc_state->mode.hdisplay ||
fb->height != crtc_state->mode.vdisplay) {
DRM_DEBUG_KMS("Invalid framebuffer size %ux%u\n",
fb->width, fb->height);
if ((conn_state->rotation == DRM_MODE_ROTATE_0 &&
fb->width != crtc_state->mode.hdisplay &&
fb->height != crtc_state->mode.vdisplay) ||
(conn_state->rotation == (DRM_MODE_ROTATE_0 | DRM_MODE_TRANSPOSE) &&
fb->width != crtc_state->mode.vdisplay &&
fb->height != crtc_state->mode.hdisplay)) {
DRM_DEBUG_KMS("Invalid framebuffer size %ux%u vs mode %ux%u\n",
fb->width, fb->height,
crtc_state->mode.hdisplay, crtc_state->mode.vdisplay);
return -EINVAL;
}

Expand Down Expand Up @@ -330,6 +336,9 @@ static void vc4_txp_connector_atomic_commit(struct drm_connector *conn,
*/
ctrl |= TXP_ALPHA_INVERT;

if (conn_state->rotation & DRM_MODE_TRANSPOSE)
ctrl |= TXP_TRANSPOSE;

if (!drm_dev_enter(drm, &idx))
return;

Expand Down Expand Up @@ -608,6 +617,10 @@ static int vc4_txp_bind(struct device *dev, struct device *master, void *data)
if (ret)
return ret;

drm_connector_create_rotation_property(&txp->connector.base, DRM_MODE_ROTATE_0,
DRM_MODE_ROTATE_0 |
DRM_MODE_TRANSPOSE);

ret = devm_request_irq(dev, irq, vc4_txp_interrupt, 0,
dev_name(dev), txp);
if (ret)
Expand Down
5 changes: 5 additions & 0 deletions include/drm/drm_blend.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
struct drm_device;
struct drm_atomic_state;
struct drm_plane;
struct drm_connector;

static inline bool drm_rotation_90_or_270(unsigned int rotation)
{
Expand All @@ -58,4 +59,8 @@ int drm_atomic_normalize_zpos(struct drm_device *dev,
struct drm_atomic_state *state);
int drm_plane_create_blend_mode_property(struct drm_plane *plane,
unsigned int supported_modes);

int drm_connector_create_rotation_property(struct drm_connector *conn,
unsigned int rotation,
unsigned int supported_rotations);
#endif
11 changes: 11 additions & 0 deletions include/drm/drm_connector.h
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,11 @@ struct drm_connector_state {
* DRM blob property for HDR output metadata
*/
struct drm_property_blob *hdr_output_metadata;

/**
* @rotation: Connector property to rotate the maximum output image.
*/
u32 rotation;
};

/**
Expand Down Expand Up @@ -1696,6 +1701,12 @@ struct drm_connector {
*/
struct drm_property *privacy_screen_hw_state_property;

/**
* @rotation_property: Optional DRM property controlling rotation of the
* output.
*/
struct drm_property *rotation_property;

#define DRM_CONNECTOR_POLL_HPD (1 << 0)
#define DRM_CONNECTOR_POLL_CONNECT (1 << 1)
#define DRM_CONNECTOR_POLL_DISCONNECT (1 << 2)
Expand Down
2 changes: 1 addition & 1 deletion include/drm/drm_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ struct drm_crtc_state {
* @plane_mask: Bitmask of drm_plane_mask(plane) of planes attached to
* this CRTC.
*/
u32 plane_mask;
u64 plane_mask;

/**
* @connector_mask: Bitmask of drm_connector_mask(connector) of
Expand Down
4 changes: 2 additions & 2 deletions include/drm/drm_plane.h
Original file line number Diff line number Diff line change
Expand Up @@ -915,9 +915,9 @@ static inline unsigned int drm_plane_index(const struct drm_plane *plane)
* drm_plane_mask - find the mask of a registered plane
* @plane: plane to find mask for
*/
static inline u32 drm_plane_mask(const struct drm_plane *plane)
static inline u64 drm_plane_mask(const struct drm_plane *plane)
{
return 1 << drm_plane_index(plane);
return 1ULL << drm_plane_index(plane);
}

struct drm_plane * drm_plane_from_index(struct drm_device *dev, int idx);
Expand Down
1 change: 1 addition & 0 deletions include/uapi/drm/drm_mode.h
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ extern "C" {
*/
#define DRM_MODE_REFLECT_X (1<<4)
#define DRM_MODE_REFLECT_Y (1<<5)
#define DRM_MODE_TRANSPOSE (1<<6)

/*
* DRM_MODE_REFLECT_MASK
Expand Down
Loading