drm/rockchip: add support interlace mode output
add interlace timing config for hdmi/cvbs interlace output mode Change-Id: Ic0bb06667a5c56d81f5229b7ef87baef9e0e5f32 Signed-off-by: Sandy Huang <hjc@rock-chips.com> (Cherry pick from commit 3452c2ff12f80f249bc54d28bc3c52d089f76a8a)
This commit is contained in:
parent
79feefb115
commit
ccd843b928
|
|
@ -311,6 +311,87 @@ static int display_get_timing_from_dts(struct panel_state *panel_state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_set_crtcinfo - set CRTC modesetting timing parameters
|
||||
* @p: mode
|
||||
* @adjust_flags: a combination of adjustment flags
|
||||
*
|
||||
* Setup the CRTC modesetting timing parameters for @p, adjusting if necessary.
|
||||
*
|
||||
* - The CRTC_INTERLACE_HALVE_V flag can be used to halve vertical timings of
|
||||
* interlaced modes.
|
||||
* - The CRTC_STEREO_DOUBLE flag can be used to compute the timings for
|
||||
* buffers containing two eyes (only adjust the timings when needed, eg. for
|
||||
* "frame packing" or "side by side full").
|
||||
* - The CRTC_NO_DBLSCAN and CRTC_NO_VSCAN flags request that adjustment *not*
|
||||
* be performed for doublescan and vscan > 1 modes respectively.
|
||||
*/
|
||||
void drm_mode_set_crtcinfo(struct drm_display_mode *p, int adjust_flags)
|
||||
{
|
||||
if ((p == NULL) || ((p->type & DRM_MODE_TYPE_CRTC_C) == DRM_MODE_TYPE_BUILTIN))
|
||||
return;
|
||||
|
||||
if (p->flags & DRM_MODE_FLAG_DBLCLK)
|
||||
p->crtc_clock = 2 * p->clock;
|
||||
else
|
||||
p->crtc_clock = p->clock;
|
||||
p->crtc_hdisplay = p->hdisplay;
|
||||
p->crtc_hsync_start = p->hsync_start;
|
||||
p->crtc_hsync_end = p->hsync_end;
|
||||
p->crtc_htotal = p->htotal;
|
||||
p->crtc_hskew = p->hskew;
|
||||
p->crtc_vdisplay = p->vdisplay;
|
||||
p->crtc_vsync_start = p->vsync_start;
|
||||
p->crtc_vsync_end = p->vsync_end;
|
||||
p->crtc_vtotal = p->vtotal;
|
||||
|
||||
if (p->flags & DRM_MODE_FLAG_INTERLACE) {
|
||||
if (adjust_flags & CRTC_INTERLACE_HALVE_V) {
|
||||
p->crtc_vdisplay /= 2;
|
||||
p->crtc_vsync_start /= 2;
|
||||
p->crtc_vsync_end /= 2;
|
||||
p->crtc_vtotal /= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(adjust_flags & CRTC_NO_DBLSCAN)) {
|
||||
if (p->flags & DRM_MODE_FLAG_DBLSCAN) {
|
||||
p->crtc_vdisplay *= 2;
|
||||
p->crtc_vsync_start *= 2;
|
||||
p->crtc_vsync_end *= 2;
|
||||
p->crtc_vtotal *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!(adjust_flags & CRTC_NO_VSCAN)) {
|
||||
if (p->vscan > 1) {
|
||||
p->crtc_vdisplay *= p->vscan;
|
||||
p->crtc_vsync_start *= p->vscan;
|
||||
p->crtc_vsync_end *= p->vscan;
|
||||
p->crtc_vtotal *= p->vscan;
|
||||
}
|
||||
}
|
||||
|
||||
if (adjust_flags & CRTC_STEREO_DOUBLE) {
|
||||
unsigned int layout = p->flags & DRM_MODE_FLAG_3D_MASK;
|
||||
|
||||
switch (layout) {
|
||||
case DRM_MODE_FLAG_3D_FRAME_PACKING:
|
||||
p->crtc_clock *= 2;
|
||||
p->crtc_vdisplay += p->crtc_vtotal;
|
||||
p->crtc_vsync_start += p->crtc_vtotal;
|
||||
p->crtc_vsync_end += p->crtc_vtotal;
|
||||
p->crtc_vtotal += p->crtc_vtotal;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
p->crtc_vblank_start = min(p->crtc_vsync_start, p->crtc_vdisplay);
|
||||
p->crtc_vblank_end = max(p->crtc_vsync_end, p->crtc_vtotal);
|
||||
p->crtc_hblank_start = min(p->crtc_hsync_start, p->crtc_hdisplay);
|
||||
p->crtc_hblank_end = max(p->crtc_hsync_end, p->crtc_htotal);
|
||||
}
|
||||
|
||||
static int display_get_timing(struct display_state *state)
|
||||
{
|
||||
struct connector_state *conn_state = &state->conn_state;
|
||||
|
|
@ -372,6 +453,7 @@ static int display_init(struct display_state *state)
|
|||
struct crtc_state *crtc_state = &state->crtc_state;
|
||||
const struct rockchip_crtc *crtc = crtc_state->crtc;
|
||||
const struct rockchip_crtc_funcs *crtc_funcs = crtc->funcs;
|
||||
struct drm_display_mode *mode = &conn_state->mode;
|
||||
int ret = 0;
|
||||
|
||||
if (state->is_init)
|
||||
|
|
@ -405,6 +487,7 @@ static int display_init(struct display_state *state)
|
|||
if (ret)
|
||||
goto deinit;
|
||||
}
|
||||
drm_mode_set_crtcinfo(mode, CRTC_INTERLACE_HALVE_V);
|
||||
|
||||
if (crtc_funcs->init) {
|
||||
ret = crtc_funcs->init(state);
|
||||
|
|
|
|||
|
|
@ -140,15 +140,15 @@ static int rockchip_vop_init(struct display_state *state)
|
|||
const struct rockchip_crtc *crtc = crtc_state->crtc;
|
||||
const struct vop_data *vop_data = crtc->data;
|
||||
struct vop *vop;
|
||||
u16 hsync_len = mode->hsync_end - mode->hsync_start;
|
||||
u16 hdisplay = mode->hdisplay;
|
||||
u16 htotal = mode->htotal;
|
||||
u16 hact_st = mode->htotal - mode->hsync_start;
|
||||
u16 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
|
||||
u16 hdisplay = mode->crtc_hdisplay;
|
||||
u16 htotal = mode->crtc_htotal;
|
||||
u16 hact_st = mode->crtc_htotal - mode->crtc_hsync_start;
|
||||
u16 hact_end = hact_st + hdisplay;
|
||||
u16 vdisplay = mode->vdisplay;
|
||||
u16 vtotal = mode->vtotal;
|
||||
u16 vsync_len = mode->vsync_end - mode->vsync_start;
|
||||
u16 vact_st = mode->vtotal - mode->vsync_start;
|
||||
u16 vdisplay = mode->crtc_vdisplay;
|
||||
u16 vtotal = mode->crtc_vtotal;
|
||||
u16 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
|
||||
u16 vact_st = mode->crtc_vtotal - mode->crtc_vsync_start;
|
||||
u16 vact_end = vact_st + vdisplay;
|
||||
struct clk dclk, aclk;
|
||||
u32 val;
|
||||
|
|
@ -312,11 +312,31 @@ static int rockchip_vop_init(struct display_state *state)
|
|||
val |= hact_end;
|
||||
VOP_CTRL_SET(vop, hact_st_end, val);
|
||||
VOP_CTRL_SET(vop, hpost_st_end, val);
|
||||
VOP_CTRL_SET(vop, vtotal_pw, (vtotal << 16) | vsync_len);
|
||||
val = vact_st << 16;
|
||||
val |= vact_end;
|
||||
VOP_CTRL_SET(vop, vact_st_end, val);
|
||||
VOP_CTRL_SET(vop, vpost_st_end, val);
|
||||
if (mode->flags & DRM_MODE_FLAG_INTERLACE) {
|
||||
u16 vact_st_f1 = vtotal + vact_st + 1;
|
||||
u16 vact_end_f1 = vact_st_f1 + vdisplay;
|
||||
|
||||
val = vact_st_f1 << 16 | vact_end_f1;
|
||||
VOP_CTRL_SET(vop, vact_st_end_f1, val);
|
||||
VOP_CTRL_SET(vop, vpost_st_end_f1, val);
|
||||
|
||||
val = vtotal << 16 | (vtotal + vsync_len);
|
||||
VOP_CTRL_SET(vop, vs_st_end_f1, val);
|
||||
VOP_CTRL_SET(vop, dsp_interlace, 1);
|
||||
VOP_CTRL_SET(vop, p2i_en, 1);
|
||||
vtotal += vtotal + 1;
|
||||
} else {
|
||||
VOP_CTRL_SET(vop, dsp_interlace, 0);
|
||||
VOP_CTRL_SET(vop, p2i_en, 0);
|
||||
}
|
||||
VOP_CTRL_SET(vop, vtotal_pw, (vtotal << 16) | vsync_len);
|
||||
|
||||
VOP_CTRL_SET(vop, core_dclk_div,
|
||||
!!(mode->flags & DRM_MODE_FLAG_DBLCLK));
|
||||
VOP_CTRL_SET(vop, standby, 1);
|
||||
VOP_LINE_FLAG_SET(vop, line_flag_num[0], vact_end - 3);
|
||||
VOP_LINE_FLAG_SET(vop, line_flag_num[1],
|
||||
|
|
|
|||
|
|
@ -7,13 +7,18 @@
|
|||
#ifndef _DRM_MODES_H
|
||||
#define _DRM_MODES_H
|
||||
|
||||
#define DRM_MODE_TYPE_BUILTIN BIT(0)
|
||||
#define DRM_MODE_TYPE_CLOCK_C (BIT(1) | DRM_MODE_TYPE_BUILTIN)
|
||||
#define DRM_MODE_TYPE_CRTC_C (BIT(2) | DRM_MODE_TYPE_BUILTIN)
|
||||
#define DRM_MODE_TYPE_PREFERRED BIT(3)
|
||||
#define DRM_MODE_TYPE_DEFAULT BIT(4)
|
||||
#define DRM_MODE_TYPE_USERDEF BIT(5)
|
||||
#define DRM_MODE_TYPE_DRIVER BIT(6)
|
||||
#define DRM_DISPLAY_INFO_LEN 32
|
||||
#define DRM_CONNECTOR_NAME_LEN 32
|
||||
#define DRM_DISPLAY_MODE_LEN 32
|
||||
#define DRM_PROP_NAME_LEN 32
|
||||
|
||||
#define DRM_MODE_TYPE_BUILTIN (1<<0)
|
||||
#define DRM_MODE_TYPE_CLOCK_C ((1<<1) | DRM_MODE_TYPE_BUILTIN)
|
||||
#define DRM_MODE_TYPE_CRTC_C ((1<<2) | DRM_MODE_TYPE_BUILTIN)
|
||||
#define DRM_MODE_TYPE_PREFERRED (1<<3)
|
||||
#define DRM_MODE_TYPE_DEFAULT (1<<4)
|
||||
#define DRM_MODE_TYPE_USERDEF (1<<5)
|
||||
#define DRM_MODE_TYPE_DRIVER (1<<6)
|
||||
|
||||
/* Video mode flags */
|
||||
/* bit compatible with the xorg definitions. */
|
||||
|
|
@ -114,6 +119,14 @@ enum v4l2_colorspace {
|
|||
V4L2_COLORSPACE_DCI_P3 = 12,
|
||||
};
|
||||
|
||||
#define CRTC_INTERLACE_HALVE_V (1 << 0) /* halve V values for interlacing */
|
||||
#define CRTC_STEREO_DOUBLE (1 << 1) /* adjust timings for stereo modes */
|
||||
#define CRTC_NO_DBLSCAN (1 << 2) /* don't adjust doublescan */
|
||||
#define CRTC_NO_VSCAN (1 << 3) /* don't adjust doublescan */
|
||||
#define CRTC_STEREO_DOUBLE_ONLY (CRTC_STEREO_DOUBLE | CRTC_NO_DBLSCAN | CRTC_NO_VSCAN)
|
||||
|
||||
#define DRM_MODE_FLAG_3D_MAX DRM_MODE_FLAG_3D_SIDE_BY_SIDE_HALF
|
||||
|
||||
struct drm_display_mode {
|
||||
/* Proposed mode values */
|
||||
int clock; /* in kHz */
|
||||
|
|
@ -129,6 +142,23 @@ struct drm_display_mode {
|
|||
int vscan;
|
||||
unsigned int flags;
|
||||
int picture_aspect_ratio;
|
||||
int hskew;
|
||||
unsigned int type;
|
||||
/* Actual mode we give to hw */
|
||||
int crtc_clock; /* in KHz */
|
||||
int crtc_hdisplay;
|
||||
int crtc_hblank_start;
|
||||
int crtc_hblank_end;
|
||||
int crtc_hsync_start;
|
||||
int crtc_hsync_end;
|
||||
int crtc_htotal;
|
||||
int crtc_hskew;
|
||||
int crtc_vdisplay;
|
||||
int crtc_vblank_start;
|
||||
int crtc_vblank_end;
|
||||
int crtc_vsync_start;
|
||||
int crtc_vsync_end;
|
||||
int crtc_vtotal;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue