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
parent
0beb0c1b1f
commit
ca73b88ec3
|
@ -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);
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue