Skip to contentSkip to conversation

drm/msm/dsi: Add support for DSI on MSM8960/APQ8064

PATCH Superseded Archit Taneja 4 participants 52 messages Oct 14, 2015 – Dec 7, 2015 1 message not in the archive

Subsystems (5)
lore
Share & tools
lore
#0 lore raw

cover drm/msm/dsi: Add support for DSI on MSM8960/APQ8064

Add support for DSI on 8960/8064. The DSI IP used in these chips is an older version(DSIv2) of what we have right now(DSI6G).

The bulk of the additions come thanks to a different PHY/PLL. The DSI host in itself doesn't have too many changes.

Archit Taneja (12):
drm/msm/dsi: Update generated header for 8960 drm/msm/dsi: Add support for 28nm PHY on 8960 drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY drm/msm/dsi: Use a better way to figure out DSI version drm/msm/dsi: Delay dsi_clk_init
drm/msm/dsi: Parse bus clocks from a list drm/msm/dsi: Set up link clocks for DSIv2 drm/msm/dsi: Add dsi_cfg for APQ8064
drm/msm/dsi: Don't use iommu for command TX buffer for DSIv2 drm/msm/dsi: SFPB: Update generated headers drm/msm/dsi: Enable MMSS SPFB port via syscon
dt-bindings: Add DSIv2 documentation

 Documentation/devicetree/bindings/drm/msm/dsi.txt |  10 +-
 drivers/gpu/drm/msm/Kconfig                       |   8 +
 drivers/gpu/drm/msm/Makefile                      |   2 +
 drivers/gpu/drm/msm/dsi/dsi.h                     |   6 +-
 drivers/gpu/drm/msm/dsi/dsi.xml.h                 | 243 +++++++---
 drivers/gpu/drm/msm/dsi/dsi_cfg.c                 |  35 +-
 drivers/gpu/drm/msm/dsi/dsi_cfg.h                 |   4 +
 drivers/gpu/drm/msm/dsi/dsi_host.c                | 497 ++++++++++++++------
 drivers/gpu/drm/msm/dsi/dsi_manager.c             |   6 +-
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c             |   4 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h             |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c   | 195 ++++++++
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c             |   3 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h             |  10 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c   | 529 ++++++++++++++++++++++
 drivers/gpu/drm/msm/dsi/sfpb.xml.h                |  26 +-
 16 files changed, 1363 insertions(+), 216 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#1 lore raw

PATCH 1/12 drm/msm/dsi: Update generated header for 8960

The DSI PLL and PHY registers are already there for 8960, but their offsets are relative to the top level DSI controller base.

Make the offsets relative to the individual sub blocks. Add "28nm" in the register names while we're at it.

---
 drivers/gpu/drm/msm/dsi/dsi.xml.h | 243 +++++++++++++++++++++++++++-----------
 1 file changed, 177 insertions(+), 66 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.xml.h +177 -66
index 1d2e32f..3d6297f 100644
@@ -8,17 +8,8 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2015-05-20 20:03:07)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2015-05-20 20:03:07)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2015-05-20 20:03:07)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29154 bytes, from 2015-08-10 21:25:43)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-20 20:03:14)
+- /local/mnt/workspace/source_trees/envytools/rnndb/../rnndb/dsi/dsi.xml    (  27887 bytes, from 2015-09-02 06:17:10)
+- /local/mnt/workspace/source_trees/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2015-02-09 03:18:10)
 
 Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <[email protected]> (robclark)
@@ -567,114 +558,234 @@ static inline uint32_t DSI_VERSION_MAJOR(uint32_t val)
 #define REG_DSI_8x60_PHY_CAL_STATUS				0x000000fc
 #define DSI_8x60_PHY_CAL_STATUS_CAL_BUSY			0x10000000
 
-static inline uint32_t REG_DSI_8960_LN(uint32_t i0) { return 0x00000300 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN(uint32_t i0) { return 0x00000000 + 0x40*i0; }
 
-static inline uint32_t REG_DSI_8960_LN_CFG_0(uint32_t i0) { return 0x00000300 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_CFG_0(uint32_t i0) { return 0x00000000 + 0x40*i0; }
 
-static inline uint32_t REG_DSI_8960_LN_CFG_1(uint32_t i0) { return 0x00000304 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_CFG_1(uint32_t i0) { return 0x00000004 + 0x40*i0; }
 
-static inline uint32_t REG_DSI_8960_LN_CFG_2(uint32_t i0) { return 0x00000308 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_CFG_2(uint32_t i0) { return 0x00000008 + 0x40*i0; }
 
-static inline uint32_t REG_DSI_8960_LN_TEST_DATAPATH(uint32_t i0) { return 0x0000030c + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_TEST_DATAPATH(uint32_t i0) { return 0x0000000c + 0x40*i0; }
 
-static inline uint32_t REG_DSI_8960_LN_TEST_STR_0(uint32_t i0) { return 0x00000314 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_TEST_STR_0(uint32_t i0) { return 0x00000014 + 0x40*i0; }
 
-static inline uint32_t REG_DSI_8960_LN_TEST_STR_1(uint32_t i0) { return 0x00000318 + 0x40*i0; }
+static inline uint32_t REG_DSI_28nm_8960_PHY_LN_TEST_STR_1(uint32_t i0) { return 0x00000018 + 0x40*i0; }
 
-#define REG_DSI_8960_PHY_LNCK_CFG_0				0x00000400
+#define REG_DSI_28nm_8960_PHY_LNCK_CFG_0			0x00000100
 
-#define REG_DSI_8960_PHY_LNCK_CFG_1				0x00000404
+#define REG_DSI_28nm_8960_PHY_LNCK_CFG_1			0x00000104
 
-#define REG_DSI_8960_PHY_LNCK_CFG_2				0x00000408
+#define REG_DSI_28nm_8960_PHY_LNCK_CFG_2			0x00000108
 
-#define REG_DSI_8960_PHY_LNCK_TEST_DATAPATH			0x0000040c
+#define REG_DSI_28nm_8960_PHY_LNCK_TEST_DATAPATH		0x0000010c
 
-#define REG_DSI_8960_PHY_LNCK_TEST_STR0				0x00000414
+#define REG_DSI_28nm_8960_PHY_LNCK_TEST_STR0			0x00000114
 
-#define REG_DSI_8960_PHY_LNCK_TEST_STR1				0x00000418
+#define REG_DSI_28nm_8960_PHY_LNCK_TEST_STR1			0x00000118
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_0				0x00000440
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_0			0x00000140
+#define DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__MASK		0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__SHIFT		0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_0_CLK_ZERO__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_1			0x00000144
+#define DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__MASK		0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__SHIFT	0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_1_CLK_TRAIL__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_2			0x00000148
+#define DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__MASK	0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__SHIFT	0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_2_CLK_PREPARE__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_3			0x0000014c
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_4			0x00000150
+#define DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__MASK		0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__SHIFT		0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_4_HS_EXIT__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_5			0x00000154
+#define DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__MASK		0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__SHIFT		0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_5_HS_ZERO__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_6			0x00000158
+#define DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__MASK	0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__SHIFT	0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_6_HS_PREPARE__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_7			0x0000015c
+#define DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__MASK		0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__SHIFT		0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_7_HS_TRAIL__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_8			0x00000160
+#define DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__MASK		0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__SHIFT		0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_8_HS_RQST__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_9			0x00000164
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__MASK		0x00000007
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__SHIFT		0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_GO__MASK;
+}
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__MASK		0x00000070
+#define DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__SHIFT		4
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_9_TA_SURE__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_10			0x00000168
+#define DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__MASK		0x00000007
+#define DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__SHIFT		0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_10_TA_GET__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_TIMING_CTRL_11			0x0000016c
+#define DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__MASK	0x000000ff
+#define DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__SHIFT	0
+static inline uint32_t DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD(uint32_t val)
+{
+	return ((val) << DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__SHIFT) & DSI_28nm_8960_PHY_TIMING_CTRL_11_TRIG3_CMD__MASK;
+}
+
+#define REG_DSI_28nm_8960_PHY_CTRL_0				0x00000170
+
+#define REG_DSI_28nm_8960_PHY_CTRL_1				0x00000174
+
+#define REG_DSI_28nm_8960_PHY_CTRL_2				0x00000178
+
+#define REG_DSI_28nm_8960_PHY_CTRL_3				0x0000017c
+
+#define REG_DSI_28nm_8960_PHY_STRENGTH_0			0x00000180
+
+#define REG_DSI_28nm_8960_PHY_STRENGTH_1			0x00000184
+
+#define REG_DSI_28nm_8960_PHY_STRENGTH_2			0x00000188
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_0			0x0000018c
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_1			0x00000190
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_2			0x00000194
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_3			0x00000198
+
+#define REG_DSI_28nm_8960_PHY_BIST_CTRL_4			0x0000019c
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_1				0x00000444
+#define REG_DSI_28nm_8960_PHY_LDO_CTRL				0x000001b0
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_2				0x00000448
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_0		0x00000000
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_3				0x0000044c
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_1		0x00000004
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_4				0x00000450
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_2		0x00000008
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_5				0x00000454
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_3		0x0000000c
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_6				0x00000458
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_4		0x00000010
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_7				0x0000045c
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CTRL_5		0x00000014
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_8				0x00000460
+#define REG_DSI_28nm_8960_PHY_MISC_REGULATOR_CAL_PWR_CFG	0x00000018
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_9				0x00000464
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_TRIGGER		0x00000028
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_10				0x00000468
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_0			0x0000002c
 
-#define REG_DSI_8960_PHY_TIMING_CTRL_11				0x0000046c
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_1			0x00000030
 
-#define REG_DSI_8960_PHY_CTRL_0					0x00000470
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_SW_CFG_2			0x00000034
 
-#define REG_DSI_8960_PHY_CTRL_1					0x00000474
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_0			0x00000038
 
-#define REG_DSI_8960_PHY_CTRL_2					0x00000478
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_1			0x0000003c
 
-#define REG_DSI_8960_PHY_CTRL_3					0x0000047c
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_2			0x00000040
 
-#define REG_DSI_8960_PHY_STRENGTH_0				0x00000480
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_3			0x00000044
 
-#define REG_DSI_8960_PHY_STRENGTH_1				0x00000484
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_HW_CFG_4			0x00000048
 
-#define REG_DSI_8960_PHY_STRENGTH_2				0x00000488
+#define REG_DSI_28nm_8960_PHY_MISC_CAL_STATUS			0x00000050
+#define DSI_28nm_8960_PHY_MISC_CAL_STATUS_CAL_BUSY		0x00000010
 
-#define REG_DSI_8960_PHY_BIST_CTRL_0				0x0000048c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_0			0x00000000
+#define DSI_28nm_8960_PHY_PLL_CTRL_0_ENABLE			0x00000001
 
-#define REG_DSI_8960_PHY_BIST_CTRL_1				0x00000490
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_1			0x00000004
 
-#define REG_DSI_8960_PHY_BIST_CTRL_2				0x00000494
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_2			0x00000008
 
-#define REG_DSI_8960_PHY_BIST_CTRL_3				0x00000498
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_3			0x0000000c
 
-#define REG_DSI_8960_PHY_BIST_CTRL_4				0x0000049c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_4			0x00000010
 
-#define REG_DSI_8960_PHY_LDO_CTRL				0x000004b0
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_5			0x00000014
 
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_0			0x00000500
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_6			0x00000018
 
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_1			0x00000504
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_7			0x0000001c
 
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_2			0x00000508
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_8			0x00000020
 
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_3			0x0000050c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_9			0x00000024
 
-#define REG_DSI_8960_PHY_REGULATOR_CTRL_4			0x00000510
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_10			0x00000028
 
-#define REG_DSI_8960_PHY_REGULATOR_CAL_PWR_CFG			0x00000518
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_11			0x0000002c
 
-#define REG_DSI_8960_PHY_CAL_HW_TRIGGER				0x00000528
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_12			0x00000030
 
-#define REG_DSI_8960_PHY_CAL_SW_CFG_0				0x0000052c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_13			0x00000034
 
-#define REG_DSI_8960_PHY_CAL_SW_CFG_1				0x00000530
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_14			0x00000038
 
-#define REG_DSI_8960_PHY_CAL_SW_CFG_2				0x00000534
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_15			0x0000003c
 
-#define REG_DSI_8960_PHY_CAL_HW_CFG_0				0x00000538
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_16			0x00000040
 
-#define REG_DSI_8960_PHY_CAL_HW_CFG_1				0x0000053c
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_17			0x00000044
 
-#define REG_DSI_8960_PHY_CAL_HW_CFG_2				0x00000540
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_18			0x00000048
 
-#define REG_DSI_8960_PHY_CAL_HW_CFG_3				0x00000544
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_19			0x0000004c
 
-#define REG_DSI_8960_PHY_CAL_HW_CFG_4				0x00000548
+#define REG_DSI_28nm_8960_PHY_PLL_CTRL_20			0x00000050
 
-#define REG_DSI_8960_PHY_CAL_STATUS				0x00000550
-#define DSI_8960_PHY_CAL_STATUS_CAL_BUSY			0x00000010
+#define REG_DSI_28nm_8960_PHY_PLL_RDY				0x00000080
+#define DSI_28nm_8960_PHY_PLL_RDY_PLL_RDY			0x00000001
 
 static inline uint32_t REG_DSI_28nm_PHY_LN(uint32_t i0) { return 0x00000000 + 0x40*i0; }
 
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#2 lore raw

PATCH 2/12 drm/msm/dsi: Add support for 28nm PHY on 8960

In reply to Archit Taneja

DSI PHY on MSM8960 and APQ8064 is a 28nm PHY that's different from the supported 28nm LP PHY found in newer chips.

Add support for the new PHY.

---
 drivers/gpu/drm/msm/Kconfig                     |   8 +
 drivers/gpu/drm/msm/Makefile                    |   1 +
 drivers/gpu/drm/msm/dsi/dsi.h                   |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c           |   4 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h           |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 195 ++++++++++++++++++++++++
 6 files changed, 210 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
drivers/gpu/drm/msm/Kconfig +8 -0
index 8e6c7c6..38a618e 100644
@@ -68,3 +68,11 @@ config DRM_MSM_DSI_20NM_PHY
 	default y
 	help
 	  Choose this option if the 20nm DSI PHY is used on the platform.
+
+config DRM_MSM_DSI_28NM_8960_PHY
+	bool "Enable DSI 28nm 8960 PHY driver in MSM DRM"
+	depends on DRM_MSM_DSI
+	default y
+	help
+	  Choose this option if the 28nm DSI PHY 8960 variant is used on the
+	  platform.
drivers/gpu/drm/msm/Makefile +1 -0
index 0a543eb..96bcb66 100644
@@ -62,6 +62,7 @@ msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
 
 msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o
 msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o
+msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o
 
 ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)
 msm-y += dsi/pll/dsi_pll.o
drivers/gpu/drm/msm/dsi/dsi.h +1 -0
index 5f5a373..8140e8b 100644
@@ -31,6 +31,7 @@ enum msm_dsi_phy_type {
 	MSM_DSI_PHY_28NM_HPM,
 	MSM_DSI_PHY_28NM_LP,
 	MSM_DSI_PHY_20NM,
+	MSM_DSI_PHY_28NM_8960,
 	MSM_DSI_PHY_MAX
 };
 
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +4 -0
index 401ff58..d54e450 100644
@@ -277,6 +277,10 @@ static const struct of_device_id dsi_phy_dt_match[] = {
 	{ .compatible = "qcom,dsi-phy-20nm",
 	  .data = &dsi_phy_20nm_cfgs },
 #endif
+#ifdef CONFIG_DRM_MSM_DSI_28NM_8960_PHY
+	{ .compatible = "qcom,dsi-phy-28nm-8960",
+	  .data = &dsi_phy_28nm_8960_cfgs },
+#endif
 	{}
 };
 
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +1 -0
index 0456b25..0d54ed0 100644
@@ -43,6 +43,7 @@ struct msm_dsi_phy_cfg {
 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs;
 
 struct msm_dsi_dphy_timing {
 	u32 clk_pre;
drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c new file +195 -0

195 lines not on this page · raw message

Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#3 lore raw

PATCH 3/12 drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY

In reply to Archit Taneja

Add DSI PLL common clock framework clocks for 8960 PHY.

The PLL here is different from the ones found in B family msm chips. As before, the DSI provides two clocks to the outside world. dsixpll and dsixpllbyte (x = 1, 2). dsixpll is a regular clock divider, but dsixpllbyte is modelled as a custom clock divider.

dsixpllbyte is the starting point of the PLL configuration. It is the one that sets up the VCO clock rate. We need the VCO clock rate in the
form: F * byteclk, where F is a multiplication factor that varies on the byte clock the DSI driver is trying to set. We use the custom clk_ops for dsixpllbyte to ensure that the parent (VCO) is set at this rate.

An additional divider (POSTDIV1) generates the bitclk. Since bit clock can be derived from byteclock, we calculate it internally, and don't expose it as a clock.

---
 drivers/gpu/drm/msm/Makefile                    |   1 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c           |   3 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h           |  10 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c | 529 ++++++++++++++++++++++++
 4 files changed, 543 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
drivers/gpu/drm/msm/Makefile +1 -0
index 96bcb66..93cc042 100644
@@ -67,6 +67,7 @@ msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o
 ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)
 msm-y += dsi/pll/dsi_pll.o
 msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o
+msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o
 endif
 
 obj-$(CONFIG_DRM_MSM)	+= msm.o
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c +3 -0
index 5104fc9..5cd438f 100644
@@ -151,6 +151,9 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
 	case MSM_DSI_PHY_28NM_LP:
 		pll = msm_dsi_pll_28nm_init(pdev, type, id);
 		break;
+	case MSM_DSI_PHY_28NM_8960:
+		pll = msm_dsi_pll_28nm_8960_init(pdev, id);
+		break;
 	default:
 		pll = ERR_PTR(-ENXIO);
 		break;
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h +10 -0
index 063caa2..80b6038 100644
@@ -93,6 +93,16 @@ static inline struct msm_dsi_pll *msm_dsi_pll_28nm_init(
 	return ERR_PTR(-ENODEV);
 }
 #endif
+#ifdef CONFIG_DRM_MSM_DSI_28NM_8960_PHY
+struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device *pdev,
+					       int id);
+#else
+struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device *pdev,
+					       int id)
+{
+	return ERR_PTR(-ENODEV);
+}
+#endif
 
 #endif /* __DSI_PLL_H__ */
 
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +529 -0

529 lines not on this page · raw message

Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#4 lore raw

Re: [PATCH 03/12] drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY

Quoted 10 lines · Archit Taneja
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +4 -0
new file mode 100644
index 0000000..e71b4ee
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 14

Quoted 10 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +10 -0
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>

Is this include used?

Quoted 6 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +6 -0
+#include <linux/clk-provider.h>
+
+#include "dsi_pll.h"
+#include "dsi.xml.h"
+
+/*

[..]

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 96

Quoted 5 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +5 -0
+
+#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)
+
+static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
+				    u32 nb_tries, u32 timeout_us)

Why not use unsigned types for these counts? I don't imagine we care about being precisely 32 bits.

Quoted 4 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +4 -0
+{
+	bool pll_locked = false;
+	u32 val;
+

[..]

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 311

Quoted 6 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +6 -0
+	DBG("id=%d", pll_28nm->id);
+
+	/*
+	 * before enabling the PLL, configure the bit clock divider since we
+	 * don't expose it as a clock to the outside world
+	 * 1: read back the byte clock divider that should aready be set

s/aready/already/

Quoted 8 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +8 -0
+	 * 2: divide by 8 to get bit clock divider
+	 * 3: write it to POSTDIV1
+	 */
+	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
+	byte_div = val + 1;
+	bit_div = byte_div / 8;
+
+	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);

[..]

Quoted 5 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +5 -0
+
+static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	int i;

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 415

Quoted 10 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +10 -0
+
+	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,
+					pll_28nm->clks, pll_28nm->num_clks);
+
+	for (i = 0; i < NUM_PROVIDED_CLKS; i++)
+		pll_28nm->provided_clks[i] = NULL;
+
+	pll_28nm->num_clks = 0;
+	pll_28nm->clk_data.clks = NULL;
+	pll_28nm->clk_data.clk_num = 0;

Is all this really necessary?

Quoted 6 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +6 -0
+}
+
+static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
+{
+	char clk_name[32], parent[32], vco_name[32];
+	struct clk_init_data vco_init = {

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 431

Quoted 10 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +10 -0
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.name = vco_name,
+		.ops = &clk_ops_dsi_pll_28nm_vco,
+	};
+	struct device *dev = &pll_28nm->pdev->dev;
+	struct clk **clks = pll_28nm->clks;
+	struct clk **provided_clks = pll_28nm->provided_clks;
+	struct clk_bytediv *bytediv;
+	struct clk_init_data bytediv_init;
	struct clk_init_data bytediv_init = { };

Just in case we add some new field there?

Quoted 16 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +16 -0
+	int ret, num = 0;
+
+	DBG("%d", pll_28nm->id);
+
+	bytediv = devm_kzalloc(dev, sizeof(*bytediv), GFP_KERNEL);
+	if (!bytediv)
+		return -ENOMEM;
+
+	pll_28nm->bytediv = bytediv;
+
+	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);
+	pll_28nm->base.clk_hw.init = &vco_init;
+
+	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);
+
+	/* prepare and register bytediv */

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 457

Quoted 10 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +10 -0
+	bytediv->hw.init = &bytediv_init;
+	bytediv->reg = pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_9;
+
+	snprintf(parent, 32, "dsi%dvco_clk", pll_28nm->id);
+	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
+
+	bytediv_init.name = clk_name;
+	bytediv_init.ops = &clk_bytediv_ops;
+	bytediv_init.flags = CLK_SET_RATE_PARENT;
+	bytediv_init.parent_names = (const char *[]) { parent };

Can't we just do &parent instead of this anonymous array?

Quoted 3 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +3 -0
+	bytediv_init.num_parents = 1;
+
+	/* DIV2 */
Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#5 lore raw

Re: [PATCH 03/12] drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY

Quoted 15 lines · Stephen Boyd
Quoted 14 lines · Archit Taneja
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +8 -0
new file mode 100644
index 0000000..e71b4ee
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
Quoted 8 lines

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 14

Quoted 6 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +6 -0
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>

Is this include used?

It isn't. I'll remove it.

Quoted 8 lines
Quoted 7 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +6 -0
+#include <linux/clk-provider.h>
+
+#include "dsi_pll.h"
+#include "dsi.xml.h"
+
+/*

[..]

Quoted 8 lines

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 96

Quoted 5 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +5 -0
+
+#define to_pll_28nm(x)	container_of(x, struct dsi_pll_28nm, base)
+
+static bool pll_28nm_poll_for_ready(struct dsi_pll_28nm *pll_28nm,
+				    u32 nb_tries, u32 timeout_us)

Why not use unsigned types for these counts? I don't imagine we care about being precisely 32 bits.

Yeah. We don't even need an unsigned type. I'll replace it with integer type.

Quoted 6 lines
Quoted 5 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +4 -0
+{
+	bool pll_locked = false;
+	u32 val;
+

[..]

Quoted 8 lines

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 311

Quoted 6 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +6 -0
+	DBG("id=%d", pll_28nm->id);
+
+	/*
+	 * before enabling the PLL, configure the bit clock divider since we
+	 * don't expose it as a clock to the outside world
+	 * 1: read back the byte clock divider that should aready be set

s/aready/already/

Thanks, I'll fix this.

Quoted 19 lines
Quoted 9 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +8 -0
+	 * 2: divide by 8 to get bit clock divider
+	 * 3: write it to POSTDIV1
+	 */
+	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_9);
+	byte_div = val + 1;
+	bit_div = byte_div / 8;
+
+	val = pll_read(base + REG_DSI_28nm_8960_PHY_PLL_CTRL_8);

[..]

Quoted 9 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +9 -0
+
+static void dsi_pll_28nm_destroy(struct msm_dsi_pll *pll)
+{
+	struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+	int i;
+
+	msm_dsi_pll_helper_unregister_clks(pll_28nm->pdev,
+					pll_28nm->clks, pll_28nm->num_clks);
+
Quoted 8 lines

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 415

Quoted 6 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +6 -0
+	for (i = 0; i < NUM_PROVIDED_CLKS; i++)
+		pll_28nm->provided_clks[i] = NULL;
+
+	pll_28nm->num_clks = 0;
+	pll_28nm->clk_data.clks = NULL;
+	pll_28nm->clk_data.clk_num = 0;

Is all this really necessary?

It isn't. I copy pasted from dsi_pll_28nm.c and it had this. Will make a patch to remove it from that file too.

Quoted 21 lines
Quoted 7 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +6 -0
+}
+
+static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
+{
+	char clk_name[32], parent[32], vco_name[32];
+	struct clk_init_data vco_init = {

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 431

Quoted 10 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +10 -0
+		.parent_names = (const char *[]){ "pxo" },
+		.num_parents = 1,
+		.name = vco_name,
+		.ops = &clk_ops_dsi_pll_28nm_vco,
+	};
+	struct device *dev = &pll_28nm->pdev->dev;
+	struct clk **clks = pll_28nm->clks;
+	struct clk **provided_clks = pll_28nm->provided_clks;
+	struct clk_bytediv *bytediv;
+	struct clk_init_data bytediv_init;
	struct clk_init_data bytediv_init = { };
Quoted 1 line

Just in case we add some new field there?

Will do.

Quoted 21 lines
Quoted 21 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +20 -0
+	int ret, num = 0;
+
+	DBG("%d", pll_28nm->id);
+
+	bytediv = devm_kzalloc(dev, sizeof(*bytediv), GFP_KERNEL);
+	if (!bytediv)
+		return -ENOMEM;
+
+	pll_28nm->bytediv = bytediv;
+
+	snprintf(vco_name, 32, "dsi%dvco_clk", pll_28nm->id);
+	pll_28nm->base.clk_hw.init = &vco_init;
+
+	clks[num++] = clk_register(dev, &pll_28nm->base.clk_hw);
+
+	/* prepare and register bytediv */
+	bytediv->hw.init = &bytediv_init;
+	bytediv->reg = pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_9;
+
+	snprintf(parent, 32, "dsi%dvco_clk", pll_28nm->id);
Quoted 8 lines

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 457

Quoted 6 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +6 -0
+	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
+
+	bytediv_init.name = clk_name;
+	bytediv_init.ops = &clk_bytediv_ops;
+	bytediv_init.flags = CLK_SET_RATE_PARENT;
+	bytediv_init.parent_names = (const char *[]) { parent };

Can't we just do &parent instead of this anonymous array?

&parent doesn't make sense here. parent in this function is an array of characters, not a pointer to a character.

I can think of only this way. We do something similar when we call clk_register_mux() in dsi_pll_28nm.c.

Archit

Quoted 5 lines
Quoted 4 lines
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +3 -0
+	bytediv_init.num_parents = 1;
+
+	/* DIV2 */
Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#6 lore raw

Re: [PATCH 03/12] drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY

Quoted 17 lines · Archit Taneja
Quoted 13 lines · Stephen Boyd

drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c line 457

Quoted 10 lines · Archit Taneja
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +10 -0
+	bytediv->hw.init = &bytediv_init;
+	bytediv->reg = pll_28nm->mmio + REG_DSI_28nm_8960_PHY_PLL_CTRL_9;
+
+	snprintf(parent, 32, "dsi%dvco_clk", pll_28nm->id);
+	snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
+
+	bytediv_init.name = clk_name;
+	bytediv_init.ops = &clk_bytediv_ops;
+	bytediv_init.flags = CLK_SET_RATE_PARENT;
+	bytediv_init.parent_names = (const char *[]) { parent };

Can't we just do &parent instead of this anonymous array?

Quoted 6 lines

&parent doesn't make sense here. parent in this function is an array of characters, not a pointer to a character.

I can think of only this way. We do something similar when we call clk_register_mux() in dsi_pll_28nm.c.

Oh I missed that. Why not allocate the strings instead of putting them on the stack?

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#7 lore raw

PATCH 4/12 drm/msm/dsi: Use a better way to figure out DSI version

In reply to Archit Taneja

The current version checking mechanism works fine for DSI6G blocks. It doesn't work so well for older generation DSIv2 blocks.

The initial read of REG_DSI_6G_HW_VERSION(offset 0x0) would result in a read of REG_DSI_CTRL for DSIv2. This register won't necessarily be 0 on DSIv2. It can be non zero if DSI was previously initialized by the bootloader.

Instead of reading offset 0x0, we now read offset 0x1f0. For DSIv2, this register is DSI_VERSION, and is bound to be non-zero. On DSI6G, this register(offset 0x1f0) is SCRATCH_REGISTER_0, which no one ever seems to touch, and from all register dumps I'vc seen, holds 0 all the time.

Modify dsi_get_version to read REG_DSI_VERSION to determine whether we are DSI6G or DSIv2.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +18 -6
index 8d82973f..f26e8be 100644
@@ -33,17 +33,24 @@
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 {
 	u32 ver;
-	u32 ver_6g;
 
 	if (!major || !minor)
 		return -EINVAL;
 
-	/* From DSI6G(v3), addition of a 6G_HW_VERSION register at offset 0
+	/*
+	 * From DSI6G(v3), addition of a 6G_HW_VERSION register at offset 0
 	 * makes all other registers 4-byte shifted down.
+	 *
+	 * In order to identify between DSI6G(v3) and beyond, and DSIv2 and
+	 * older, we read the DSI_VERSION register without any shift(offset
+	 * 0x1f0). In the case of DSIv2, this hast to be a non-zero value. In
+	 * the case of DSI6G, this has to be zero (the offset points to a
+	 * scratch register which we never touch)
 	 */
-	ver_6g = msm_readl(base + REG_DSI_6G_HW_VERSION);
-	if (ver_6g == 0) {
-		ver = msm_readl(base + REG_DSI_VERSION);
+
+	ver = msm_readl(base + REG_DSI_VERSION);
+	if (ver) {
+		/* older dsi host, there is no register shift */
 		ver = FIELD(ver, DSI_VERSION_MAJOR);
 		if (ver <= MSM_DSI_VER_MAJOR_V2) {
 			/* old versions */
@@ -54,12 +61,17 @@ static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 			return -EINVAL;
 		}
 	} else {
+		/*
+		 * newer host, offset 0 has 6G_HW_VERSION, the rest of the
+		 * registers are shifted down, read DSI_VERSION again with
+		 * the shifted offset
+		 */
 		ver = msm_readl(base + DSI_6G_REG_SHIFT + REG_DSI_VERSION);
 		ver = FIELD(ver, DSI_VERSION_MAJOR);
 		if (ver == MSM_DSI_VER_MAJOR_6G) {
 			/* 6G version */
 			*major = ver;
-			*minor = ver_6g;
+			*minor = msm_readl(base + REG_DSI_6G_HW_VERSION);
 			return 0;
 		} else {
 			return -EINVAL;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#8 lore raw

PATCH 5/12 drm/msm/dsi: Delay dsi_clk_init

In reply to Archit Taneja

Initialize clocks only after we get the DSI host version. This will allow us to get clocks using a pre-defined list based on the DSI major/minor version of the host. This is required since clock requirements of different major DSI revisions(v2 vs 6g) aren't the same.

Modify dsi_get_version to get the interface clock, and then put it after it is used.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +22 -10
index f26e8be..12ac3bc3 100644
@@ -177,21 +177,31 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
 						struct msm_dsi_host *msm_host)
 {
 	const struct msm_dsi_cfg_handler *cfg_hnd = NULL;
+	struct device *dev = &msm_host->pdev->dev;
 	struct regulator *gdsc_reg;
+	struct clk *ahb_clk;
 	int ret;
 	u32 major = 0, minor = 0;
 
-	gdsc_reg = regulator_get(&msm_host->pdev->dev, "gdsc");
+	gdsc_reg = regulator_get(dev, "gdsc");
 	if (IS_ERR(gdsc_reg)) {
 		pr_err("%s: cannot get gdsc\n", __func__);
 		goto exit;
 	}
+
+	ahb_clk = clk_get(dev, "iface_clk");
+	if (IS_ERR(ahb_clk)) {
+		pr_err("%s: cannot get interface clock\n", __func__);
+		goto put_gdsc;
+	}
+
 	ret = regulator_enable(gdsc_reg);
 	if (ret) {
 		pr_err("%s: unable to enable gdsc\n", __func__);
-		goto put_gdsc;
+		goto put_clk;
 	}
-	ret = clk_prepare_enable(msm_host->ahb_clk);
+
+	ret = clk_prepare_enable(ahb_clk);
 	if (ret) {
 		pr_err("%s: unable to enable ahb_clk\n", __func__);
 		goto disable_gdsc;
@@ -208,9 +218,11 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
 	DBG("%s: Version %x:%x\n", __func__, major, minor);
 
 disable_clks:
-	clk_disable_unprepare(msm_host->ahb_clk);
+	clk_disable_unprepare(ahb_clk);
 disable_gdsc:
 	regulator_disable(gdsc_reg);
+put_clk:
+	clk_put(ahb_clk);
 put_gdsc:
 	regulator_put(gdsc_reg);
 exit:
@@ -1420,12 +1432,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 		goto fail;
 	}
 
-	ret = dsi_clk_init(msm_host);
-	if (ret) {
-		pr_err("%s: unable to initialize dsi clks\n", __func__);
-		goto fail;
-	}
-
 	msm_host->ctrl_base = msm_ioremap(pdev, "dsi_ctrl", "DSI CTRL");
 	if (IS_ERR(msm_host->ctrl_base)) {
 		pr_err("%s: unable to map Dsi ctrl base\n", __func__);
@@ -1449,6 +1455,12 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 		goto fail;
 	}
 
+	ret = dsi_clk_init(msm_host);
+	if (ret) {
+		pr_err("%s: unable to initialize dsi clks\n", __func__);
+		goto fail;
+	}
+
 	msm_host->rx_buf = devm_kzalloc(&pdev->dev, SZ_4K, GFP_KERNEL);
 	if (!msm_host->rx_buf) {
 		pr_err("%s: alloc rx temp buf failed\n", __func__);
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#9 lore raw

PATCH 6/12 drm/msm/dsi: Parse bus clocks from a list

In reply to Archit Taneja

DSI bus clocks seem to vary between different DSI host versions, and the SOC to which they belong. Even the enable/disable sequence varies.

Provide a list of bus clock names in dsi_cfg. The driver will use this to retrieve the clocks, and enable/disable them.

Add bus clock lists for DSI6G, and DSI for MSM8916(this is DSI6G too, but there is no MMSS_CC specific clock since there is no MMSS clock controller on 8916).

---
 drivers/gpu/drm/msm/dsi/dsi.h      |   1 +
 drivers/gpu/drm/msm/dsi/dsi_cfg.c  |  16 +++++-
 drivers/gpu/drm/msm/dsi/dsi_cfg.h  |   2 +
 drivers/gpu/drm/msm/dsi/dsi_host.c | 107 ++++++++++++-------------------------
 4 files changed, 53 insertions(+), 73 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.h +1 -0
index 8140e8b..7336b55 100644
@@ -36,6 +36,7 @@ enum msm_dsi_phy_type {
 };
 
 #define DSI_DEV_REGULATOR_MAX	8
+#define DSI_BUS_CLK_MAX		4
 
 /* Regulators for DSI devices */
 struct dsi_reg_entry {
drivers/gpu/drm/msm/dsi/dsi_cfg.c +15 -1
index 5872d5e..c40044f 100644
@@ -18,6 +18,10 @@ static const struct msm_dsi_config dsi_v2_cfg = {
 	.io_offset = 0,
 };
 
+static const char * const dsi_6g_bus_clk_names[] = {
+	"mdp_core_clk", "iface_clk", "bus_clk", "core_mmss_clk",
+};
+
 static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
 	.io_offset = DSI_6G_REG_SHIFT,
 	.reg_cfg = {
@@ -29,6 +33,12 @@ static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
 			{"vddio", 1800000, 1800000, 100000, 100},
 		},
 	},
+	.bus_clk_names = dsi_6g_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names),
+};
+
+static const char * const dsi_8916_bus_clk_names[] = {
+	"mdp_core_clk", "iface_clk", "bus_clk",
 };
 
 static const struct msm_dsi_config msm8916_dsi_cfg = {
@@ -42,6 +52,8 @@ static const struct msm_dsi_config msm8916_dsi_cfg = {
 			{"vddio", 1800000, 1800000, 100000, 100},
 		},
 	},
+	.bus_clk_names = dsi_8916_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_8916_bus_clk_names),
 };
 
 static const struct msm_dsi_config msm8994_dsi_cfg = {
@@ -57,7 +69,9 @@ static const struct msm_dsi_config msm8994_dsi_cfg = {
 			{"lab_reg", -1, -1, -1, -1},
 			{"ibb_reg", -1, -1, -1, -1},
 		},
-	}
+	},
+	.bus_clk_names = dsi_6g_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names),
 };
 
 static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
drivers/gpu/drm/msm/dsi/dsi_cfg.h +2 -0
index 4cf8872..5a36836 100644
@@ -30,6 +30,8 @@
 struct msm_dsi_config {
 	u32 io_offset;
 	struct dsi_reg_config reg_cfg;
+	const char * const *bus_clk_names;
+	const int num_bus_clks;
 };
 
 struct msm_dsi_cfg_handler {
drivers/gpu/drm/msm/dsi/dsi_host.c +35 -72

140 lines not on this page · raw message

Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#10 lore raw

PATCH 7/12 drm/msm/dsi: Set up link clocks for DSIv2

In reply to Archit Taneja

DSIv2 (DSI on older A family chips) has slightly different link clock requirements.

First, we have an extra clock called src_clk (with a dedicated RCG). This is required by the DSI controller to process the pixel data coming from MDP. It needs to be set at the rate "pclk * bytes_per_pixel".

We also need to explicitly configure esc_clk. On DSI6G chips, we don't need to set a rate to esc_clk because its RCG is always sourced from crystal clock (19.2 Mhz in all cases), which is within the escape clock frequency range in the mipi DSI spec. For chips with DSIv2, the crystal clock rate may not be within the required range (27Mhz on APQ8064). Therefore, we derive it from the DSI byte clock. We calculate an esc_clck rate that is within the mipi spec and also divisible by the byte clock rate.

When setting rate and enabling the link clocks, we make sure that byte_clk is configured before esc_clk, and src_clk before pixel_clk. We create two different link_enable funcs for DSI6G and DSIv2 since the sequences are different.

We also obtain two extra source clocks (dsi_src_clk and esc_src_clk) and set their parent to the clocks provided by DSI PLL.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 193 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 188 insertions(+), 5 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +188 -5
index 008726f..16c5cfb 100644
@@ -113,6 +113,14 @@ struct msm_dsi_host {
 	struct clk *pixel_clk_src;
 
 	u32 byte_clk_rate;
+	u32 esc_clk_rate;
+
+	/* DSI v2 specific clocks */
+	struct clk *src_clk;
+	struct clk *esc_clk_src;
+	struct clk *dsi_clk_src;
+
+	u32 src_clk_rate;
 
 	struct gpio_desc *disp_en_gpio;
 	struct gpio_desc *te_gpio;
@@ -318,7 +326,8 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host)
 static int dsi_clk_init(struct msm_dsi_host *msm_host)
 {
 	struct device *dev = &msm_host->pdev->dev;
-	const struct msm_dsi_config *cfg = msm_host->cfg_hnd->cfg;
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
+	const struct msm_dsi_config *cfg = cfg_hnd->cfg;
 	int i, ret = 0;
 
 	/* get bus clocks */
@@ -377,6 +386,34 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host)
 		goto exit;
 	}
 
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) {
+		msm_host->src_clk = devm_clk_get(dev, "src_clk");
+		if (IS_ERR(msm_host->src_clk)) {
+			ret = PTR_ERR(msm_host->src_clk);
+			pr_err("%s: can't find dsi_src_clk. ret=%d\n",
+				__func__, ret);
+			msm_host->src_clk = NULL;
+			goto exit;
+		}
+
+		msm_host->esc_clk_src = devm_clk_get(dev, "esc_clk_src");
+		if (IS_ERR(msm_host->esc_clk_src)) {
+			ret = PTR_ERR(msm_host->esc_clk_src);
+			pr_err("%s: can't find esc_clk_src. ret=%d\n",
+				__func__, ret);
+			msm_host->esc_clk_src = NULL;
+			goto exit;
+		}
+
+		msm_host->dsi_clk_src = devm_clk_get(dev, "dsi_clk_src");
+		if (IS_ERR(msm_host->dsi_clk_src)) {
+			ret = PTR_ERR(msm_host->dsi_clk_src);
+			pr_err("%s: can't find dsi_clk_src. ret=%d\n",
+				__func__, ret);
+			msm_host->dsi_clk_src = NULL;
+			goto exit;
+		}
+	}
 exit:
 	return ret;
 }
@@ -416,7 +453,7 @@ static void dsi_bus_clk_disable(struct msm_dsi_host *msm_host)
 		clk_disable_unprepare(msm_host->bus_clks[i]);
 }
 
-static int dsi_link_clk_enable(struct msm_dsi_host *msm_host)
+static int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host)
 {
 	int ret;
 
@@ -463,11 +500,98 @@ error:
 	return ret;
 }
 
-static void dsi_link_clk_disable(struct msm_dsi_host *msm_host)
+static int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host)
 {
+	int ret;
+
+	DBG("Set clk rates: pclk=%d, byteclk=%d, esc_clk=%d, dsi_src_clk=%d",
+		msm_host->mode->clock, msm_host->byte_clk_rate,
+		msm_host->esc_clk_rate, msm_host->src_clk_rate);
+
+	ret = clk_set_rate(msm_host->byte_clk, msm_host->byte_clk_rate);
+	if (ret) {
+		pr_err("%s: Failed to set rate byte clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_set_rate(msm_host->esc_clk, msm_host->esc_clk_rate);
+	if (ret) {
+		pr_err("%s: Failed to set rate esc clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_set_rate(msm_host->src_clk, msm_host->src_clk_rate);
+	if (ret) {
+		pr_err("%s: Failed to set rate src clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000);
+	if (ret) {
+		pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_prepare_enable(msm_host->byte_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi byte clk\n", __func__);
+		goto error;
+	}
+
+	ret = clk_prepare_enable(msm_host->esc_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi esc clk\n", __func__);
+		goto esc_clk_err;
+	}
+
+	ret = clk_prepare_enable(msm_host->src_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi src clk\n", __func__);
+		goto src_clk_err;
+	}
+
+	ret = clk_prepare_enable(msm_host->pixel_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi pixel clk\n", __func__);
+		goto pixel_clk_err;
+	}
+
+	return 0;
+
+pixel_clk_err:
+	clk_disable_unprepare(msm_host->src_clk);
+src_clk_err:
 	clk_disable_unprepare(msm_host->esc_clk);
-	clk_disable_unprepare(msm_host->pixel_clk);
+esc_clk_err:
 	clk_disable_unprepare(msm_host->byte_clk);
+error:
+	return ret;
+}
+
+static int dsi_link_clk_enable(struct msm_dsi_host *msm_host)
+{
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
+
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G)
+		return dsi_link_clk_enable_6g(msm_host);
+	else
+		return dsi_link_clk_enable_v2(msm_host);
+}
+
+static void dsi_link_clk_disable(struct msm_dsi_host *msm_host)
+{
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
+
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) {
+		clk_disable_unprepare(msm_host->esc_clk);
+		clk_disable_unprepare(msm_host->pixel_clk);
+		clk_disable_unprepare(msm_host->byte_clk);
+	} else {
+		clk_disable_unprepare(msm_host->pixel_clk);
+		clk_disable_unprepare(msm_host->src_clk);
+		clk_disable_unprepare(msm_host->esc_clk);
+		clk_disable_unprepare(msm_host->byte_clk);
+	}
 }
 
 static int dsi_clk_ctrl(struct msm_dsi_host *msm_host, bool enable)
@@ -502,6 +626,7 @@ unlock_ret:
 static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host)
 {
 	struct drm_display_mode *mode = msm_host->mode;
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
 	u8 lanes = msm_host->lanes;
 	u32 bpp = dsi_get_bpp(msm_host->format);
 	u32 pclk_rate;
@@ -521,6 +646,47 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host)
 
 	DBG("pclk=%d, bclk=%d", pclk_rate, msm_host->byte_clk_rate);
 
+	msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk);
+
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) {
+		unsigned int esc_mhz, esc_div;
+		unsigned long byte_mhz;
+
+		msm_host->src_clk_rate = (pclk_rate * bpp) / 8;
+
+		/*
+		 * esc clock is byte clock followed by a 4 bit divider,
+		 * we need to find an escape clock frequency within the
+		 * mipi DSI spec range within the maximum divider limit
+		 * We iterate here between an escape clock frequencey
+		 * between 20 Mhz to 5 Mhz and pick up the first one
+		 * that can be supported by our divider
+		 */
+
+		byte_mhz = msm_host->byte_clk_rate / 1000000;
+
+		for (esc_mhz = 20; esc_mhz >= 5; esc_mhz--) {
+			esc_div = DIV_ROUND_UP(byte_mhz, esc_mhz);
+
+			/*
+			 * TODO: Ideally, we shouldn't know what sort of divider
+			 * is available in mmss_cc, we're just assuming that
+			 * it'll always be a 4 bit divider. Need to come up with
+			 * a better way here.
+			 */
+			if (esc_div >= 1 && esc_div <= 16)
+				break;
+		}
+
+		if (esc_mhz < 5)
+			return -EINVAL;
+
+		msm_host->esc_clk_rate = msm_host->byte_clk_rate / esc_div;
+
+		DBG("esc=%d, src=%d", msm_host->esc_clk_rate,
+			msm_host->src_clk_rate);
+	}
+
 	return 0;
 }
 
@@ -1753,6 +1919,7 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
 	struct msm_dsi_pll *src_pll)
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
 	struct clk *byte_clk_provider, *pixel_clk_provider;
 	int ret;
 
@@ -1778,6 +1945,22 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
 		goto exit;
 	}
 
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) {
+		ret = clk_set_parent(msm_host->dsi_clk_src, pixel_clk_provider);
+		if (ret) {
+			pr_err("%s: can't set parent to dsi_clk_src. ret=%d\n",
+				__func__, ret);
+			goto exit;
+		}
+
+		ret = clk_set_parent(msm_host->esc_clk_src, byte_clk_provider);
+		if (ret) {
+			pr_err("%s: can't set parent to esc_clk_src. ret=%d\n",
+				__func__, ret);
+			goto exit;
+		}
+	}
+
 exit:
 	return ret;
 }
@@ -1849,7 +2032,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 	dsi_phy_sw_reset(msm_host);
 	ret = msm_dsi_manager_phy_enable(msm_host->id,
 					msm_host->byte_clk_rate * 8,
-					clk_get_rate(msm_host->esc_clk),
+					msm_host->esc_clk_rate,
 					&clk_pre, &clk_post);
 	dsi_bus_clk_disable(msm_host);
 	if (ret) {
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#11 lore raw

PATCH 8/12 drm/msm/dsi: Add dsi_cfg for APQ8064

In reply to Archit Taneja

Add a dsi_cfg entry for APQ8064. Since this is the first DSIv2 chip to be supported, add a list of bus clocks that are required by the DSIv2 block.

---
 drivers/gpu/drm/msm/dsi/dsi_cfg.c | 19 ++++++++++++++++---
 drivers/gpu/drm/msm/dsi/dsi_cfg.h |  2 ++
 2 files changed, 18 insertions(+), 3 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_cfg.c +16 -3
index c40044f..2a827d8 100644
@@ -13,9 +13,22 @@
 
 #include "dsi_cfg.h"
 
-/* DSI v2 has not been supported by now */
-static const struct msm_dsi_config dsi_v2_cfg = {
+static const char * const dsi_v2_bus_clk_names[] = {
+	"core_mmss_clk", "iface_clk", "bus_clk",
+};
+
+static const struct msm_dsi_config apq8064_dsi_cfg = {
 	.io_offset = 0,
+	.reg_cfg = {
+		.num = 3,
+		.regs = {
+			{"vdda", 1200000, 1200000, 100000, 100},
+			{"avdd", 3000000, 3000000, 110000, 100},
+			{"vddio", 1800000, 1800000, 100000, 100},
+		},
+	},
+	.bus_clk_names = dsi_v2_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_v2_bus_clk_names),
 };
 
 static const char * const dsi_6g_bus_clk_names[] = {
@@ -75,7 +88,7 @@ static const struct msm_dsi_config msm8994_dsi_cfg = {
 };
 
 static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
-	{MSM_DSI_VER_MAJOR_V2, U32_MAX, &dsi_v2_cfg},
+	{MSM_DSI_VER_MAJOR_V2, MSM_DSI_V2_VER_MINOR_8064, &apq8064_dsi_cfg},
 	{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0,
 						&msm8974_apq8084_dsi_cfg},
 	{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1,
drivers/gpu/drm/msm/dsi/dsi_cfg.h +2 -0
index 5a36836..a68c836 100644
@@ -25,6 +25,8 @@
 #define MSM_DSI_6G_VER_MINOR_V1_3	0x10030000
 #define MSM_DSI_6G_VER_MINOR_V1_3_1	0x10030001
 
+#define MSM_DSI_V2_VER_MINOR_8064	0x0
+
 #define DSI_6G_REG_SHIFT	4
 
 struct msm_dsi_config {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#12 lore raw

PATCH 9/12 drm/msm/dsi: Don't use iommu for command TX buffer for DSIv2

In reply to Archit Taneja

We currently use iommu allocated DMA buffers for sending DSI commands. DSIv2 doesn't have a port connected to the MDP iommu. Therefore, it can't use iommu allocated buffers to fetch DSI commands.

Use a regular contiguous DMA buffer if we are DSIv2.

---
 drivers/gpu/drm/msm/dsi/dsi.h         |   4 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c    | 110 +++++++++++++++++++++++-----------
 drivers/gpu/drm/msm/dsi/dsi_manager.c |   6 +-
 3 files changed, 79 insertions(+), 41 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.h +2 -2
index 7336b55..749fbb2 100644
@@ -91,7 +91,7 @@ int msm_dsi_manager_phy_enable(int id,
 		u32 *clk_pre, u32 *clk_post);
 void msm_dsi_manager_phy_disable(int id);
 int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg);
-bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len);
+bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len);
 int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
 void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
 
@@ -145,7 +145,7 @@ int msm_dsi_host_cmd_tx(struct mipi_dsi_host *host,
 int msm_dsi_host_cmd_rx(struct mipi_dsi_host *host,
 					const struct mipi_dsi_msg *msg);
 void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host,
-					u32 iova, u32 len);
+					u32 dma_base, u32 len);
 int msm_dsi_host_enable(struct mipi_dsi_host *host);
 int msm_dsi_host_disable(struct mipi_dsi_host *host);
 int msm_dsi_host_power_on(struct mipi_dsi_host *host);
drivers/gpu/drm/msm/dsi/dsi_host.c +74 -36

183 lines not on this page · raw message

drivers/gpu/drm/msm/dsi/dsi_manager.c +3 -3
index 0455ff7..58ba7ec 100644
@@ -774,7 +774,7 @@ restore_host0:
 	return ret;
 }
 
-bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len)
+bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len)
 {
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 	struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
@@ -784,9 +784,9 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len)
 		return false;
 
 	if (IS_SYNC_NEEDED() && msm_dsi0)
-		msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, iova, len);
+		msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, dma_base, len);
 
-	msm_dsi_host_cmd_xfer_commit(host, iova, len);
+	msm_dsi_host_cmd_xfer_commit(host, dma_base, len);
 
 	return true;
 }
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#13 lore raw

PATCH 10/12 drm/msm/dsi: SFPB: Update generated headers

In reply to Archit Taneja

Update SFPB register data now that we intend to use it.

---
 drivers/gpu/drm/msm/dsi/sfpb.xml.h | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)
drivers/gpu/drm/msm/dsi/sfpb.xml.h +14 -12
index 06cbddf..63947b2 100644
@@ -8,17 +8,8 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    676 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2015-05-20 20:03:07)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  20915 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   2576 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  36021 bytes, from 2015-07-09 22:10:24)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  26057 bytes, from 2015-08-14 21:47:57)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2015-05-20 20:03:07)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1686 bytes, from 2015-05-20 20:03:14)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2015-05-20 20:03:07)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  29154 bytes, from 2015-08-10 21:25:43)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml             (  10416 bytes, from 2015-05-20 20:03:14)
+- /local/mnt/workspace/source_trees/envytools/rnndb/../rnndb/dsi/sfpb.xml   (    602 bytes, from 2015-10-14 11:09:08)
+- /local/mnt/workspace/source_trees/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2015-02-09 03:18:10)
 
 Copyright (C) 2013-2015 by the following authors:
 - Rob Clark <[email protected]> (robclark)
@@ -45,7 +36,18 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
 
 
-#define REG_SFPB_CFG						0x00000058
+enum sfpb_ahb_arb_master_port_en {
+	SFPB_MASTER_PORT_ENABLE = 3,
+	SFPB_MASTER_PORT_DISABLE = 0,
+};
+
+#define REG_SFPB_GPREG						0x00000058
+#define SFPB_GPREG_MASTER_PORT_EN__MASK				0x00001800
+#define SFPB_GPREG_MASTER_PORT_EN__SHIFT			11
+static inline uint32_t SFPB_GPREG_MASTER_PORT_EN(enum sfpb_ahb_arb_master_port_en val)
+{
+	return ((val) << SFPB_GPREG_MASTER_PORT_EN__SHIFT) & SFPB_GPREG_MASTER_PORT_EN__MASK;
+}
 
 
 #endif /* SFPB_XML */
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#14 lore raw

PATCH 11/12 drm/msm/dsi: Enable MMSS SPFB port via syscon

In reply to Archit Taneja

For DSIv2 to work, we need to enable MMSS_AHB_ARB_MASTER_PORT in MMSS_SFPB. We enable the required bitfield by retrieving MMSS_SFPB regmap pointer via syscon.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
drivers/gpu/drm/msm/dsi/dsi_host.c +33 -0
index 006591d..5f3142a 100644
@@ -24,10 +24,13 @@
 #include <linux/of_graph.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spinlock.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 #include <video/mipi_display.h>
 
 #include "dsi.h"
 #include "dsi.xml.h"
+#include "sfpb.xml.h"
 #include "dsi_cfg.h"
 
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
@@ -149,6 +152,8 @@ struct msm_dsi_host {
 
 	u8 *rx_buf;
 
+	struct regmap *sfpb;
+
 	struct drm_display_mode *mode;
 
 	/* connected device info */
@@ -1573,6 +1578,16 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 
 	msm_host->device_node = device_node;
 
+	if (of_property_read_bool(np, "syscon-sfpb")) {
+		msm_host->sfpb = syscon_regmap_lookup_by_phandle(np,
+					"syscon-sfpb");
+		if (IS_ERR(msm_host->sfpb)) {
+			dev_err(dev, "%s: failed to get sfpb regmap\n",
+				__func__);
+			return PTR_ERR(msm_host->sfpb);
+		}
+	}
+
 	return 0;
 }
 
@@ -2036,6 +2051,20 @@ int msm_dsi_host_disable(struct mipi_dsi_host *host)
 	return 0;
 }
 
+static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable)
+{
+	enum sfpb_ahb_arb_master_port_en en;
+
+	if (!msm_host->sfpb)
+		return;
+
+	en = enable ? SFPB_MASTER_PORT_ENABLE : SFPB_MASTER_PORT_DISABLE;
+
+	regmap_update_bits(msm_host->sfpb, REG_SFPB_GPREG,
+			SFPB_GPREG_MASTER_PORT_EN__MASK,
+			SFPB_GPREG_MASTER_PORT_EN(en));
+}
+
 int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
@@ -2048,6 +2077,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 		goto unlock_ret;
 	}
 
+	msm_dsi_sfpb_config(msm_host, true);
+
 	ret = dsi_calc_clk_rate(msm_host);
 	if (ret) {
 		pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
@@ -2135,6 +2166,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)
 
 	dsi_host_regulator_disable(msm_host);
 
+	msm_dsi_sfpb_config(msm_host, false);
+
 	DBG("-");
 
 	msm_host->power_on = false;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#15 lore raw

PATCH 12/12 dt-bindings: Add DSIv2 documentation

In reply to Archit Taneja

Add additional property info needed for DSIv2 DT.

---
 Documentation/devicetree/bindings/drm/msm/dsi.txt | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/drm/msm/dsi.txt +9 -1
index d56923c..75f8492 100644
@@ -13,18 +13,25 @@ Required properties:
 - power-domains: Should be <&mmcc MDSS_GDSC>.
 - clocks: device clocks
   See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
-- clock-names: the following clocks are required:
+- clock-names: these vary based on the DSI version. For DSI6G:
   * "bus_clk"
   * "byte_clk"
+  * "byte_clk_src
   * "core_clk"
   * "core_mmss_clk"
   * "iface_clk"
   * "mdp_core_clk"
   * "pixel_clk"
+  * "pixel_clk_src"
+  For DSIv2, we need a few more:
+   * "dsi_clk_src"
+   * "esc_clk_src"
+   * "src_clk"
 - vdd-supply: phandle to vdd regulator device node
 - vddio-supply: phandle to vdd-io regulator device node
 - vdda-supply: phandle to vdda regulator device node
 - qcom,dsi-phy: phandle to DSI PHY device node
+- syscon-sfpb: A phandle to mmss_sfpb syscon node (only for DSIv2)
 
 Optional properties:
 - panel@0: Node of panel connected to this DSI controller.
@@ -51,6 +58,7 @@ Required properties:
   * "qcom,dsi-phy-28nm-hpm"
   * "qcom,dsi-phy-28nm-lp"
   * "qcom,dsi-phy-20nm"
+  * "qcom,dsi-phy-28nm-8960"
 - reg: Physical base address and length of the registers of PLL, PHY and PHY
   regulator
 - reg-names: The names of register regions. The following regions are required:
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#16 lore raw

v2 cover drm/msm/dsi: Add support for DSI on MSM8960/APQ8064

In reply to Archit Taneja

Add support for DSI on 8960/8064. The DSI IP used in these chips is an older version(DSIv2) of what we have right now(DSI6G).

The bulk of the additions come thanks to a different PHY/PLL. The DSI host in itself doesn't have too many changes.

Changes in v2:
- Incorporated Stephen's comments for the DSI PLL patch.
- The dsi.xml.h and sfpb.xml.h changes were already picked up by Rob. Removed those patches.

Archit Taneja (10):
drm/msm/dsi: Add support for 28nm PHY on 8960 drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY drm/msm/dsi: Use a better way to figure out DSI version drm/msm/dsi: Delay dsi_clk_init
drm/msm/dsi: Parse bus clocks from a list drm/msm/dsi: Set up link clocks for DSIv2 drm/msm/dsi: Add dsi_cfg for APQ8064
drm/msm/dsi: Don't use iommu for command TX buffer for DSIv2 drm/msm/dsi: Enable MMSS SPFB port via syscon
dt-bindings: Add DSIv2 documentation

 .../devicetree/bindings/display/msm/dsi.txt        |  10 +-
 drivers/gpu/drm/msm/Kconfig                        |   8 +
 drivers/gpu/drm/msm/Makefile                       |   2 +
 drivers/gpu/drm/msm/dsi/dsi.h                      |   6 +-
 drivers/gpu/drm/msm/dsi/dsi_cfg.c                  |  35 +-
 drivers/gpu/drm/msm/dsi/dsi_cfg.h                  |   4 +
 drivers/gpu/drm/msm/dsi/dsi_host.c                 | 497 ++++++++++++++-----
 drivers/gpu/drm/msm/dsi/dsi_manager.c              |   6 +-
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c              |   4 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h              |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c    | 195 ++++++++
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c              |   3 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h              |  10 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c    | 533 +++++++++++++++++++++
 14 files changed, 1176 insertions(+), 138 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#17 lore raw

PATCH v2 1/10 drm/msm/dsi: Add support for 28nm PHY on 8960

DSI PHY on MSM8960 and APQ8064 is a 28nm PHY that's different from the supported 28nm LP PHY found in newer chips.

Add support for the new PHY.

---
 drivers/gpu/drm/msm/Kconfig                     |   8 +
 drivers/gpu/drm/msm/Makefile                    |   1 +
 drivers/gpu/drm/msm/dsi/dsi.h                   |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c           |   4 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h           |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 195 ++++++++++++++++++++++++
 6 files changed, 210 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
drivers/gpu/drm/msm/Kconfig +8 -0
index 84d3ec9..215495c 100644
@@ -54,3 +54,11 @@ config DRM_MSM_DSI_20NM_PHY
 	default y
 	help
 	  Choose this option if the 20nm DSI PHY is used on the platform.
