drm/ast: Add primary plane

Like the original mode-setting code, the primary plane supports XRGB888,
RGB565 and C8. The plane itself only pins BOs and sets the base address
and scanline offset. The mode-setting code will be located in the CRTC's
atomic helpers.

v2:
	* don't set plane call-back functions to NULL explicitly
	* define plane format array in global scope

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20191107083404.6852-7-tzimmermann@suse.de
This commit is contained in:
Thomas Zimmermann 2019-11-07 09:34:01 +01:00
parent 259d14a76a
commit a6ff807b71
2 changed files with 89 additions and 2 deletions

View File

@ -121,6 +121,8 @@ struct ast_private {
unsigned int next_index; unsigned int next_index;
} cursor; } cursor;
struct drm_plane primary_plane;
bool support_wide_screen; bool support_wide_screen;
enum { enum {
ast_use_p2a, ast_use_p2a,

View File

@ -31,6 +31,8 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_atomic_state_helper.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_fourcc.h> #include <drm/drm_fourcc.h>
@ -51,6 +53,7 @@ static int ast_cursor_set(struct drm_crtc *crtc,
static int ast_cursor_move(struct drm_crtc *crtc, static int ast_cursor_move(struct drm_crtc *crtc,
int x, int y); int x, int y);
static inline void ast_load_palette_index(struct ast_private *ast, static inline void ast_load_palette_index(struct ast_private *ast,
u8 index, u8 red, u8 green, u8 index, u8 red, u8 green,
u8 blue) u8 blue)
@ -538,6 +541,62 @@ static void ast_set_start_address_crt1(struct drm_crtc *crtc, unsigned offset)
} }
/*
* Primary plane
*/
static const uint32_t ast_primary_plane_formats[] = {
DRM_FORMAT_XRGB8888,
DRM_FORMAT_RGB565,
DRM_FORMAT_C8,
};
int ast_primary_plane_helper_atomic_check(struct drm_plane *plane,
struct drm_plane_state *state)
{
return 0;
}
void ast_primary_plane_helper_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
struct drm_plane_state *state = plane->state;
struct drm_crtc *crtc = state->crtc;
struct drm_gem_vram_object *gbo;
s64 gpu_addr;
if (!crtc || !state->fb)
return;
gbo = drm_gem_vram_of_gem(state->fb->obj[0]);
gpu_addr = drm_gem_vram_offset(gbo);
if (WARN_ON_ONCE(gpu_addr < 0))
return; /* Bug: we didn't pin the BO to VRAM in prepare_fb. */
ast_set_offset_reg(crtc);
ast_set_start_address_crt1(crtc, (u32)gpu_addr);
}
static const struct drm_plane_helper_funcs ast_primary_plane_helper_funcs = {
.prepare_fb = drm_gem_vram_plane_helper_prepare_fb,
.cleanup_fb = drm_gem_vram_plane_helper_cleanup_fb,
.atomic_check = ast_primary_plane_helper_atomic_check,
.atomic_update = ast_primary_plane_helper_atomic_update,
};
static const struct drm_plane_funcs ast_primary_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
.destroy = drm_plane_cleanup,
.reset = drm_atomic_helper_plane_reset,
.atomic_duplicate_state = drm_atomic_helper_plane_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_plane_destroy_state,
};
/*
* CRTC
*/
static void ast_crtc_dpms(struct drm_crtc *crtc, int mode) static void ast_crtc_dpms(struct drm_crtc *crtc, int mode)
{ {
struct ast_private *ast = crtc->dev->dev_private; struct ast_private *ast = crtc->dev->dev_private;
@ -711,16 +770,26 @@ static const struct drm_crtc_funcs ast_crtc_funcs = {
static int ast_crtc_init(struct drm_device *dev) static int ast_crtc_init(struct drm_device *dev)
{ {
struct ast_private *ast = dev->dev_private;
struct ast_crtc *crtc; struct ast_crtc *crtc;
int ret;
crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL); crtc = kzalloc(sizeof(struct ast_crtc), GFP_KERNEL);
if (!crtc) if (!crtc)
return -ENOMEM; return -ENOMEM;
drm_crtc_init(dev, &crtc->base, &ast_crtc_funcs); ret = drm_crtc_init_with_planes(dev, &crtc->base, &ast->primary_plane,
NULL, &ast_crtc_funcs, NULL);
if (ret)
goto err_kfree;
drm_mode_crtc_set_gamma_size(&crtc->base, 256); drm_mode_crtc_set_gamma_size(&crtc->base, 256);
drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs); drm_crtc_helper_add(&crtc->base, &ast_crtc_helper_funcs);
return 0; return 0;
err_kfree:
kfree(crtc);
return ret;
} }
static void ast_encoder_destroy(struct drm_encoder *encoder) static void ast_encoder_destroy(struct drm_encoder *encoder)
@ -754,7 +823,6 @@ static void ast_encoder_commit(struct drm_encoder *encoder)
} }
static const struct drm_encoder_helper_funcs ast_enc_helper_funcs = { static const struct drm_encoder_helper_funcs ast_enc_helper_funcs = {
.dpms = ast_encoder_dpms, .dpms = ast_encoder_dpms,
.prepare = ast_encoder_prepare, .prepare = ast_encoder_prepare,
@ -976,10 +1044,27 @@ static void ast_cursor_fini(struct drm_device *dev)
int ast_mode_init(struct drm_device *dev) int ast_mode_init(struct drm_device *dev)
{ {
struct ast_private *ast = dev->dev_private;
int ret;
memset(&ast->primary_plane, 0, sizeof(ast->primary_plane));
ret = drm_universal_plane_init(dev, &ast->primary_plane, 0x01,
&ast_primary_plane_funcs,
ast_primary_plane_formats,
ARRAY_SIZE(ast_primary_plane_formats),
NULL, DRM_PLANE_TYPE_PRIMARY, NULL);
if (ret) {
DRM_ERROR("ast: drm_universal_plane_init() failed: %d\n", ret);
return ret;
}
drm_plane_helper_add(&ast->primary_plane,
&ast_primary_plane_helper_funcs);
ast_cursor_init(dev); ast_cursor_init(dev);
ast_crtc_init(dev); ast_crtc_init(dev);
ast_encoder_init(dev); ast_encoder_init(dev);
ast_connector_init(dev); ast_connector_init(dev);
return 0; return 0;
} }