drm: imx: imx-hdmi: split phy configuration to platform driver
hdmi phy configuration is platform specific, which can be adjusted according to the board to get the best SI Signed-off-by: Andy Yan <andy.yan@rock-chips.com> Tested-by: Russell King <rmk+kernel@arm.linux.org.uk> Acked-by: Russell King <rmk+kernel@arm.linux.org.uk> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
This commit is contained in:
parent
3d1b35a3d9
commit
aaa757a092
|
@ -713,76 +713,14 @@ static void imx_hdmi_phy_sel_interface_control(struct imx_hdmi *hdmi, u8 enable)
|
||||||
HDMI_PHY_CONF0_SELDIPIF_MASK);
|
HDMI_PHY_CONF0_SELDIPIF_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum {
|
|
||||||
RES_8,
|
|
||||||
RES_10,
|
|
||||||
RES_12,
|
|
||||||
RES_MAX,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct mpll_config {
|
|
||||||
unsigned long mpixelclock;
|
|
||||||
struct {
|
|
||||||
u16 cpce;
|
|
||||||
u16 gmp;
|
|
||||||
} res[RES_MAX];
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct mpll_config mpll_config[] = {
|
|
||||||
{
|
|
||||||
45250000, {
|
|
||||||
{ 0x01e0, 0x0000 },
|
|
||||||
{ 0x21e1, 0x0000 },
|
|
||||||
{ 0x41e2, 0x0000 }
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
92500000, {
|
|
||||||
{ 0x0140, 0x0005 },
|
|
||||||
{ 0x2141, 0x0005 },
|
|
||||||
{ 0x4142, 0x0005 },
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
148500000, {
|
|
||||||
{ 0x00a0, 0x000a },
|
|
||||||
{ 0x20a1, 0x000a },
|
|
||||||
{ 0x40a2, 0x000a },
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
~0UL, {
|
|
||||||
{ 0x00a0, 0x000a },
|
|
||||||
{ 0x2001, 0x000f },
|
|
||||||
{ 0x4002, 0x000f },
|
|
||||||
},
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct curr_ctrl {
|
|
||||||
unsigned long mpixelclock;
|
|
||||||
u16 curr[RES_MAX];
|
|
||||||
};
|
|
||||||
|
|
||||||
static const struct curr_ctrl curr_ctrl[] = {
|
|
||||||
/* pixelclk bpp8 bpp10 bpp12 */
|
|
||||||
{
|
|
||||||
54000000, { 0x091c, 0x091c, 0x06dc },
|
|
||||||
}, {
|
|
||||||
58400000, { 0x091c, 0x06dc, 0x06dc },
|
|
||||||
}, {
|
|
||||||
72000000, { 0x06dc, 0x06dc, 0x091c },
|
|
||||||
}, {
|
|
||||||
74250000, { 0x06dc, 0x0b5c, 0x091c },
|
|
||||||
}, {
|
|
||||||
118800000, { 0x091c, 0x091c, 0x06dc },
|
|
||||||
}, {
|
|
||||||
216000000, { 0x06dc, 0x0b5c, 0x091c },
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
|
static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
|
||||||
unsigned char res, int cscon)
|
unsigned char res, int cscon)
|
||||||
{
|
{
|
||||||
unsigned res_idx, i;
|
unsigned res_idx, i;
|
||||||
u8 val, msec;
|
u8 val, msec;
|
||||||
|
const struct mpll_config *mpll_config = hdmi->plat_data->mpll_cfg;
|
||||||
|
const struct curr_ctrl *curr_ctrl = hdmi->plat_data->cur_ctr;
|
||||||
|
const struct sym_term *sym_term = hdmi->plat_data->sym_term;
|
||||||
|
|
||||||
if (prep)
|
if (prep)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -828,7 +766,7 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
|
||||||
hdmi_phy_test_clear(hdmi, 0);
|
hdmi_phy_test_clear(hdmi, 0);
|
||||||
|
|
||||||
/* PLL/MPLL Cfg - always match on final entry */
|
/* PLL/MPLL Cfg - always match on final entry */
|
||||||
for (i = 0; i < ARRAY_SIZE(mpll_config) - 1; i++)
|
for (i = 0; mpll_config[i].mpixelclock != (~0UL); i++)
|
||||||
if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||||
mpll_config[i].mpixelclock)
|
mpll_config[i].mpixelclock)
|
||||||
break;
|
break;
|
||||||
|
@ -836,12 +774,12 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
|
||||||
hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
|
hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].cpce, 0x06);
|
||||||
hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
|
hdmi_phy_i2c_write(hdmi, mpll_config[i].res[res_idx].gmp, 0x15);
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(curr_ctrl); i++)
|
for (i = 0; curr_ctrl[i].mpixelclock != (~0UL); i++)
|
||||||
if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||||
curr_ctrl[i].mpixelclock)
|
curr_ctrl[i].mpixelclock)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
if (i >= ARRAY_SIZE(curr_ctrl)) {
|
if (curr_ctrl[i].mpixelclock == (~0UL)) {
|
||||||
dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
|
dev_err(hdmi->dev, "Pixel clock %d - unsupported by HDMI\n",
|
||||||
hdmi->hdmi_data.video_mode.mpixelclock);
|
hdmi->hdmi_data.video_mode.mpixelclock);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -852,10 +790,17 @@ static int hdmi_phy_configure(struct imx_hdmi *hdmi, unsigned char prep,
|
||||||
|
|
||||||
hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
|
hdmi_phy_i2c_write(hdmi, 0x0000, 0x13); /* PLLPHBYCTRL */
|
||||||
hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
|
hdmi_phy_i2c_write(hdmi, 0x0006, 0x17);
|
||||||
|
|
||||||
|
for (i = 0; sym_term[i].mpixelclock != (~0UL); i++)
|
||||||
|
if (hdmi->hdmi_data.video_mode.mpixelclock <=
|
||||||
|
sym_term[i].mpixelclock)
|
||||||
|
break;
|
||||||
|
|
||||||
/* RESISTANCE TERM 133Ohm Cfg */
|
/* RESISTANCE TERM 133Ohm Cfg */
|
||||||
hdmi_phy_i2c_write(hdmi, 0x0005, 0x19); /* TXTERM */
|
hdmi_phy_i2c_write(hdmi, sym_term[i].term, 0x19); /* TXTERM */
|
||||||
/* PREEMP Cgf 0.00 */
|
/* PREEMP Cgf 0.00 */
|
||||||
hdmi_phy_i2c_write(hdmi, 0x800d, 0x09); /* CKSYMTXCTRL */
|
hdmi_phy_i2c_write(hdmi, sym_term[i].sym_ctr, 0x09); /* CKSYMTXCTRL */
|
||||||
|
|
||||||
/* TX/CK LVL 10 */
|
/* TX/CK LVL 10 */
|
||||||
hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */
|
hdmi_phy_i2c_write(hdmi, 0x01ad, 0x0E); /* VLEVCTRL */
|
||||||
/* REMOVE CLK TERM */
|
/* REMOVE CLK TERM */
|
||||||
|
|
|
@ -1037,6 +1037,35 @@ enum imx_hdmi_devtype {
|
||||||
|
|
||||||
struct imx_hdmi_plat_data {
|
struct imx_hdmi_plat_data {
|
||||||
enum imx_hdmi_devtype dev_type;
|
enum imx_hdmi_devtype dev_type;
|
||||||
|
const struct mpll_config *mpll_cfg;
|
||||||
|
const struct curr_ctrl *cur_ctr;
|
||||||
|
const struct sym_term *sym_term;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
RES_8,
|
||||||
|
RES_10,
|
||||||
|
RES_12,
|
||||||
|
RES_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct mpll_config {
|
||||||
|
unsigned long mpixelclock;
|
||||||
|
struct {
|
||||||
|
u16 cpce;
|
||||||
|
u16 gmp;
|
||||||
|
} res[RES_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct curr_ctrl {
|
||||||
|
unsigned long mpixelclock;
|
||||||
|
u16 curr[RES_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sym_term {
|
||||||
|
unsigned long mpixelclock;
|
||||||
|
u16 sym_ctr; /*clock symbol and transmitter control*/
|
||||||
|
u16 term; /*transmission termination value*/
|
||||||
};
|
};
|
||||||
|
|
||||||
int imx_hdmi_bind(struct device *dev, struct device *master,
|
int imx_hdmi_bind(struct device *dev, struct device *master,
|
||||||
|
|
|
@ -28,6 +28,57 @@ struct imx_hdmi_priv {
|
||||||
struct regmap *regmap;
|
struct regmap *regmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct mpll_config imx_mpll_cfg[] = {
|
||||||
|
{
|
||||||
|
45250000, {
|
||||||
|
{ 0x01e0, 0x0000 },
|
||||||
|
{ 0x21e1, 0x0000 },
|
||||||
|
{ 0x41e2, 0x0000 }
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
92500000, {
|
||||||
|
{ 0x0140, 0x0005 },
|
||||||
|
{ 0x2141, 0x0005 },
|
||||||
|
{ 0x4142, 0x0005 },
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
148500000, {
|
||||||
|
{ 0x00a0, 0x000a },
|
||||||
|
{ 0x20a1, 0x000a },
|
||||||
|
{ 0x40a2, 0x000a },
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
~0UL, {
|
||||||
|
{ 0x00a0, 0x000a },
|
||||||
|
{ 0x2001, 0x000f },
|
||||||
|
{ 0x4002, 0x000f },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct curr_ctrl imx_cur_ctr[] = {
|
||||||
|
/* pixelclk bpp8 bpp10 bpp12 */
|
||||||
|
{
|
||||||
|
54000000, { 0x091c, 0x091c, 0x06dc },
|
||||||
|
}, {
|
||||||
|
58400000, { 0x091c, 0x06dc, 0x06dc },
|
||||||
|
}, {
|
||||||
|
72000000, { 0x06dc, 0x06dc, 0x091c },
|
||||||
|
}, {
|
||||||
|
74250000, { 0x06dc, 0x0b5c, 0x091c },
|
||||||
|
}, {
|
||||||
|
118800000, { 0x091c, 0x091c, 0x06dc },
|
||||||
|
}, {
|
||||||
|
216000000, { 0x06dc, 0x0b5c, 0x091c },
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct sym_term imx_sym_term[] = {
|
||||||
|
/*pixelclk symbol term*/
|
||||||
|
{ 148500000, 0x800d, 0x0005 },
|
||||||
|
{ ~0UL, 0x0000, 0x0000 }
|
||||||
|
};
|
||||||
|
|
||||||
static int imx_hdmi_parse_dt(struct imx_hdmi_priv *hdmi)
|
static int imx_hdmi_parse_dt(struct imx_hdmi_priv *hdmi)
|
||||||
{
|
{
|
||||||
struct device_node *np = hdmi->dev->of_node;
|
struct device_node *np = hdmi->dev->of_node;
|
||||||
|
@ -88,10 +139,16 @@ static struct drm_encoder_funcs imx_hdmi_encoder_funcs = {
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct imx_hdmi_plat_data imx6q_hdmi_drv_data = {
|
static struct imx_hdmi_plat_data imx6q_hdmi_drv_data = {
|
||||||
|
.mpll_cfg = imx_mpll_cfg,
|
||||||
|
.cur_ctr = imx_cur_ctr,
|
||||||
|
.sym_term = imx_sym_term,
|
||||||
.dev_type = IMX6Q_HDMI,
|
.dev_type = IMX6Q_HDMI,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct imx_hdmi_plat_data imx6dl_hdmi_drv_data = {
|
static struct imx_hdmi_plat_data imx6dl_hdmi_drv_data = {
|
||||||
|
.mpll_cfg = imx_mpll_cfg,
|
||||||
|
.cur_ctr = imx_cur_ctr,
|
||||||
|
.sym_term = imx_sym_term,
|
||||||
.dev_type = IMX6DL_HDMI,
|
.dev_type = IMX6DL_HDMI,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue