drm/rockchip: filter the edid modes accordinig to vop max output resolution
Signed-off-by: Sandy Huang <hjc@rock-chips.com> Change-Id: Id338a2b3bc659799c4fb391d36fa814c44e0274d
This commit is contained in:
parent
af50552e4f
commit
cf53642aa6
|
|
@ -2423,6 +2423,8 @@ int rockchip_dw_hdmi_get_timing(struct display_state *state)
|
|||
drm_rk_filter_whitelist(&hdmi->edid_data);
|
||||
if (hdmi->phy.ops->mode_valid)
|
||||
hdmi->phy.ops->mode_valid(hdmi, state);
|
||||
drm_mode_max_resolution_filter(&hdmi->edid_data,
|
||||
&state->crtc_state.max_output);
|
||||
if (!drm_mode_prune_invalid(&hdmi->edid_data)) {
|
||||
printf("can't find valid hdmi mode\n");
|
||||
return -EINVAL;
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ struct rockchip_crtc {
|
|||
};
|
||||
|
||||
struct rockchip_crtc_funcs {
|
||||
int (*preinit)(struct display_state *state);
|
||||
int (*init)(struct display_state *state);
|
||||
void (*deinit)(struct display_state *state);
|
||||
int (*set_plane)(struct display_state *state);
|
||||
|
|
|
|||
|
|
@ -338,6 +338,23 @@ static int display_get_timing_from_dts(struct panel_state *panel_state,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_max_resolution_filter - mark modes out of vop max resolution
|
||||
* @edid_data: structure store mode list
|
||||
* @max_output: vop max output resolution
|
||||
*/
|
||||
void drm_mode_max_resolution_filter(struct hdmi_edid_data *edid_data,
|
||||
struct vop_rect *max_output)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < edid_data->modes; i++) {
|
||||
if (edid_data->mode_buf[i].hdisplay > max_output->width ||
|
||||
edid_data->mode_buf[i].vdisplay > max_output->height)
|
||||
edid_data->mode_buf[i].invalid = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_mode_set_crtcinfo - set CRTC modesetting timing parameters
|
||||
* @p: mode
|
||||
|
|
@ -552,6 +569,12 @@ static int display_init(struct display_state *state)
|
|||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (crtc_funcs->preinit) {
|
||||
ret = crtc_funcs->preinit(state);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (panel_state->panel)
|
||||
rockchip_panel_init(panel_state->panel);
|
||||
|
||||
|
|
|
|||
|
|
@ -62,6 +62,11 @@ struct rockchip_mcu_timing {
|
|||
int mcu_hold_mode;
|
||||
};
|
||||
|
||||
struct vop_rect {
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
struct crtc_state {
|
||||
struct udevice *dev;
|
||||
struct rockchip_crtc *crtc;
|
||||
|
|
@ -85,6 +90,7 @@ struct crtc_state {
|
|||
bool yuv_overlay;
|
||||
struct rockchip_mcu_timing mcu_timing;
|
||||
u32 dual_channel_swap;
|
||||
struct vop_rect max_output;
|
||||
};
|
||||
|
||||
struct panel_state {
|
||||
|
|
@ -176,4 +182,7 @@ int display_send_mcu_cmd(struct display_state *state, u32 type, u32 val);
|
|||
bool drm_mode_is_420(const struct drm_display_info *display,
|
||||
struct drm_display_mode *mode);
|
||||
|
||||
void drm_mode_max_resolution_filter(struct hdmi_edid_data *edid_data,
|
||||
struct vop_rect *max_output);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -193,6 +193,15 @@ static void vop_mcu_mode(struct display_state *state, struct vop *vop)
|
|||
VOP_CTRL_SET(vop, mcu_rw_pend, crtc_state->mcu_timing.mcu_rw_pend);
|
||||
}
|
||||
|
||||
static int rockchip_vop_preinit(struct display_state *state)
|
||||
{
|
||||
const struct vop_data *vop_data = state->crtc_state.crtc->data;
|
||||
|
||||
state->crtc_state.max_output = vop_data->max_output;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rockchip_vop_init(struct display_state *state)
|
||||
{
|
||||
struct crtc_state *crtc_state = &state->crtc_state;
|
||||
|
|
@ -239,7 +248,6 @@ static int rockchip_vop_init(struct display_state *state)
|
|||
vop->csc_table = vop_data->csc_table;
|
||||
vop->win_csc = vop_data->win_csc;
|
||||
vop->version = vop_data->version;
|
||||
vop->max_output = vop_data->max_output;
|
||||
|
||||
/* Process 'assigned-{clocks/clock-parents/clock-rates}' properties */
|
||||
ret = clk_set_defaults(crtc_state->dev);
|
||||
|
|
@ -505,12 +513,6 @@ static void scl_vop_cal_scl_fac(struct vop *vop,
|
|||
if (!vop->win->scl)
|
||||
return;
|
||||
|
||||
if (dst_w > vop->max_output.width) {
|
||||
printf("Maximum destination width %d exceeded\n",
|
||||
vop->max_output.width);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!vop->win->scl->ext) {
|
||||
VOP_SCL_SET(vop, scale_yrgb_x,
|
||||
scl_cal_scale2(src_w, dst_w));
|
||||
|
|
@ -658,6 +660,14 @@ static int rockchip_vop_set_plane(struct display_state *state)
|
|||
int xvir = crtc_state->xvir;
|
||||
int x_mirror = 0, y_mirror = 0;
|
||||
|
||||
if ((crtc_w > crtc_state->max_output.width) ||
|
||||
(crtc_h > crtc_state->max_output.height)){
|
||||
printf("Maximum destination %dx%d exceeded\n",
|
||||
crtc_state->max_output.width,
|
||||
crtc_state->max_output.height);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
act_info = (src_h - 1) << 16;
|
||||
act_info |= (src_w - 1) & 0xffff;
|
||||
|
||||
|
|
@ -817,6 +827,7 @@ static int rockchip_vop_send_mcu_cmd(struct display_state *state,
|
|||
}
|
||||
|
||||
const struct rockchip_crtc_funcs rockchip_vop_funcs = {
|
||||
.preinit = rockchip_vop_preinit,
|
||||
.init = rockchip_vop_init,
|
||||
.set_plane = rockchip_vop_set_plane,
|
||||
.prepare = rockchip_vop_prepare,
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#ifndef _ROCKCHIP_VOP_H_
|
||||
#define _ROCKCHIP_VOP_H_
|
||||
#include "rockchip_display.h"
|
||||
|
||||
/*
|
||||
* major: IP major vertion, used for IP structure
|
||||
|
|
@ -426,11 +427,6 @@ struct vop_grf_ctrl {
|
|||
struct vop_reg grf_dclk_inv;
|
||||
};
|
||||
|
||||
struct vop_rect {
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
struct vop_csc_table {
|
||||
const uint32_t *r2y_bt601;
|
||||
const uint32_t *r2y_bt601_12_235;
|
||||
|
|
@ -477,7 +473,6 @@ struct vop {
|
|||
const struct vop_csc_table *csc_table;
|
||||
const struct vop_csc *win_csc;
|
||||
int win_offset;
|
||||
struct vop_rect max_output;
|
||||
};
|
||||
|
||||
static inline void vop_writel(struct vop *vop, uint32_t offset, uint32_t v)
|
||||
|
|
|
|||
Loading…
Reference in New Issue