drm/exynos/hdmi: add Exynos5433 support
HDMI on Exynos5433 differs from previous versions: - different HDMI-PHY settings, - different clocks, - SYSREG registers for enabling reference clock, - MODE_SET register in HDMI-PHY. It is distinguished from other variants by different compatible string. Signed-off-by: Andrzej Hajda <a.hajda@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
This commit is contained in:
parent
2f1cad0d2d
commit
68cd004e54
|
@ -112,6 +112,7 @@ struct string_array_spec {
|
||||||
struct hdmi_driver_data {
|
struct hdmi_driver_data {
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
unsigned int is_apb_phy:1;
|
unsigned int is_apb_phy:1;
|
||||||
|
unsigned int has_sysreg:1;
|
||||||
struct hdmiphy_configs phy_confs;
|
struct hdmiphy_configs phy_confs;
|
||||||
struct string_array_spec clk_gates;
|
struct string_array_spec clk_gates;
|
||||||
/*
|
/*
|
||||||
|
@ -140,6 +141,7 @@ struct hdmi_context {
|
||||||
struct gpio_desc *hpd_gpio;
|
struct gpio_desc *hpd_gpio;
|
||||||
int irq;
|
int irq;
|
||||||
struct regmap *pmureg;
|
struct regmap *pmureg;
|
||||||
|
struct regmap *sysreg;
|
||||||
struct clk **clk_gates;
|
struct clk **clk_gates;
|
||||||
struct clk **clk_muxes;
|
struct clk **clk_muxes;
|
||||||
struct regulator_bulk_data regul_bulk[ARRAY_SIZE(supply)];
|
struct regulator_bulk_data regul_bulk[ARRAY_SIZE(supply)];
|
||||||
|
@ -516,6 +518,90 @@ static const struct hdmiphy_config hdmiphy_5420_configs[] = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct hdmiphy_config hdmiphy_5433_configs[] = {
|
||||||
|
{
|
||||||
|
.pixel_clock = 27000000,
|
||||||
|
.conf = {
|
||||||
|
0x01, 0x51, 0x22, 0x51, 0x08, 0xfc, 0x88, 0x46,
|
||||||
|
0x72, 0x50, 0x24, 0x0c, 0x24, 0x0f, 0x7c, 0xa5,
|
||||||
|
0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30,
|
||||||
|
0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.pixel_clock = 27027000,
|
||||||
|
.conf = {
|
||||||
|
0x01, 0x51, 0x2d, 0x72, 0x64, 0x09, 0x88, 0xc3,
|
||||||
|
0x71, 0x50, 0x24, 0x14, 0x24, 0x0f, 0x7c, 0xa5,
|
||||||
|
0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30,
|
||||||
|
0x28, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.pixel_clock = 40000000,
|
||||||
|
.conf = {
|
||||||
|
0x01, 0x51, 0x32, 0x55, 0x01, 0x00, 0x88, 0x02,
|
||||||
|
0x4d, 0x50, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
|
||||||
|
0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
|
||||||
|
0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.pixel_clock = 50000000,
|
||||||
|
.conf = {
|
||||||
|
0x01, 0x51, 0x34, 0x40, 0x64, 0x09, 0x88, 0xc3,
|
||||||
|
0x3d, 0x50, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
|
||||||
|
0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
|
||||||
|
0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.pixel_clock = 65000000,
|
||||||
|
.conf = {
|
||||||
|
0x01, 0x51, 0x36, 0x31, 0x40, 0x10, 0x04, 0xc6,
|
||||||
|
0x2e, 0xe8, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
|
||||||
|
0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
|
||||||
|
0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.pixel_clock = 74176000,
|
||||||
|
.conf = {
|
||||||
|
0x01, 0x51, 0x3E, 0x35, 0x5B, 0xDE, 0x88, 0x42,
|
||||||
|
0x53, 0x51, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
|
||||||
|
0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
|
||||||
|
0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.pixel_clock = 74250000,
|
||||||
|
.conf = {
|
||||||
|
0x01, 0x51, 0x3E, 0x35, 0x40, 0xF0, 0x88, 0xC2,
|
||||||
|
0x52, 0x51, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
|
||||||
|
0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
|
||||||
|
0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.pixel_clock = 108000000,
|
||||||
|
.conf = {
|
||||||
|
0x01, 0x51, 0x2d, 0x15, 0x01, 0x00, 0x88, 0x02,
|
||||||
|
0x72, 0x52, 0x44, 0x8C, 0x27, 0x00, 0x7C, 0xAC,
|
||||||
|
0xD6, 0x2B, 0x67, 0x00, 0x00, 0x04, 0x00, 0x30,
|
||||||
|
0x08, 0x10, 0x01, 0x01, 0x48, 0x40, 0x00, 0x40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.pixel_clock = 148500000,
|
||||||
|
.conf = {
|
||||||
|
0x01, 0x51, 0x1f, 0x00, 0x40, 0xf8, 0x88, 0xc1,
|
||||||
|
0x52, 0x52, 0x24, 0x0c, 0x24, 0x0f, 0x7c, 0xa5,
|
||||||
|
0xd4, 0x2b, 0x87, 0x00, 0x00, 0x04, 0x00, 0x30,
|
||||||
|
0x08, 0x10, 0x01, 0x01, 0x48, 0x4a, 0x00, 0x40,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const char * const hdmi_clk_gates4[] = {
|
static const char * const hdmi_clk_gates4[] = {
|
||||||
"hdmi", "sclk_hdmi"
|
"hdmi", "sclk_hdmi"
|
||||||
};
|
};
|
||||||
|
@ -524,6 +610,15 @@ static const char * const hdmi_clk_muxes4[] = {
|
||||||
"sclk_pixel", "sclk_hdmiphy", "mout_hdmi"
|
"sclk_pixel", "sclk_hdmiphy", "mout_hdmi"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char * const hdmi_clk_gates5433[] = {
|
||||||
|
"hdmi_pclk", "hdmi_i_pclk", "i_tmds_clk", "i_pixel_clk", "i_spdif_clk"
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char * const hdmi_clk_muxes5433[] = {
|
||||||
|
"oscclk", "tmds_clko", "tmds_clko_user",
|
||||||
|
"oscclk", "pixel_clko", "pixel_clko_user"
|
||||||
|
};
|
||||||
|
|
||||||
static const struct hdmi_driver_data exynos4210_hdmi_driver_data = {
|
static const struct hdmi_driver_data exynos4210_hdmi_driver_data = {
|
||||||
.type = HDMI_TYPE13,
|
.type = HDMI_TYPE13,
|
||||||
.phy_confs = INIT_ARRAY_SPEC(hdmiphy_v13_configs),
|
.phy_confs = INIT_ARRAY_SPEC(hdmiphy_v13_configs),
|
||||||
|
@ -546,6 +641,15 @@ static const struct hdmi_driver_data exynos5420_hdmi_driver_data = {
|
||||||
.clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
|
.clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes4),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct hdmi_driver_data exynos5433_hdmi_driver_data = {
|
||||||
|
.type = HDMI_TYPE14,
|
||||||
|
.is_apb_phy = 1,
|
||||||
|
.has_sysreg = 1,
|
||||||
|
.phy_confs = INIT_ARRAY_SPEC(hdmiphy_5433_configs),
|
||||||
|
.clk_gates = INIT_ARRAY_SPEC(hdmi_clk_gates5433),
|
||||||
|
.clk_muxes = INIT_ARRAY_SPEC(hdmi_clk_muxes5433),
|
||||||
|
};
|
||||||
|
|
||||||
static inline u32 hdmi_map_reg(struct hdmi_context *hdata, u32 reg_id)
|
static inline u32 hdmi_map_reg(struct hdmi_context *hdata, u32 reg_id)
|
||||||
{
|
{
|
||||||
if ((reg_id & 0xffff0000) == HDMI_MAPPED_BASE)
|
if ((reg_id & 0xffff0000) == HDMI_MAPPED_BASE)
|
||||||
|
@ -1539,6 +1643,8 @@ static void hdmi_v14_mode_apply(struct hdmi_context *hdata)
|
||||||
hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
|
hdmi_reg_writev(hdata, HDMI_TG_HACT_ST_L, 2, m->htotal - m->hdisplay);
|
||||||
hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
|
hdmi_reg_writev(hdata, HDMI_TG_HACT_SZ_L, 2, m->hdisplay);
|
||||||
hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
|
hdmi_reg_writev(hdata, HDMI_TG_V_FSZ_L, 2, m->vtotal);
|
||||||
|
if (hdata->drv_data == &exynos5433_hdmi_driver_data)
|
||||||
|
hdmi_reg_writeb(hdata, HDMI_TG_DECON_EN, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void hdmi_mode_apply(struct hdmi_context *hdata)
|
static void hdmi_mode_apply(struct hdmi_context *hdata)
|
||||||
|
@ -1563,6 +1669,14 @@ static void hdmiphy_conf_reset(struct hdmi_context *hdata)
|
||||||
usleep_range(10000, 12000);
|
usleep_range(10000, 12000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hdmiphy_enable_mode_set(struct hdmi_context *hdata, bool enable)
|
||||||
|
{
|
||||||
|
u8 v = enable ? HDMI_PHY_ENABLE_MODE_SET : HDMI_PHY_DISABLE_MODE_SET;
|
||||||
|
|
||||||
|
if (hdata->drv_data == &exynos5433_hdmi_driver_data)
|
||||||
|
writel(v, hdata->regs_hdmiphy + HDMIPHY5433_MODE_SET_DONE);
|
||||||
|
}
|
||||||
|
|
||||||
static void hdmiphy_conf_apply(struct hdmi_context *hdata)
|
static void hdmiphy_conf_apply(struct hdmi_context *hdata)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
@ -1574,12 +1688,14 @@ static void hdmiphy_conf_apply(struct hdmi_context *hdata)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hdmiphy_enable_mode_set(hdata, true);
|
||||||
ret = hdmiphy_reg_write_buf(hdata, 0,
|
ret = hdmiphy_reg_write_buf(hdata, 0,
|
||||||
hdata->drv_data->phy_confs.data[i].conf, 32);
|
hdata->drv_data->phy_confs.data[i].conf, 32);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
DRM_ERROR("failed to configure hdmiphy\n");
|
DRM_ERROR("failed to configure hdmiphy\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
hdmiphy_enable_mode_set(hdata, false);
|
||||||
|
|
||||||
usleep_range(10000, 12000);
|
usleep_range(10000, 12000);
|
||||||
}
|
}
|
||||||
|
@ -1612,6 +1728,15 @@ static void hdmi_mode_set(struct drm_encoder *encoder,
|
||||||
hdata->cea_video_id = drm_match_cea_mode(mode);
|
hdata->cea_video_id = drm_match_cea_mode(mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void hdmi_set_refclk(struct hdmi_context *hdata, bool on)
|
||||||
|
{
|
||||||
|
if (!hdata->sysreg)
|
||||||
|
return;
|
||||||
|
|
||||||
|
regmap_update_bits(hdata->sysreg, EXYNOS5433_SYSREG_DISP_HDMI_PHY,
|
||||||
|
SYSREG_HDMI_REFCLK_INT_CLK, on ? ~0 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
static void hdmi_enable(struct drm_encoder *encoder)
|
static void hdmi_enable(struct drm_encoder *encoder)
|
||||||
{
|
{
|
||||||
struct hdmi_context *hdata = encoder_to_hdmi(encoder);
|
struct hdmi_context *hdata = encoder_to_hdmi(encoder);
|
||||||
|
@ -1627,6 +1752,8 @@ static void hdmi_enable(struct drm_encoder *encoder)
|
||||||
regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
|
regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
|
||||||
PMU_HDMI_PHY_ENABLE_BIT, 1);
|
PMU_HDMI_PHY_ENABLE_BIT, 1);
|
||||||
|
|
||||||
|
hdmi_set_refclk(hdata, true);
|
||||||
|
|
||||||
hdmi_conf_apply(hdata);
|
hdmi_conf_apply(hdata);
|
||||||
|
|
||||||
hdata->powered = true;
|
hdata->powered = true;
|
||||||
|
@ -1659,6 +1786,8 @@ static void hdmi_disable(struct drm_encoder *encoder)
|
||||||
|
|
||||||
cancel_delayed_work(&hdata->hotplug_work);
|
cancel_delayed_work(&hdata->hotplug_work);
|
||||||
|
|
||||||
|
hdmi_set_refclk(hdata, false);
|
||||||
|
|
||||||
regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
|
regmap_update_bits(hdata->pmureg, PMU_HDMI_PHY_CONTROL,
|
||||||
PMU_HDMI_PHY_ENABLE_BIT, 0);
|
PMU_HDMI_PHY_ENABLE_BIT, 0);
|
||||||
|
|
||||||
|
@ -1813,6 +1942,9 @@ static struct of_device_id hdmi_match_types[] = {
|
||||||
}, {
|
}, {
|
||||||
.compatible = "samsung,exynos5420-hdmi",
|
.compatible = "samsung,exynos5420-hdmi",
|
||||||
.data = &exynos5420_hdmi_driver_data,
|
.data = &exynos5420_hdmi_driver_data,
|
||||||
|
}, {
|
||||||
|
.compatible = "samsung,exynos5433-hdmi",
|
||||||
|
.data = &exynos5433_hdmi_driver_data,
|
||||||
}, {
|
}, {
|
||||||
/* end node */
|
/* end node */
|
||||||
}
|
}
|
||||||
|
@ -1980,6 +2112,16 @@ out_get_phy_port:
|
||||||
goto err_hdmiphy;
|
goto err_hdmiphy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hdata->drv_data->has_sysreg) {
|
||||||
|
hdata->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
|
||||||
|
"samsung,sysreg-phandle");
|
||||||
|
if (IS_ERR(hdata->sysreg)) {
|
||||||
|
DRM_ERROR("sysreg regmap lookup failed.\n");
|
||||||
|
ret = -EPROBE_DEFER;
|
||||||
|
goto err_hdmiphy;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pm_runtime_enable(dev);
|
pm_runtime_enable(dev);
|
||||||
|
|
||||||
ret = component_add(&pdev->dev, &hdmi_component_ops);
|
ret = component_add(&pdev->dev, &hdmi_component_ops);
|
||||||
|
|
|
@ -586,10 +586,12 @@
|
||||||
#define HDMI_TG_VACT_ST4_L HDMI_TG_BASE(0x0070)
|
#define HDMI_TG_VACT_ST4_L HDMI_TG_BASE(0x0070)
|
||||||
#define HDMI_TG_VACT_ST4_H HDMI_TG_BASE(0x0074)
|
#define HDMI_TG_VACT_ST4_H HDMI_TG_BASE(0x0074)
|
||||||
#define HDMI_TG_3D HDMI_TG_BASE(0x00F0)
|
#define HDMI_TG_3D HDMI_TG_BASE(0x00F0)
|
||||||
|
#define HDMI_TG_DECON_EN HDMI_TG_BASE(0x01e0)
|
||||||
|
|
||||||
/* HDMI PHY Registers Offsets*/
|
/* HDMI PHY Registers Offsets*/
|
||||||
#define HDMIPHY_POWER (0x74 >> 2)
|
#define HDMIPHY_POWER 0x74
|
||||||
#define HDMIPHY_MODE_SET_DONE (0x7c >> 2)
|
#define HDMIPHY_MODE_SET_DONE 0x7c
|
||||||
|
#define HDMIPHY5433_MODE_SET_DONE 0x84
|
||||||
|
|
||||||
/* HDMI PHY Values */
|
/* HDMI PHY Values */
|
||||||
#define HDMI_PHY_POWER_ON 0x80
|
#define HDMI_PHY_POWER_ON 0x80
|
||||||
|
@ -603,4 +605,7 @@
|
||||||
#define PMU_HDMI_PHY_CONTROL 0x700
|
#define PMU_HDMI_PHY_CONTROL 0x700
|
||||||
#define PMU_HDMI_PHY_ENABLE_BIT BIT(0)
|
#define PMU_HDMI_PHY_ENABLE_BIT BIT(0)
|
||||||
|
|
||||||
|
#define EXYNOS5433_SYSREG_DISP_HDMI_PHY 0x1008
|
||||||
|
#define SYSREG_HDMI_REFCLK_INT_CLK 1
|
||||||
|
|
||||||
#endif /* SAMSUNG_REGS_HDMI_H */
|
#endif /* SAMSUNG_REGS_HDMI_H */
|
||||||
|
|
Loading…
Reference in New Issue