+
+config DRM_MSM_DSI_28NM_8960_PHY
+	bool "Enable DSI 28nm 8960 PHY driver in MSM DRM"
+	depends on DRM_MSM_DSI
+	default y
+	help
+	  Choose this option if the 28nm DSI PHY 8960 variant is used on the
+	  platform.
drivers/gpu/drm/msm/Makefile +1 -0
index 1c90290..7523eca 100644
@@ -62,6 +62,7 @@ msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
 
 msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o
 msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o
+msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o
 
 ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)
 msm-y += dsi/pll/dsi_pll.o
drivers/gpu/drm/msm/dsi/dsi.h +1 -0
index 5f5a373..8140e8b 100644
@@ -31,6 +31,7 @@ enum msm_dsi_phy_type {
 	MSM_DSI_PHY_28NM_HPM,
 	MSM_DSI_PHY_28NM_LP,
 	MSM_DSI_PHY_20NM,
+	MSM_DSI_PHY_28NM_8960,
 	MSM_DSI_PHY_MAX
 };
 
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +4 -0
index f1f955f..91a95fb 100644
@@ -277,6 +277,10 @@ static const struct of_device_id dsi_phy_dt_match[] = {
 	{ .compatible = "qcom,dsi-phy-20nm",
 	  .data = &dsi_phy_20nm_cfgs },
 #endif
+#ifdef CONFIG_DRM_MSM_DSI_28NM_8960_PHY
+	{ .compatible = "qcom,dsi-phy-28nm-8960",
+	  .data = &dsi_phy_28nm_8960_cfgs },
+#endif
 	{}
 };
 
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +1 -0
index 0456b25..0d54ed0 100644
@@ -43,6 +43,7 @@ struct msm_dsi_phy_cfg {
 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs;
 
 struct msm_dsi_dphy_timing {
 	u32 clk_pre;
drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c new file +195 -0

195 lines not on this page · raw message

Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#18 lore raw

PATCH v2 2/10 drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY

In reply to Archit Taneja

Add DSI PLL common clock framework clocks for 8960 PHY.

The PLL here is different from the ones found in B family msm chips. As before, the DSI provides two clocks to the outside world. dsixpll and dsixpllbyte (x = 1, 2). dsixpll is a regular clock divider, but dsixpllbyte is modelled as a custom clock divider.

dsixpllbyte is the starting point of the PLL configuration. It is the one that sets up the VCO clock rate. We need the VCO clock rate in the
form: F * byteclk, where F is a multiplication factor that varies on the byte clock the DSI driver is trying to set. We use the custom clk_ops for dsixpllbyte to ensure that the parent (VCO) is set at this rate.

An additional divider (POSTDIV1) generates the bitclk. Since bit clock can be derived from byteclock, we calculate it internally, and don't expose it as a clock.

---
 drivers/gpu/drm/msm/Makefile                    |   1 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c           |   3 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h           |  10 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c | 533 ++++++++++++++++++++++++
 4 files changed, 547 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
drivers/gpu/drm/msm/Makefile +1 -0
index 7523eca..156a93d 100644
@@ -67,6 +67,7 @@ msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o
 ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)
 msm-y += dsi/pll/dsi_pll.o
 msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o
+msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o
 endif
 
 obj-$(CONFIG_DRM_MSM)	+= msm.o
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c +3 -0
index 5104fc9..5cd438f 100644
@@ -151,6 +151,9 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
 	case MSM_DSI_PHY_28NM_LP:
 		pll = msm_dsi_pll_28nm_init(pdev, type, id);
 		break;
+	case MSM_DSI_PHY_28NM_8960:
+		pll = msm_dsi_pll_28nm_8960_init(pdev, id);
+		break;
 	default:
 		pll = ERR_PTR(-ENXIO);
 		break;
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h +10 -0
index 063caa2..80b6038 100644
@@ -93,6 +93,16 @@ static inline struct msm_dsi_pll *msm_dsi_pll_28nm_init(
 	return ERR_PTR(-ENODEV);
 }
 #endif
+#ifdef CONFIG_DRM_MSM_DSI_28NM_8960_PHY
+struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device *pdev,
+					       int id);
+#else
+struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device *pdev,
+					       int id)
+{
+	return ERR_PTR(-ENODEV);
+}
+#endif
 
 #endif /* __DSI_PLL_H__ */
 
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +533 -0

533 lines not on this page · raw message

Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#19 lore raw

PATCH v2 3/10 drm/msm/dsi: Use a better way to figure out DSI version

In reply to Archit Taneja

The current version checking mechanism works fine for DSI6G blocks. It doesn't work so well for older generation DSIv2 blocks.

The initial read of REG_DSI_6G_HW_VERSION(offset 0x0) would result in a read of REG_DSI_CTRL for DSIv2. This register won't necessarily be 0 on DSIv2. It can be non zero if DSI was previously initialized by the bootloader.

Instead of reading offset 0x0, we now read offset 0x1f0. For DSIv2, this register is DSI_VERSION, and is bound to be non-zero. On DSI6G, this register(offset 0x1f0) is SCRATCH_REGISTER_0, which no one ever seems to touch, and from all register dumps I'vc seen, holds 0 all the time.

Modify dsi_get_version to read REG_DSI_VERSION to determine whether we are DSI6G or DSIv2.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +18 -6
index 4c49868..8e8fcc7 100644
@@ -33,17 +33,24 @@
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 {
 	u32 ver;
-	u32 ver_6g;
 
 	if (!major || !minor)
 		return -EINVAL;
 
-	/* From DSI6G(v3), addition of a 6G_HW_VERSION register at offset 0
+	/*
+	 * From DSI6G(v3), addition of a 6G_HW_VERSION register at offset 0
 	 * makes all other registers 4-byte shifted down.
+	 *
+	 * In order to identify between DSI6G(v3) and beyond, and DSIv2 and
+	 * older, we read the DSI_VERSION register without any shift(offset
+	 * 0x1f0). In the case of DSIv2, this hast to be a non-zero value. In
+	 * the case of DSI6G, this has to be zero (the offset points to a
+	 * scratch register which we never touch)
 	 */
-	ver_6g = msm_readl(base + REG_DSI_6G_HW_VERSION);
-	if (ver_6g == 0) {
-		ver = msm_readl(base + REG_DSI_VERSION);
+
+	ver = msm_readl(base + REG_DSI_VERSION);
+	if (ver) {
+		/* older dsi host, there is no register shift */
 		ver = FIELD(ver, DSI_VERSION_MAJOR);
 		if (ver <= MSM_DSI_VER_MAJOR_V2) {
 			/* old versions */
@@ -54,12 +61,17 @@ static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 			return -EINVAL;
 		}
 	} else {
+		/*
+		 * newer host, offset 0 has 6G_HW_VERSION, the rest of the
+		 * registers are shifted down, read DSI_VERSION again with
+		 * the shifted offset
+		 */
 		ver = msm_readl(base + DSI_6G_REG_SHIFT + REG_DSI_VERSION);
 		ver = FIELD(ver, DSI_VERSION_MAJOR);
 		if (ver == MSM_DSI_VER_MAJOR_6G) {
 			/* 6G version */
 			*major = ver;
-			*minor = ver_6g;
+			*minor = msm_readl(base + REG_DSI_6G_HW_VERSION);
 			return 0;
 		} else {
 			return -EINVAL;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#20 lore raw

PATCH v2 4/10 drm/msm/dsi: Delay dsi_clk_init

In reply to Archit Taneja

Initialize clocks only after we get the DSI host version. This will allow us to get clocks using a pre-defined list based on the DSI major/minor version of the host. This is required since clock requirements of different major DSI revisions(v2 vs 6g) aren't the same.

Modify dsi_get_version to get the interface clock, and then put it after it is used.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +22 -10
index 8e8fcc7..cbcf8dd 100644
@@ -177,21 +177,31 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
 						struct msm_dsi_host *msm_host)
 {
 	const struct msm_dsi_cfg_handler *cfg_hnd = NULL;
+	struct device *dev = &msm_host->pdev->dev;
 	struct regulator *gdsc_reg;
+	struct clk *ahb_clk;
 	int ret;
 	u32 major = 0, minor = 0;
 
-	gdsc_reg = regulator_get(&msm_host->pdev->dev, "gdsc");
+	gdsc_reg = regulator_get(dev, "gdsc");
 	if (IS_ERR(gdsc_reg)) {
 		pr_err("%s: cannot get gdsc\n", __func__);
 		goto exit;
 	}
+
+	ahb_clk = clk_get(dev, "iface_clk");
+	if (IS_ERR(ahb_clk)) {
+		pr_err("%s: cannot get interface clock\n", __func__);
+		goto put_gdsc;
+	}
+
 	ret = regulator_enable(gdsc_reg);
 	if (ret) {
 		pr_err("%s: unable to enable gdsc\n", __func__);
-		goto put_gdsc;
+		goto put_clk;
 	}
-	ret = clk_prepare_enable(msm_host->ahb_clk);
+
+	ret = clk_prepare_enable(ahb_clk);
 	if (ret) {
 		pr_err("%s: unable to enable ahb_clk\n", __func__);
 		goto disable_gdsc;
@@ -208,9 +218,11 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
 	DBG("%s: Version %x:%x\n", __func__, major, minor);
 
 disable_clks:
-	clk_disable_unprepare(msm_host->ahb_clk);
+	clk_disable_unprepare(ahb_clk);
 disable_gdsc:
 	regulator_disable(gdsc_reg);
+put_clk:
+	clk_put(ahb_clk);
 put_gdsc:
 	regulator_put(gdsc_reg);
 exit:
@@ -1420,12 +1432,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 		goto fail;
 	}
 
-	ret = dsi_clk_init(msm_host);
-	if (ret) {
-		pr_err("%s: unable to initialize dsi clks\n", __func__);
-		goto fail;
-	}
-
 	msm_host->ctrl_base = msm_ioremap(pdev, "dsi_ctrl", "DSI CTRL");
 	if (IS_ERR(msm_host->ctrl_base)) {
 		pr_err("%s: unable to map Dsi ctrl base\n", __func__);
@@ -1449,6 +1455,12 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 		goto fail;
 	}
 
+	ret = dsi_clk_init(msm_host);
+	if (ret) {
+		pr_err("%s: unable to initialize dsi clks\n", __func__);
+		goto fail;
+	}
+
 	msm_host->rx_buf = devm_kzalloc(&pdev->dev, SZ_4K, GFP_KERNEL);
 	if (!msm_host->rx_buf) {
 		pr_err("%s: alloc rx temp buf failed\n", __func__);
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#21 lore raw

PATCH v2 5/10 drm/msm/dsi: Parse bus clocks from a list

In reply to Archit Taneja

DSI bus clocks seem to vary between different DSI host versions, and the SOC to which they belong. Even the enable/disable sequence varies.

Provide a list of bus clock names in dsi_cfg. The driver will use this to retrieve the clocks, and enable/disable them.

Add bus clock lists for DSI6G, and DSI for MSM8916(this is DSI6G too, but there is no MMSS_CC specific clock since there is no MMSS clock controller on 8916).

---
 drivers/gpu/drm/msm/dsi/dsi.h      |   1 +
 drivers/gpu/drm/msm/dsi/dsi_cfg.c  |  16 +++++-
 drivers/gpu/drm/msm/dsi/dsi_cfg.h  |   2 +
 drivers/gpu/drm/msm/dsi/dsi_host.c | 107 ++++++++++++-------------------------
 4 files changed, 53 insertions(+), 73 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.h +1 -0
index 8140e8b..7336b55 100644
@@ -36,6 +36,7 @@ enum msm_dsi_phy_type {
 };
 
 #define DSI_DEV_REGULATOR_MAX	8
+#define DSI_BUS_CLK_MAX		4
 
 /* Regulators for DSI devices */
 struct dsi_reg_entry {
drivers/gpu/drm/msm/dsi/dsi_cfg.c +15 -1
index 5872d5e..c40044f 100644
@@ -18,6 +18,10 @@ static const struct msm_dsi_config dsi_v2_cfg = {
 	.io_offset = 0,
 };
 
+static const char * const dsi_6g_bus_clk_names[] = {
+	"mdp_core_clk", "iface_clk", "bus_clk", "core_mmss_clk",
+};
+
 static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
 	.io_offset = DSI_6G_REG_SHIFT,
 	.reg_cfg = {
@@ -29,6 +33,12 @@ static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
 			{"vddio", 1800000, 1800000, 100000, 100},
 		},
 	},
+	.bus_clk_names = dsi_6g_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names),
+};
+
+static const char * const dsi_8916_bus_clk_names[] = {
+	"mdp_core_clk", "iface_clk", "bus_clk",
 };
 
 static const struct msm_dsi_config msm8916_dsi_cfg = {
@@ -42,6 +52,8 @@ static const struct msm_dsi_config msm8916_dsi_cfg = {
 			{"vddio", 1800000, 1800000, 100000, 100},
 		},
 	},
+	.bus_clk_names = dsi_8916_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_8916_bus_clk_names),
 };
 
 static const struct msm_dsi_config msm8994_dsi_cfg = {
@@ -57,7 +69,9 @@ static const struct msm_dsi_config msm8994_dsi_cfg = {
 			{"lab_reg", -1, -1, -1, -1},
 			{"ibb_reg", -1, -1, -1, -1},
 		},
-	}
+	},
+	.bus_clk_names = dsi_6g_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names),
 };
 
 static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
drivers/gpu/drm/msm/dsi/dsi_cfg.h +2 -0
index 4cf8872..5a36836 100644
@@ -30,6 +30,8 @@
 struct msm_dsi_config {
 	u32 io_offset;
 	struct dsi_reg_config reg_cfg;
+	const char * const *bus_clk_names;
+	const int num_bus_clks;
 };
 
 struct msm_dsi_cfg_handler {
drivers/gpu/drm/msm/dsi/dsi_host.c +35 -72

140 lines not on this page · raw message

Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#22 lore raw

PATCH v2 6/10 drm/msm/dsi: Set up link clocks for DSIv2

In reply to Archit Taneja

DSIv2 (DSI on older A family chips) has slightly different link clock requirements.

First, we have an extra clock called src_clk (with a dedicated RCG). This is required by the DSI controller to process the pixel data coming from MDP. It needs to be set at the rate "pclk * bytes_per_pixel".

We also need to explicitly configure esc_clk. On DSI6G chips, we don't need to set a rate to esc_clk because its RCG is always sourced from crystal clock (19.2 Mhz in all cases), which is within the escape clock frequency range in the mipi DSI spec. For chips with DSIv2, the crystal clock rate may not be within the required range (27Mhz on APQ8064). Therefore, we derive it from the DSI byte clock. We calculate an esc_clck rate that is within the mipi spec and also divisible by the byte clock rate.

When setting rate and enabling the link clocks, we make sure that byte_clk is configured before esc_clk, and src_clk before pixel_clk. We create two different link_enable funcs for DSI6G and DSIv2 since the sequences are different.

We also obtain two extra source clocks (dsi_src_clk and esc_src_clk) and set their parent to the clocks provided by DSI PLL.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 193 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 188 insertions(+), 5 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +188 -5
index 1da9adb2..6665371 100644
@@ -113,6 +113,14 @@ struct msm_dsi_host {
 	struct clk *pixel_clk_src;
 
 	u32 byte_clk_rate;
+	u32 esc_clk_rate;
+
+	/* DSI v2 specific clocks */
+	struct clk *src_clk;
+	struct clk *esc_clk_src;
+	struct clk *dsi_clk_src;
+
+	u32 src_clk_rate;
 
 	struct gpio_desc *disp_en_gpio;
 	struct gpio_desc *te_gpio;
@@ -318,7 +326,8 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host)
 static int dsi_clk_init(struct msm_dsi_host *msm_host)
 {
 	struct device *dev = &msm_host->pdev->dev;
-	const struct msm_dsi_config *cfg = msm_host->cfg_hnd->cfg;
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
+	const struct msm_dsi_config *cfg = cfg_hnd->cfg;
 	int i, ret = 0;
 
 	/* get bus clocks */
@@ -377,6 +386,34 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host)
 		goto exit;
 	}
 
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) {
+		msm_host->src_clk = devm_clk_get(dev, "src_clk");
+		if (IS_ERR(msm_host->src_clk)) {
+			ret = PTR_ERR(msm_host->src_clk);
+			pr_err("%s: can't find dsi_src_clk. ret=%d\n",
+				__func__, ret);
+			msm_host->src_clk = NULL;
+			goto exit;
+		}
+
+		msm_host->esc_clk_src = devm_clk_get(dev, "esc_clk_src");
+		if (IS_ERR(msm_host->esc_clk_src)) {
+			ret = PTR_ERR(msm_host->esc_clk_src);
+			pr_err("%s: can't find esc_clk_src. ret=%d\n",
+				__func__, ret);
+			msm_host->esc_clk_src = NULL;
+			goto exit;
+		}
+
+		msm_host->dsi_clk_src = devm_clk_get(dev, "dsi_clk_src");
+		if (IS_ERR(msm_host->dsi_clk_src)) {
+			ret = PTR_ERR(msm_host->dsi_clk_src);
+			pr_err("%s: can't find dsi_clk_src. ret=%d\n",
+				__func__, ret);
+			msm_host->dsi_clk_src = NULL;
+			goto exit;
+		}
+	}
 exit:
 	return ret;
 }
@@ -416,7 +453,7 @@ static void dsi_bus_clk_disable(struct msm_dsi_host *msm_host)
 		clk_disable_unprepare(msm_host->bus_clks[i]);
 }
 
-static int dsi_link_clk_enable(struct msm_dsi_host *msm_host)
+static int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host)
 {
 	int ret;
 
@@ -463,11 +500,98 @@ error:
 	return ret;
 }
 
-static void dsi_link_clk_disable(struct msm_dsi_host *msm_host)
+static int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host)
 {
+	int ret;
+
+	DBG("Set clk rates: pclk=%d, byteclk=%d, esc_clk=%d, dsi_src_clk=%d",
+		msm_host->mode->clock, msm_host->byte_clk_rate,
+		msm_host->esc_clk_rate, msm_host->src_clk_rate);
+
+	ret = clk_set_rate(msm_host->byte_clk, msm_host->byte_clk_rate);
+	if (ret) {
+		pr_err("%s: Failed to set rate byte clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_set_rate(msm_host->esc_clk, msm_host->esc_clk_rate);
+	if (ret) {
+		pr_err("%s: Failed to set rate esc clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_set_rate(msm_host->src_clk, msm_host->src_clk_rate);
+	if (ret) {
+		pr_err("%s: Failed to set rate src clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000);
+	if (ret) {
+		pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_prepare_enable(msm_host->byte_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi byte clk\n", __func__);
+		goto error;
+	}
+
+	ret = clk_prepare_enable(msm_host->esc_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi esc clk\n", __func__);
+		goto esc_clk_err;
+	}
+
+	ret = clk_prepare_enable(msm_host->src_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi src clk\n", __func__);
+		goto src_clk_err;
+	}
+
+	ret = clk_prepare_enable(msm_host->pixel_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi pixel clk\n", __func__);
+		goto pixel_clk_err;
+	}
+
+	return 0;
+
+pixel_clk_err:
+	clk_disable_unprepare(msm_host->src_clk);
+src_clk_err:
 	clk_disable_unprepare(msm_host->esc_clk);
-	clk_disable_unprepare(msm_host->pixel_clk);
+esc_clk_err:
 	clk_disable_unprepare(msm_host->byte_clk);
+error:
+	return ret;
+}
+
+static int dsi_link_clk_enable(struct msm_dsi_host *msm_host)
+{
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
+
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G)
+		return dsi_link_clk_enable_6g(msm_host);
+	else
+		return dsi_link_clk_enable_v2(msm_host);
+}
+
+static void dsi_link_clk_disable(struct msm_dsi_host *msm_host)
+{
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
+
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) {
+		clk_disable_unprepare(msm_host->esc_clk);
+		clk_disable_unprepare(msm_host->pixel_clk);
+		clk_disable_unprepare(msm_host->byte_clk);
+	} else {
+		clk_disable_unprepare(msm_host->pixel_clk);
+		clk_disable_unprepare(msm_host->src_clk);
+		clk_disable_unprepare(msm_host->esc_clk);
+		clk_disable_unprepare(msm_host->byte_clk);
+	}
 }
 
 static int dsi_clk_ctrl(struct msm_dsi_host *msm_host, bool enable)
@@ -502,6 +626,7 @@ unlock_ret:
 static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host)
 {
 	struct drm_display_mode *mode = msm_host->mode;
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
 	u8 lanes = msm_host->lanes;
 	u32 bpp = dsi_get_bpp(msm_host->format);
 	u32 pclk_rate;
@@ -521,6 +646,47 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host)
 
 	DBG("pclk=%d, bclk=%d", pclk_rate, msm_host->byte_clk_rate);
 
+	msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk);
+
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) {
+		unsigned int esc_mhz, esc_div;
+		unsigned long byte_mhz;
+
+		msm_host->src_clk_rate = (pclk_rate * bpp) / 8;
+
+		/*
+		 * esc clock is byte clock followed by a 4 bit divider,
+		 * we need to find an escape clock frequency within the
+		 * mipi DSI spec range within the maximum divider limit
+		 * We iterate here between an escape clock frequencey
+		 * between 20 Mhz to 5 Mhz and pick up the first one
+		 * that can be supported by our divider
+		 */
+
+		byte_mhz = msm_host->byte_clk_rate / 1000000;
+
+		for (esc_mhz = 20; esc_mhz >= 5; esc_mhz--) {
+			esc_div = DIV_ROUND_UP(byte_mhz, esc_mhz);
+
+			/*
+			 * TODO: Ideally, we shouldn't know what sort of divider
+			 * is available in mmss_cc, we're just assuming that
+			 * it'll always be a 4 bit divider. Need to come up with
+			 * a better way here.
+			 */
+			if (esc_div >= 1 && esc_div <= 16)
+				break;
+		}
+
+		if (esc_mhz < 5)
+			return -EINVAL;
+
+		msm_host->esc_clk_rate = msm_host->byte_clk_rate / esc_div;
+
+		DBG("esc=%d, src=%d", msm_host->esc_clk_rate,
+			msm_host->src_clk_rate);
+	}
+
 	return 0;
 }
 
@@ -1753,6 +1919,7 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
 	struct msm_dsi_pll *src_pll)
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
 	struct clk *byte_clk_provider, *pixel_clk_provider;
 	int ret;
 
@@ -1778,6 +1945,22 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
 		goto exit;
 	}
 
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) {
+		ret = clk_set_parent(msm_host->dsi_clk_src, pixel_clk_provider);
+		if (ret) {
+			pr_err("%s: can't set parent to dsi_clk_src. ret=%d\n",
+				__func__, ret);
+			goto exit;
+		}
+
+		ret = clk_set_parent(msm_host->esc_clk_src, byte_clk_provider);
+		if (ret) {
+			pr_err("%s: can't set parent to esc_clk_src. ret=%d\n",
+				__func__, ret);
+			goto exit;
+		}
+	}
+
 exit:
 	return ret;
 }
@@ -1849,7 +2032,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 	dsi_phy_sw_reset(msm_host);
 	ret = msm_dsi_manager_phy_enable(msm_host->id,
 					msm_host->byte_clk_rate * 8,
-					clk_get_rate(msm_host->esc_clk),
+					msm_host->esc_clk_rate,
 					&clk_pre, &clk_post);
 	dsi_bus_clk_disable(msm_host);
 	if (ret) {
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#23 lore raw

PATCH v2 7/10 drm/msm/dsi: Add dsi_cfg for APQ8064

In reply to Archit Taneja

Add a dsi_cfg entry for APQ8064. Since this is the first DSIv2 chip to be supported, add a list of bus clocks that are required by the DSIv2 block.

---
 drivers/gpu/drm/msm/dsi/dsi_cfg.c | 19 ++++++++++++++++---
 drivers/gpu/drm/msm/dsi/dsi_cfg.h |  2 ++
 2 files changed, 18 insertions(+), 3 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_cfg.c +16 -3
index c40044f..2a827d8 100644
@@ -13,9 +13,22 @@
 
 #include "dsi_cfg.h"
 
-/* DSI v2 has not been supported by now */
-static const struct msm_dsi_config dsi_v2_cfg = {
+static const char * const dsi_v2_bus_clk_names[] = {
+	"core_mmss_clk", "iface_clk", "bus_clk",
+};
+
+static const struct msm_dsi_config apq8064_dsi_cfg = {
 	.io_offset = 0,
+	.reg_cfg = {
+		.num = 3,
+		.regs = {
+			{"vdda", 1200000, 1200000, 100000, 100},
+			{"avdd", 3000000, 3000000, 110000, 100},
+			{"vddio", 1800000, 1800000, 100000, 100},
+		},
+	},
+	.bus_clk_names = dsi_v2_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_v2_bus_clk_names),
 };
 
 static const char * const dsi_6g_bus_clk_names[] = {
@@ -75,7 +88,7 @@ static const struct msm_dsi_config msm8994_dsi_cfg = {
 };
 
 static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
-	{MSM_DSI_VER_MAJOR_V2, U32_MAX, &dsi_v2_cfg},
+	{MSM_DSI_VER_MAJOR_V2, MSM_DSI_V2_VER_MINOR_8064, &apq8064_dsi_cfg},
 	{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0,
 						&msm8974_apq8084_dsi_cfg},
 	{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1,
drivers/gpu/drm/msm/dsi/dsi_cfg.h +2 -0
index 5a36836..a68c836 100644
@@ -25,6 +25,8 @@
 #define MSM_DSI_6G_VER_MINOR_V1_3	0x10030000
 #define MSM_DSI_6G_VER_MINOR_V1_3_1	0x10030001
 
+#define MSM_DSI_V2_VER_MINOR_8064	0x0
+
 #define DSI_6G_REG_SHIFT	4
 
 struct msm_dsi_config {
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#24 lore raw

PATCH v2 8/10 drm/msm/dsi: Don't use iommu for command TX buffer for DSIv2

In reply to Archit Taneja

We currently use iommu allocated DMA buffers for sending DSI commands. DSIv2 doesn't have a port connected to the MDP iommu. Therefore, it can't use iommu allocated buffers to fetch DSI commands.

Use a regular contiguous DMA buffer if we are DSIv2.

---
 drivers/gpu/drm/msm/dsi/dsi.h         |   4 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c    | 110 +++++++++++++++++++++++-----------
 drivers/gpu/drm/msm/dsi/dsi_manager.c |   6 +-
 3 files changed, 79 insertions(+), 41 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.h +2 -2
index 7336b55..749fbb2 100644
@@ -91,7 +91,7 @@ int msm_dsi_manager_phy_enable(int id,
 		u32 *clk_pre, u32 *clk_post);
 void msm_dsi_manager_phy_disable(int id);
 int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg);
-bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len);
+bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len);
 int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
 void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
 
@@ -145,7 +145,7 @@ int msm_dsi_host_cmd_tx(struct mipi_dsi_host *host,
 int msm_dsi_host_cmd_rx(struct mipi_dsi_host *host,
 					const struct mipi_dsi_msg *msg);
 void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host,
-					u32 iova, u32 len);
+					u32 dma_base, u32 len);
 int msm_dsi_host_enable(struct mipi_dsi_host *host);
 int msm_dsi_host_disable(struct mipi_dsi_host *host);
 int msm_dsi_host_power_on(struct mipi_dsi_host *host);
drivers/gpu/drm/msm/dsi/dsi_host.c +74 -36

183 lines not on this page · raw message

drivers/gpu/drm/msm/dsi/dsi_manager.c +3 -3
index 0455ff7..58ba7ec 100644
@@ -774,7 +774,7 @@ restore_host0:
 	return ret;
 }
 
-bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len)
+bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len)
 {
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 	struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
@@ -784,9 +784,9 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len)
 		return false;
 
 	if (IS_SYNC_NEEDED() && msm_dsi0)
-		msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, iova, len);
+		msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, dma_base, len);
 
-	msm_dsi_host_cmd_xfer_commit(host, iova, len);
+	msm_dsi_host_cmd_xfer_commit(host, dma_base, len);
 
 	return true;
 }
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#25 lore raw

PATCH v2 9/10 drm/msm/dsi: Enable MMSS SPFB port via syscon

In reply to Archit Taneja

For DSIv2 to work, we need to enable MMSS_AHB_ARB_MASTER_PORT in MMSS_SFPB. We enable the required bitfield by retrieving MMSS_SFPB regmap pointer via syscon.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
drivers/gpu/drm/msm/dsi/dsi_host.c +33 -0
index afc2546..7a71f11 100644
@@ -24,10 +24,13 @@
 #include <linux/of_graph.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spinlock.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 #include <video/mipi_display.h>
 
 #include "dsi.h"
 #include "dsi.xml.h"
+#include "sfpb.xml.h"
 #include "dsi_cfg.h"
 
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
@@ -149,6 +152,8 @@ struct msm_dsi_host {
 
 	u8 *rx_buf;
 
+	struct regmap *sfpb;
+
 	struct drm_display_mode *mode;
 
 	/* connected device info */
@@ -1573,6 +1578,16 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 
 	msm_host->device_node = device_node;
 
+	if (of_property_read_bool(np, "syscon-sfpb")) {
+		msm_host->sfpb = syscon_regmap_lookup_by_phandle(np,
+					"syscon-sfpb");
+		if (IS_ERR(msm_host->sfpb)) {
+			dev_err(dev, "%s: failed to get sfpb regmap\n",
+				__func__);
+			return PTR_ERR(msm_host->sfpb);
+		}
+	}
+
 	return 0;
 }
 
@@ -2036,6 +2051,20 @@ int msm_dsi_host_disable(struct mipi_dsi_host *host)
 	return 0;
 }
 
+static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable)
+{
+	enum sfpb_ahb_arb_master_port_en en;
+
+	if (!msm_host->sfpb)
+		return;
+
+	en = enable ? SFPB_MASTER_PORT_ENABLE : SFPB_MASTER_PORT_DISABLE;
+
+	regmap_update_bits(msm_host->sfpb, REG_SFPB_GPREG,
+			SFPB_GPREG_MASTER_PORT_EN__MASK,
+			SFPB_GPREG_MASTER_PORT_EN(en));
+}
+
 int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
@@ -2048,6 +2077,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 		goto unlock_ret;
 	}
 
+	msm_dsi_sfpb_config(msm_host, true);
+
 	ret = dsi_calc_clk_rate(msm_host);
 	if (ret) {
 		pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
@@ -2135,6 +2166,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)
 
 	dsi_host_regulator_disable(msm_host);
 
+	msm_dsi_sfpb_config(msm_host, false);
+
 	DBG("-");
 
 	msm_host->power_on = false;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#26 lore raw

PATCH v2 10/10 dt-bindings: Add DSIv2 documentation

In reply to Archit Taneja

Add additional property info needed for DSIv2 DT.

---
 Documentation/devicetree/bindings/display/msm/dsi.txt | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/msm/dsi.txt +9 -1
index f344b9e..ca65a34 100644
@@ -13,18 +13,25 @@ Required properties:
 - power-domains: Should be <&mmcc MDSS_GDSC>.
 - clocks: device clocks
   See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
-- clock-names: the following clocks are required:
+- clock-names: these vary based on the DSI version. For DSI6G:
   * "bus_clk"
   * "byte_clk"
+  * "byte_clk_src
   * "core_clk"
   * "core_mmss_clk"
   * "iface_clk"
   * "mdp_core_clk"
   * "pixel_clk"
+  * "pixel_clk_src"
+  For DSIv2, we need a few more:
+   * "dsi_clk_src"
+   * "esc_clk_src"
+   * "src_clk"
 - vdd-supply: phandle to vdd regulator device node
 - vddio-supply: phandle to vdd-io regulator device node
 - vdda-supply: phandle to vdda regulator device node
 - qcom,dsi-phy: phandle to DSI PHY device node
+- syscon-sfpb: A phandle to mmss_sfpb syscon node (only for DSIv2)
 
 Optional properties:
 - panel@0: Node of panel connected to this DSI controller.
@@ -51,6 +58,7 @@ Required properties:
   * "qcom,dsi-phy-28nm-hpm"
   * "qcom,dsi-phy-28nm-lp"
   * "qcom,dsi-phy-20nm"
+  * "qcom,dsi-phy-28nm-8960"
 - reg: Physical base address and length of the registers of PLL, PHY and PHY
   regulator
 - reg-names: The names of register regions. The following regions are required:
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
maintainer
#27 lore raw

Re: [PATCH v2 10/10] dt-bindings: Add DSIv2 documentation

+dt list

Quoted 1 line · Archit Taneja

Add additional property info needed for DSIv2 DT.

Please use get_maintainers.pl.

Quoted 10 lines
---
 Documentation/devicetree/bindings/display/msm/dsi.txt | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/msm/dsi.txt +0 -0
index f344b9e..ca65a34 100644

Documentation/devicetree/bindings/display/msm/dsi.txt Required properties: · line 19

Quoted 8 lines
Documentation/devicetree/bindings/display/msm/dsi.txt +2 -1
@@ -13,18 +13,25 @@ Required properties:
 - power-domains: Should be <&mmcc MDSS_GDSC>.
 - clocks: device clocks
   See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
-- clock-names: the following clocks are required:
+- clock-names: these vary based on the DSI version. For DSI6G:
   * "bus_clk"
   * "byte_clk"
+  * "byte_clk_src

This sounds like the parent of byte_clk. Is that really a clock within the block?

Documentation/devicetree/bindings/display/msm/dsi.txt Required properties: · line 26

Quoted 7 lines
Documentation/devicetree/bindings/display/msm/dsi.txt +2 -0
   * "core_clk"
   * "core_mmss_clk"
   * "iface_clk"
   * "mdp_core_clk"
   * "pixel_clk"
+  * "pixel_clk_src"
+  For DSIv2, we need a few more:

What is the overall order of clocks? As listed?

Quoted 27 lines
Documentation/devicetree/bindings/display/msm/dsi.txt +5 -1
+   * "dsi_clk_src"
+   * "esc_clk_src"
+   * "src_clk"
 - vdd-supply: phandle to vdd regulator device node
 - vddio-supply: phandle to vdd-io regulator device node
 - vdda-supply: phandle to vdda regulator device node
 - qcom,dsi-phy: phandle to DSI PHY device node
+- syscon-sfpb: A phandle to mmss_sfpb syscon node (only for DSIv2)
 
 Optional properties:
 - panel@0: Node of panel connected to this DSI controller.
@@ -51,6 +58,7 @@ Required properties:
   * "qcom,dsi-phy-28nm-hpm"
   * "qcom,dsi-phy-28nm-lp"
   * "qcom,dsi-phy-20nm"
+  * "qcom,dsi-phy-28nm-8960"
 - reg: Physical base address and length of the registers of PLL, PHY and PHY
   regulator
 - reg-names: The names of register regions. The following regions are required:
--

The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

#28 lore raw

Re: [PATCH v2 10/10] dt-bindings: Add DSIv2 documentation

Hi Rob,

Quoted 6 lines · Rob Herring

+dt list

Quoted 1 line · Archit Taneja

Add additional property info needed for DSIv2 DT.

Please use get_maintainers.pl.

Sorry about that, missed out doing that posting this time.

Quoted 6 lines
Quoted 6 lines
---
  Documentation/devicetree/bindings/display/msm/dsi.txt | 10 +++++++++-
  1 file changed, 9 insertions(+), 1 deletion(-)
Quoted 16 lines

Documentation/devicetree/bindings/display/msm/dsi.txt Required properties: · line 19

Quoted 13 lines
Documentation/devicetree/bindings/display/msm/dsi.txt +2 -1
index f344b9e..ca65a34 100644
@@ -13,18 +13,25 @@ Required properties:
  - power-domains: Should be <&mmcc MDSS_GDSC>.
  - clocks: device clocks
    See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
-- clock-names: the following clocks are required:
+- clock-names: these vary based on the DSI version. For DSI6G:
    * "bus_clk"
    * "byte_clk"
+  * "byte_clk_src

This sounds like the parent of byte_clk. Is that really a clock within the block?

byte_clk_src isn't in the block, but byte_clk_src's parent is one of the PLLs in this block. We take this clock so that we can re-parent it to an appropriate PLL. The decision of what PLL to choose needs to be done by the DSI block's driver.

Quoted 10 lines

Documentation/devicetree/bindings/display/msm/dsi.txt Required properties: · line 26

Quoted 8 lines
Documentation/devicetree/bindings/display/msm/dsi.txt +2 -0
    * "core_clk"
    * "core_mmss_clk"
    * "iface_clk"
    * "mdp_core_clk"
    * "pixel_clk"
+  * "pixel_clk_src"
+  For DSIv2, we need a few more:

What is the overall order of clocks? As listed?

Order in which the driver does clk_get? It uses the clock name to get each one individually, so the order doesn't matter as such.

I don't think it the order of clk_get in the driver is the same as what's been listed here. I can fix it if that's the norm.

Thanks,
Archit

Quoted 28 lines
Quoted 28 lines
Documentation/devicetree/bindings/display/msm/dsi.txt +5 -1
+   * "dsi_clk_src"
+   * "esc_clk_src"
+   * "src_clk"
  - vdd-supply: phandle to vdd regulator device node
  - vddio-supply: phandle to vdd-io regulator device node
  - vdda-supply: phandle to vdda regulator device node
  - qcom,dsi-phy: phandle to DSI PHY device node
+- syscon-sfpb: A phandle to mmss_sfpb syscon node (only for DSIv2)
 
  Optional properties:
  - panel@0: Node of panel connected to this DSI controller.
@@ -51,6 +58,7 @@ Required properties:
    * "qcom,dsi-phy-28nm-hpm"
    * "qcom,dsi-phy-28nm-lp"
    * "qcom,dsi-phy-20nm"
+  * "qcom,dsi-phy-28nm-8960"
  - reg: Physical base address and length of the registers of PLL, PHY and PHY
    regulator
  - reg-names: The names of register regions. The following regions are required:
--

The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel

A message that is not in the archive (sent off-list or not yet received): [email protected]

#30 lore raw

Re: [PATCH v2 10/10] dt-bindings: Add DSIv2 documentation

+Stephen

Quoted 44 lines · Archit Taneja

Hi Rob,

Quoted 10 lines · Rob Herring

+dt list

Quoted 2 lines · Archit Taneja

Add additional property info needed for DSIv2 DT.

Please use get_maintainers.pl.

Sorry about that, missed out doing that posting this time.

Quoted 17 lines
Quoted 17 lines
---
  Documentation/devicetree/bindings/display/msm/dsi.txt | 10 +++++++++-
  1 file changed, 9 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/msm/dsi.txt +0 -0
index f344b9e..ca65a34 100644
@@ -13,18 +13,25 @@ Required properties:
  - power-domains: Should be <&mmcc MDSS_GDSC>.
  - clocks: device clocks
    See Documentation/devicetree/bindings/clocks/clock-bindings.txt for

details.
-- clock-names: the following clocks are required:

Quoted 8 lines
Quoted 4 lines

+- clock-names: these vary based on the DSI version. For DSI6G:
* "bus_clk"
* "byte_clk"
+ * "byte_clk_src

This sounds like the parent of byte_clk. Is that really a clock within the block?

Quoted 4 lines

byte_clk_src isn't in the block, but byte_clk_src's parent is one of the PLLs in this block. We take this clock so that we can re-parent it to an appropriate PLL. The decision of what PLL to choose needs to be done by the DSI block's driver.

Seems like abuse to me. The list of clocks should match what are inputs to the block, not what the driver happens to need. Without a full understanding of the clock tree here, I don't have a suggestion. Maybe Stephen does.

Quoted 9 lines
Quoted 9 lines
Quoted 7 lines

* "core_clk"
* "core_mmss_clk"
* "iface_clk"
* "mdp_core_clk"
* "pixel_clk"

Documentation/devicetree/bindings/display/msm/dsi.txt +2 -0
+  * "pixel_clk_src"
+  For DSIv2, we need a few more:
Quoted 6 lines
Quoted 1 line

What is the overall order of clocks? As listed?

Order in which the driver does clk_get? It uses the clock name to get each one individually, so the order doesn't matter as such.

The order in DT. You may use the names, but the order should still be specified.

Rob
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html

#31 lore raw

Re: [PATCH v2 10/10] dt-bindings: Add DSIv2 documentation

Quoted 52 lines · Rob Herring

+Stephen

Quoted 44 lines · Archit Taneja

Hi Rob,

Quoted 10 lines · Rob Herring

+dt list

Quoted 2 lines · Archit Taneja

Add additional property info needed for DSIv2 DT.

Please use get_maintainers.pl.

