1
0
Fork 0

MLK-18477-2 gpu: imx: dpu: framegen: Explicitly use bypass clk for TMDS encoder

The framegen driver should get PLL clock, bypass clock and display
selection/mux clock via device tree if available.  It may use bypass
clock when a TMDS encoder is connected with the framegen, otherwise,
PLL clock is used.  This way, the assigned-clocks and assigned-clock-parents
device tree properties can be removed from the dpu device tree node.

Signed-off-by: Liu Ying <victor.liu@nxp.com>
pull/10/head
Liu Ying 2018-06-01 16:14:40 +08:00 committed by Jason Liu
parent 0beb0c1b1f
commit ca73b88ec3
5 changed files with 77 additions and 20 deletions

View File

@ -493,20 +493,39 @@ static void dpu_crtc_atomic_flush(struct drm_crtc *crtc,
static void dpu_crtc_mode_set_nofb(struct drm_crtc *crtc)
{
struct drm_device *dev = crtc->dev;
struct dpu_crtc *dpu_crtc = to_dpu_crtc(crtc);
struct imx_crtc_state *imx_crtc_state = to_imx_crtc_state(crtc->state);
struct drm_display_mode *mode = &crtc->state->adjusted_mode;
struct drm_encoder *encoder;
struct dpu_plane *dplane = to_dpu_plane(crtc->primary);
struct dpu_plane_res *res = &dplane->grp->res;
struct dpu_extdst *plane_ed = res->ed[dplane->stream_id];
extdst_src_sel_t ed_src;
unsigned long encoder_types = 0;
u32 encoder_mask;
bool encoder_type_has_tmds = false;
dev_dbg(dpu_crtc->dev, "%s: mode->hdisplay: %d\n", __func__,
mode->hdisplay);
dev_dbg(dpu_crtc->dev, "%s: mode->vdisplay: %d\n", __func__,
mode->vdisplay);
framegen_cfg_videomode(dpu_crtc->fg, mode);
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
encoder_mask = 1 << drm_encoder_index(encoder);
if (!(crtc->state->encoder_mask & encoder_mask))
continue;
encoder_types |= BIT(encoder->encoder_type);
}
if (encoder_types & BIT(DRM_MODE_ENCODER_TMDS)) {
encoder_type_has_tmds = true;
dev_dbg(dpu_crtc->dev, "%s: encoder type has TMDS\n", __func__);
}
framegen_cfg_videomode(dpu_crtc->fg, mode, encoder_type_has_tmds);
framegen_displaymode(dpu_crtc->fg, FGDM__SEC_ON_TOP);
framegen_panic_displaymode(dpu_crtc->fg, FGDM__TEST);

View File

@ -543,12 +543,13 @@ static const struct dpu_devtype dpu_type_v1 = {
.has_capture = true,
.has_prefetch = false,
.has_prefetch_fixup = false,
.has_disp_sel_clk = false,
.pixel_link_quirks = false,
.pixel_link_nhvsync = false,
.version = DPU_V1,
};
static const struct dpu_devtype dpu_type_v2 = {
static const struct dpu_devtype dpu_type_v2_qm = {
.cm_ofs = 0x0,
.cfs = &cfs_v2,
.decs = &decs_v2,
@ -572,12 +573,13 @@ static const struct dpu_devtype dpu_type_v2 = {
.has_capture = false,
.has_prefetch = true,
.has_prefetch_fixup = false,
.has_disp_sel_clk = true,
.pixel_link_quirks = true,
.pixel_link_nhvsync = true,
.version = DPU_V2,
};
static const struct dpu_devtype dpu_type_v2_with_prefetch_fixup = {
static const struct dpu_devtype dpu_type_v2_qxp = {
.cm_ofs = 0x0,
.cfs = &cfs_v2,
.decs = &decs_v2,
@ -601,6 +603,7 @@ static const struct dpu_devtype dpu_type_v2_with_prefetch_fixup = {
.has_capture = false,
.has_prefetch = true,
.has_prefetch_fixup = true,
.has_disp_sel_clk = false,
.pixel_link_quirks = true,
.pixel_link_nhvsync = true,
.version = DPU_V2,
@ -609,10 +612,10 @@ static const struct dpu_devtype dpu_type_v2_with_prefetch_fixup = {
static const struct of_device_id dpu_dt_ids[] = {
{
.compatible = "fsl,imx8qm-dpu",
.data = &dpu_type_v2,
.data = &dpu_type_v2_qm,
}, {
.compatible = "fsl,imx8qxp-dpu",
.data = &dpu_type_v2_with_prefetch_fixup,
.data = &dpu_type_v2_qxp,
}, {
/* sentinel */
}

View File

@ -102,10 +102,13 @@ typedef enum {
struct dpu_framegen {
void __iomem *base;
struct clk *clk_pll;
struct clk *clk_bypass;
struct clk *clk_disp_sel;
struct clk *clk_disp;
struct mutex mutex;
int id;
bool inuse;
bool use_bypass_clk;
struct dpu_soc *dpu;
};
@ -220,8 +223,11 @@ void framegen_shdtokgen(struct dpu_framegen *fg)
}
EXPORT_SYMBOL_GPL(framegen_shdtokgen);
void framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m)
void
framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m,
bool encoder_type_has_tmds)
{
const struct dpu_devtype *devtype = fg->dpu->devtype;
u32 hact, htotal, hsync, hsbp;
u32 vact, vtotal, vsync, vsbp;
u32 val;
@ -269,12 +275,6 @@ void framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m)
disp_clock_rate = m->clock * 1000;
/* find an even divisor for PLL */
do {
div += 2;
pll_clock_rate = disp_clock_rate * div;
} while (pll_clock_rate < PLL_MIN_FREQ_HZ);
/*
* To workaround setting clock rate failure issue
* when the system resumes back from PM sleep mode,
@ -282,10 +282,30 @@ void framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m)
* their rates, otherwise, setting the clock rates
* will fail.
*/
clk_get_rate(fg->clk_pll);
clk_get_rate(fg->clk_disp);
clk_set_rate(fg->clk_pll, pll_clock_rate);
clk_set_rate(fg->clk_disp, disp_clock_rate);
if (devtype->has_disp_sel_clk && encoder_type_has_tmds) {
clk_set_parent(fg->clk_disp_sel, fg->clk_bypass);
clk_get_rate(fg->clk_disp);
clk_set_rate(fg->clk_disp, disp_clock_rate);
fg->use_bypass_clk = true;
} else {
/* find an even divisor for PLL */
do {
div += 2;
pll_clock_rate = disp_clock_rate * div;
} while (pll_clock_rate < PLL_MIN_FREQ_HZ);
if (devtype->has_disp_sel_clk)
clk_set_parent(fg->clk_disp_sel, fg->clk_pll);
clk_get_rate(fg->clk_pll);
clk_get_rate(fg->clk_disp);
clk_set_rate(fg->clk_pll, pll_clock_rate);
clk_set_rate(fg->clk_disp, disp_clock_rate);
fg->use_bypass_clk = false;
}
}
EXPORT_SYMBOL_GPL(framegen_cfg_videomode);
@ -433,14 +453,16 @@ EXPORT_SYMBOL_GPL(framegen_wait_for_frame_counter_moving);
void framegen_enable_clock(struct dpu_framegen *fg)
{
clk_prepare_enable(fg->clk_pll);
if (!fg->use_bypass_clk)
clk_prepare_enable(fg->clk_pll);
clk_prepare_enable(fg->clk_disp);
}
EXPORT_SYMBOL_GPL(framegen_enable_clock);
void framegen_disable_clock(struct dpu_framegen *fg)
{
clk_disable_unprepare(fg->clk_pll);
if (!fg->use_bypass_clk)
clk_disable_unprepare(fg->clk_pll);
clk_disable_unprepare(fg->clk_disp);
}
EXPORT_SYMBOL_GPL(framegen_disable_clock);
@ -526,6 +548,17 @@ int dpu_fg_init(struct dpu_soc *dpu, unsigned int id,
if (IS_ERR(fg->clk_pll))
return PTR_ERR(fg->clk_pll);
if (dpu->devtype->has_disp_sel_clk) {
fg->clk_bypass = devm_clk_get(dpu->dev, "bypass0");
if (IS_ERR(fg->clk_bypass))
return PTR_ERR(fg->clk_bypass);
fg->clk_disp_sel = devm_clk_get(dpu->dev,
id ? "disp1_sel" : "disp0_sel");
if (IS_ERR(fg->clk_disp_sel))
return PTR_ERR(fg->clk_disp_sel);
}
fg->clk_disp = devm_clk_get(dpu->dev, id ? "disp1" : "disp0");
if (IS_ERR(fg->clk_disp))
return PTR_ERR(fg->clk_disp);

View File

@ -208,6 +208,7 @@ struct dpu_devtype {
bool has_capture;
bool has_prefetch;
bool has_prefetch_fixup;
bool has_disp_sel_clk;
bool pixel_link_quirks;
bool pixel_link_nhvsync; /* HSYNC and VSYNC high active */
unsigned int version;

View File

@ -591,8 +591,9 @@ struct dpu_framegen;
void framegen_enable(struct dpu_framegen *fg);
void framegen_disable(struct dpu_framegen *fg);
void framegen_shdtokgen(struct dpu_framegen *fg);
void framegen_cfg_videomode(struct dpu_framegen *fg,
struct drm_display_mode *m);
void
framegen_cfg_videomode(struct dpu_framegen *fg, struct drm_display_mode *m,
bool encoder_type_has_tmds);
void framegen_pkickconfig(struct dpu_framegen *fg, bool enable);
void framegen_sacfg(struct dpu_framegen *fg, unsigned int x, unsigned int y);
void framegen_displaymode(struct dpu_framegen *fg, fgdm_t mode);