|
@@ -11,6 +11,7 @@
|
|
*/
|
|
*/
|
|
|
|
|
|
#include <drm/drmP.h>
|
|
#include <drm/drmP.h>
|
|
|
|
+#include <drm/drm_atomic.h>
|
|
#include <drm/drm_atomic_helper.h>
|
|
#include <drm/drm_atomic_helper.h>
|
|
#include <drm/drm_fb_cma_helper.h>
|
|
#include <drm/drm_fb_cma_helper.h>
|
|
#include <drm/drm_gem_cma_helper.h>
|
|
#include <drm/drm_gem_cma_helper.h>
|
|
@@ -36,7 +37,6 @@
|
|
#define LAYER_V_VAL(x) (((x) & 0x1fff) << 16)
|
|
#define LAYER_V_VAL(x) (((x) & 0x1fff) << 16)
|
|
#define MALIDP_LAYER_COMP_SIZE 0x010
|
|
#define MALIDP_LAYER_COMP_SIZE 0x010
|
|
#define MALIDP_LAYER_OFFSET 0x014
|
|
#define MALIDP_LAYER_OFFSET 0x014
|
|
-#define MALIDP_LAYER_STRIDE 0x018
|
|
|
|
|
|
|
|
/*
|
|
/*
|
|
* This 4-entry look-up-table is used to determine the full 8-bit alpha value
|
|
* This 4-entry look-up-table is used to determine the full 8-bit alpha value
|
|
@@ -67,13 +67,14 @@ drm_plane_state *malidp_duplicate_plane_state(struct drm_plane *plane)
|
|
return NULL;
|
|
return NULL;
|
|
|
|
|
|
state = kmalloc(sizeof(*state), GFP_KERNEL);
|
|
state = kmalloc(sizeof(*state), GFP_KERNEL);
|
|
- if (state) {
|
|
|
|
- m_state = to_malidp_plane_state(plane->state);
|
|
|
|
- __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
|
|
|
|
- state->rotmem_size = m_state->rotmem_size;
|
|
|
|
- state->format = m_state->format;
|
|
|
|
- state->n_planes = m_state->n_planes;
|
|
|
|
- }
|
|
|
|
|
|
+ if (!state)
|
|
|
|
+ return NULL;
|
|
|
|
+
|
|
|
|
+ m_state = to_malidp_plane_state(plane->state);
|
|
|
|
+ __drm_atomic_helper_plane_duplicate_state(plane, &state->base);
|
|
|
|
+ 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;
|
|
}
|
|
}
|
|
@@ -102,8 +103,10 @@ 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);
|
|
|
|
+ struct drm_crtc_state *crtc_state;
|
|
struct drm_framebuffer *fb;
|
|
struct drm_framebuffer *fb;
|
|
- int i;
|
|
|
|
|
|
+ struct drm_rect clip = { 0 };
|
|
|
|
+ int i, ret;
|
|
u32 src_w, src_h;
|
|
u32 src_w, src_h;
|
|
|
|
|
|
if (!state->crtc || !state->fb)
|
|
if (!state->crtc || !state->fb)
|
|
@@ -131,8 +134,17 @@ static int malidp_de_plane_check(struct drm_plane *plane,
|
|
if ((state->crtc_w > mp->hwdev->max_line_size) ||
|
|
if ((state->crtc_w > mp->hwdev->max_line_size) ||
|
|
(state->crtc_h > mp->hwdev->max_line_size) ||
|
|
(state->crtc_h > mp->hwdev->max_line_size) ||
|
|
(state->crtc_w < mp->hwdev->min_line_size) ||
|
|
(state->crtc_w < mp->hwdev->min_line_size) ||
|
|
- (state->crtc_h < mp->hwdev->min_line_size) ||
|
|
|
|
- (state->crtc_w != src_w) || (state->crtc_h != src_h))
|
|
|
|
|
|
+ (state->crtc_h < mp->hwdev->min_line_size))
|
|
|
|
+ return -EINVAL;
|
|
|
|
+
|
|
|
|
+ /*
|
|
|
|
+ * DP550/650 video layers can accept 3 plane formats only if
|
|
|
|
+ * fb->pitches[1] == fb->pitches[2] since they don't have a
|
|
|
|
+ * third plane stride register.
|
|
|
|
+ */
|
|
|
|
+ if (ms->n_planes == 3 &&
|
|
|
|
+ !(mp->hwdev->features & MALIDP_DEVICE_LV_HAS_3_STRIDES) &&
|
|
|
|
+ (state->fb->pitches[1] != state->fb->pitches[2]))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
/* packed RGB888 / BGR888 can't be rotated or flipped */
|
|
/* packed RGB888 / BGR888 can't be rotated or flipped */
|
|
@@ -141,6 +153,16 @@ static int malidp_de_plane_check(struct drm_plane *plane,
|
|
fb->format->format == DRM_FORMAT_BGR888))
|
|
fb->format->format == DRM_FORMAT_BGR888))
|
|
return -EINVAL;
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
+ crtc_state = drm_atomic_get_existing_crtc_state(state->state, state->crtc);
|
|
|
|
+ clip.x2 = crtc_state->adjusted_mode.hdisplay;
|
|
|
|
+ clip.y2 = crtc_state->adjusted_mode.vdisplay;
|
|
|
|
+ ret = drm_plane_helper_check_state(state, &clip,
|
|
|
|
+ DRM_PLANE_HELPER_NO_SCALING,
|
|
|
|
+ DRM_PLANE_HELPER_NO_SCALING,
|
|
|
|
+ true, true);
|
|
|
|
+ if (ret)
|
|
|
|
+ return ret;
|
|
|
|
+
|
|
ms->rotmem_size = 0;
|
|
ms->rotmem_size = 0;
|
|
if (state->rotation & MALIDP_ROTATED_MASK) {
|
|
if (state->rotation & MALIDP_ROTATED_MASK) {
|
|
int val;
|
|
int val;
|
|
@@ -157,6 +179,25 @@ static int malidp_de_plane_check(struct drm_plane *plane,
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void malidp_de_set_plane_pitches(struct malidp_plane *mp,
|
|
|
|
+ int num_planes, unsigned int pitches[3])
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+ int num_strides = num_planes;
|
|
|
|
+
|
|
|
|
+ if (!mp->layer->stride_offset)
|
|
|
|
+ return;
|
|
|
|
+
|
|
|
|
+ if (num_planes == 3)
|
|
|
|
+ num_strides = (mp->hwdev->features &
|
|
|
|
+ MALIDP_DEVICE_LV_HAS_3_STRIDES) ? 3 : 2;
|
|
|
|
+
|
|
|
|
+ for (i = 0; i < num_strides; ++i)
|
|
|
|
+ malidp_hw_write(mp->hwdev, pitches[i],
|
|
|
|
+ mp->layer->base +
|
|
|
|
+ mp->layer->stride_offset + i * 4);
|
|
|
|
+}
|
|
|
|
+
|
|
static void malidp_de_plane_update(struct drm_plane *plane,
|
|
static void malidp_de_plane_update(struct drm_plane *plane,
|
|
struct drm_plane_state *old_state)
|
|
struct drm_plane_state *old_state)
|
|
{
|
|
{
|
|
@@ -174,13 +215,8 @@ static void malidp_de_plane_update(struct drm_plane *plane,
|
|
/* 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;
|
|
src_h = plane->state->src_h >> 16;
|
|
src_h = plane->state->src_h >> 16;
|
|
- if (plane->state->rotation & MALIDP_ROTATED_MASK) {
|
|
|
|
- dest_w = plane->state->crtc_h;
|
|
|
|
- dest_h = plane->state->crtc_w;
|
|
|
|
- } else {
|
|
|
|
- dest_w = plane->state->crtc_w;
|
|
|
|
- dest_h = plane->state->crtc_h;
|
|
|
|
- }
|
|
|
|
|
|
+ dest_w = plane->state->crtc_w;
|
|
|
|
+ dest_h = plane->state->crtc_h;
|
|
|
|
|
|
malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
|
|
malidp_hw_write(mp->hwdev, ms->format, mp->layer->base);
|
|
|
|
|
|
@@ -189,11 +225,12 @@ static void malidp_de_plane_update(struct drm_plane *plane,
|
|
ptr = mp->layer->ptr + (i << 4);
|
|
ptr = mp->layer->ptr + (i << 4);
|
|
|
|
|
|
obj = drm_fb_cma_get_gem_obj(plane->state->fb, i);
|
|
obj = drm_fb_cma_get_gem_obj(plane->state->fb, i);
|
|
|
|
+ obj->paddr += plane->state->fb->offsets[i];
|
|
malidp_hw_write(mp->hwdev, lower_32_bits(obj->paddr), ptr);
|
|
malidp_hw_write(mp->hwdev, lower_32_bits(obj->paddr), ptr);
|
|
malidp_hw_write(mp->hwdev, upper_32_bits(obj->paddr), ptr + 4);
|
|
malidp_hw_write(mp->hwdev, upper_32_bits(obj->paddr), ptr + 4);
|
|
- malidp_hw_write(mp->hwdev, plane->state->fb->pitches[i],
|
|
|
|
- mp->layer->base + MALIDP_LAYER_STRIDE);
|
|
|
|
}
|
|
}
|
|
|
|
+ malidp_de_set_plane_pitches(mp, ms->n_planes,
|
|
|
|
+ plane->state->fb->pitches);
|
|
|
|
|
|
malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
|
|
malidp_hw_write(mp->hwdev, LAYER_H_VAL(src_w) | LAYER_V_VAL(src_h),
|
|
mp->layer->base + MALIDP_LAYER_SIZE);
|
|
mp->layer->base + MALIDP_LAYER_SIZE);
|
|
@@ -211,11 +248,12 @@ static void malidp_de_plane_update(struct drm_plane *plane,
|
|
|
|
|
|
/* 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)
|
|
- val = ilog2(plane->state->rotation & DRM_ROTATE_MASK) << LAYER_ROT_OFFSET;
|
|
|
|
|
|
+ val |= ilog2(plane->state->rotation & DRM_ROTATE_MASK) <<
|
|
|
|
+ LAYER_ROT_OFFSET;
|
|
if (plane->state->rotation & DRM_REFLECT_X)
|
|
if (plane->state->rotation & DRM_REFLECT_X)
|
|
- val |= LAYER_V_FLIP;
|
|
|
|
- if (plane->state->rotation & DRM_REFLECT_Y)
|
|
|
|
val |= LAYER_H_FLIP;
|
|
val |= LAYER_H_FLIP;
|
|
|
|
+ if (plane->state->rotation & DRM_REFLECT_Y)
|
|
|
|
+ val |= LAYER_V_FLIP;
|
|
|
|
|
|
/*
|
|
/*
|
|
* always enable pixel alpha blending until we have a way to change
|
|
* always enable pixel alpha blending until we have a way to change
|
|
@@ -258,7 +296,7 @@ int malidp_de_planes_init(struct drm_device *drm)
|
|
u32 *formats;
|
|
u32 *formats;
|
|
int ret, i, j, n;
|
|
int ret, i, j, n;
|
|
|
|
|
|
- formats = kcalloc(map->n_input_formats, sizeof(*formats), GFP_KERNEL);
|
|
|
|
|
|
+ formats = kcalloc(map->n_pixel_formats, sizeof(*formats), GFP_KERNEL);
|
|
if (!formats) {
|
|
if (!formats) {
|
|
ret = -ENOMEM;
|
|
ret = -ENOMEM;
|
|
goto cleanup;
|
|
goto cleanup;
|
|
@@ -274,9 +312,9 @@ int malidp_de_planes_init(struct drm_device *drm)
|
|
}
|
|
}
|
|
|
|
|
|
/* build the list of DRM supported formats based on the map */
|
|
/* build the list of DRM supported formats based on the map */
|
|
- for (n = 0, j = 0; j < map->n_input_formats; j++) {
|
|
|
|
- if ((map->input_formats[j].layer & id) == id)
|
|
|
|
- formats[n++] = map->input_formats[j].format;
|
|
|
|
|
|
+ for (n = 0, j = 0; j < map->n_pixel_formats; j++) {
|
|
|
|
+ if ((map->pixel_formats[j].layer & id) == id)
|
|
|
|
+ formats[n++] = map->pixel_formats[j].format;
|
|
}
|
|
}
|
|
|
|
|
|
plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
|
|
plane_type = (i == 0) ? DRM_PLANE_TYPE_PRIMARY :
|