Sorry about that, missed out doing that posting this time.

Quoted 17 lines
Quoted 17 lines
---
   Documentation/devicetree/bindings/display/msm/dsi.txt | 10 +++++++++-
   1 file changed, 9 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/msm/dsi.txt +0 -0
index f344b9e..ca65a34 100644
@@ -13,18 +13,25 @@ Required properties:
   - power-domains: Should be <&mmcc MDSS_GDSC>.
   - clocks: device clocks
     See Documentation/devicetree/bindings/clocks/clock-bindings.txt for

details.
-- clock-names: the following clocks are required:

Quoted 8 lines
Quoted 4 lines

+- clock-names: these vary based on the DSI version. For DSI6G:
* "bus_clk"
* "byte_clk"
+ * "byte_clk_src

This sounds like the parent of byte_clk. Is that really a clock within the block?

Quoted 4 lines

byte_clk_src isn't in the block, but byte_clk_src's parent is one of the PLLs in this block. We take this clock so that we can re-parent it to an appropriate PLL. The decision of what PLL to choose needs to be done by the DSI block's driver.

Quoted 4 lines

Seems like abuse to me. The list of clocks should match what are inputs to the block, not what the driver happens to need. Without a full understanding of the clock tree here, I don't have a suggestion. Maybe Stephen does.

We don't need specify byte_clk_src (and other xyz_clk_src clocks) via DT. There is a static link set up between byte_clk and byte_clk_src by our clock driver that never changes. We can retrieve it in the driver itself using clk_get_parent(byte_clk). This way we stick to only input clocks.

Stephen, does that sound okay?

Quoted 10 lines
Quoted 10 lines
Quoted 10 lines
Quoted 8 lines

* "core_clk"
* "core_mmss_clk"
* "iface_clk"
* "mdp_core_clk"
* "pixel_clk"

Documentation/devicetree/bindings/display/msm/dsi.txt +2 -0
+  * "pixel_clk_src"
+  For DSIv2, we need a few more:
Quoted 8 lines
Quoted 6 lines
Quoted 1 line

What is the overall order of clocks? As listed?

Order in which the driver does clk_get? It uses the clock name to get each one individually, so the order doesn't matter as such.

The order in DT. You may use the names, but the order should still be specified.

Okay. I'll cross check and make sure the order is as in our DT files.

Archit

Quoted 7 lines

Rob
--
To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#32 lore raw

Re: [PATCH v2 10/10] dt-bindings: Add DSIv2 documentation

Quoted 60 lines · Archit Taneja
Quoted 52 lines · Rob Herring

+Stephen

Quoted 44 lines · Archit Taneja

Hi Rob,

Quoted 10 lines · Rob Herring

+dt list

Quoted 2 lines · Archit Taneja

Add additional property info needed for DSIv2 DT.

Please use get_maintainers.pl.

Sorry about that, missed out doing that posting this time.

Quoted 17 lines
Quoted 17 lines
---
  Documentation/devicetree/bindings/display/msm/dsi.txt | 10 +++++++++-
  1 file changed, 9 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/msm/dsi.txt +0 -0
index f344b9e..ca65a34 100644
@@ -13,18 +13,25 @@ Required properties:
  - power-domains: Should be <&mmcc MDSS_GDSC>.
  - clocks: device clocks
    See Documentation/devicetree/bindings/clocks/clock-bindings.txt for

details.
-- clock-names: the following clocks are required:

Quoted 8 lines
Quoted 4 lines

+- clock-names: these vary based on the DSI version. For DSI6G:
* "bus_clk"
* "byte_clk"
+ * "byte_clk_src

This sounds like the parent of byte_clk. Is that really a clock within the block?

Quoted 4 lines

byte_clk_src isn't in the block, but byte_clk_src's parent is one of the PLLs in this block. We take this clock so that we can re-parent it to an appropriate PLL. The decision of what PLL to choose needs to be done by the DSI block's driver.

Quoted 4 lines

Seems like abuse to me. The list of clocks should match what are inputs to the block, not what the driver happens to need. Without a full understanding of the clock tree here, I don't have a suggestion. Maybe Stephen does.

Quoted 8 lines

We don't need specify byte_clk_src (and other xyz_clk_src clocks) via DT. There is a static link set up between byte_clk and byte_clk_src by our clock driver that never changes. We can retrieve it in the driver itself using clk_get_parent(byte_clk). This way we stick to only input clocks.

Stephen, does that sound okay?

I guess so. From the DT perspective it's "correct" so sure.

It would be nice if we could use assigned-clock-parents though. As far as I can recall that's hard because the clock tree looks like a cyclic graph when we take a clock provider level view. The display block consumes the byte_clk and provides the source of it too. So if we used assigned parents we would need to wait for both clocks to be registered with the framework before we can reconfigure the parent of byte_clk_src to be the PLL that the display clock outputs. Unfortunately, of_clk_set_defaults() is called during device driver probe, which in the display driver case would be before the PLL is registered.

My only thought there would be to make of_clk_set_defaults() wait until both clocks are registered before it does any parent setting. But only in the case where the assigned parents contains a clock that is provided by the node being processed. I suppose the simplest thing to do would be to skip it during the device driver probe and handle it when the clk provider is registered.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#33 lore raw

Re: [PATCH v2 10/10] dt-bindings: Add DSIv2 documentation

Quoted 8 lines · Stephen Boyd

My only thought there would be to make of_clk_set_defaults() wait until both clocks are registered before it does any parent setting. But only in the case where the assigned parents contains a clock that is provided by the node being processed. I suppose the simplest thing to do would be to skip it during the device driver probe and handle it when the clk provider is registered.

Actually it looks like we already have the code for that.

	if (clkspec.np == node && !clk_supplier)
		return 0;

So assigned parents should "just work"?

Signature · 6 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#34 lore raw

Re: [PATCH v2 10/10] dt-bindings: Add DSIv2 documentation

Quoted 10 lines · Stephen Boyd
Quoted 8 lines · Stephen Boyd

My only thought there would be to make of_clk_set_defaults() wait until both clocks are registered before it does any parent setting. But only in the case where the assigned parents contains a clock that is provided by the node being processed. I suppose the simplest thing to do would be to skip it during the device driver probe and handle it when the clk provider is registered.

Quoted 6 lines

Actually it looks like we already have the code for that.

	if (clkspec.np == node && !clk_supplier)
		return 0;

So assigned parents should "just work"?

I tried using assigned-parents and it works fine.

The issue you mentioned above doesn't apply in our case, because we have two different devices for "dsi" and "dsi_phy". dsi_phy is the clock provider here and dsi is the one that wants to assign clocks.

If there was only one dsi device representing both DSI and PHY, then we'd hit the condition you mentioned.

Thanks,
Archit

Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#35 lore raw

Re: [PATCH v2 10/10] dt-bindings: Add DSIv2 documentation

In reply to Stephen Boyd
Quoted 83 lines · Stephen Boyd
Quoted 60 lines · Archit Taneja
Quoted 52 lines · Rob Herring

+Stephen

Quoted 44 lines · Archit Taneja

Hi Rob,

Quoted 10 lines · Rob Herring

+dt list

Quoted 2 lines · Archit Taneja

Add additional property info needed for DSIv2 DT.

Please use get_maintainers.pl.

Sorry about that, missed out doing that posting this time.

Quoted 17 lines
Quoted 17 lines
---
   Documentation/devicetree/bindings/display/msm/dsi.txt | 10 +++++++++-
   1 file changed, 9 insertions(+), 1 deletion(-)
Documentation/devicetree/bindings/display/msm/dsi.txt +0 -0
index f344b9e..ca65a34 100644
@@ -13,18 +13,25 @@ Required properties:
   - power-domains: Should be <&mmcc MDSS_GDSC>.
   - clocks: device clocks
     See Documentation/devicetree/bindings/clocks/clock-bindings.txt for

details.
-- clock-names: the following clocks are required:

Quoted 8 lines
Quoted 4 lines

+- clock-names: these vary based on the DSI version. For DSI6G:
* "bus_clk"
* "byte_clk"
+ * "byte_clk_src

This sounds like the parent of byte_clk. Is that really a clock within the block?

Quoted 4 lines

byte_clk_src isn't in the block, but byte_clk_src's parent is one of the PLLs in this block. We take this clock so that we can re-parent it to an appropriate PLL. The decision of what PLL to choose needs to be done by the DSI block's driver.

Quoted 4 lines

Seems like abuse to me. The list of clocks should match what are inputs to the block, not what the driver happens to need. Without a full understanding of the clock tree here, I don't have a suggestion. Maybe Stephen does.

Quoted 8 lines

We don't need specify byte_clk_src (and other xyz_clk_src clocks) via DT. There is a static link set up between byte_clk and byte_clk_src by our clock driver that never changes. We can retrieve it in the driver itself using clk_get_parent(byte_clk). This way we stick to only input clocks.

Stephen, does that sound okay?

I guess so. From the DT perspective it's "correct" so sure.

It would be nice if we could use assigned-clock-parents though. As far as I can recall that's hard because the clock tree looks like a cyclic graph when we take a clock provider level view. The display block consumes the byte_clk and provides the source of it too. So if we used assigned parents we would need to wait for both clocks to be registered with the framework before we can reconfigure the parent of byte_clk_src to be the PLL that the display clock outputs. Unfortunately, of_clk_set_defaults() is called during device driver probe, which in the display driver case would be before the PLL is registered.

Quoted 7 lines

My only thought there would be to make of_clk_set_defaults() wait until both clocks are registered before it does any parent setting. But only in the case where the assigned parents contains a clock that is provided by the node being processed. I suppose the simplest thing to do would be to skip it during the device driver probe and handle it when the clk provider is registered.

The assigned-clock-parents stuff you mentioned is needed to set a default link between the one of the DSI PLLs and the RCG, right? I just wanted to make clear if we were still discussing the same issue.

From what I understand, we don't need the assigned-clock-parents stuff
to establish a link between byte_clk_src(RCG clock) and byte_clk(branch clock). That's a fixed link set up by the clock structs provided in the gcc driver and doesn't need to be specially assigned, and just a clk_get_parent in the driver does the job there.

About assigning a parent to the RCG, wouldn't that be xo by default, and changed by the drm/msm driver to one of the PLLs when the need arrives? I didn't get why we need to establish that beforehand in DT?

Archit

Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#36 lore raw

Re: [PATCH v2 10/10] dt-bindings: Add DSIv2 documentation

Quoted 10 lines · Archit Taneja
Quoted 8 lines · Stephen Boyd

My only thought there would be to make of_clk_set_defaults() wait until both clocks are registered before it does any parent setting. But only in the case where the assigned parents contains a clock that is provided by the node being processed. I suppose the simplest thing to do would be to skip it during the device driver probe and handle it when the clk provider is registered.

Quoted 4 lines

The assigned-clock-parents stuff you mentioned is needed to set a default link between the one of the DSI PLLs and the RCG, right? I just wanted to make clear if we were still discussing the same issue.

Yes.

Quoted 7 lines

From what I understand, we don't need the assigned-clock-parents stuff to establish a link between byte_clk_src(RCG clock) and byte_clk(branch clock). That's a fixed link set up by the clock structs provided in the gcc driver and doesn't need to be specially assigned, and just a
clk_get_parent in the driver does the job there.

There's only one parent of the byte_clk and that's byte_clk_src. So yes, there's no need to describe that in DT and clk_get_parent() works fine.

Quoted 5 lines

About assigning a parent to the RCG, wouldn't that be xo by default, and changed by the drm/msm driver to one of the PLLs when the need arrives? I didn't get why we need to establish that beforehand in DT?

Yes, it would be XO out of reset, but we have no idea what the bootloader is doing. I thought the problem was that byte_clk_src is not actually an input to the DSI device. The proposal was to have DT specify byte_clk_src and byte_clk in the clocks array so that byte_clk_src could be reparented to the PLL and the byte_clk could be enabled/disabled. If we use DT to do the parent configuring then the DSI node doesn't have the byte_clk_src in its clocks array and thus DT is reflecting reality.

If we want to dynamically switch the parent of byte_clk_src to be different PLLs at runtime, then yes we'll need to get the parent of the byte_clk (which is byte_clk_src) and set the PLL as the parent. Or we'll need to make clk_set_parent() on the byte_clk transparently set the grand-parent to be the PLL. In that case we may need to introduce some sort of flag like CLK_SET_PARENT_GRANDPARENT to add this type of behavior.

I don't have a huge problem with

clk_set_parent(clk_get_parent(byte_clk), PLL)

except that this fails the abstraction test. It leaks information about the clock tree into a driver that shouldn't need to know that on this particular SoC there's a clock in between the PLL and the byte_clk. Future designs may not have the intermediate clock and then we'll need to update the driver to handle the difference, when we could have added the flag and things would work the same.

Signature · 2 lines
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
#37 lore raw

Re: [PATCH v2 10/10] dt-bindings: Add DSIv2 documentation

Quoted 36 lines · Stephen Boyd
Quoted 10 lines · Archit Taneja
Quoted 8 lines · Stephen Boyd

My only thought there would be to make of_clk_set_defaults() wait until both clocks are registered before it does any parent setting. But only in the case where the assigned parents contains a clock that is provided by the node being processed. I suppose the simplest thing to do would be to skip it during the device driver probe and handle it when the clk provider is registered.

Quoted 4 lines

The assigned-clock-parents stuff you mentioned is needed to set a default link between the one of the DSI PLLs and the RCG, right? I just wanted to make clear if we were still discussing the same issue.

Yes.

Quoted 7 lines

From what I understand, we don't need the assigned-clock-parents stuff
to establish a link between byte_clk_src(RCG clock) and byte_clk(branch clock). That's a fixed link set up by the clock structs provided in the gcc driver and doesn't need to be specially assigned, and just a
clk_get_parent in the driver does the job there.

There's only one parent of the byte_clk and that's byte_clk_src. So yes, there's no need to describe that in DT and clk_get_parent() works fine.

Quoted 5 lines

About assigning a parent to the RCG, wouldn't that be xo by default, and changed by the drm/msm driver to one of the PLLs when the need arrives? I didn't get why we need to establish that beforehand in DT?

Quoted 8 lines

Yes, it would be XO out of reset, but we have no idea what the bootloader is doing. I thought the problem was that byte_clk_src is not actually an input to the DSI device. The proposal was to have DT specify byte_clk_src and byte_clk in the clocks array so that byte_clk_src could be reparented to the PLL and the byte_clk could be enabled/disabled. If we use DT to do the parent configuring then the DSI node doesn't have the byte_clk_src in its clocks array and thus DT is reflecting reality.

Okay, I understand your point now.

Quoted 13 lines

If we want to dynamically switch the parent of byte_clk_src to be different PLLs at runtime, then yes we'll need to get the parent of the byte_clk (which is byte_clk_src) and set the PLL as the parent. Or we'll need to make clk_set_parent() on the byte_clk transparently set the grand-parent to be the PLL. In that case we may need to introduce some sort of flag like CLK_SET_PARENT_GRANDPARENT to add this type of behavior.

I don't have a huge problem with

clk_set_parent(clk_get_parent(byte_clk), PLL)

Quoted 7 lines

except that this fails the abstraction test. It leaks information about the clock tree into a driver that shouldn't need to know that on this particular SoC there's a clock in between the PLL and the byte_clk. Future designs may not have the intermediate clock and then we'll need to update the driver to handle the difference, when we could have added the flag and things would work the same.

I will have to check if we really require dynamic PLL configuration or not. At the moment, the driver reads another DT param (that identifies if we are in dual dsi mode) and then sets the appropriate PLL as parent. So, in a sense, it is relying on DT already for setting the parent.

I guess we can do the following:

- use assigned-clock-parents in DT to set the default PLL parent (provided it works out of the box)

- Within the driver, still do the 'clk_set_parent(clk_get_parent(byte_clk), PLL)' thing and remove it later if dynamic switching isn't needed at all if the parent PLL is known beforehand in all use cases.

Archit

Quoted 1 line
Signature · 5 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#38 lore raw

v3 cover drm/msm/dsi: Add support for DSI on MSM8960/APQ8064

In reply to Archit Taneja

Add support for DSI on 8960/8064. The DSI IP used in these chips is an older version(DSIv2) of what we have right now(DSI6G).

The bulk of the additions come thanks to a different PHY/PLL. The DSI host in itself doesn't have too many changes.

Changes in v3:
- Add a patch that removes the need to provide source clocks (RCG clocks) via DT, as suggested by Rob Herring.
- Make cleaner dt-binding doc patches.

Changes in v2:
- Incorporated Stephen's comments for the DSI PLL patch.
- The dsi.xml.h and sfpb.xml.h changes were already picked up by Rob. Removed those patches.

Archit Taneja (12):
drm/msm/dsi: Don't get byte/pixel source clocks from DT drm/msm/dsi: Add support for 28nm PHY on 8960 drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY drm/msm/dsi: Use a better way to figure out DSI version drm/msm/dsi: Delay dsi_clk_init
drm/msm/dsi: Parse bus clocks from a list drm/msm/dsi: Set up link clocks for DSIv2 drm/msm/dsi: Add dsi_cfg for APQ8064
drm/msm/dsi: Don't use iommu for command TX buffer for DSIv2 drm/msm/dsi: Enable MMSS SPFB port via syscon
dt-bindings: msm/dsi: Fix the order in which clocks are listed
dt-bindings: msm/dsi: Add DSIv2 documentation

 .../devicetree/bindings/display/msm/dsi.txt        |  12 +-
 drivers/gpu/drm/msm/Kconfig                        |   8 +
 drivers/gpu/drm/msm/Makefile                       |   2 +
 drivers/gpu/drm/msm/dsi/dsi.h                      |   6 +-
 drivers/gpu/drm/msm/dsi/dsi_cfg.c                  |  35 +-
 drivers/gpu/drm/msm/dsi/dsi_cfg.h                  |   4 +
 drivers/gpu/drm/msm/dsi/dsi_host.c                 | 508 ++++++++++++++------
 drivers/gpu/drm/msm/dsi/dsi_manager.c              |   6 +-
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c              |   4 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h              |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c    | 195 ++++++++
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c              |   3 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h              |  10 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c    | 533 +++++++++++++++++++++
 14 files changed, 1178 insertions(+), 149 deletions(-)
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#39 lore raw

PATCH v3 1/12 drm/msm/dsi: Don't get byte/pixel source clocks from DT

We retrieve the byte and pixel source clocks (RCG clocks) in the dsi driver via DT. These are needed so that we can re-parent these source clocks if we want to drive it using a different DSI PLL.

We shouldn't get these via DT because they aren't clocks that directly serve as inputs to the dsi host.

Fortunately, there is a static parent-child link between the byte_clk_src/pixel_clk_src and byte_clk/pixel_clk clocks. So, we can retrieve the source clocks via clk_get_parent.

Do this instead of retrieving via DT.

Cc Rob Herring <[email protected]>
Cc Stephen Boyd <[email protected]>
---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 15 ++++++---------
 1 file changed, 6 insertions(+), 9 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +6 -9
index 4c49868..aec97c8 100644
@@ -356,20 +356,17 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host)
 		goto exit;
 	}
 
-	msm_host->byte_clk_src = devm_clk_get(dev, "byte_clk_src");
-	if (IS_ERR(msm_host->byte_clk_src)) {
-		ret = PTR_ERR(msm_host->byte_clk_src);
+	msm_host->byte_clk_src = clk_get_parent(msm_host->byte_clk);
+	if (!msm_host->byte_clk_src) {
+		ret = -ENODEV;
 		pr_err("%s: can't find byte_clk_src. ret=%d\n", __func__, ret);
-		msm_host->byte_clk_src = NULL;
 		goto exit;
 	}
 
-	msm_host->pixel_clk_src = devm_clk_get(dev, "pixel_clk_src");
-	if (IS_ERR(msm_host->pixel_clk_src)) {
-		ret = PTR_ERR(msm_host->pixel_clk_src);
+	msm_host->pixel_clk_src = clk_get_parent(msm_host->pixel_clk);
+	if (!msm_host->pixel_clk_src) {
+		ret = -ENODEV;
 		pr_err("%s: can't find pixel_clk_src. ret=%d\n", __func__, ret);
-		msm_host->pixel_clk_src = NULL;
-		goto exit;
 	}
 
 exit:
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#40 lore raw

PATCH v3 2/12 drm/msm/dsi: Add support for 28nm PHY on 8960

In reply to Archit Taneja

DSI PHY on MSM8960 and APQ8064 is a 28nm PHY that's different from the supported 28nm LP PHY found in newer chips.

Add support for the new PHY.

---
 drivers/gpu/drm/msm/Kconfig                     |   8 +
 drivers/gpu/drm/msm/Makefile                    |   1 +
 drivers/gpu/drm/msm/dsi/dsi.h                   |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.c           |   4 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy.h           |   1 +
 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c | 195 ++++++++++++++++++++++++
 6 files changed, 210 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c
drivers/gpu/drm/msm/Kconfig +8 -0
index 84d3ec9..215495c 100644
@@ -54,3 +54,11 @@ config DRM_MSM_DSI_20NM_PHY
 	default y
 	help
 	  Choose this option if the 20nm DSI PHY is used on the platform.
+
+config DRM_MSM_DSI_28NM_8960_PHY
+	bool "Enable DSI 28nm 8960 PHY driver in MSM DRM"
+	depends on DRM_MSM_DSI
+	default y
+	help
+	  Choose this option if the 28nm DSI PHY 8960 variant is used on the
+	  platform.
drivers/gpu/drm/msm/Makefile +1 -0
index 2224fdd..1888fd3 100644
@@ -63,6 +63,7 @@ msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
 
 msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/phy/dsi_phy_28nm.o
 msm-$(CONFIG_DRM_MSM_DSI_20NM_PHY) += dsi/phy/dsi_phy_20nm.o
+msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o
 
 ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)
 msm-y += dsi/pll/dsi_pll.o
drivers/gpu/drm/msm/dsi/dsi.h +1 -0
index 5f5a373..8140e8b 100644
@@ -31,6 +31,7 @@ enum msm_dsi_phy_type {
 	MSM_DSI_PHY_28NM_HPM,
 	MSM_DSI_PHY_28NM_LP,
 	MSM_DSI_PHY_20NM,
+	MSM_DSI_PHY_28NM_8960,
 	MSM_DSI_PHY_MAX
 };
 
drivers/gpu/drm/msm/dsi/phy/dsi_phy.c +4 -0
index f1f955f..91a95fb 100644
@@ -277,6 +277,10 @@ static const struct of_device_id dsi_phy_dt_match[] = {
 	{ .compatible = "qcom,dsi-phy-20nm",
 	  .data = &dsi_phy_20nm_cfgs },
 #endif
+#ifdef CONFIG_DRM_MSM_DSI_28NM_8960_PHY
+	{ .compatible = "qcom,dsi-phy-28nm-8960",
+	  .data = &dsi_phy_28nm_8960_cfgs },
+#endif
 	{}
 };
 
drivers/gpu/drm/msm/dsi/phy/dsi_phy.h +1 -0
index 0456b25..0d54ed0 100644
@@ -43,6 +43,7 @@ struct msm_dsi_phy_cfg {
 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_hpm_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_28nm_lp_cfgs;
 extern const struct msm_dsi_phy_cfg dsi_phy_20nm_cfgs;
+extern const struct msm_dsi_phy_cfg dsi_phy_28nm_8960_cfgs;
 
 struct msm_dsi_dphy_timing {
 	u32 clk_pre;
drivers/gpu/drm/msm/dsi/phy/dsi_phy_28nm_8960.c new file +195 -0

195 lines not on this page · raw message

Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#41 lore raw

PATCH v3 3/12 drm/msm/dsi: Add DSI PLL for 28nm 8960 PHY

In reply to Archit Taneja

Add DSI PLL common clock framework clocks for 8960 PHY.

The PLL here is different from the ones found in B family msm chips. As before, the DSI provides two clocks to the outside world. dsixpll and dsixpllbyte (x = 1, 2). dsixpll is a regular clock divider, but dsixpllbyte is modelled as a custom clock divider.

dsixpllbyte is the starting point of the PLL configuration. It is the one that sets up the VCO clock rate. We need the VCO clock rate in the
form: F * byteclk, where F is a multiplication factor that varies on the byte clock the DSI driver is trying to set. We use the custom clk_ops for dsixpllbyte to ensure that the parent (VCO) is set at this rate.

An additional divider (POSTDIV1) generates the bitclk. Since bit clock can be derived from byteclock, we calculate it internally, and don't expose it as a clock.

---
 drivers/gpu/drm/msm/Makefile                    |   1 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.c           |   3 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll.h           |  10 +
 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c | 533 ++++++++++++++++++++++++
 4 files changed, 547 insertions(+)
 create mode 100644 drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c
drivers/gpu/drm/msm/Makefile +1 -0
index 1888fd3..065ad41 100644
@@ -68,6 +68,7 @@ msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/phy/dsi_phy_28nm_8960.o
 ifeq ($(CONFIG_DRM_MSM_DSI_PLL),y)
 msm-y += dsi/pll/dsi_pll.o
 msm-$(CONFIG_DRM_MSM_DSI_28NM_PHY) += dsi/pll/dsi_pll_28nm.o
+msm-$(CONFIG_DRM_MSM_DSI_28NM_8960_PHY) += dsi/pll/dsi_pll_28nm_8960.o
 endif
 
 obj-$(CONFIG_DRM_MSM)	+= msm.o
drivers/gpu/drm/msm/dsi/pll/dsi_pll.c +3 -0
index 5104fc9..5cd438f 100644
@@ -151,6 +151,9 @@ struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
 	case MSM_DSI_PHY_28NM_LP:
 		pll = msm_dsi_pll_28nm_init(pdev, type, id);
 		break;
+	case MSM_DSI_PHY_28NM_8960:
+		pll = msm_dsi_pll_28nm_8960_init(pdev, id);
+		break;
 	default:
 		pll = ERR_PTR(-ENXIO);
 		break;
drivers/gpu/drm/msm/dsi/pll/dsi_pll.h +10 -0
index 063caa2..80b6038 100644
@@ -93,6 +93,16 @@ static inline struct msm_dsi_pll *msm_dsi_pll_28nm_init(
 	return ERR_PTR(-ENODEV);
 }
 #endif
+#ifdef CONFIG_DRM_MSM_DSI_28NM_8960_PHY
+struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device *pdev,
+					       int id);
+#else
+struct msm_dsi_pll *msm_dsi_pll_28nm_8960_init(struct platform_device *pdev,
+					       int id)
+{
+	return ERR_PTR(-ENODEV);
+}
+#endif
 
 #endif /* __DSI_PLL_H__ */
 
drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm_8960.c new file +533 -0

533 lines not on this page · raw message

Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#42 lore raw

PATCH v3 4/12 drm/msm/dsi: Use a better way to figure out DSI version

In reply to Archit Taneja

The current version checking mechanism works fine for DSI6G blocks. It doesn't work so well for older generation DSIv2 blocks.

The initial read of REG_DSI_6G_HW_VERSION(offset 0x0) would result in a read of REG_DSI_CTRL for DSIv2. This register won't necessarily be 0 on DSIv2. It can be non zero if DSI was previously initialized by the bootloader.

Instead of reading offset 0x0, we now read offset 0x1f0. For DSIv2, this register is DSI_VERSION, and is bound to be non-zero. On DSI6G, this register(offset 0x1f0) is SCRATCH_REGISTER_0, which no one ever seems to touch, and from all register dumps I'vc seen, holds 0 all the time.

Modify dsi_get_version to read REG_DSI_VERSION to determine whether we are DSI6G or DSIv2.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 24 ++++++++++++++++++------
 1 file changed, 18 insertions(+), 6 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +18 -6
index aec97c8..7a365df 100644
@@ -33,17 +33,24 @@
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 {
 	u32 ver;
-	u32 ver_6g;
 
 	if (!major || !minor)
 		return -EINVAL;
 
-	/* From DSI6G(v3), addition of a 6G_HW_VERSION register at offset 0
+	/*
+	 * From DSI6G(v3), addition of a 6G_HW_VERSION register at offset 0
 	 * makes all other registers 4-byte shifted down.
+	 *
+	 * In order to identify between DSI6G(v3) and beyond, and DSIv2 and
+	 * older, we read the DSI_VERSION register without any shift(offset
+	 * 0x1f0). In the case of DSIv2, this hast to be a non-zero value. In
+	 * the case of DSI6G, this has to be zero (the offset points to a
+	 * scratch register which we never touch)
 	 */
-	ver_6g = msm_readl(base + REG_DSI_6G_HW_VERSION);
-	if (ver_6g == 0) {
-		ver = msm_readl(base + REG_DSI_VERSION);
+
+	ver = msm_readl(base + REG_DSI_VERSION);
+	if (ver) {
+		/* older dsi host, there is no register shift */
 		ver = FIELD(ver, DSI_VERSION_MAJOR);
 		if (ver <= MSM_DSI_VER_MAJOR_V2) {
 			/* old versions */
@@ -54,12 +61,17 @@ static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
 			return -EINVAL;
 		}
 	} else {
+		/*
+		 * newer host, offset 0 has 6G_HW_VERSION, the rest of the
+		 * registers are shifted down, read DSI_VERSION again with
+		 * the shifted offset
+		 */
 		ver = msm_readl(base + DSI_6G_REG_SHIFT + REG_DSI_VERSION);
 		ver = FIELD(ver, DSI_VERSION_MAJOR);
 		if (ver == MSM_DSI_VER_MAJOR_6G) {
 			/* 6G version */
 			*major = ver;
-			*minor = ver_6g;
+			*minor = msm_readl(base + REG_DSI_6G_HW_VERSION);
 			return 0;
 		} else {
 			return -EINVAL;
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#43 lore raw

PATCH v3 5/12 drm/msm/dsi: Delay dsi_clk_init

In reply to Archit Taneja

Initialize clocks only after we get the DSI host version. This will allow us to get clocks using a pre-defined list based on the DSI major/minor version of the host. This is required since clock requirements of different major DSI revisions(v2 vs 6g) aren't the same.

Modify dsi_get_version to get the interface clock, and then put it after it is used.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 32 ++++++++++++++++++++++----------
 1 file changed, 22 insertions(+), 10 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +22 -10
index 7a365df..f787024 100644
@@ -177,21 +177,31 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
 						struct msm_dsi_host *msm_host)
 {
 	const struct msm_dsi_cfg_handler *cfg_hnd = NULL;
+	struct device *dev = &msm_host->pdev->dev;
 	struct regulator *gdsc_reg;
+	struct clk *ahb_clk;
 	int ret;
 	u32 major = 0, minor = 0;
 
-	gdsc_reg = regulator_get(&msm_host->pdev->dev, "gdsc");
+	gdsc_reg = regulator_get(dev, "gdsc");
 	if (IS_ERR(gdsc_reg)) {
 		pr_err("%s: cannot get gdsc\n", __func__);
 		goto exit;
 	}
+
+	ahb_clk = clk_get(dev, "iface_clk");
+	if (IS_ERR(ahb_clk)) {
+		pr_err("%s: cannot get interface clock\n", __func__);
+		goto put_gdsc;
+	}
+
 	ret = regulator_enable(gdsc_reg);
 	if (ret) {
 		pr_err("%s: unable to enable gdsc\n", __func__);
-		goto put_gdsc;
+		goto put_clk;
 	}
-	ret = clk_prepare_enable(msm_host->ahb_clk);
+
+	ret = clk_prepare_enable(ahb_clk);
 	if (ret) {
 		pr_err("%s: unable to enable ahb_clk\n", __func__);
 		goto disable_gdsc;
@@ -208,9 +218,11 @@ static const struct msm_dsi_cfg_handler *dsi_get_config(
 	DBG("%s: Version %x:%x\n", __func__, major, minor);
 
 disable_clks:
-	clk_disable_unprepare(msm_host->ahb_clk);
+	clk_disable_unprepare(ahb_clk);
 disable_gdsc:
 	regulator_disable(gdsc_reg);
+put_clk:
+	clk_put(ahb_clk);
 put_gdsc:
 	regulator_put(gdsc_reg);
 exit:
@@ -1417,12 +1429,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 		goto fail;
 	}
 
-	ret = dsi_clk_init(msm_host);
-	if (ret) {
-		pr_err("%s: unable to initialize dsi clks\n", __func__);
-		goto fail;
-	}
-
 	msm_host->ctrl_base = msm_ioremap(pdev, "dsi_ctrl", "DSI CTRL");
 	if (IS_ERR(msm_host->ctrl_base)) {
 		pr_err("%s: unable to map Dsi ctrl base\n", __func__);
@@ -1446,6 +1452,12 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
 		goto fail;
 	}
 
+	ret = dsi_clk_init(msm_host);
+	if (ret) {
+		pr_err("%s: unable to initialize dsi clks\n", __func__);
+		goto fail;
+	}
+
 	msm_host->rx_buf = devm_kzalloc(&pdev->dev, SZ_4K, GFP_KERNEL);
 	if (!msm_host->rx_buf) {
 		pr_err("%s: alloc rx temp buf failed\n", __func__);
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#44 lore raw

PATCH v3 6/12 drm/msm/dsi: Parse bus clocks from a list

In reply to Archit Taneja

DSI bus clocks seem to vary between different DSI host versions, and the SOC to which they belong. Even the enable/disable sequence varies.

Provide a list of bus clock names in dsi_cfg. The driver will use this to retrieve the clocks, and enable/disable them.

Add bus clock lists for DSI6G, and DSI for MSM8916(this is DSI6G too, but there is no MMSS_CC specific clock since there is no MMSS clock controller on 8916).

---
 drivers/gpu/drm/msm/dsi/dsi.h      |   1 +
 drivers/gpu/drm/msm/dsi/dsi_cfg.c  |  16 +++++-
 drivers/gpu/drm/msm/dsi/dsi_cfg.h  |   2 +
 drivers/gpu/drm/msm/dsi/dsi_host.c | 107 ++++++++++++-------------------------
 4 files changed, 53 insertions(+), 73 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.h +1 -0
index 8140e8b..7336b55 100644
@@ -36,6 +36,7 @@ enum msm_dsi_phy_type {
 };
 
 #define DSI_DEV_REGULATOR_MAX	8
+#define DSI_BUS_CLK_MAX		4
 
 /* Regulators for DSI devices */
 struct dsi_reg_entry {
drivers/gpu/drm/msm/dsi/dsi_cfg.c +15 -1
index 5872d5e..c40044f 100644
@@ -18,6 +18,10 @@ static const struct msm_dsi_config dsi_v2_cfg = {
 	.io_offset = 0,
 };
 
+static const char * const dsi_6g_bus_clk_names[] = {
+	"mdp_core_clk", "iface_clk", "bus_clk", "core_mmss_clk",
+};
+
 static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
 	.io_offset = DSI_6G_REG_SHIFT,
 	.reg_cfg = {
@@ -29,6 +33,12 @@ static const struct msm_dsi_config msm8974_apq8084_dsi_cfg = {
 			{"vddio", 1800000, 1800000, 100000, 100},
 		},
 	},
+	.bus_clk_names = dsi_6g_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names),
+};
+
+static const char * const dsi_8916_bus_clk_names[] = {
+	"mdp_core_clk", "iface_clk", "bus_clk",
 };
 
 static const struct msm_dsi_config msm8916_dsi_cfg = {
@@ -42,6 +52,8 @@ static const struct msm_dsi_config msm8916_dsi_cfg = {
 			{"vddio", 1800000, 1800000, 100000, 100},
 		},
 	},
+	.bus_clk_names = dsi_8916_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_8916_bus_clk_names),
 };
 
 static const struct msm_dsi_config msm8994_dsi_cfg = {
@@ -57,7 +69,9 @@ static const struct msm_dsi_config msm8994_dsi_cfg = {
 			{"lab_reg", -1, -1, -1, -1},
 			{"ibb_reg", -1, -1, -1, -1},
 		},
-	}
+	},
+	.bus_clk_names = dsi_6g_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_6g_bus_clk_names),
 };
 
 static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
drivers/gpu/drm/msm/dsi/dsi_cfg.h +2 -0
index 4cf8872..5a36836 100644
@@ -30,6 +30,8 @@
 struct msm_dsi_config {
 	u32 io_offset;
 	struct dsi_reg_config reg_cfg;
+	const char * const *bus_clk_names;
+	const int num_bus_clks;
 };
 
 struct msm_dsi_cfg_handler {
drivers/gpu/drm/msm/dsi/dsi_host.c +35 -72

140 lines not on this page · raw message

Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#45 lore raw

PATCH v3 7/12 drm/msm/dsi: Set up link clocks for DSIv2

In reply to Archit Taneja

DSIv2 (DSI on older A family chips) has slightly different link clock requirements.

First, we have an extra clock called src_clk (with a dedicated RCG). This is required by the DSI controller to process the pixel data coming from MDP. It needs to be set at the rate "pclk * bytes_per_pixel".

We also need to explicitly configure esc_clk. On DSI6G chips, we don't need to set a rate to esc_clk because its RCG is always sourced from crystal clock (19.2 Mhz in all cases), which is within the escape clock frequency range in the mipi DSI spec. For chips with DSIv2, the crystal clock rate may not be within the required range (27Mhz on APQ8064). Therefore, we derive it from the DSI byte clock. We calculate an esc_clck rate that is within the mipi spec and also divisible by the byte clock rate.

When setting rate and enabling the link clocks, we make sure that byte_clk is configured before esc_clk, and src_clk before pixel_clk. We create two different link_enable funcs for DSI6G and DSIv2 since the sequences are different.

We also obtain two extra source clocks (dsi_src_clk and esc_src_clk) and set their parent to the clocks provided by DSI PLL.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 191 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 186 insertions(+), 5 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_host.c +186 -5
index 56c7535..6ec2178 100644
@@ -113,6 +113,14 @@ struct msm_dsi_host {
 	struct clk *pixel_clk_src;
 
 	u32 byte_clk_rate;
+	u32 esc_clk_rate;
+
+	/* DSI v2 specific clocks */
+	struct clk *src_clk;
+	struct clk *esc_clk_src;
+	struct clk *dsi_clk_src;
+
+	u32 src_clk_rate;
 
 	struct gpio_desc *disp_en_gpio;
 	struct gpio_desc *te_gpio;
@@ -318,7 +326,8 @@ static int dsi_regulator_init(struct msm_dsi_host *msm_host)
 static int dsi_clk_init(struct msm_dsi_host *msm_host)
 {
 	struct device *dev = &msm_host->pdev->dev;
-	const struct msm_dsi_config *cfg = msm_host->cfg_hnd->cfg;
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
+	const struct msm_dsi_config *cfg = cfg_hnd->cfg;
 	int i, ret = 0;
 
 	/* get bus clocks */
@@ -372,8 +381,34 @@ static int dsi_clk_init(struct msm_dsi_host *msm_host)
 	if (!msm_host->pixel_clk_src) {
 		ret = -ENODEV;
 		pr_err("%s: can't find pixel_clk_src. ret=%d\n", __func__, ret);
+		goto exit;
 	}
 
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) {
+		msm_host->src_clk = devm_clk_get(dev, "src_clk");
+		if (IS_ERR(msm_host->src_clk)) {
+			ret = PTR_ERR(msm_host->src_clk);
+			pr_err("%s: can't find dsi_src_clk. ret=%d\n",
+				__func__, ret);
+			msm_host->src_clk = NULL;
+			goto exit;
+		}
+
+		msm_host->esc_clk_src = clk_get_parent(msm_host->esc_clk);
+		if (!msm_host->esc_clk_src) {
+			ret = -ENODEV;
+			pr_err("%s: can't get esc_clk_src. ret=%d\n",
+				__func__, ret);
+			goto exit;
+		}
+
+		msm_host->dsi_clk_src = clk_get_parent(msm_host->src_clk);
+		if (!msm_host->dsi_clk_src) {
+			ret = -ENODEV;
+			pr_err("%s: can't get dsi_clk_src. ret=%d\n",
+				__func__, ret);
+		}
+	}
 exit:
 	return ret;
 }
@@ -413,7 +448,7 @@ static void dsi_bus_clk_disable(struct msm_dsi_host *msm_host)
 		clk_disable_unprepare(msm_host->bus_clks[i]);
 }
 
-static int dsi_link_clk_enable(struct msm_dsi_host *msm_host)
+static int dsi_link_clk_enable_6g(struct msm_dsi_host *msm_host)
 {
 	int ret;
 
@@ -460,11 +495,98 @@ error:
 	return ret;
 }
 
-static void dsi_link_clk_disable(struct msm_dsi_host *msm_host)
+static int dsi_link_clk_enable_v2(struct msm_dsi_host *msm_host)
 {
+	int ret;
+
+	DBG("Set clk rates: pclk=%d, byteclk=%d, esc_clk=%d, dsi_src_clk=%d",
+		msm_host->mode->clock, msm_host->byte_clk_rate,
+		msm_host->esc_clk_rate, msm_host->src_clk_rate);
+
+	ret = clk_set_rate(msm_host->byte_clk, msm_host->byte_clk_rate);
+	if (ret) {
+		pr_err("%s: Failed to set rate byte clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_set_rate(msm_host->esc_clk, msm_host->esc_clk_rate);
+	if (ret) {
+		pr_err("%s: Failed to set rate esc clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_set_rate(msm_host->src_clk, msm_host->src_clk_rate);
+	if (ret) {
+		pr_err("%s: Failed to set rate src clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_set_rate(msm_host->pixel_clk, msm_host->mode->clock * 1000);
+	if (ret) {
+		pr_err("%s: Failed to set rate pixel clk, %d\n", __func__, ret);
+		goto error;
+	}
+
+	ret = clk_prepare_enable(msm_host->byte_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi byte clk\n", __func__);
+		goto error;
+	}
+
+	ret = clk_prepare_enable(msm_host->esc_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi esc clk\n", __func__);
+		goto esc_clk_err;
+	}
+
+	ret = clk_prepare_enable(msm_host->src_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi src clk\n", __func__);
+		goto src_clk_err;
+	}
+
+	ret = clk_prepare_enable(msm_host->pixel_clk);
+	if (ret) {
+		pr_err("%s: Failed to enable dsi pixel clk\n", __func__);
+		goto pixel_clk_err;
+	}
+
+	return 0;
+
+pixel_clk_err:
+	clk_disable_unprepare(msm_host->src_clk);
+src_clk_err:
 	clk_disable_unprepare(msm_host->esc_clk);
-	clk_disable_unprepare(msm_host->pixel_clk);
+esc_clk_err:
 	clk_disable_unprepare(msm_host->byte_clk);
+error:
+	return ret;
+}
+
+static int dsi_link_clk_enable(struct msm_dsi_host *msm_host)
+{
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
+
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G)
+		return dsi_link_clk_enable_6g(msm_host);
+	else
+		return dsi_link_clk_enable_v2(msm_host);
+}
+
+static void dsi_link_clk_disable(struct msm_dsi_host *msm_host)
+{
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
+
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_6G) {
+		clk_disable_unprepare(msm_host->esc_clk);
+		clk_disable_unprepare(msm_host->pixel_clk);
+		clk_disable_unprepare(msm_host->byte_clk);
+	} else {
+		clk_disable_unprepare(msm_host->pixel_clk);
+		clk_disable_unprepare(msm_host->src_clk);
+		clk_disable_unprepare(msm_host->esc_clk);
+		clk_disable_unprepare(msm_host->byte_clk);
+	}
 }
 
 static int dsi_clk_ctrl(struct msm_dsi_host *msm_host, bool enable)
@@ -499,6 +621,7 @@ unlock_ret:
 static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host)
 {
 	struct drm_display_mode *mode = msm_host->mode;
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
 	u8 lanes = msm_host->lanes;
 	u32 bpp = dsi_get_bpp(msm_host->format);
 	u32 pclk_rate;
@@ -518,6 +641,47 @@ static int dsi_calc_clk_rate(struct msm_dsi_host *msm_host)
 
 	DBG("pclk=%d, bclk=%d", pclk_rate, msm_host->byte_clk_rate);
 
+	msm_host->esc_clk_rate = clk_get_rate(msm_host->esc_clk);
+
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) {
+		unsigned int esc_mhz, esc_div;
+		unsigned long byte_mhz;
+
+		msm_host->src_clk_rate = (pclk_rate * bpp) / 8;
+
+		/*
+		 * esc clock is byte clock followed by a 4 bit divider,
+		 * we need to find an escape clock frequency within the
+		 * mipi DSI spec range within the maximum divider limit
+		 * We iterate here between an escape clock frequencey
+		 * between 20 Mhz to 5 Mhz and pick up the first one
+		 * that can be supported by our divider
+		 */
+
+		byte_mhz = msm_host->byte_clk_rate / 1000000;
+
+		for (esc_mhz = 20; esc_mhz >= 5; esc_mhz--) {
+			esc_div = DIV_ROUND_UP(byte_mhz, esc_mhz);
+
+			/*
+			 * TODO: Ideally, we shouldn't know what sort of divider
+			 * is available in mmss_cc, we're just assuming that
+			 * it'll always be a 4 bit divider. Need to come up with
+			 * a better way here.
+			 */
+			if (esc_div >= 1 && esc_div <= 16)
+				break;
+		}
+
+		if (esc_mhz < 5)
+			return -EINVAL;
+
+		msm_host->esc_clk_rate = msm_host->byte_clk_rate / esc_div;
+
+		DBG("esc=%d, src=%d", msm_host->esc_clk_rate,
+			msm_host->src_clk_rate);
+	}
+
 	return 0;
 }
 
@@ -1750,6 +1914,7 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
 	struct msm_dsi_pll *src_pll)
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
+	const struct msm_dsi_cfg_handler *cfg_hnd = msm_host->cfg_hnd;
 	struct clk *byte_clk_provider, *pixel_clk_provider;
 	int ret;
 
@@ -1775,6 +1940,22 @@ int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
 		goto exit;
 	}
 
+	if (cfg_hnd->major == MSM_DSI_VER_MAJOR_V2) {
+		ret = clk_set_parent(msm_host->dsi_clk_src, pixel_clk_provider);
+		if (ret) {
+			pr_err("%s: can't set parent to dsi_clk_src. ret=%d\n",
+				__func__, ret);
+			goto exit;
+		}
+
+		ret = clk_set_parent(msm_host->esc_clk_src, byte_clk_provider);
+		if (ret) {
+			pr_err("%s: can't set parent to esc_clk_src. ret=%d\n",
+				__func__, ret);
+			goto exit;
+		}
+	}
+
 exit:
 	return ret;
 }
@@ -1846,7 +2027,7 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 	dsi_phy_sw_reset(msm_host);
 	ret = msm_dsi_manager_phy_enable(msm_host->id,
 					msm_host->byte_clk_rate * 8,
-					clk_get_rate(msm_host->esc_clk),
+					msm_host->esc_clk_rate,
 					&clk_pre, &clk_post);
 	dsi_bus_clk_disable(msm_host);
 	if (ret) {
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#46 lore raw

PATCH v3 8/12 drm/msm/dsi: Add dsi_cfg for APQ8064

In reply to Archit Taneja

Add a dsi_cfg entry for APQ8064. Since this is the first DSIv2 chip to be supported, add a list of bus clocks that are required by the DSIv2 block.

---
 drivers/gpu/drm/msm/dsi/dsi_cfg.c | 19 ++++++++++++++++---
 drivers/gpu/drm/msm/dsi/dsi_cfg.h |  2 ++
 2 files changed, 18 insertions(+), 3 deletions(-)
drivers/gpu/drm/msm/dsi/dsi_cfg.c +16 -3
index c40044f..2a827d8 100644
@@ -13,9 +13,22 @@
 
 #include "dsi_cfg.h"
 
-/* DSI v2 has not been supported by now */
-static const struct msm_dsi_config dsi_v2_cfg = {
+static const char * const dsi_v2_bus_clk_names[] = {
+	"core_mmss_clk", "iface_clk", "bus_clk",
+};
+
+static const struct msm_dsi_config apq8064_dsi_cfg = {
 	.io_offset = 0,
+	.reg_cfg = {
+		.num = 3,
+		.regs = {
+			{"vdda", 1200000, 1200000, 100000, 100},
+			{"avdd", 3000000, 3000000, 110000, 100},
+			{"vddio", 1800000, 1800000, 100000, 100},
+		},
+	},
+	.bus_clk_names = dsi_v2_bus_clk_names,
+	.num_bus_clks = ARRAY_SIZE(dsi_v2_bus_clk_names),
 };
 
 static const char * const dsi_6g_bus_clk_names[] = {
@@ -75,7 +88,7 @@ static const struct msm_dsi_config msm8994_dsi_cfg = {
 };
 
 static const struct msm_dsi_cfg_handler dsi_cfg_handlers[] = {
-	{MSM_DSI_VER_MAJOR_V2, U32_MAX, &dsi_v2_cfg},
+	{MSM_DSI_VER_MAJOR_V2, MSM_DSI_V2_VER_MINOR_8064, &apq8064_dsi_cfg},
 	{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_0,
 						&msm8974_apq8084_dsi_cfg},
 	{MSM_DSI_VER_MAJOR_6G, MSM_DSI_6G_VER_MINOR_V1_1,
drivers/gpu/drm/msm/dsi/dsi_cfg.h +2 -0
index 5a36836..a68c836 100644
@@ -25,6 +25,8 @@
 #define MSM_DSI_6G_VER_MINOR_V1_3	0x10030000
 #define MSM_DSI_6G_VER_MINOR_V1_3_1	0x10030001
 
+#define MSM_DSI_V2_VER_MINOR_8064	0x0
+
 #define DSI_6G_REG_SHIFT	4
 
 struct msm_dsi_config {
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#47 lore raw

PATCH v3 9/12 drm/msm/dsi: Don't use iommu for command TX buffer for DSIv2

In reply to Archit Taneja

We currently use iommu allocated DMA buffers for sending DSI commands. DSIv2 doesn't have a port connected to the MDP iommu. Therefore, it can't use iommu allocated buffers to fetch DSI commands.

Use a regular contiguous DMA buffer if we are DSIv2.

---
 drivers/gpu/drm/msm/dsi/dsi.h         |   4 +-
 drivers/gpu/drm/msm/dsi/dsi_host.c    | 110 +++++++++++++++++++++++-----------
 drivers/gpu/drm/msm/dsi/dsi_manager.c |   6 +-
 3 files changed, 79 insertions(+), 41 deletions(-)
drivers/gpu/drm/msm/dsi/dsi.h +2 -2
index 7336b55..749fbb2 100644
@@ -91,7 +91,7 @@ int msm_dsi_manager_phy_enable(int id,
 		u32 *clk_pre, u32 *clk_post);
 void msm_dsi_manager_phy_disable(int id);
 int msm_dsi_manager_cmd_xfer(int id, const struct mipi_dsi_msg *msg);
-bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len);
+bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len);
 int msm_dsi_manager_register(struct msm_dsi *msm_dsi);
 void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
 
@@ -145,7 +145,7 @@ int msm_dsi_host_cmd_tx(struct mipi_dsi_host *host,
 int msm_dsi_host_cmd_rx(struct mipi_dsi_host *host,
 					const struct mipi_dsi_msg *msg);
 void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host,
-					u32 iova, u32 len);
+					u32 dma_base, u32 len);
 int msm_dsi_host_enable(struct mipi_dsi_host *host);
 int msm_dsi_host_disable(struct mipi_dsi_host *host);
 int msm_dsi_host_power_on(struct mipi_dsi_host *host);
drivers/gpu/drm/msm/dsi/dsi_host.c +74 -36

183 lines not on this page · raw message

drivers/gpu/drm/msm/dsi/dsi_manager.c +3 -3
index 0455ff7..58ba7ec 100644
@@ -774,7 +774,7 @@ restore_host0:
 	return ret;
 }
 
-bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len)
+bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 dma_base, u32 len)
 {
 	struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
 	struct msm_dsi *msm_dsi0 = dsi_mgr_get_dsi(DSI_0);
@@ -784,9 +784,9 @@ bool msm_dsi_manager_cmd_xfer_trigger(int id, u32 iova, u32 len)
 		return false;
 
 	if (IS_SYNC_NEEDED() && msm_dsi0)
-		msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, iova, len);
+		msm_dsi_host_cmd_xfer_commit(msm_dsi0->host, dma_base, len);
 
-	msm_dsi_host_cmd_xfer_commit(host, iova, len);
+	msm_dsi_host_cmd_xfer_commit(host, dma_base, len);
 
 	return true;
 }
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#48 lore raw

