drm/rockchip: vop: support overscan setting

Change-Id: I2213c7da45fd625d154a9bf11c79ec5608b06a0e
Signed-off-by: Mark Yao <mark.yao@rock-chips.com>
This commit is contained in:
Mark Yao
2017-01-11 10:14:26 +08:00
committed by Huang, Tao
parent d05454aafc
commit 5ce649ed79
4 changed files with 148 additions and 8 deletions

View File

@@ -67,6 +67,10 @@ struct rockchip_atomic_commit {
struct rockchip_crtc_state {
struct drm_crtc_state base;
int left_margin;
int right_margin;
int top_margin;
int bottom_margin;
int afbdc_win_format;
int afbdc_win_width;
int afbdc_win_height;

View File

@@ -1717,6 +1717,44 @@ err_free_pzpos:
return ret;
}
static void vop_post_config(struct drm_crtc *crtc)
{
struct vop *vop = to_vop(crtc);
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
struct drm_display_mode *mode = &crtc->state->adjusted_mode;
u16 vtotal = mode->crtc_vtotal;
u16 hdisplay = mode->crtc_hdisplay;
u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
u16 vdisplay = mode->crtc_vdisplay;
u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
u16 hsize = hdisplay * (s->left_margin + s->right_margin) / 200;
u16 vsize = vdisplay * (s->top_margin + s->bottom_margin) / 200;
u16 hact_end, vact_end;
u32 val;
hact_st += hdisplay * (100 - s->left_margin) / 200;
hact_end = hact_st + hsize;
val = hact_st << 16;
val |= hact_end;
VOP_CTRL_SET(vop, hpost_st_end, val);
vact_st += vdisplay * (100 - s->top_margin) / 200;
vact_end = vact_st + vsize;
val = vact_st << 16;
val |= vact_end;
VOP_CTRL_SET(vop, vpost_st_end, val);
val = scl_cal_scale2(vdisplay, vsize) << 16;
val |= scl_cal_scale2(hdisplay, hsize);
VOP_CTRL_SET(vop, post_scl_factor, val);
VOP_CTRL_SET(vop, post_scl_ctrl, 0x3);
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
u16 vact_st_f1 = vtotal + vact_st + 1;
u16 vact_end_f1 = vact_st_f1 + vsize;
val = vact_st_f1 << 16 | vact_end_f1;
VOP_CTRL_SET(vop, vpost_st_end_f1, val);
}
}
static void vop_cfg_update(struct drm_crtc *crtc,
struct drm_crtc_state *old_crtc_state)
{
@@ -1740,6 +1778,7 @@ static void vop_cfg_update(struct drm_crtc *crtc,
VOP_CTRL_SET(vop, afbdc_en, s->afbdc_en);
VOP_CTRL_SET(vop, dsp_layer_sel, s->dsp_layer_sel);
vop_post_config(crtc);
spin_unlock(&vop->reg_lock);
}
@@ -1824,20 +1863,30 @@ static void vop_crtc_destroy(struct drm_crtc *crtc)
static void vop_crtc_reset(struct drm_crtc *crtc)
{
if (crtc->state)
__drm_atomic_helper_crtc_destroy_state(crtc, crtc->state);
kfree(crtc->state);
struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc->state);
crtc->state = kzalloc(sizeof(struct rockchip_crtc_state), GFP_KERNEL);
if (crtc->state)
crtc->state->crtc = crtc;
if (crtc->state) {
__drm_atomic_helper_crtc_destroy_state(crtc, crtc->state);
kfree(s);
}
s = kzalloc(sizeof(*s), GFP_KERNEL);
if (!s)
return;
crtc->state = &s->base;
crtc->state->crtc = crtc;
s->left_margin = 100;
s->right_margin = 100;
s->top_margin = 100;
s->bottom_margin = 100;
}
static struct drm_crtc_state *vop_crtc_duplicate_state(struct drm_crtc *crtc)
{
struct rockchip_crtc_state *rockchip_state;
struct rockchip_crtc_state *rockchip_state, *old_state;
rockchip_state = kzalloc(sizeof(*rockchip_state), GFP_KERNEL);
old_state = to_rockchip_crtc_state(crtc->state);
rockchip_state = kmemdup(old_state, sizeof(*old_state), GFP_KERNEL);
if (!rockchip_state)
return NULL;
@@ -1854,11 +1903,79 @@ static void vop_crtc_destroy_state(struct drm_crtc *crtc,
kfree(s);
}
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 drm_mode_config *mode_config = &drm_dev->mode_config;
struct rockchip_crtc_state *s = to_rockchip_crtc_state(state);
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;
}
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);
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,
};
@@ -2061,6 +2178,18 @@ static int vop_create_crtc(struct vop *vop)
crtc->port = port;
rockchip_register_crtc_funcs(crtc, &private_crtc_funcs);
ret = drm_mode_create_tv_properties(drm_dev, 0, NULL);
if (ret)
goto err_unregister_crtc_funcs;
#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
if (VOP_CTRL_SUPPORT(vop, afbdc_en))
feature |= BIT(ROCKCHIP_DRM_CRTC_FEATURE_AFBDC);
drm_object_attach_property(&crtc->base, vop->feature_prop,
@@ -2068,6 +2197,8 @@ static int vop_create_crtc(struct vop *vop)
return 0;
err_unregister_crtc_funcs:
rockchip_unregister_crtc_funcs(crtc);
err_cleanup_crtc:
drm_crtc_cleanup(crtc);
err_cleanup_planes:

View File

@@ -83,6 +83,8 @@ struct vop_ctrl {
struct vop_reg hpost_st_end;
struct vop_reg vpost_st_end;
struct vop_reg vpost_st_end_f1;
struct vop_reg post_scl_factor;
struct vop_reg post_scl_ctrl;
struct vop_reg dsp_interlace;
struct vop_reg global_regdone_en;
struct vop_reg auto_gate_en;

View File

@@ -178,6 +178,9 @@ static const struct vop_ctrl rk3288_ctrl_data = {
.hpost_st_end = VOP_REG(RK3288_POST_DSP_HACT_INFO, 0x1fff1fff, 0),
.vpost_st_end = VOP_REG(RK3288_POST_DSP_VACT_INFO, 0x1fff1fff, 0),
.vpost_st_end_f1 = VOP_REG(RK3288_POST_DSP_VACT_INFO_F1, 0x1fff1fff, 0),
.post_scl_factor = VOP_REG(RK3288_POST_SCL_FACTOR_YRGB, 0xffffffff, 0),
.post_scl_ctrl = VOP_REG(RK3288_POST_SCL_CTRL, 0x3, 0),
.dsp_interlace = VOP_REG(RK3288_DSP_CTRL0, 0x1, 10),
.auto_gate_en = VOP_REG(RK3288_SYS_CTRL, 0x1, 23),
.dsp_layer_sel = VOP_REG(RK3288_DSP_CTRL1, 0xff, 8),