================================
Required properties:
-- compatible: "rockchip,rk3288-dw-hdmi",
+- compatible: "rockchip,rk3228-dw-hdmi",
+ "rockchip,rk3288-dw-hdmi",
"rockchip,rk3328-dw-hdmi",
"rockchip,rk3368-dw-hdmi",
"rockchip,rk3399-dw-hdmi";
phandle to the VPLL clock, name should be "vpll",
phandle to the GRF clock, name should be "grf".
- rockchip,phy-table: the parameter table of hdmi phy configuration.
+- phys: phandle to third party HDMI PHY node
+- phy-names: the string "hdmi_phy" when is found in a node, along with "phys"
+ attribute, provides phandle to HDMI PHY node
Example:
hdmi: hdmi@ff980000 {
phy_type = hdmi_readb(hdmi, HDMI_CONFIG2_ID);
/*
- * RK3328 phy_type is DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
+ * RK3228 and RK3328 phy_type is DW_HDMI_PHY_DWC_HDMI20_TX_PHY,
* but it has a vedor phy.
*/
if (phy_type == DW_HDMI_PHY_VENDOR_PHY ||
- hdmi->dev_type == RK3328_HDMI) {
+ hdmi->dev_type == RK3328_HDMI ||
+ hdmi->dev_type == RK3228_HDMI) {
/* Vendor PHYs require support from the glue layer. */
if (!hdmi->plat_data->phy_ops || !hdmi->plat_data->phy_name) {
dev_err(hdmi->dev,
u32 reg, val;
char kbuf[25];
+ if (hdmi->dev_type == RK3228_HDMI)
+ return -EFAULT;
+
if (copy_from_user(kbuf, buf, count))
return -EFAULT;
if (sscanf(kbuf, "%x%x", ®, &val) == -1)
struct dw_hdmi *hdmi = s->private;
u32 i, total, val;
+ if (hdmi->dev_type == RK3228_HDMI)
+ return 0;
+
seq_puts(s, "\n>>>hdmi_phy reg\n");
if (hdmi->dev_type != RK3328_HDMI)
total = 0x28;
#include <linux/rockchip/cpu.h>
#include <linux/regmap.h>
#include <linux/pm_runtime.h>
+#include <linux/phy/phy.h>
#include <drm/drm_of.h>
#include <drm/drmP.h>
#include "rockchip_drm_drv.h"
#include "rockchip_drm_vop.h"
+#define RK3228_GRF_SOC_CON2 0x0408
+#define RK3228_DDC_MASK_EN ((3 << 13) | (3 << (13 + 16)))
+#define RK3228_GRF_SOC_CON6 0x0418
+#define RK3228_IO_3V_DOMAIN ((7 << 4) | (7 << (4 + 16)))
+
#define RK3288_GRF_SOC_CON6 0x025C
#define RK3288_HDMI_LCDC_SEL BIT(4)
#define RK3399_GRF_SOC_CON20 0x6250
struct clk *hdmiphy_clk;
struct clk *hclk_vio;
struct clk_hw hdmiphy_clkhw;
+
+ struct phy *phy;
};
#define to_rockchip_hdmi(x) container_of(x, struct rockchip_hdmi, x)
const struct inno_phy_config *inno_phy_config = inno_phy_cfg;
u32 val, i, chipversion = 1;
+ if (hdmi->dev_type == RK3228_HDMI) {
+ phy_power_on(hdmi->phy);
+ return 0;
+ }
+
if (rockchip_get_cpu_version())
chipversion = 2;
{
struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data;
+ if (hdmi->dev_type == RK3228_HDMI) {
+ phy_power_off(hdmi->phy);
+ return;
+ }
+
/* Power off driver */
inno_phy_writel(hdmi, 0xb2, 0);
/* Power off band gap */
enum drm_connector_status status;
status = dw_hdmi_phy_read_hpd(dw_hdmi, data);
+
+ if (hdmi->dev_type == RK3228_HDMI)
+ return status;
+
if (status == connector_status_connected)
regmap_write(hdmi->regmap,
RK3328_GRF_SOC_CON4,
.write = inno_dw_hdmi_phy_write,
};
+static const struct dw_hdmi_plat_data rk3228_hdmi_drv_data = {
+ .mode_valid = dw_hdmi_rockchip_mode_valid,
+ .phy_ops = &inno_dw_hdmi_phy_ops,
+ .phy_name = "inno_dw_hdmi_phy",
+ .dev_type = RK3228_HDMI,
+};
+
static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = {
.mode_valid = dw_hdmi_rockchip_mode_valid,
.mpll_cfg = rockchip_mpll_cfg,
};
static const struct of_device_id dw_hdmi_rockchip_dt_ids[] = {
+ { .compatible = "rockchip,rk3228-dw-hdmi",
+ .data = &rk3228_hdmi_drv_data
+ },
{ .compatible = "rockchip,rk3288-dw-hdmi",
.data = &rk3288_hdmi_drv_data
},
if (ret < 0)
return ret;
inno_dw_hdmi_phy_clk_register(hdmi);
+ } else if (hdmi->dev_type == RK3228_HDMI) {
+ hdmi->phy = devm_phy_get(dev, "hdmi_phy");
+ if (IS_ERR(hdmi->phy)) {
+ ret = PTR_ERR(hdmi->phy);
+ dev_err(dev, "failed to get phy: %d\n", ret);
+ return ret;
+ }
+ plat_data->phy_data = hdmi;
+ regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON2,
+ RK3228_DDC_MASK_EN);
+ regmap_write(hdmi->regmap, RK3228_GRF_SOC_CON6,
+ RK3228_IO_3V_DOMAIN);
}
drm_encoder_helper_add(encoder, &dw_hdmi_rockchip_encoder_helper_funcs);