PATCH v3 10/12 drm/msm/dsi: Enable MMSS SPFB port via syscon

In reply to Archit Taneja

For DSIv2 to work, we need to enable MMSS_AHB_ARB_MASTER_PORT in MMSS_SFPB. We enable the required bitfield by retrieving MMSS_SFPB regmap pointer via syscon.

---
 drivers/gpu/drm/msm/dsi/dsi_host.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)
drivers/gpu/drm/msm/dsi/dsi_host.c +33 -0
index bbf7f72..f61b88e 100644
@@ -24,10 +24,13 @@
 #include <linux/of_graph.h>
 #include <linux/regulator/consumer.h>
 #include <linux/spinlock.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 #include <video/mipi_display.h>
 
 #include "dsi.h"
 #include "dsi.xml.h"
+#include "sfpb.xml.h"
 #include "dsi_cfg.h"
 
 static int dsi_get_version(const void __iomem *base, u32 *major, u32 *minor)
@@ -149,6 +152,8 @@ struct msm_dsi_host {
 
 	u8 *rx_buf;
 
+	struct regmap *sfpb;
+
 	struct drm_display_mode *mode;
 
 	/* connected device info */
@@ -1568,6 +1573,16 @@ static int dsi_host_parse_dt(struct msm_dsi_host *msm_host)
 
 	msm_host->device_node = device_node;
 
+	if (of_property_read_bool(np, "syscon-sfpb")) {
+		msm_host->sfpb = syscon_regmap_lookup_by_phandle(np,
+					"syscon-sfpb");
+		if (IS_ERR(msm_host->sfpb)) {
+			dev_err(dev, "%s: failed to get sfpb regmap\n",
+				__func__);
+			return PTR_ERR(msm_host->sfpb);
+		}
+	}
+
 	return 0;
 }
 
@@ -2031,6 +2046,20 @@ int msm_dsi_host_disable(struct mipi_dsi_host *host)
 	return 0;
 }
 
+static void msm_dsi_sfpb_config(struct msm_dsi_host *msm_host, bool enable)
+{
+	enum sfpb_ahb_arb_master_port_en en;
+
+	if (!msm_host->sfpb)
+		return;
+
+	en = enable ? SFPB_MASTER_PORT_ENABLE : SFPB_MASTER_PORT_DISABLE;
+
+	regmap_update_bits(msm_host->sfpb, REG_SFPB_GPREG,
+			SFPB_GPREG_MASTER_PORT_EN__MASK,
+			SFPB_GPREG_MASTER_PORT_EN(en));
+}
+
 int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 {
 	struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
@@ -2043,6 +2072,8 @@ int msm_dsi_host_power_on(struct mipi_dsi_host *host)
 		goto unlock_ret;
 	}
 
+	msm_dsi_sfpb_config(msm_host, true);
+
 	ret = dsi_calc_clk_rate(msm_host);
 	if (ret) {
 		pr_err("%s: unable to calc clk rate, %d\n", __func__, ret);
@@ -2130,6 +2161,8 @@ int msm_dsi_host_power_off(struct mipi_dsi_host *host)
 
 	dsi_host_regulator_disable(msm_host);
 
+	msm_dsi_sfpb_config(msm_host, false);
+
 	DBG("-");
 
 	msm_host->power_on = false;
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#49 lore raw

PATCH v3 11/12 dt-bindings: msm/dsi: Fix the order in which clocks are listed

In reply to Archit Taneja

List the clocks in the order that's used in DT. We don't have mdp/dsi DT nodes for any SoC in upstream yet, but we align with the order we intend to use.

---
 Documentation/devicetree/bindings/display/msm/dsi.txt | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
Documentation/devicetree/bindings/display/msm/dsi.txt +4 -4
index f344b9e..e097955 100644
@@ -14,13 +14,13 @@ Required properties:
 - clocks: device clocks
   See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
 - clock-names: the following clocks are required:
+  * "mdp_core_clk"
+  * "iface_clk"
   * "bus_clk"
-  * "byte_clk"
-  * "core_clk"
   * "core_mmss_clk"
-  * "iface_clk"
-  * "mdp_core_clk"
+  * "byte_clk"
   * "pixel_clk"
+  * "core_clk"
 - vdd-supply: phandle to vdd regulator device node
 - vddio-supply: phandle to vdd-io regulator device node
 - vdda-supply: phandle to vdda regulator device node
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
maintainer Acked-by on v3 11/12
#50 lore raw

Re: [PATCH v3 11/12] dt-bindings: msm/dsi: Fix the order in which clocks are listed

Quoted 8 lines · Archit Taneja

List the clocks in the order that's used in DT. We don't have mdp/dsi DT nodes for any SoC in upstream yet, but we align with the order we intend to use.

Quoted 30 lines
---
 Documentation/devicetree/bindings/display/msm/dsi.txt | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
Documentation/devicetree/bindings/display/msm/dsi.txt +4 -4
index f344b9e..e097955 100644
@@ -14,13 +14,13 @@ Required properties:
 - clocks: device clocks
   See Documentation/devicetree/bindings/clocks/clock-bindings.txt for details.
 - clock-names: the following clocks are required:
+  * "mdp_core_clk"
+  * "iface_clk"
   * "bus_clk"
-  * "byte_clk"
-  * "core_clk"
   * "core_mmss_clk"
-  * "iface_clk"
-  * "mdp_core_clk"
+  * "byte_clk"
   * "pixel_clk"
+  * "core_clk"
 - vdd-supply: phandle to vdd regulator device node
 - vddio-supply: phandle to vdd-io regulator device node
 - vdda-supply: phandle to vdda regulator device node
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation
#51 lore raw

PATCH v3 12/12 dt-bindings: msm/dsi: Add DSIv2 documentation

In reply to Archit Taneja

Add additional property info needed for DSIv2 DT.

---
 Documentation/devicetree/bindings/display/msm/dsi.txt | 4 ++++
 1 file changed, 4 insertions(+)
Documentation/devicetree/bindings/display/msm/dsi.txt +4 -0
index e097955..e7423be 100644
@@ -21,10 +21,13 @@ Required properties:
   * "byte_clk"
   * "pixel_clk"
   * "core_clk"
+  For DSIv2, we need an additional clock:
+   * "src_clk"
 - vdd-supply: phandle to vdd regulator device node
 - vddio-supply: phandle to vdd-io regulator device node
 - vdda-supply: phandle to vdda regulator device node
 - qcom,dsi-phy: phandle to DSI PHY device node
+- syscon-sfpb: A phandle to mmss_sfpb syscon node (only for DSIv2)
 
 Optional properties:
 - panel@0: Node of panel connected to this DSI controller.
@@ -51,6 +54,7 @@ Required properties:
   * "qcom,dsi-phy-28nm-hpm"
   * "qcom,dsi-phy-28nm-lp"
   * "qcom,dsi-phy-20nm"
+  * "qcom,dsi-phy-28nm-8960"
 - reg: Physical base address and length of the registers of PLL, PHY and PHY
   regulator
 - reg-names: The names of register regions. The following regions are required:
Signature · 7 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
maintainer Acked-by on v3 12/12
#52 lore raw

Re: [PATCH v3 12/12] dt-bindings: msm/dsi: Add DSIv2 documentation

Quoted 6 lines · Archit Taneja

Add additional property info needed for DSIv2 DT.

Quoted 34 lines
---
 Documentation/devicetree/bindings/display/msm/dsi.txt | 4 ++++
 1 file changed, 4 insertions(+)
Documentation/devicetree/bindings/display/msm/dsi.txt +4 -0
index e097955..e7423be 100644
@@ -21,10 +21,13 @@ Required properties:
   * "byte_clk"
   * "pixel_clk"
   * "core_clk"
+  For DSIv2, we need an additional clock:
+   * "src_clk"
 - vdd-supply: phandle to vdd regulator device node
 - vddio-supply: phandle to vdd-io regulator device node
 - vdda-supply: phandle to vdda regulator device node
 - qcom,dsi-phy: phandle to DSI PHY device node
+- syscon-sfpb: A phandle to mmss_sfpb syscon node (only for DSIv2)
 
 Optional properties:
 - panel@0: Node of panel connected to this DSI controller.
@@ -51,6 +54,7 @@ Required properties:
   * "qcom,dsi-phy-28nm-hpm"
   * "qcom,dsi-phy-28nm-lp"
   * "qcom,dsi-phy-20nm"
+  * "qcom,dsi-phy-28nm-8960"
 - reg: Physical base address and length of the registers of PLL, PHY and PHY
   regulator
 - reg-names: The names of register regions. The following regions are required:
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel