@@ -217,6 +217,17 @@ static void phy_update_bits(struct inno_dsidphy *inno,
writel(tmp, inno->phy_base + reg);
}
+static void host_update_bits(struct inno_dsidphy *inno,
+ u32 reg, u32 mask, u32 val)
+{
+ unsigned int tmp, orig;
+
+ orig = readl(inno->host_base + reg);
+ tmp = orig & ~mask;
+ tmp |= val & mask;
+ writel(tmp, inno->host_base + reg);
+}
+
static int inno_is_valid_phy_mode(struct inno_dsidphy *inno)
{
switch (inno->mode) {
@@ -224,6 +235,10 @@ static int inno_is_valid_phy_mode(struct inno_dsidphy *inno)
break;
case PHY_MODE_LVDS:
break;
+ case PHY_MODE_TTL:
+ if (IS_ERR(inno->host_base))
+ return -EINVAL;
+ break;
default:
return -EINVAL;
}
@@ -506,6 +521,32 @@ static void inno_dsidphy_lvds_mode_enable(struct inno_dsidphy *inno)
LVDS_DATA_LANE2_EN | LVDS_DATA_LANE3_EN);
}
+static void inno_dsidphy_ttl_mode_enable(struct inno_dsidphy *inno)
+{
+ /* Select TTL mode */
+ phy_update_bits(inno, REGISTER_PART_LVDS, 0x03,
+ MODE_ENABLE_MASK, TTL_MODE_ENABLE);
+ /* Reset digital logic */
+ phy_update_bits(inno, REGISTER_PART_LVDS, 0x00,
+ LVDS_DIGITAL_INTERNAL_RESET_MASK,
+ LVDS_DIGITAL_INTERNAL_RESET_ENABLE);
+ udelay(1);
+ phy_update_bits(inno, REGISTER_PART_LVDS, 0x00,
+ LVDS_DIGITAL_INTERNAL_RESET_MASK,
+ LVDS_DIGITAL_INTERNAL_RESET_DISABLE);
+ /* Enable digital logic */
+ phy_update_bits(inno, REGISTER_PART_LVDS, 0x01,
+ LVDS_DIGITAL_INTERNAL_ENABLE_MASK,
+ LVDS_DIGITAL_INTERNAL_ENABLE);
+ /* Enable analog driver */
+ phy_update_bits(inno, REGISTER_PART_LVDS, 0x0b,
+ LVDS_LANE_EN_MASK, LVDS_CLK_LANE_EN |
+ LVDS_DATA_LANE0_EN | LVDS_DATA_LANE1_EN |
+ LVDS_DATA_LANE2_EN | LVDS_DATA_LANE3_EN);
+ /* Enable for clk lane in TTL mode */
+ host_update_bits(inno, DSI_PHY_RSTZ, PHY_ENABLECLK, PHY_ENABLECLK);
+}
+
static int inno_dsidphy_power_on(struct phy *phy)
{
struct inno_dsidphy *inno = phy_get_drvdata(phy);
@@ -533,6 +574,9 @@ static int inno_dsidphy_power_on(struct phy *phy)
case PHY_MODE_LVDS:
inno_dsidphy_lvds_mode_enable(inno);
break;
+ case PHY_MODE_TTL:
+ inno_dsidphy_ttl_mode_enable(inno);
+ break;
default:
return -EINVAL;
}
@@ -561,6 +605,10 @@ static int inno_dsidphy_power_off(struct phy *phy)
LVDS_PLL_POWER_MASK | LVDS_BANDGAP_POWER_MASK,
LVDS_PLL_POWER_OFF | LVDS_BANDGAP_POWER_DOWN);
+ /* Disable for clk lane in TTL mode */
+ if (!IS_ERR(inno->host_base))
+ host_update_bits(inno, DSI_PHY_RSTZ, PHY_ENABLECLK, 0);
+
pm_runtime_put(inno->dev);
clk_disable_unprepare(inno->ref_clk);
clk_disable_unprepare(inno->pclk_phy);
@@ -576,6 +624,7 @@ static int inno_dsidphy_set_mode(struct phy *phy, enum phy_mode mode,
switch (mode) {
case PHY_MODE_MIPI_DPHY:
case PHY_MODE_LVDS:
+ case PHY_MODE_TTL:
inno->mode = mode;
break;
default:
@@ -630,6 +679,10 @@ static int inno_dsidphy_probe(struct platform_device *pdev)
if (IS_ERR(inno->phy_base))
return PTR_ERR(inno->phy_base);
+ inno->host_base = devm_platform_ioremap_resource(pdev, 1);
+ if (IS_ERR(inno->host_base))
+ dev_warn(dev, "TTL mode is not supported\n");
+
inno->ref_clk = devm_clk_get(dev, "ref");
if (IS_ERR(inno->ref_clk)) {
ret = PTR_ERR(inno->ref_clk);