drm/rockchip: inno_hdmi: add rk3128 hdmi support

Change-Id: I929880020f4a72e61d21b7af4d73a98da337b10b
Signed-off-by: Huicong Xu <xhc@rock-chips.com>
This commit is contained in:
Huicong Xu
2017-10-27 11:20:50 +08:00
committed by Tao Huang
parent 370364aed7
commit c2322ff698

View File

@@ -47,6 +47,22 @@ struct inno_hdmi_i2c {
struct completion cmp;
};
enum inno_hdmi_dev_type {
RK3036_HDMI,
RK3128_HDMI,
};
struct inno_hdmi_phy_config {
unsigned long mpixelclock;
u8 pre_emphasis; /* pre-emphasis value */
u8 vlev_ctr; /* voltage level control */
};
struct inno_hdmi_plat_data {
enum inno_hdmi_dev_type dev_type;
struct inno_hdmi_phy_config *phy_config;
};
struct inno_hdmi {
struct device *dev;
struct drm_device *drm_dev;
@@ -62,6 +78,7 @@ struct inno_hdmi {
struct i2c_adapter *ddc;
unsigned int tmds_rate;
const struct inno_hdmi_plat_data *plat_data;
struct hdmi_data_info hdmi_data;
struct drm_display_mode previous_mode;
@@ -189,12 +206,20 @@ static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
{
const struct inno_hdmi_phy_config *phy_config =
hdmi->plat_data->phy_config;
switch (mode) {
case NORMAL:
inno_hdmi_sys_power(hdmi, false);
hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f);
hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb);
for (; phy_config->mpixelclock != ~0UL; phy_config++)
if (hdmi->tmds_rate <= phy_config->mpixelclock)
break;
if (!phy_config->mpixelclock)
return;
hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS,
phy_config->pre_emphasis);
hdmi_writeb(hdmi, HDMI_PHY_DRIVER, phy_config->vlev_ctr);
hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
@@ -383,6 +408,12 @@ static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
{
int value;
if (hdmi->plat_data->dev_type == RK3036_HDMI) {
value = BIT(20) | BIT(21);
value |= mode->flags & DRM_MODE_FLAG_PHSYNC ? BIT(4) : 0;
value |= mode->flags & DRM_MODE_FLAG_PVSYNC ? BIT(5) : 0;
hdmi_writeb(hdmi, 0x148, value);
}
/* Set detail external video timing polarity and interlace mode */
value = v_EXTERANL_VIDEO(1);
value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
@@ -804,6 +835,41 @@ static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
return adap;
}
static struct inno_hdmi_phy_config rk3036_hdmi_phy_config[] = {
/* pixelclk pre-emp vlev */
{ 74250000, 0x3f, 0xbb },
{ 165000000, 0x6f, 0xbb },
{ ~0UL, 0x00, 0x00 }
};
static struct inno_hdmi_phy_config rk3128_hdmi_phy_config[] = {
/* pixelclk pre-emp vlev */
{ 74250000, 0x3f, 0xaa },
{ 165000000, 0x5f, 0xaa },
{ ~0UL, 0x00, 0x00 }
};
static const struct inno_hdmi_plat_data rk3036_hdmi_drv_data = {
.dev_type = RK3036_HDMI,
.phy_config = rk3036_hdmi_phy_config,
};
static const struct inno_hdmi_plat_data rk3128_hdmi_drv_data = {
.dev_type = RK3128_HDMI,
.phy_config = rk3128_hdmi_phy_config,
};
static const struct of_device_id inno_hdmi_dt_ids[] = {
{ .compatible = "rockchip,rk3036-inno-hdmi",
.data = &rk3036_hdmi_drv_data,
},
{ .compatible = "rockchip,rk3128-inno-hdmi",
.data = &rk3128_hdmi_drv_data,
},
{},
};
MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
static int inno_hdmi_bind(struct device *dev, struct device *master,
void *data)
{
@@ -820,6 +886,7 @@ static int inno_hdmi_bind(struct device *dev, struct device *master,
hdmi->dev = dev;
hdmi->drm_dev = drm;
hdmi->plat_data = device_get_match_data(hdmi->dev);
iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
hdmi->regs = devm_ioremap_resource(dev, iores);
@@ -918,13 +985,6 @@ static int inno_hdmi_remove(struct platform_device *pdev)
return 0;
}
static const struct of_device_id inno_hdmi_dt_ids[] = {
{ .compatible = "rockchip,rk3036-inno-hdmi",
},
{},
};
MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
struct platform_driver inno_hdmi_driver = {
.probe = inno_hdmi_probe,
.remove = inno_hdmi_remove,