Commit c765102a authored by Dave Airlie's avatar Dave Airlie

Merge branch 'for-upstream/mali-dp' of git://linux-arm.org/linux-ld into drm-next

Here is the list of fixes that I have for drm/mali-dp. They've been on the mailing
lists for a while and merged into linux-next for a few weeks, but due to holiday and
travel to Linux Plumbers I did not send the pull request earlier. I don't know if
these patches can be pulled into v4.9 still (they will conflict with Ville Syrjälä's
cleanup of DRM_ROTATE series that is already in drm-next), but if you do that would
be great.

* 'for-upstream/mali-dp' of git://linux-arm.org/linux-ld:
  drm: mali-dp: Clear CVAL when leaving config mode
  drm/arm: mark symbols static where possible
  drm: mali-dp: Add support for setting plane's rotation property from userspace.
  drm: mali-dp: Don't set DRM_PLANE_COMMIT_ACTIVE_ONLY
  drm: mali-dp: Store internal format and n_planes in plane state
  drm: mali-dp: Enable alpha blending
  drm: mali-dp: Refactor plane initialisation
  arm: mali-dp: Extract mode_config cleanup into malidp_fini
  drm: mali-dp: Add pitch alignment check for planes
  drm: mali-dp: Add pitch alignment check function
  drm: mali-dp: Set the drm->irq_enabled flag to match driver's state.
  drm: mali-dp: Clear the config_valid flag before using it in wait_event.
parents 90233ee5 e64053f0
...@@ -42,6 +42,7 @@ static int malidp_set_and_wait_config_valid(struct drm_device *drm) ...@@ -42,6 +42,7 @@ static int malidp_set_and_wait_config_valid(struct drm_device *drm)
struct malidp_hw_device *hwdev = malidp->dev; struct malidp_hw_device *hwdev = malidp->dev;
int ret; int ret;
atomic_set(&malidp->config_valid, 0);
hwdev->set_config_valid(hwdev); hwdev->set_config_valid(hwdev);
/* don't wait for config_valid flag if we are in config mode */ /* don't wait for config_valid flag if we are in config mode */
if (hwdev->in_config_mode(hwdev)) if (hwdev->in_config_mode(hwdev))
...@@ -91,8 +92,7 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state) ...@@ -91,8 +92,7 @@ static void malidp_atomic_commit_tail(struct drm_atomic_state *state)
drm_atomic_helper_commit_modeset_disables(drm, state); drm_atomic_helper_commit_modeset_disables(drm, state);
drm_atomic_helper_commit_modeset_enables(drm, state); drm_atomic_helper_commit_modeset_enables(drm, state);
drm_atomic_helper_commit_planes(drm, state, drm_atomic_helper_commit_planes(drm, state, 0);
DRM_PLANE_COMMIT_ACTIVE_ONLY);
malidp_atomic_commit_hw_done(state); malidp_atomic_commit_hw_done(state);
...@@ -155,6 +155,12 @@ static int malidp_init(struct drm_device *drm) ...@@ -155,6 +155,12 @@ static int malidp_init(struct drm_device *drm)
return 0; return 0;
} }
static void malidp_fini(struct drm_device *drm)
{
malidp_de_planes_destroy(drm);
drm_mode_config_cleanup(drm);
}
static int malidp_irq_init(struct platform_device *pdev) static int malidp_irq_init(struct platform_device *pdev)
{ {
int irq_de, irq_se, ret = 0; int irq_de, irq_se, ret = 0;
...@@ -375,6 +381,8 @@ static int malidp_bind(struct device *dev) ...@@ -375,6 +381,8 @@ static int malidp_bind(struct device *dev)
if (ret < 0) if (ret < 0)
goto irq_init_fail; goto irq_init_fail;
drm->irq_enabled = true;
ret = drm_vblank_init(drm, drm->mode_config.num_crtc); ret = drm_vblank_init(drm, drm->mode_config.num_crtc);
if (ret < 0) { if (ret < 0) {
DRM_ERROR("failed to initialise vblank\n"); DRM_ERROR("failed to initialise vblank\n");
...@@ -400,6 +408,7 @@ static int malidp_bind(struct device *dev) ...@@ -400,6 +408,7 @@ static int malidp_bind(struct device *dev)
vblank_fail: vblank_fail:
malidp_se_irq_fini(drm); malidp_se_irq_fini(drm);
malidp_de_irq_fini(drm); malidp_de_irq_fini(drm);
drm->irq_enabled = false;
irq_init_fail: irq_init_fail:
component_unbind_all(dev, drm); component_unbind_all(dev, drm);
bind_fail: bind_fail:
...@@ -408,8 +417,7 @@ static int malidp_bind(struct device *dev) ...@@ -408,8 +417,7 @@ static int malidp_bind(struct device *dev)
port_fail: port_fail:
drm_dev_unregister(drm); drm_dev_unregister(drm);
register_fail: register_fail:
malidp_de_planes_destroy(drm); malidp_fini(drm);
drm_mode_config_cleanup(drm);
init_fail: init_fail:
drm->dev_private = NULL; drm->dev_private = NULL;
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
...@@ -442,8 +450,7 @@ static void malidp_unbind(struct device *dev) ...@@ -442,8 +450,7 @@ static void malidp_unbind(struct device *dev)
of_node_put(malidp->crtc.port); of_node_put(malidp->crtc.port);
malidp->crtc.port = NULL; malidp->crtc.port = NULL;
drm_dev_unregister(drm); drm_dev_unregister(drm);
malidp_de_planes_destroy(drm); malidp_fini(drm);
drm_mode_config_cleanup(drm);
drm->dev_private = NULL; drm->dev_private = NULL;
dev_set_drvdata(dev, NULL); dev_set_drvdata(dev, NULL);
clk_disable_unprepare(hwdev->mclk); clk_disable_unprepare(hwdev->mclk);
......
...@@ -39,6 +39,9 @@ struct malidp_plane_state { ...@@ -39,6 +39,9 @@ struct malidp_plane_state {
/* size of the required rotation memory if plane is rotated */ /* size of the required rotation memory if plane is rotated */
u32 rotmem_size; u32 rotmem_size;
/* internal format ID */
u8 format;
u8 n_planes;
}; };
#define to_malidp_plane(x) container_of(x, struct malidp_plane, base) #define to_malidp_plane(x) container_of(x, struct malidp_plane, base)
......
...@@ -125,6 +125,7 @@ static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev) ...@@ -125,6 +125,7 @@ static void malidp500_leave_config_mode(struct malidp_hw_device *hwdev)
{ {
u32 status, count = 100; u32 status, count = 100;
malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP500_CONFIG_VALID);
malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL); malidp_hw_clearbits(hwdev, MALIDP500_DC_CONFIG_REQ, MALIDP500_DC_CONTROL);
while (count) { while (count) {
status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS); status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
...@@ -266,6 +267,7 @@ static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev) ...@@ -266,6 +267,7 @@ static void malidp550_leave_config_mode(struct malidp_hw_device *hwdev)
{ {
u32 status, count = 100; u32 status, count = 100;
malidp_hw_clearbits(hwdev, MALIDP_CFG_VALID, MALIDP550_CONFIG_VALID);
malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL); malidp_hw_clearbits(hwdev, MALIDP550_DC_CONFIG_REQ, MALIDP550_DC_CONTROL);
while (count) { while (count) {
status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS); status = malidp_hw_read(hwdev, hwdev->map.dc_base + MALIDP_REG_STATUS);
...@@ -436,6 +438,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { ...@@ -436,6 +438,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
}, },
.input_formats = malidp500_de_formats, .input_formats = malidp500_de_formats,
.n_input_formats = ARRAY_SIZE(malidp500_de_formats), .n_input_formats = ARRAY_SIZE(malidp500_de_formats),
.bus_align_bytes = 8,
}, },
.query_hw = malidp500_query_hw, .query_hw = malidp500_query_hw,
.enter_config_mode = malidp500_enter_config_mode, .enter_config_mode = malidp500_enter_config_mode,
...@@ -468,6 +471,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { ...@@ -468,6 +471,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
}, },
.input_formats = malidp550_de_formats, .input_formats = malidp550_de_formats,
.n_input_formats = ARRAY_SIZE(malidp550_de_formats), .n_input_formats = ARRAY_SIZE(malidp550_de_formats),
.bus_align_bytes = 8,
}, },
.query_hw = malidp550_query_hw, .query_hw = malidp550_query_hw,
.enter_config_mode = malidp550_enter_config_mode, .enter_config_mode = malidp550_enter_config_mode,
...@@ -501,6 +505,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = { ...@@ -501,6 +505,7 @@ const struct malidp_hw_device malidp_device[MALIDP_MAX_DEVICES] = {
}, },
.input_formats = malidp550_de_formats, .input_formats = malidp550_de_formats,
.n_input_formats = ARRAY_SIZE(malidp550_de_formats), .n_input_formats = ARRAY_SIZE(malidp550_de_formats),
.bus_align_bytes = 16,
}, },
.query_hw = malidp650_query_hw, .query_hw = malidp650_query_hw,
.enter_config_mode = malidp550_enter_config_mode, .enter_config_mode = malidp550_enter_config_mode,
......
...@@ -88,6 +88,9 @@ struct malidp_hw_regmap { ...@@ -88,6 +88,9 @@ struct malidp_hw_regmap {
/* list of supported input formats for each layer */ /* list of supported input formats for each layer */
const struct malidp_input_format *input_formats; const struct malidp_input_format *input_formats;
const u8 n_input_formats; const u8 n_input_formats;
/* pitch alignment requirement in bytes */
const u8 bus_align_bytes;
}; };
struct malidp_hw_device { struct malidp_hw_device {
...@@ -229,6 +232,12 @@ void malidp_se_irq_fini(struct drm_device *drm); ...@@ -229,6 +232,12 @@ void malidp_se_irq_fini(struct drm_device *drm);
u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map, u8 malidp_hw_get_format_id(const struct malidp_hw_regmap *map,
u8 layer_id, u32 format); u8 layer_id, u32 format);
static inline bool malidp_hw_pitch_valid(struct malidp_hw_device *hwdev,
unsigned int pitch)
{
return !(pitch & (hwdev->map.bus_align_bytes - 1));
}
/* /*
* background color components are defined as 12bits values, * background color components are defined as 12bits values,
* they will be shifted right when stored on hardware that * they will be shifted right when stored on hardware that
......
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
#define LAYER_H_FLIP (1 << 10) #define LAYER_H_FLIP (1 << 10)
#define LAYER_V_FLIP (1 << 11) #define LAYER_V_FLIP (1 << 11)
#define LAYER_ROT_MASK (0xf << 8) #define LAYER_ROT_MASK (0xf << 8)
#define LAYER_COMP_MASK (0x3 << 12)
#define LAYER_COMP_PIXEL (0x3 << 12)
#define LAYER_COMP_PLANE (0x2 << 12)
#define MALIDP_LAYER_COMPOSE 0x008
#define MALIDP_LAYER_SIZE 0x00c #define MALIDP_LAYER_SIZE 0x00c
#define LAYER_H_VAL(x) (((x) & 0x1fff) << 0) #define LAYER_H_VAL(x) (((x) & 0x1fff) << 0)
#define LAYER_V_VAL(x) (((x) & 0x1fff) << 16) #define LAYER_V_VAL(x) (((x) & 0x1fff) << 16)
...@@ -34,6 +38,14 @@ ...@@ -34,6 +38,14 @@
#define MALIDP_LAYER_OFFSET 0x014 #define MALIDP_LAYER_OFFSET 0x014
#define MALIDP_LAYER_STRIDE 0x018 #define MALIDP_LAYER_STRIDE 0x018
/*
* This 4-entry look-up-table is used to determine the full 8-bit alpha value
* for formats with 1- or 2-bit alpha channels.
* We set it to give 100%/0% opacity for 1-bit formats and 100%/66%/33%/0%
* opacity for 2-bit formats.
*/
#define MALIDP_ALPHA_LUT 0xffaa5500
static void malidp_de_plane_destroy(struct drm_plane *plane) static void malidp_de_plane_destroy(struct drm_plane *plane)
{ {
struct malidp_plane *mp = to_malidp_plane(plane); struct malidp_plane *mp = to_malidp_plane(plane);
...@@ -46,7 +58,8 @@ static void malidp_de_plane_destroy(struct drm_plane *plane) ...@@ -46,7 +58,8 @@ static void malidp_de_plane_destroy(struct drm_plane *plane)
devm_kfree(plane->dev->dev, mp); devm_kfree(plane->dev->dev, mp);
} }
struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) static struct
drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
{ {
struct malidp_plane_state *state, *m_state; struct malidp_plane_state *state, *m_state;
...@@ -58,13 +71,15 @@ struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane) ...@@ -58,13 +71,15 @@ struct drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
m_state = to_malidp_plane_state(plane->state); m_state = to_malidp_plane_state(plane->state);
__drm_atomic_helper_plane_duplicate_state(plane, &state->base); __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
state->rotmem_size = m_state->rotmem_size; state->rotmem_size = m_state->rotmem_size;
state->format = m_state->format;
state->n_planes = m_state->n_planes;
} }
return &state->base; return &state->base;
} }
void malidp_destroy_plane_state(struct drm_plane *plane, static void malidp_destroy_plane_state(struct drm_plane *plane,
struct drm_plane_state *state) struct drm_plane_state *state)
{ {
struct malidp_plane_state *m_state = to_malidp_plane_state(state); struct malidp_plane_state *m_state = to_malidp_plane_state(state);
...@@ -75,6 +90,7 @@ void malidp_destroy_plane_state(struct drm_plane *plane, ...@@ -75,6 +90,7 @@ void malidp_destroy_plane_state(struct drm_plane *plane,
static const struct drm_plane_funcs malidp_de_plane_funcs = { static const struct drm_plane_funcs malidp_de_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane, .update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane, .disable_plane = drm_atomic_helper_disable_plane,
.set_property = drm_atomic_helper_plane_set_property,
.destroy = malidp_de_plane_destroy, .destroy = malidp_de_plane_destroy,
.reset = drm_atomic_helper_plane_reset, .reset = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = malidp_duplicate_plane_state, .atomic_duplicate_state = malidp_duplicate_plane_state,
...@@ -86,17 +102,29 @@ static int malidp_de_plane_check(struct drm_plane *plane, ...@@ -86,17 +102,29 @@ static int malidp_de_plane_check(struct drm_plane *plane,
{ {
struct malidp_plane *mp = to_malidp_plane(plane); struct malidp_plane *mp = to_malidp_plane(plane);
struct malidp_plane_state *ms = to_malidp_plane_state(state); struct malidp_plane_state *ms = to_malidp_plane_state(state);
u8 format_id; struct drm_framebuffer *fb;
int i;
u32 src_w, src_h; u32 src_w, src_h;
if (!state->crtc || !state->fb) if (!state->crtc || !state->fb)
return 0; return 0;
format_id = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id, fb = state->fb;
state->fb->pixel_format);
if (format_id == MALIDP_INVALID_FORMAT_ID) ms->format = malidp_hw_get_format_id(&mp->hwdev->map, mp->layer->id,
fb->pixel_format);
if (ms->format == MALIDP_INVALID_FORMAT_ID)
return -EINVAL; return -EINVAL;
ms->n_planes = drm_format_num_planes(fb->pixel_format);
for (i = 0; i < ms->n_planes; i++) {
if (!malidp_hw_pitch_valid(mp->hwdev, fb->pitches[i])) {
DRM_DEBUG_KMS("Invalid pitch %u for plane %d\n",
fb->pitches[i], i);
return -EINVAL;
}
}
src_w = state->src_w >> 16; src_w = state->src_w >> 16;
src_h = state->src_h >> 16; src_h = state->src_h >> 16;
...@@ -135,17 +163,13 @@ static void malidp_de_plane_update(struct drm_plane *plane, ...@@ -135,17 +163,13 @@ static void malidp_de_plane_update(struct drm_plane *plane,
struct drm_gem_cma_object *obj; struct drm_gem_cma_object *obj;
struct malidp_plane *mp; struct malidp_plane *mp;
const struct malidp_hw_regmap *map; const struct malidp_hw_regmap *map;
u8 format_id; struct malidp_plane_state *ms = to_malidp_plane_state(plane->state);
u16 ptr; u16 ptr;
u32 format, src_w, src_h, dest_w, dest_h, val = 0; u32 src_w, src_h, dest_w, dest_h, val;
int num_planes, i; int i;
mp = to_malidp_plane(plane); mp = to_malidp_plane(plane);
map = &mp->hwdev->map; map = &mp->hwdev->map;
format = plane->state->fb->pixel_format;
format_id = malidp_hw_get_format_id(map, mp->layer->id, format);
num_planes = drm_format_num_planes(format);
/* convert src values from Q16 fixed point to integer */ /* convert src values from Q16 fixed point to integer */
src_w = plane->state->src_w >> 16; src_w = plane->state->src_w >> 16;
...@@ -158,9 +182,9 @@ static void malidp_de_plane_update(struct drm_plane *plane, ...@@ -158,9 +182,9 @@ static void malidp_de_plane_update(struct drm_plane *plane,
dest_h = plane->state->crtc_h; dest_h = plane->state->crtc_h;
} }
malidp_hw_write(mp->hwdev, format_id, mp->layer->base); malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
for (i = 0; i < num_planes; i++) { for (i = 0; i < ms->n_planes; i++) {
/* calculate the offset for the layer's plane registers */ /* calculate the offset for the layer's plane registers */
ptr = mp->layer->ptr + (i << 4); ptr = mp->layer->ptr + (i << 4);
...@@ -181,9 +205,9 @@ static void malidp_de_plane_update(struct drm_plane *plane, ...@@ -181,9 +205,9 @@ static void malidp_de_plane_update(struct drm_plane *plane,
LAYER_V_VAL(plane->state->crtc_y), LAYER_V_VAL(plane->state->crtc_y),
mp->layer->base + MALIDP_LAYER_OFFSET); mp->layer->base + MALIDP_LAYER_OFFSET);
/* first clear the rotation bits in the register */ /* first clear the rotation bits */
malidp_hw_clearbits(mp->hwdev, LAYER_ROT_MASK, val = malidp_hw_read(mp->hwdev, mp->layer->base + MALIDP_LAYER_CONTROL);
mp->layer->base + MALIDP_LAYER_CONTROL); val &= ~LAYER_ROT_MASK;
/* setup the rotation and axis flip bits */ /* setup the rotation and axis flip bits */
if (plane->state->rotation & DRM_ROTATE_MASK) if (plane->state->rotation & DRM_ROTATE_MASK)
...@@ -193,11 +217,18 @@ static void malidp_de_plane_update(struct drm_plane *plane, ...@@ -193,11 +217,18 @@ static void malidp_de_plane_update(struct drm_plane *plane,
if (plane->state->rotation & DRM_REFLECT_Y) if (plane->state->rotation & DRM_REFLECT_Y)
val |= LAYER_H_FLIP; val |= LAYER_H_FLIP;
/*
* always enable pixel alpha blending until we have a way to change
* blend modes
*/
val &= ~LAYER_COMP_MASK;
val |= LAYER_COMP_PIXEL;
/* set the 'enable layer' bit */ /* set the 'enable layer' bit */
val |= LAYER_ENABLE; val |= LAYER_ENABLE;
malidp_hw_setbits(mp->hwdev, val, malidp_hw_write(mp->hwdev, val,
mp->layer->base + MALIDP_LAYER_CONTROL); mp->layer->base + MALIDP_LAYER_CONTROL);
} }
static void malidp_de_plane_disable(struct drm_plane *plane, static void malidp_de_plane_disable(struct drm_plane *plane,
...@@ -222,6 +253,8 @@ int malidp_de_planes_init(struct drm_device *drm) ...@@ -222,6 +253,8 @@ int malidp_de_planes_init(struct drm_device *drm)
struct malidp_plane *plane = NULL; struct malidp_plane *plane = NULL;
enum drm_plane_type plane_type; enum drm_plane_type plane_type;
unsigned long crtcs = 1 << drm->mode_config.num_crtc; unsigned long crtcs = 1 << drm->mode_config.num_crtc;
unsigned long flags = DRM_ROTATE_0 | DRM_ROTATE_90 | DRM_ROTATE_180 |
DRM_ROTATE_270 | DRM_REFLECT_X | DRM_REFLECT_Y;
u32 *formats; u32 *formats;
int ret, i, j, n; int ret, i, j, n;
...@@ -254,23 +287,18 @@ int malidp_de_planes_init(struct drm_device *drm) ...@@ -254,23 +287,18 @@ int malidp_de_planes_init(struct drm_device *drm)
if (ret < 0) if (ret < 0)
goto cleanup; goto cleanup;
/* SMART layer can't be rotated */
if (id != DE_SMART) {
unsigned long flags = DRM_ROTATE_0 |
DRM_ROTATE_90 |
DRM_ROTATE_180 |
DRM_ROTATE_270 |
DRM_REFLECT_X |
DRM_REFLECT_Y;
drm_plane_create_rotation_property(&plane->base,
DRM_ROTATE_0,
flags);
}
drm_plane_helper_add(&plane->base, drm_plane_helper_add(&plane->base,
&malidp_de_plane_helper_funcs); &malidp_de_plane_helper_funcs);
plane->hwdev = malidp->dev; plane->hwdev = malidp->dev;
plane->layer = &map->layers[i]; plane->layer = &map->layers[i];
/* Skip the features which the SMART layer doesn't have */
if (id == DE_SMART)
continue;
drm_plane_create_rotation_property(&plane->base, DRM_ROTATE_0, flags);
malidp_hw_write(malidp->dev, MALIDP_ALPHA_LUT,
plane->layer->base + MALIDP_LAYER_COMPOSE);
} }
kfree(formats); kfree(formats);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment