drm/rockchip: driver: add support more property

Change-Id: If2cbc617d9346713efaf7dc4dd5c393e8605f91d
Signed-off-by: Sandy Huang <hjc@rock-chips.com>
This commit is contained in:
Sandy Huang
2019-06-19 14:15:08 +08:00
committed by Tao Huang
parent 8166dc7eb5
commit 35c52e2194
5 changed files with 370 additions and 11 deletions

View File

@@ -37,6 +37,8 @@
#include "rockchip_drm_fbdev.h"
#include "rockchip_drm_gem.h"
#include "../drm_internal.h"
#define DRIVER_NAME "rockchip"
#define DRIVER_DESC "RockChip Soc DRM"
#define DRIVER_DATE "20140818"
@@ -571,6 +573,7 @@ static int update_state(struct drm_device *drm_dev,
struct rockchip_drm_mode_set *set,
unsigned int *plane_mask)
{
struct rockchip_drm_private *priv = drm_dev->dev_private;
struct drm_crtc *crtc = set->crtc;
struct drm_connector *connector = set->connector;
struct drm_display_mode *mode = set->mode;
@@ -578,6 +581,7 @@ static int update_state(struct drm_device *drm_dev,
struct drm_crtc_state *crtc_state;
struct drm_connector_state *conn_state;
int ret;
struct rockchip_crtc_state *s;
crtc_state = drm_atomic_get_crtc_state(state, crtc);
if (IS_ERR(crtc_state))
@@ -585,6 +589,11 @@ static int update_state(struct drm_device *drm_dev,
conn_state = drm_atomic_get_connector_state(state, connector);
if (IS_ERR(conn_state))
return PTR_ERR(conn_state);
s = to_rockchip_crtc_state(crtc_state);
s->left_margin = set->left_margin;
s->right_margin = set->right_margin;
s->top_margin = set->top_margin;
s->bottom_margin = set->bottom_margin;
if (set->mode_changed) {
ret = drm_atomic_set_crtc_for_connector(conn_state, crtc);
@@ -630,13 +639,17 @@ static int update_state(struct drm_device *drm_dev,
drm_framebuffer_put(set->fb);
ret = drm_atomic_set_crtc_for_plane(primary_state, crtc);
/*
* TODO:
* some vop maybe not support ymirror, but force use it now.
* drm_atomic_plane_set_property(crtc->primary, primary_state,
* mode_config->rotation_property,
* BIT(DRM_REFLECT_Y));
*/
if (set->ymirror) {
/*
* TODO:
* some vop maybe not support ymirror, but force use it now.
*/
ret = drm_atomic_set_property(state,
&primary_state->plane->base,
priv->logo_ymirror_prop, true);
if (ret)
DRM_ERROR("Failed to initial logo_ymirror_prop\n");
}
return ret;
}
@@ -675,7 +688,11 @@ static void show_loader_logo(struct drm_device *drm_dev)
}
state->acquire_ctx = mode_config->acquire_ctx;
for_each_child_of_node(root, route) {
if (!of_device_is_available(route))
continue;
set = of_parse_display_resource(drm_dev, route);
if (!set)
continue;
@@ -865,6 +882,50 @@ static void rockchip_iommu_cleanup(struct drm_device *drm_dev)
iommu_domain_free(private->domain);
}
static int rockchip_drm_create_properties(struct drm_device *dev)
{
struct drm_property *prop;
struct rockchip_drm_private *private = dev->dev_private;
prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
"EOTF", 0, 5);
if (!prop)
return -ENOMEM;
private->eotf_prop = prop;
prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
"COLOR_SPACE", 0, 12);
if (!prop)
return -ENOMEM;
private->color_space_prop = prop;
prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
"GLOBAL_ALPHA", 0, 255);
if (!prop)
return -ENOMEM;
private->global_alpha_prop = prop;
prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
"BLEND_MODE", 0, 1);
if (!prop)
return -ENOMEM;
private->blend_mode_prop = prop;
prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
"ALPHA_SCALE", 0, 1);
if (!prop)
return -ENOMEM;
private->alpha_scale_prop = prop;
prop = drm_property_create_range(dev, DRM_MODE_PROP_ATOMIC,
"LOGO_YMIRROR", 0, 1);
if (!prop)
return -ENOMEM;
private->logo_ymirror_prop = prop;
return drm_mode_create_tv_properties(dev, 0, NULL);
}
static int rockchip_gem_pool_init(struct drm_device *drm)
{
struct rockchip_drm_private *private = drm->dev_private;
@@ -905,6 +966,84 @@ static void rockchip_gem_pool_destroy(struct drm_device *drm)
gen_pool_destroy(private->secure_buffer_pool);
}
static void rockchip_attach_connector_property(struct drm_device *drm)
{
struct drm_connector *connector;
struct drm_mode_config *conf = &drm->mode_config;
struct drm_connector_list_iter conn_iter;
mutex_lock(&drm->mode_config.mutex);
#define ROCKCHIP_PROP_ATTACH(prop, v) \
drm_object_attach_property(&connector->base, prop, v)
drm_connector_list_iter_begin(drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
ROCKCHIP_PROP_ATTACH(conf->tv_brightness_property, 100);
ROCKCHIP_PROP_ATTACH(conf->tv_contrast_property, 100);
ROCKCHIP_PROP_ATTACH(conf->tv_saturation_property, 100);
ROCKCHIP_PROP_ATTACH(conf->tv_hue_property, 100);
}
drm_connector_list_iter_end(&conn_iter);
#undef ROCKCHIP_PROP_ATTACH
mutex_unlock(&drm->mode_config.mutex);
}
static void rockchip_drm_set_property_default(struct drm_device *drm)
{
struct drm_connector *connector;
struct drm_mode_config *conf = &drm->mode_config;
struct drm_atomic_state *state;
int ret;
struct drm_connector_list_iter conn_iter;
drm_modeset_lock_all(drm);
state = drm_atomic_helper_duplicate_state(drm, conf->acquire_ctx);
if (!state) {
DRM_ERROR("failed to alloc atomic state\n");
goto err_unlock;
}
state->acquire_ctx = conf->acquire_ctx;
#define CONNECTOR_SET_PROP(prop, val) \
do { \
ret = drm_atomic_set_property(state, &connector->base, \
prop, \
val); \
if (ret) \
DRM_ERROR("Connector[%d]: Failed to initial %s\n", \
connector->base.id, #prop); \
} while (0)
drm_connector_list_iter_begin(drm, &conn_iter);
drm_for_each_connector_iter(connector, &conn_iter) {
struct drm_connector_state *connector_state;
connector_state = drm_atomic_get_connector_state(state,
connector);
if (IS_ERR(connector_state))
DRM_ERROR("Connector[%d]: Failed to get state\n",
connector->base.id);
CONNECTOR_SET_PROP(conf->tv_brightness_property, 50);
CONNECTOR_SET_PROP(conf->tv_contrast_property, 50);
CONNECTOR_SET_PROP(conf->tv_saturation_property, 50);
CONNECTOR_SET_PROP(conf->tv_hue_property, 50);
}
drm_connector_list_iter_end(&conn_iter);
#undef CONNECTOR_SET_PROP
ret = drm_atomic_commit(state);
WARN_ON(ret == -EDEADLK);
if (ret)
DRM_ERROR("Failed to update properties\n");
err_unlock:
drm_modeset_unlock_all(drm);
}
static int rockchip_drm_bind(struct device *dev)
{
struct drm_device *drm_dev;
@@ -935,17 +1074,19 @@ static int rockchip_drm_bind(struct device *dev)
drm_mode_config_init(drm_dev);
rockchip_drm_mode_config_init(drm_dev);
rockchip_drm_create_properties(drm_dev);
/* Try to bind all sub drivers. */
ret = component_bind_all(dev, drm_dev);
if (ret)
goto err_mode_config_cleanup;
rockchip_attach_connector_property(drm_dev);
ret = drm_vblank_init(drm_dev, drm_dev->mode_config.num_crtc);
if (ret)
goto err_unbind_all;
drm_mode_config_reset(drm_dev);
rockchip_drm_set_property_default(drm_dev);
/*
* enable drm irq mode.

View File

@@ -119,6 +119,12 @@ struct rockchip_logo {
*/
struct rockchip_drm_private {
struct rockchip_logo *logo;
struct drm_property *logo_ymirror_prop;
struct drm_property *eotf_prop;
struct drm_property *color_space_prop;
struct drm_property *global_alpha_prop;
struct drm_property *blend_mode_prop;
struct drm_property *alpha_scale_prop;
struct drm_fb_helper *fbdev_helper;
struct drm_gem_object *fbdev_bo;
struct drm_atomic_state *state;

View File

@@ -23,7 +23,6 @@ rockchip_drm_framebuffer_init(struct drm_device *dev,
void rockchip_drm_framebuffer_fini(struct drm_framebuffer *fb);
void rockchip_drm_mode_config_init(struct drm_device *dev);
struct drm_framebuffer *
rockchip_fb_alloc(struct drm_device *dev, const struct drm_mode_fb_cmd2 *mode_cmd,
struct drm_gem_object **obj, struct rockchip_logo *logo,

View File

@@ -1678,6 +1678,7 @@ static int vop_atomic_plane_set_property(struct drm_plane *plane,
struct drm_property *property,
uint64_t val)
{
struct rockchip_drm_private *private = plane->dev->dev_private;
struct vop_win *win = to_vop_win(plane);
struct vop_plane_state *plane_state = &win->state;
@@ -1685,8 +1686,35 @@ static int vop_atomic_plane_set_property(struct drm_plane *plane,
plane_state->zpos = val;
return 0;
}
if (property == private->logo_ymirror_prop) {
WARN_ON(!rockchip_fb_is_logo(state->fb));
plane_state->logo_ymirror = val;
return 0;
}
if (property == private->eotf_prop) {
plane_state->eotf = val;
return 0;
}
if (property == private->color_space_prop) {
plane_state->color_space = val;
return 0;
}
if (property == private->global_alpha_prop) {
plane_state->global_alpha = val;
return 0;
}
if (property == private->blend_mode_prop) {
plane_state->blend_mode = val;
return 0;
}
DRM_ERROR("failed to set vop plane property id:%d, name:%s\n",
property->base.id, property->name);
DRM_ERROR("failed to set vop plane property\n");
return -EINVAL;
}
@@ -1697,13 +1725,41 @@ static int vop_atomic_plane_get_property(struct drm_plane *plane,
{
struct vop_win *win = to_vop_win(plane);
struct vop_plane_state *plane_state = &win->state;
struct rockchip_drm_private *private = plane->dev->dev_private;
if (property == win->vop->plane_zpos_prop) {
*val = plane_state->zpos;
return 0;
}
DRM_ERROR("failed to get vop plane property\n");
if (property == private->logo_ymirror_prop) {
*val = plane_state->logo_ymirror;
return 0;
}
if (property == private->eotf_prop) {
*val = plane_state->eotf;
return 0;
}
if (property == private->color_space_prop) {
*val = plane_state->color_space;
return 0;
}
if (property == private->global_alpha_prop) {
*val = plane_state->global_alpha;
return 0;
}
if (property == private->blend_mode_prop) {
*val = plane_state->blend_mode;
return 0;
}
DRM_ERROR("failed to get vop plane property id:%d, name:%s\n",
property->base.id, property->name);
return -EINVAL;
}
@@ -2785,11 +2841,87 @@ vop_crtc_verify_crc_source(struct drm_crtc *crtc, const char *source_name,
}
#endif
static int vop_crtc_atomic_get_property(struct drm_crtc *crtc,
const struct drm_crtc_state *state,
struct drm_property *property,
uint64_t *val)
{
struct drm_device *drm_dev = crtc->dev;
struct rockchip_drm_private *private = drm_dev->dev_private;
struct drm_mode_config *mode_config = &drm_dev->mode_config;
struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
struct vop *vop = to_vop(crtc);
if (property == mode_config->tv_left_margin_property) {
*val = s->left_margin;
return 0;
}
if (property == mode_config->tv_right_margin_property) {
*val = s->right_margin;
return 0;
}
if (property == mode_config->tv_top_margin_property) {
*val = s->top_margin;
return 0;
}
if (property == mode_config->tv_bottom_margin_property) {
*val = s->bottom_margin;
return 0;
}
if (property == private->alpha_scale_prop) {
*val = (vop->data->feature & VOP_FEATURE_ALPHA_SCALE) ? 1 : 0;
return 0;
}
DRM_ERROR("failed to get vop crtc property\n");
return -EINVAL;
}
static int vop_crtc_atomic_set_property(struct drm_crtc *crtc,
struct drm_crtc_state *state,
struct drm_property *property,
uint64_t val)
{
struct drm_device *drm_dev = crtc->dev;
struct drm_mode_config *mode_config = &drm_dev->mode_config;
struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
//struct vop *vop = to_vop(crtc);
if (property == mode_config->tv_left_margin_property) {
s->left_margin = val;
return 0;
}
if (property == mode_config->tv_right_margin_property) {
s->right_margin = val;
return 0;
}
if (property == mode_config->tv_top_margin_property) {
s->top_margin = val;
return 0;
}
if (property == mode_config->tv_bottom_margin_property) {
s->bottom_margin = val;
return 0;
}
DRM_ERROR("failed to set vop crtc property\n");
return -EINVAL;
}
static const struct drm_crtc_funcs vop_crtc_funcs = {
.set_config = drm_atomic_helper_set_config,
.page_flip = drm_atomic_helper_page_flip,
.destroy = vop_crtc_destroy,
.reset = vop_crtc_reset,
.atomic_get_property = vop_crtc_atomic_get_property,
.atomic_set_property = vop_crtc_atomic_set_property,
.atomic_duplicate_state = vop_crtc_duplicate_state,
.atomic_destroy_state = vop_crtc_destroy_state,
.enable_vblank = vop_crtc_enable_vblank,
@@ -2933,7 +3065,9 @@ static void vop_plane_add_properties(struct vop *vop,
static int vop_plane_init(struct vop *vop, struct vop_win *win,
unsigned long possible_crtcs)
{
struct rockchip_drm_private *private = vop->drm_dev->dev_private;
struct drm_plane *share = NULL;
uint64_t feature = 0;
int ret;
if (win->parent)
@@ -2950,16 +3084,44 @@ static int vop_plane_init(struct vop *vop, struct vop_win *win,
drm_object_attach_property(&win->base.base,
vop->plane_zpos_prop, win->win_id);
if (VOP_WIN_SUPPORT(vop, win, ymirror))
drm_object_attach_property(&win->base.base, private->logo_ymirror_prop, 0);
if (win->phy->scl)
feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_SCALE);
if (VOP_WIN_SUPPORT(vop, win, src_alpha_ctl) ||
VOP_WIN_SUPPORT(vop, win, alpha_en))
feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_ALPHA);
if (win->feature & WIN_FEATURE_HDR2SDR)
feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_HDR2SDR);
if (win->feature & WIN_FEATURE_SDR2HDR)
feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_SDR2HDR);
if (win->feature & WIN_FEATURE_AFBDC)
feature |= BIT(ROCKCHIP_DRM_PLANE_FEATURE_AFBDC);
drm_object_attach_property(&win->base.base, vop->plane_feature_prop,
feature);
drm_object_attach_property(&win->base.base, private->eotf_prop, 0);
drm_object_attach_property(&win->base.base,
private->color_space_prop, 0);
if (VOP_WIN_SUPPORT(vop, win, global_alpha_val))
drm_object_attach_property(&win->base.base,
private->global_alpha_prop, 0xff);
drm_object_attach_property(&win->base.base,
private->blend_mode_prop, 0);
return 0;
}
static int vop_create_crtc(struct vop *vop)
{
struct device *dev = vop->dev;
const struct vop_data *vop_data = vop->data;
struct drm_device *drm_dev = vop->drm_dev;
struct rockchip_drm_private *private = drm_dev->dev_private;
struct drm_plane *primary = NULL, *cursor = NULL, *plane, *tmp;
struct drm_crtc *crtc = &vop->crtc;
struct device_node *port;
uint64_t feature = 0;
int ret = 0;
int i;
@@ -3027,6 +3189,20 @@ static int vop_create_crtc(struct vop *vop)
init_completion(&vop->line_flag_completion);
crtc->port = port;
#define VOP_ATTACH_MODE_CONFIG_PROP(prop, v) \
drm_object_attach_property(&crtc->base, drm_dev->mode_config.prop, v)
VOP_ATTACH_MODE_CONFIG_PROP(tv_left_margin_property, 100);
VOP_ATTACH_MODE_CONFIG_PROP(tv_right_margin_property, 100);
VOP_ATTACH_MODE_CONFIG_PROP(tv_top_margin_property, 100);
VOP_ATTACH_MODE_CONFIG_PROP(tv_bottom_margin_property, 100);
#undef VOP_ATTACH_MODE_CONFIG_PROP
drm_object_attach_property(&crtc->base, private->alpha_scale_prop, 0);
if (vop_data->feature & VOP_FEATURE_AFBDC)
feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_AFBDC);
drm_object_attach_property(&crtc->base, vop->feature_prop,
feature);
return 0;
err_cleanup_crtc:
@@ -3075,6 +3251,16 @@ static int vop_win_init(struct vop *vop)
unsigned int i, j;
unsigned int num_wins = 0;
struct drm_property *prop;
static const struct drm_prop_enum_list props[] = {
{ ROCKCHIP_DRM_PLANE_FEATURE_SCALE, "scale" },
{ ROCKCHIP_DRM_PLANE_FEATURE_ALPHA, "alpha" },
{ ROCKCHIP_DRM_PLANE_FEATURE_HDR2SDR, "hdr2sdr" },
{ ROCKCHIP_DRM_PLANE_FEATURE_SDR2HDR, "sdr2hdr" },
{ ROCKCHIP_DRM_PLANE_FEATURE_AFBDC, "afbdc" },
};
static const struct drm_prop_enum_list crtc_props[] = {
{ ROCKCHIP_DRM_CRTC_FEATURE_AFBDC, "afbdc" },
};
for (i = 0; i < vop_data->win_size; i++) {
struct vop_win *vop_win = &vop->win[num_wins];
@@ -3122,6 +3308,28 @@ static int vop_win_init(struct vop *vop)
}
vop->plane_zpos_prop = prop;
vop->plane_feature_prop = drm_property_create_bitmask(vop->drm_dev,
DRM_MODE_PROP_IMMUTABLE, "FEATURE",
props, ARRAY_SIZE(props),
BIT(ROCKCHIP_DRM_PLANE_FEATURE_SCALE) |
BIT(ROCKCHIP_DRM_PLANE_FEATURE_ALPHA) |
BIT(ROCKCHIP_DRM_PLANE_FEATURE_HDR2SDR) |
BIT(ROCKCHIP_DRM_PLANE_FEATURE_SDR2HDR) |
BIT(ROCKCHIP_DRM_PLANE_FEATURE_AFBDC));
if (!vop->plane_feature_prop) {
DRM_ERROR("failed to create feature property\n");
return -EINVAL;
}
vop->feature_prop = drm_property_create_bitmask(vop->drm_dev,
DRM_MODE_PROP_IMMUTABLE, "FEATURE",
crtc_props, ARRAY_SIZE(crtc_props),
BIT(ROCKCHIP_DRM_CRTC_FEATURE_AFBDC));
if (!vop->feature_prop) {
DRM_ERROR("failed to create vop feature property\n");
return -EINVAL;
}
return 0;
}

View File

@@ -913,4 +913,9 @@ drm_atomic_crtc_needs_modeset(const struct drm_crtc_state *state)
state->connectors_changed;
}
int drm_atomic_set_property(struct drm_atomic_state *state,
struct drm_mode_object *obj,
struct drm_property *prop,
uint64_t prop_value);
#endif /* DRM_ATOMIC_H_ */