aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/drm/msm/dsi.txt120
-rw-r--r--Documentation/devicetree/bindings/drm/msm/edp.txt60
-rw-r--r--Documentation/devicetree/bindings/drm/msm/hdmi.txt6
-rw-r--r--drivers/gpu/drm/drm_crtc.c18
-rw-r--r--drivers/gpu/drm/msm/Kconfig7
-rw-r--r--drivers/gpu/drm/msm/Makefile5
-rw-r--r--drivers/gpu/drm/msm/adreno/a2xx.xml.h6
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx.xml.h168
-rw-r--r--drivers/gpu/drm/msm/adreno/a3xx_gpu.c15
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx.xml.h420
-rw-r--r--drivers/gpu/drm/msm/adreno/a4xx_gpu.c3
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_common.xml.h6
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c12
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.c34
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_gpu.h9
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h31
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c43
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.h61
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.xml.h163
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_host.c120
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_manager.c79
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi_phy.c315
-rw-r--r--drivers/gpu/drm/msm/dsi/mmss_cc.xml.h12
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll.c164
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll.h89
-rw-r--r--drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c652
-rw-r--r--drivers/gpu/drm/msm/dsi/sfpb.xml.h12
-rw-r--r--drivers/gpu/drm/msm/edp/edp.xml.h101
-rw-r--r--drivers/gpu/drm/msm/edp/edp_aux.c12
-rw-r--r--drivers/gpu/drm/msm/edp/edp_ctrl.c9
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.xml.h99
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_connector.c43
-rw-r--r--drivers/gpu/drm/msm/hdmi/qfprom.xml.h12
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h32
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c39
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c9
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h3
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c2
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c22
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h398
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c20
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c128
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c11
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h3
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c24
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c7
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h1
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_common.xml.h16
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_format.c6
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_kms.h2
-rw-r--r--drivers/gpu/drm/msm/msm_atomic.c46
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c27
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h4
-rw-r--r--drivers/gpu/drm/msm/msm_gem.c4
-rw-r--r--drivers/gpu/drm/msm/msm_gem.h1
-rw-r--r--drivers/gpu/drm/msm/msm_gem_submit.c1
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.c52
-rw-r--r--drivers/gpu/drm/msm/msm_gpu.h6
-rw-r--r--drivers/gpu/drm/msm/msm_kms.h3
-rw-r--r--include/uapi/drm/drm_fourcc.h15
-rw-r--r--include/uapi/drm/msm_drm.h76
62 files changed, 3475 insertions, 391 deletions
diff --git a/Documentation/devicetree/bindings/drm/msm/dsi.txt b/Documentation/devicetree/bindings/drm/msm/dsi.txt
new file mode 100644
index 000000000000..cd8fe6cf536c
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/msm/dsi.txt
@@ -0,0 +1,120 @@
+Qualcomm Technologies Inc. adreno/snapdragon DSI output
+
+DSI Controller:
+Required properties:
+- compatible:
+ * "qcom,mdss-dsi-ctrl"
+- reg: Physical base address and length of the registers of controller
+- reg-names: The names of register regions. The following regions are required:
+ * "dsi_ctrl"
+- qcom,dsi-host-index: The ID of DSI controller hardware instance. This should
+ be 0 or 1, since we have 2 DSI controllers at most for now.
+- interrupts: The interrupt signal from the DSI block.
+- 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:
+ * "bus_clk"
+ * "byte_clk"
+ * "core_clk"
+ * "core_mmss_clk"
+ * "iface_clk"
+ * "mdp_core_clk"
+ * "pixel_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
+
+Optional properties:
+- panel@0: Node of panel connected to this DSI controller.
+ See files in Documentation/devicetree/bindings/panel/ for each supported
+ panel.
+- qcom,dual-panel-mode: Boolean value indicating if the DSI controller is
+ driving a panel which needs 2 DSI links.
+- qcom,master-panel: Boolean value indicating if the DSI controller is driving
+ the master link of the 2-DSI panel.
+- qcom,sync-dual-panel: Boolean value indicating if the DSI controller is
+ driving a 2-DSI panel whose 2 links need receive command simultaneously.
+- interrupt-parent: phandle to the MDP block if the interrupt signal is routed
+ through MDP block
+
+DSI PHY:
+Required properties:
+- compatible: Could be the following
+ * "qcom,dsi-phy-28nm-hpm"
+ * "qcom,dsi-phy-28nm-lp"
+- 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:
+ * "dsi_pll"
+ * "dsi_phy"
+ * "dsi_phy_regulator"
+- qcom,dsi-phy-index: The ID of DSI PHY hardware instance. This should
+ be 0 or 1, since we have 2 DSI PHYs at most for now.
+- 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:
+ * "iface_clk"
+- vddio-supply: phandle to vdd-io regulator device node
+
+Example:
+ mdss_dsi0: qcom,mdss_dsi@fd922800 {
+ compatible = "qcom,mdss-dsi-ctrl";
+ qcom,dsi-host-index = <0>;
+ interrupt-parent = <&mdss_mdp>;
+ interrupts = <4 0>;
+ reg-names = "dsi_ctrl";
+ reg = <0xfd922800 0x200>;
+ power-domains = <&mmcc MDSS_GDSC>;
+ clock-names =
+ "bus_clk",
+ "byte_clk",
+ "core_clk",
+ "core_mmss_clk",
+ "iface_clk",
+ "mdp_core_clk",
+ "pixel_clk";
+ clocks =
+ <&mmcc MDSS_AXI_CLK>,
+ <&mmcc MDSS_BYTE0_CLK>,
+ <&mmcc MDSS_ESC0_CLK>,
+ <&mmcc MMSS_MISC_AHB_CLK>,
+ <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_MDP_CLK>,
+ <&mmcc MDSS_PCLK0_CLK>;
+ vdda-supply = <&pma8084_l2>;
+ vdd-supply = <&pma8084_l22>;
+ vddio-supply = <&pma8084_l12>;
+
+ qcom,dsi-phy = <&mdss_dsi_phy0>;
+
+ qcom,dual-panel-mode;
+ qcom,master-panel;
+ qcom,sync-dual-panel;
+
+ panel: panel@0 {
+ compatible = "sharp,lq101r1sx01";
+ reg = <0>;
+ link2 = <&secondary>;
+
+ power-supply = <...>;
+ backlight = <...>;
+ };
+ };
+
+ mdss_dsi_phy0: qcom,mdss_dsi_phy@fd922a00 {
+ compatible = "qcom,dsi-phy-28nm-hpm";
+ qcom,dsi-phy-index = <0>;
+ reg-names =
+ "dsi_pll",
+ "dsi_phy",
+ "dsi_phy_regulator";
+ reg = <0xfd922a00 0xd4>,
+ <0xfd922b00 0x2b0>,
+ <0xfd922d80 0x7b>;
+ clock-names = "iface_clk";
+ clocks = <&mmcc MDSS_AHB_CLK>;
+ vddio-supply = <&pma8084_l12>;
+ };
diff --git a/Documentation/devicetree/bindings/drm/msm/edp.txt b/Documentation/devicetree/bindings/drm/msm/edp.txt
new file mode 100644
index 000000000000..3a20f6ea5898
--- /dev/null
+++ b/Documentation/devicetree/bindings/drm/msm/edp.txt
@@ -0,0 +1,60 @@
+Qualcomm Technologies Inc. adreno/snapdragon eDP output
+
+Required properties:
+- compatible:
+ * "qcom,mdss-edp"
+- reg: Physical base address and length of the registers of controller and PLL
+- reg-names: The names of register regions. The following regions are required:
+ * "edp"
+ * "pll_base"
+- interrupts: The interrupt signal from the eDP block.
+- 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:
+ * "core_clk"
+ * "iface_clk"
+ * "mdp_core_clk"
+ * "pixel_clk"
+ * "link_clk"
+- #clock-cells: The value should be 1.
+- vdda-supply: phandle to vdda regulator device node
+- lvl-vdd-supply: phandle to regulator device node which is used to supply power
+ to HPD receiving chip
+- panel-en-gpios: GPIO pin to supply power to panel.
+- panel-hpd-gpios: GPIO pin used for eDP hpd.
+
+
+Optional properties:
+- interrupt-parent: phandle to the MDP block if the interrupt signal is routed
+ through MDP block
+
+Example:
+ mdss_edp: qcom,mdss_edp@fd923400 {
+ compatible = "qcom,mdss-edp";
+ reg-names =
+ "edp",
+ "pll_base";
+ reg = <0xfd923400 0x700>,
+ <0xfd923a00 0xd4>;
+ interrupt-parent = <&mdss_mdp>;
+ interrupts = <12 0>;
+ power-domains = <&mmcc MDSS_GDSC>;
+ clock-names =
+ "core_clk",
+ "pixel_clk",
+ "iface_clk",
+ "link_clk",
+ "mdp_core_clk";
+ clocks =
+ <&mmcc MDSS_EDPAUX_CLK>,
+ <&mmcc MDSS_EDPPIXEL_CLK>,
+ <&mmcc MDSS_AHB_CLK>,
+ <&mmcc MDSS_EDPLINK_CLK>,
+ <&mmcc MDSS_MDP_CLK>;
+ #clock-cells = <1>;
+ vdda-supply = <&pma8084_l12>;
+ lvl-vdd-supply = <&lvl_vreg>;
+ panel-en-gpios = <&tlmm 137 0>;
+ panel-hpd-gpios = <&tlmm 103 0>;
+ };
diff --git a/Documentation/devicetree/bindings/drm/msm/hdmi.txt b/Documentation/devicetree/bindings/drm/msm/hdmi.txt
index a29a55f3d937..c43aa53debed 100644
--- a/Documentation/devicetree/bindings/drm/msm/hdmi.txt
+++ b/Documentation/devicetree/bindings/drm/msm/hdmi.txt
@@ -20,6 +20,9 @@ Required properties:
Optional properties:
- qcom,hdmi-tx-mux-en-gpio: hdmi mux enable pin
- qcom,hdmi-tx-mux-sel-gpio: hdmi mux select pin
+- pinctrl-names: the pin control state names; should contain "default"
+- pinctrl-0: the default pinctrl state (active)
+- pinctrl-1: the "sleep" pinctrl state
Example:
@@ -44,5 +47,8 @@ Example:
qcom,hdmi-tx-hpd = <&msmgpio 72 GPIO_ACTIVE_HIGH>;
core-vdda-supply = <&pm8921_hdmi_mvs>;
hdmi-mux-supply = <&ext_3p3v>;
+ pinctrl-names = "default", "sleep";
+ pinctrl-0 = <&hpd_active &ddc_active &cec_active>;
+ pinctrl-1 = <&hpd_suspend &ddc_suspend &cec_suspend>;
};
};
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 77f87b23a6e7..b69ed97d447c 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3255,6 +3255,24 @@ static int framebuffer_check(const struct drm_mode_fb_cmd2 *r)
r->modifier[i], i);
return -EINVAL;
}
+
+ /* modifier specific checks: */
+ switch (r->modifier[i]) {
+ case DRM_FORMAT_MOD_SAMSUNG_64_32_TILE:
+ /* NOTE: the pitch restriction may be lifted later if it turns
+ * out that no hw has this restriction:
+ */
+ if (r->pixel_format != DRM_FORMAT_NV12 ||
+ width % 128 || height % 32 ||
+ r->pitches[i] % 128) {
+ DRM_DEBUG_KMS("bad modifier data for plane %d\n", i);
+ return -EINVAL;
+ }
+ break;
+
+ default:
+ break;
+ }
}
for (i = num_planes; i < 4; i++) {
diff --git a/drivers/gpu/drm/msm/Kconfig b/drivers/gpu/drm/msm/Kconfig
index 0a6f6764a37c..08ba8d0d93f5 100644
--- a/drivers/gpu/drm/msm/Kconfig
+++ b/drivers/gpu/drm/msm/Kconfig
@@ -46,3 +46,10 @@ config DRM_MSM_DSI
Choose this option if you have a need for MIPI DSI connector
support.
+config DRM_MSM_DSI_PLL
+ bool "Enable DSI PLL driver in MSM DRM"
+ depends on DRM_MSM_DSI && COMMON_CLK
+ default y
+ help
+ Choose this option to enable DSI PLL driver which provides DSI
+ source clocks under common clock framework.
diff --git a/drivers/gpu/drm/msm/Makefile b/drivers/gpu/drm/msm/Makefile
index ab2086783fee..16a81b94d6f0 100644
--- a/drivers/gpu/drm/msm/Makefile
+++ b/drivers/gpu/drm/msm/Makefile
@@ -1,4 +1,5 @@
ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/msm
+ccflags-$(CONFIG_DRM_MSM_DSI_PLL) += -Idrivers/gpu/drm/msm/dsi
msm-y := \
adreno/adreno_device.o \
@@ -50,10 +51,14 @@ msm-y := \
msm-$(CONFIG_DRM_MSM_FBDEV) += msm_fbdev.o
msm-$(CONFIG_COMMON_CLK) += mdp/mdp4/mdp4_lvds_pll.o
+
msm-$(CONFIG_DRM_MSM_DSI) += dsi/dsi.o \
dsi/dsi_host.o \
dsi/dsi_manager.o \
dsi/dsi_phy.o \
mdp/mdp5/mdp5_cmd_encoder.o
+msm-$(CONFIG_DRM_MSM_DSI_PLL) += dsi/pll/dsi_pll.o \
+ dsi/pll/dsi_pll_28nm.o
+
obj-$(CONFIG_DRM_MSM) += msm.o
diff --git a/drivers/gpu/drm/msm/adreno/a2xx.xml.h b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
index edc845fffdf4..23176e402796 100644
--- a/drivers/gpu/drm/msm/adreno/a2xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a2xx.xml.h
@@ -12,9 +12,9 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15085 bytes, from 2014-12-20 21:49:41)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 64344 bytes, from 2014-12-12 20:22:26)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 51069 bytes, from 2014-12-21 15:51:54)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14895 bytes, from 2015-04-19 15:23:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-04-12 18:16:35)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 60633 bytes, from 2015-05-20 14:48:19)
Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/adreno/a3xx.xml.h b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
index e91a739452d7..1c599e5cf318 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a3xx.xml.h
@@ -12,11 +12,11 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15085 bytes, from 2014-12-20 21:49:41)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 64344 bytes, from 2014-12-12 20:22:26)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 51069 bytes, from 2014-12-21 15:51:54)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14895 bytes, from 2015-04-19 15:23:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-04-12 18:16:35)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 60633 bytes, from 2015-05-20 14:48:19)
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -130,6 +130,10 @@ enum a3xx_tex_fmt {
TFMT_I420_Y = 24,
TFMT_I420_U = 26,
TFMT_I420_V = 27,
+ TFMT_ATC_RGB = 32,
+ TFMT_ATC_RGBA_EXPLICIT = 33,
+ TFMT_ETC1 = 34,
+ TFMT_ATC_RGBA_INTERPOLATED = 35,
TFMT_DXT1 = 36,
TFMT_DXT3 = 37,
TFMT_DXT5 = 38,
@@ -178,10 +182,13 @@ enum a3xx_tex_fmt {
TFMT_32_SINT = 92,
TFMT_32_32_SINT = 93,
TFMT_32_32_32_32_SINT = 95,
- TFMT_RGTC2_SNORM = 112,
- TFMT_RGTC2_UNORM = 113,
- TFMT_RGTC1_SNORM = 114,
- TFMT_RGTC1_UNORM = 115,
+ TFMT_ETC2_RG11_SNORM = 112,
+ TFMT_ETC2_RG11_UNORM = 113,
+ TFMT_ETC2_R11_SNORM = 114,
+ TFMT_ETC2_R11_UNORM = 115,
+ TFMT_ETC2_RGBA8 = 116,
+ TFMT_ETC2_RGB8A1 = 117,
+ TFMT_ETC2_RGB8 = 118,
};
enum a3xx_tex_fetchsize {
@@ -209,14 +216,24 @@ enum a3xx_color_fmt {
RB_R10G10B10A2_UNORM = 16,
RB_A8_UNORM = 20,
RB_R8_UNORM = 21,
+ RB_R16_FLOAT = 24,
+ RB_R16G16_FLOAT = 25,
RB_R16G16B16A16_FLOAT = 27,
RB_R11G11B10_FLOAT = 28,
+ RB_R16_SNORM = 32,
+ RB_R16G16_SNORM = 33,
+ RB_R16G16B16A16_SNORM = 35,
+ RB_R16_UNORM = 36,
+ RB_R16G16_UNORM = 37,
+ RB_R16G16B16A16_UNORM = 39,
RB_R16_SINT = 40,
RB_R16G16_SINT = 41,
RB_R16G16B16A16_SINT = 43,
RB_R16_UINT = 44,
RB_R16G16_UINT = 45,
RB_R16G16B16A16_UINT = 47,
+ RB_R32_FLOAT = 48,
+ RB_R32G32_FLOAT = 49,
RB_R32G32B32A32_FLOAT = 51,
RB_R32_SINT = 52,
RB_R32G32_SINT = 53,
@@ -265,6 +282,12 @@ enum a3xx_intp_mode {
FLAT = 1,
};
+enum a3xx_repl_mode {
+ S = 1,
+ T = 2,
+ ONE_T = 3,
+};
+
enum a3xx_tex_filter {
A3XX_TEX_NEAREST = 0,
A3XX_TEX_LINEAR = 1,
@@ -751,7 +774,7 @@ static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_SCALE_VAL(float val)
#define A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT 0
static inline uint32_t A3XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)
{
- return ((((int32_t)(val * 16384.0))) << A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
+ return ((((int32_t)(val * 64.0))) << A3XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A3XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
}
#define REG_A3XX_GRAS_SU_MODE_CONTROL 0x00002070
@@ -854,6 +877,12 @@ static inline uint32_t A3XX_RB_MODE_CONTROL_RENDER_MODE(enum a3xx_render_mode va
{
return ((val) << A3XX_RB_MODE_CONTROL_RENDER_MODE__SHIFT) & A3XX_RB_MODE_CONTROL_RENDER_MODE__MASK;
}
+#define A3XX_RB_MODE_CONTROL_MRT__MASK 0x00003000
+#define A3XX_RB_MODE_CONTROL_MRT__SHIFT 12
+static inline uint32_t A3XX_RB_MODE_CONTROL_MRT(uint32_t val)
+{
+ return ((val) << A3XX_RB_MODE_CONTROL_MRT__SHIFT) & A3XX_RB_MODE_CONTROL_MRT__MASK;
+}
#define A3XX_RB_MODE_CONTROL_MARB_CACHE_SPLIT_MODE 0x00008000
#define A3XX_RB_MODE_CONTROL_PACKER_TIMER_ENABLE 0x00010000
@@ -1246,9 +1275,21 @@ static inline uint32_t A3XX_RB_STENCIL_CONTROL_ZFAIL_BF(enum adreno_stencil_op v
#define REG_A3XX_RB_STENCIL_CLEAR 0x00002105
-#define REG_A3XX_RB_STENCIL_BUF_INFO 0x00002106
+#define REG_A3XX_RB_STENCIL_INFO 0x00002106
+#define A3XX_RB_STENCIL_INFO_STENCIL_BASE__MASK 0xfffff800
+#define A3XX_RB_STENCIL_INFO_STENCIL_BASE__SHIFT 11
+static inline uint32_t A3XX_RB_STENCIL_INFO_STENCIL_BASE(uint32_t val)
+{
+ return ((val >> 12) << A3XX_RB_STENCIL_INFO_STENCIL_BASE__SHIFT) & A3XX_RB_STENCIL_INFO_STENCIL_BASE__MASK;
+}
-#define REG_A3XX_RB_STENCIL_BUF_PITCH 0x00002107
+#define REG_A3XX_RB_STENCIL_PITCH 0x00002107
+#define A3XX_RB_STENCIL_PITCH__MASK 0xffffffff
+#define A3XX_RB_STENCIL_PITCH__SHIFT 0
+static inline uint32_t A3XX_RB_STENCIL_PITCH(uint32_t val)
+{
+ return ((val >> 3) << A3XX_RB_STENCIL_PITCH__SHIFT) & A3XX_RB_STENCIL_PITCH__MASK;
+}
#define REG_A3XX_RB_STENCILREFMASK 0x00002108
#define A3XX_RB_STENCILREFMASK_STENCILREF__MASK 0x000000ff
@@ -1356,6 +1397,7 @@ static inline uint32_t A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE(enum adreno_pa_
{
return ((val) << A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__SHIFT) & A3XX_PC_PRIM_VTX_CNTL_POLYMODE_BACK_PTYPE__MASK;
}
+#define A3XX_PC_PRIM_VTX_CNTL_POLYMODE_ENABLE 0x00001000
#define A3XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART 0x00100000
#define A3XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST 0x02000000
#define A3XX_PC_PRIM_VTX_CNTL_PSIZE 0x04000000
@@ -1805,6 +1847,102 @@ static inline uint32_t A3XX_VPC_VARYING_INTERP_MODE_CF(enum a3xx_intp_mode val)
static inline uint32_t REG_A3XX_VPC_VARYING_PS_REPL(uint32_t i0) { return 0x00002286 + 0x1*i0; }
static inline uint32_t REG_A3XX_VPC_VARYING_PS_REPL_MODE(uint32_t i0) { return 0x00002286 + 0x1*i0; }
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C0__MASK 0x00000003
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C0__SHIFT 0
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C0(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C0__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C0__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C1__MASK 0x0000000c
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C1__SHIFT 2
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C1(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C1__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C1__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C2__MASK 0x00000030
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C2__SHIFT 4
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C2(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C2__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C2__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C3__MASK 0x000000c0
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C3__SHIFT 6
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C3(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C3__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C3__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C4__MASK 0x00000300
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C4__SHIFT 8
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C4(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C4__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C4__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C5__MASK 0x00000c00
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C5__SHIFT 10
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C5(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C5__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C5__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C6__MASK 0x00003000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C6__SHIFT 12
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C6(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C6__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C6__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C7__MASK 0x0000c000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C7__SHIFT 14
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C7(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C7__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C7__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C8__MASK 0x00030000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C8__SHIFT 16
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C8(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C8__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C8__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C9__MASK 0x000c0000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_C9__SHIFT 18
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_C9(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_C9__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_C9__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CA__MASK 0x00300000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CA__SHIFT 20
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CA(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CA__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CA__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CB__MASK 0x00c00000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CB__SHIFT 22
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CB(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CB__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CB__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CC__MASK 0x03000000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CC__SHIFT 24
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CC(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CC__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CC__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CD__MASK 0x0c000000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CD__SHIFT 26
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CD(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CD__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CD__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CE__MASK 0x30000000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CE__SHIFT 28
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CE(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CE__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CE__MASK;
+}
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CF__MASK 0xc0000000
+#define A3XX_VPC_VARYING_PS_REPL_MODE_CF__SHIFT 30
+static inline uint32_t A3XX_VPC_VARYING_PS_REPL_MODE_CF(enum a3xx_repl_mode val)
+{
+ return ((val) << A3XX_VPC_VARYING_PS_REPL_MODE_CF__SHIFT) & A3XX_VPC_VARYING_PS_REPL_MODE_CF__MASK;
+}
#define REG_A3XX_VPC_VARY_CYLWRAP_ENABLE_0 0x0000228a
@@ -2107,6 +2245,12 @@ static inline uint32_t A3XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
#define REG_A3XX_SP_FS_FLAT_SHAD_MODE_REG_1 0x000022e9
#define REG_A3XX_SP_FS_OUTPUT_REG 0x000022ec
+#define A3XX_SP_FS_OUTPUT_REG_MRT__MASK 0x00000003
+#define A3XX_SP_FS_OUTPUT_REG_MRT__SHIFT 0
+static inline uint32_t A3XX_SP_FS_OUTPUT_REG_MRT(uint32_t val)
+{
+ return ((val) << A3XX_SP_FS_OUTPUT_REG_MRT__SHIFT) & A3XX_SP_FS_OUTPUT_REG_MRT__MASK;
+}
#define A3XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE 0x00000080
#define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK 0x0000ff00
#define A3XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT 8
@@ -2661,7 +2805,7 @@ static inline uint32_t A3XX_TEX_CONST_2_SWAP(enum a3xx_color_swap val)
}
#define REG_A3XX_TEX_CONST_3 0x00000003
-#define A3XX_TEX_CONST_3_LAYERSZ1__MASK 0x0000000f
+#define A3XX_TEX_CONST_3_LAYERSZ1__MASK 0x00007fff
#define A3XX_TEX_CONST_3_LAYERSZ1__SHIFT 0
static inline uint32_t A3XX_TEX_CONST_3_LAYERSZ1(uint32_t val)
{
diff --git a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
index b66c53bdc039..fd266ed963b6 100644
--- a/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a3xx_gpu.c
@@ -93,7 +93,10 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
/* Set up AOOO: */
gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO_EN, 0x0000003c);
gpu_write(gpu, REG_A3XX_VBIF_OUT_AXI_AOOO, 0x003c003c);
-
+ } else if (adreno_is_a306(adreno_gpu)) {
+ gpu_write(gpu, REG_A3XX_VBIF_ROUND_ROBIN_QOS_ARB, 0x0003);
+ gpu_write(gpu, REG_A3XX_VBIF_OUT_RD_LIM_CONF0, 0x0000000a);
+ gpu_write(gpu, REG_A3XX_VBIF_OUT_WR_LIM_CONF0, 0x0000000a);
} else if (adreno_is_a320(adreno_gpu)) {
/* Set up 16 deep read/write request queues: */
gpu_write(gpu, REG_A3XX_VBIF_IN_RD_LIM_CONF0, 0x10101010);
@@ -186,7 +189,9 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A3XX_UCHE_CACHE_MODE_CONTROL_REG, 0x00000001);
/* Enable Clock gating: */
- if (adreno_is_a320(adreno_gpu))
+ if (adreno_is_a306(adreno_gpu))
+ gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
+ else if (adreno_is_a320(adreno_gpu))
gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xbfffffff);
else if (adreno_is_a330v2(adreno_gpu))
gpu_write(gpu, REG_A3XX_RBBM_CLOCK_CTL, 0xaaaaaaaa);
@@ -271,7 +276,8 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
gpu_write(gpu, REG_A3XX_CP_PFP_UCODE_DATA, ptr[i]);
/* CP ROQ queue sizes (bytes) - RB:16, ST:16, IB1:32, IB2:64 */
- if (adreno_is_a305(adreno_gpu) || adreno_is_a320(adreno_gpu)) {
+ if (adreno_is_a305(adreno_gpu) || adreno_is_a306(adreno_gpu) ||
+ adreno_is_a320(adreno_gpu)) {
gpu_write(gpu, REG_AXXX_CP_QUEUE_THRESHOLDS,
AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB1_START(2) |
AXXX_CP_QUEUE_THRESHOLDS_CSQ_IB2_START(6) |
@@ -295,9 +301,12 @@ static int a3xx_hw_init(struct msm_gpu *gpu)
static void a3xx_recover(struct msm_gpu *gpu)
{
+ adreno_dump_info(gpu);
+
/* dump registers before resetting gpu, if enabled: */
if (hang_debug)
a3xx_dump(gpu);
+
gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 1);
gpu_read(gpu, REG_A3XX_RBBM_SW_RESET_CMD);
gpu_write(gpu, REG_A3XX_RBBM_SW_RESET_CMD, 0);
diff --git a/drivers/gpu/drm/msm/adreno/a4xx.xml.h b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
index 755723fd8ba5..3f06ecf62583 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx.xml.h
+++ b/drivers/gpu/drm/msm/adreno/a4xx.xml.h
@@ -12,11 +12,11 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15085 bytes, from 2014-12-20 21:49:41)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 64344 bytes, from 2014-12-12 20:22:26)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 51069 bytes, from 2014-12-21 15:51:54)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14895 bytes, from 2015-04-19 15:23:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-04-12 18:16:35)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 60633 bytes, from 2015-05-20 14:48:19)
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -43,10 +43,40 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
enum a4xx_color_fmt {
RB4_A8_UNORM = 1,
+ RB4_R8_UNORM = 2,
+ RB4_R4G4B4A4_UNORM = 8,
+ RB4_R5G5B5A1_UNORM = 10,
RB4_R5G6R5_UNORM = 14,
- RB4_Z16_UNORM = 15,
+ RB4_R8G8_UNORM = 15,
+ RB4_R8G8_SNORM = 16,
+ RB4_R8G8_UINT = 17,
+ RB4_R8G8_SINT = 18,
+ RB4_R16_FLOAT = 21,
+ RB4_R16_UINT = 22,
+ RB4_R16_SINT = 23,
RB4_R8G8B8_UNORM = 25,
RB4_R8G8B8A8_UNORM = 26,
+ RB4_R8G8B8A8_SNORM = 28,
+ RB4_R8G8B8A8_UINT = 29,
+ RB4_R8G8B8A8_SINT = 30,
+ RB4_R10G10B10A2_UNORM = 31,
+ RB4_R10G10B10A2_UINT = 34,
+ RB4_R11G11B10_FLOAT = 39,
+ RB4_R16G16_FLOAT = 42,
+ RB4_R16G16_UINT = 43,
+ RB4_R16G16_SINT = 44,
+ RB4_R32_FLOAT = 45,
+ RB4_R32_UINT = 46,
+ RB4_R32_SINT = 47,
+ RB4_R16G16B16A16_FLOAT = 54,
+ RB4_R16G16B16A16_UINT = 55,
+ RB4_R16G16B16A16_SINT = 56,
+ RB4_R32G32_FLOAT = 57,
+ RB4_R32G32_UINT = 58,
+ RB4_R32G32_SINT = 59,
+ RB4_R32G32B32A32_FLOAT = 60,
+ RB4_R32G32B32A32_UINT = 61,
+ RB4_R32G32B32A32_SINT = 62,
};
enum a4xx_tile_mode {
@@ -91,7 +121,14 @@ enum a4xx_vtx_fmt {
VFMT4_16_16_UNORM = 29,
VFMT4_16_16_16_UNORM = 30,
VFMT4_16_16_16_16_UNORM = 31,
+ VFMT4_32_UINT = 32,
+ VFMT4_32_32_UINT = 33,
+ VFMT4_32_32_32_UINT = 34,
+ VFMT4_32_32_32_32_UINT = 35,
+ VFMT4_32_SINT = 36,
VFMT4_32_32_SINT = 37,
+ VFMT4_32_32_32_SINT = 38,
+ VFMT4_32_32_32_32_SINT = 39,
VFMT4_8_UINT = 40,
VFMT4_8_8_UINT = 41,
VFMT4_8_8_8_UINT = 42,
@@ -125,12 +162,57 @@ enum a4xx_tex_fmt {
TFMT4_8_UNORM = 4,
TFMT4_8_8_UNORM = 14,
TFMT4_8_8_8_8_UNORM = 28,
+ TFMT4_8_8_SNORM = 15,
+ TFMT4_8_8_8_8_SNORM = 29,
+ TFMT4_8_8_UINT = 16,
+ TFMT4_8_8_8_8_UINT = 30,
+ TFMT4_8_8_SINT = 17,
+ TFMT4_8_8_8_8_SINT = 31,
+ TFMT4_16_UINT = 21,
+ TFMT4_16_16_UINT = 41,
+ TFMT4_16_16_16_16_UINT = 54,
+ TFMT4_16_SINT = 22,
+ TFMT4_16_16_SINT = 42,
+ TFMT4_16_16_16_16_SINT = 55,
+ TFMT4_32_UINT = 44,
+ TFMT4_32_32_UINT = 57,
+ TFMT4_32_32_32_32_UINT = 64,
+ TFMT4_32_SINT = 45,
+ TFMT4_32_32_SINT = 58,
+ TFMT4_32_32_32_32_SINT = 65,
TFMT4_16_FLOAT = 20,
TFMT4_16_16_FLOAT = 40,
TFMT4_16_16_16_16_FLOAT = 53,
TFMT4_32_FLOAT = 43,
TFMT4_32_32_FLOAT = 56,
TFMT4_32_32_32_32_FLOAT = 63,
+ TFMT4_9_9_9_E5_FLOAT = 32,
+ TFMT4_11_11_10_FLOAT = 37,
+ TFMT4_ATC_RGB = 100,
+ TFMT4_ATC_RGBA_EXPLICIT = 101,
+ TFMT4_ATC_RGBA_INTERPOLATED = 102,
+ TFMT4_ETC2_RG11_UNORM = 103,
+ TFMT4_ETC2_RG11_SNORM = 104,
+ TFMT4_ETC2_R11_UNORM = 105,
+ TFMT4_ETC2_R11_SNORM = 106,
+ TFMT4_ETC1 = 107,
+ TFMT4_ETC2_RGB8 = 108,
+ TFMT4_ETC2_RGBA8 = 109,
+ TFMT4_ETC2_RGB8A1 = 110,
+ TFMT4_ASTC_4x4 = 111,
+ TFMT4_ASTC_5x4 = 112,
+ TFMT4_ASTC_5x5 = 113,
+ TFMT4_ASTC_6x5 = 114,
+ TFMT4_ASTC_6x6 = 115,
+ TFMT4_ASTC_8x5 = 116,
+ TFMT4_ASTC_8x6 = 117,
+ TFMT4_ASTC_8x8 = 118,
+ TFMT4_ASTC_10x5 = 119,
+ TFMT4_ASTC_10x6 = 120,
+ TFMT4_ASTC_10x8 = 121,
+ TFMT4_ASTC_10x10 = 122,
+ TFMT4_ASTC_12x10 = 123,
+ TFMT4_ASTC_12x12 = 124,
};
enum a4xx_tex_fetchsize {
@@ -147,9 +229,16 @@ enum a4xx_depth_format {
DEPTH4_24_8 = 2,
};
+enum a4xx_tess_spacing {
+ EQUAL_SPACING = 0,
+ ODD_SPACING = 2,
+ EVEN_SPACING = 3,
+};
+
enum a4xx_tex_filter {
A4XX_TEX_NEAREST = 0,
A4XX_TEX_LINEAR = 1,
+ A4XX_TEX_ANISO = 2,
};
enum a4xx_tex_clamp {
@@ -159,6 +248,14 @@ enum a4xx_tex_clamp {
A4XX_TEX_CLAMP_NONE = 3,
};
+enum a4xx_tex_aniso {
+ A4XX_TEX_ANISO_1 = 0,
+ A4XX_TEX_ANISO_2 = 1,
+ A4XX_TEX_ANISO_4 = 2,
+ A4XX_TEX_ANISO_8 = 3,
+ A4XX_TEX_ANISO_16 = 4,
+};
+
enum a4xx_tex_swiz {
A4XX_TEX_X = 0,
A4XX_TEX_Y = 1,
@@ -279,13 +376,16 @@ static inline uint32_t A4XX_RB_MSAA_CONTROL_SAMPLES(uint32_t val)
#define A4XX_RB_RENDER_CONTROL2_YCOORD 0x00000002
#define A4XX_RB_RENDER_CONTROL2_ZCOORD 0x00000004
#define A4XX_RB_RENDER_CONTROL2_WCOORD 0x00000008
+#define A4XX_RB_RENDER_CONTROL2_SAMPLEMASK 0x00000010
#define A4XX_RB_RENDER_CONTROL2_FACENESS 0x00000020
+#define A4XX_RB_RENDER_CONTROL2_SAMPLEID 0x00000040
#define A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__MASK 0x00000380
#define A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__SHIFT 7
static inline uint32_t A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES(uint32_t val)
{
return ((val) << A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__SHIFT) & A4XX_RB_RENDER_CONTROL2_MSAA_SAMPLES__MASK;
}
+#define A4XX_RB_RENDER_CONTROL2_SAMPLEID_HR 0x00000800
#define A4XX_RB_RENDER_CONTROL2_VARYING 0x00001000
static inline uint32_t REG_A4XX_RB_MRT(uint32_t i0) { return 0x000020a4 + 0x5*i0; }
@@ -310,6 +410,12 @@ static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT(enum a4xx_color_fmt val
{
return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_FORMAT__MASK;
}
+#define A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK 0x000000c0
+#define A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT 6
+static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE(enum a4xx_tile_mode val)
+{
+ return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_TILE_MODE__MASK;
+}
#define A4XX_RB_MRT_BUF_INFO_DITHER_MODE__MASK 0x00000600
#define A4XX_RB_MRT_BUF_INFO_DITHER_MODE__SHIFT 9
static inline uint32_t A4XX_RB_MRT_BUF_INFO_DITHER_MODE(enum adreno_rb_dither_mode val)
@@ -322,6 +428,7 @@ static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_SWAP(enum a3xx_color_swap val)
{
return ((val) << A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__SHIFT) & A4XX_RB_MRT_BUF_INFO_COLOR_SWAP__MASK;
}
+#define A4XX_RB_MRT_BUF_INFO_COLOR_SRGB 0x00002000
#define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__MASK 0x007fc000
#define A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH__SHIFT 14
static inline uint32_t A4XX_RB_MRT_BUF_INFO_COLOR_BUF_PITCH(uint32_t val)
@@ -449,7 +556,12 @@ static inline uint32_t A4XX_RB_ALPHA_CONTROL_ALPHA_TEST_FUNC(enum adreno_compare
}
#define REG_A4XX_RB_FS_OUTPUT 0x000020f9
-#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND 0x00000001
+#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND__MASK 0x000000ff
+#define A4XX_RB_FS_OUTPUT_ENABLE_BLEND__SHIFT 0
+static inline uint32_t A4XX_RB_FS_OUTPUT_ENABLE_BLEND(uint32_t val)
+{
+ return ((val) << A4XX_RB_FS_OUTPUT_ENABLE_BLEND__SHIFT) & A4XX_RB_FS_OUTPUT_ENABLE_BLEND__MASK;
+}
#define A4XX_RB_FS_OUTPUT_FAST_CLEAR 0x00000100
#define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__MASK 0xffff0000
#define A4XX_RB_FS_OUTPUT_SAMPLE_MASK__SHIFT 16
@@ -458,12 +570,54 @@ static inline uint32_t A4XX_RB_FS_OUTPUT_SAMPLE_MASK(uint32_t val)
return ((val) << A4XX_RB_FS_OUTPUT_SAMPLE_MASK__SHIFT) & A4XX_RB_FS_OUTPUT_SAMPLE_MASK__MASK;
}
-#define REG_A4XX_RB_RENDER_CONTROL3 0x000020fb
-#define A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__MASK 0x0000001f
-#define A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__SHIFT 0
-static inline uint32_t A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE(uint32_t val)
+#define REG_A4XX_RB_RENDER_COMPONENTS 0x000020fb
+#define A4XX_RB_RENDER_COMPONENTS_RT0__MASK 0x0000000f
+#define A4XX_RB_RENDER_COMPONENTS_RT0__SHIFT 0
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT0(uint32_t val)
{
- return ((val) << A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__SHIFT) & A4XX_RB_RENDER_CONTROL3_COMPONENT_ENABLE__MASK;
+ return ((val) << A4XX_RB_RENDER_COMPONENTS_RT0__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT0__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT1__MASK 0x000000f0
+#define A4XX_RB_RENDER_COMPONENTS_RT1__SHIFT 4
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT1(uint32_t val)
+{
+ return ((val) << A4XX_RB_RENDER_COMPONENTS_RT1__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT1__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT2__MASK 0x00000f00
+#define A4XX_RB_RENDER_COMPONENTS_RT2__SHIFT 8
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT2(uint32_t val)
+{
+ return ((val) << A4XX_RB_RENDER_COMPONENTS_RT2__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT2__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT3__MASK 0x0000f000
+#define A4XX_RB_RENDER_COMPONENTS_RT3__SHIFT 12
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT3(uint32_t val)
+{
+ return ((val) << A4XX_RB_RENDER_COMPONENTS_RT3__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT3__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT4__MASK 0x000f0000
+#define A4XX_RB_RENDER_COMPONENTS_RT4__SHIFT 16
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT4(uint32_t val)
+{
+ return ((val) << A4XX_RB_RENDER_COMPONENTS_RT4__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT4__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT5__MASK 0x00f00000
+#define A4XX_RB_RENDER_COMPONENTS_RT5__SHIFT 20
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT5(uint32_t val)
+{
+ return ((val) << A4XX_RB_RENDER_COMPONENTS_RT5__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT5__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT6__MASK 0x0f000000
+#define A4XX_RB_RENDER_COMPONENTS_RT6__SHIFT 24
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT6(uint32_t val)
+{
+ return ((val) << A4XX_RB_RENDER_COMPONENTS_RT6__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT6__MASK;
+}
+#define A4XX_RB_RENDER_COMPONENTS_RT7__MASK 0xf0000000
+#define A4XX_RB_RENDER_COMPONENTS_RT7__SHIFT 28
+static inline uint32_t A4XX_RB_RENDER_COMPONENTS_RT7(uint32_t val)
+{
+ return ((val) << A4XX_RB_RENDER_COMPONENTS_RT7__SHIFT) & A4XX_RB_RENDER_COMPONENTS_RT7__MASK;
}
#define REG_A4XX_RB_COPY_CONTROL 0x000020fc
@@ -547,7 +701,12 @@ static inline uint32_t A4XX_RB_COPY_DEST_INFO_TILE(enum a4xx_tile_mode val)
}
#define REG_A4XX_RB_FS_OUTPUT_REG 0x00002100
-#define A4XX_RB_FS_OUTPUT_REG_COLOR_PIPE_ENABLE 0x00000001
+#define A4XX_RB_FS_OUTPUT_REG_MRT__MASK 0x0000000f
+#define A4XX_RB_FS_OUTPUT_REG_MRT__SHIFT 0
+static inline uint32_t A4XX_RB_FS_OUTPUT_REG_MRT(uint32_t val)
+{
+ return ((val) << A4XX_RB_FS_OUTPUT_REG_MRT__SHIFT) & A4XX_RB_FS_OUTPUT_REG_MRT__MASK;
+}
#define A4XX_RB_FS_OUTPUT_REG_FRAG_WRITES_Z 0x00000020
#define REG_A4XX_RB_DEPTH_CONTROL 0x00002101
@@ -930,6 +1089,10 @@ static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1_REG(uint32_t i0)
#define REG_A4XX_CP_IB2_BUFSZ 0x00000209
+#define REG_A4XX_CP_ME_NRT_ADDR 0x0000020c
+
+#define REG_A4XX_CP_ME_NRT_DATA 0x0000020d
+
#define REG_A4XX_CP_ME_RB_DONE_DATA 0x00000217
#define REG_A4XX_CP_QUEUE_THRESH2 0x00000219
@@ -940,9 +1103,9 @@ static inline uint32_t REG_A4XX_RBBM_CLOCK_DELAY_RB_MARB_CCU_L1_REG(uint32_t i0)
#define REG_A4XX_CP_ROQ_DATA 0x0000021d
-#define REG_A4XX_CP_MEQ_ADDR 0x0000021e
+#define REG_A4XX_CP_MEQ_ADDR 0x0000021e
-#define REG_A4XX_CP_MEQ_DATA 0x0000021f
+#define REG_A4XX_CP_MEQ_DATA 0x0000021f
#define REG_A4XX_CP_MERCIU_ADDR 0x00000220
@@ -1004,12 +1167,17 @@ static inline uint32_t REG_A4XX_CP_SCRATCH_REG(uint32_t i0) { return 0x00000578
#define REG_A4XX_SP_VS_STATUS 0x00000ec0
+#define REG_A4XX_SP_MODE_CONTROL 0x00000ec3
+
#define REG_A4XX_SP_PERFCTR_SP_SEL_11 0x00000ecf
#define REG_A4XX_SP_SP_CTRL_REG 0x000022c0
#define A4XX_SP_SP_CTRL_REG_BINNING_PASS 0x00080000
#define REG_A4XX_SP_INSTR_CACHE_CTRL 0x000022c1
+#define A4XX_SP_INSTR_CACHE_CTRL_VS_BUFFER 0x00000080
+#define A4XX_SP_INSTR_CACHE_CTRL_FS_BUFFER 0x00000100
+#define A4XX_SP_INSTR_CACHE_CTRL_INSTR_BUFFER 0x00000400
#define REG_A4XX_SP_VS_CTRL_REG0 0x000022c4
#define A4XX_SP_VS_CTRL_REG0_THREADMODE__MASK 0x00000001
@@ -1229,6 +1397,12 @@ static inline uint32_t A4XX_SP_FS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
#define REG_A4XX_SP_FS_LENGTH_REG 0x000022ef
#define REG_A4XX_SP_FS_OUTPUT_REG 0x000022f0
+#define A4XX_SP_FS_OUTPUT_REG_MRT__MASK 0x0000000f
+#define A4XX_SP_FS_OUTPUT_REG_MRT__SHIFT 0
+static inline uint32_t A4XX_SP_FS_OUTPUT_REG_MRT(uint32_t val)
+{
+ return ((val) << A4XX_SP_FS_OUTPUT_REG_MRT__SHIFT) & A4XX_SP_FS_OUTPUT_REG_MRT__MASK;
+}
#define A4XX_SP_FS_OUTPUT_REG_DEPTH_ENABLE 0x00000080
#define A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK 0x0000ff00
#define A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT 8
@@ -1236,6 +1410,12 @@ static inline uint32_t A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID(uint32_t val)
{
return ((val) << A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__SHIFT) & A4XX_SP_FS_OUTPUT_REG_DEPTH_REGID__MASK;
}
+#define A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__MASK 0xff000000
+#define A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__SHIFT 24
+static inline uint32_t A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID(uint32_t val)
+{
+ return ((val) << A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__SHIFT) & A4XX_SP_FS_OUTPUT_REG_SAMPLEMASK_REGID__MASK;
+}
static inline uint32_t REG_A4XX_SP_FS_MRT(uint32_t i0) { return 0x000022f1 + 0x1*i0; }
@@ -1254,6 +1434,20 @@ static inline uint32_t A4XX_SP_FS_MRT_REG_MRTFORMAT(enum a4xx_color_fmt val)
return ((val) << A4XX_SP_FS_MRT_REG_MRTFORMAT__SHIFT) & A4XX_SP_FS_MRT_REG_MRTFORMAT__MASK;
}
+#define REG_A4XX_SP_CS_CTRL_REG0 0x00002300
+
+#define REG_A4XX_SP_CS_OBJ_OFFSET_REG 0x00002301
+
+#define REG_A4XX_SP_CS_OBJ_START 0x00002302
+
+#define REG_A4XX_SP_CS_PVT_MEM_PARAM 0x00002303
+
+#define REG_A4XX_SP_CS_PVT_MEM_ADDR 0x00002304
+
+#define REG_A4XX_SP_CS_PVT_MEM_SIZE 0x00002305
+
+#define REG_A4XX_SP_CS_LENGTH_REG 0x00002306
+
#define REG_A4XX_SP_HS_OBJ_OFFSET_REG 0x0000230d
#define A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
#define A4XX_SP_HS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT 16
@@ -1268,6 +1462,14 @@ static inline uint32_t A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
return ((val) << A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_HS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
}
+#define REG_A4XX_SP_HS_OBJ_START 0x0000230e
+
+#define REG_A4XX_SP_HS_PVT_MEM_PARAM 0x0000230f
+
+#define REG_A4XX_SP_HS_PVT_MEM_ADDR 0x00002310
+
+#define REG_A4XX_SP_HS_LENGTH_REG 0x00002312
+
#define REG_A4XX_SP_DS_OBJ_OFFSET_REG 0x00002334
#define A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
#define A4XX_SP_DS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT 16
@@ -1282,6 +1484,14 @@ static inline uint32_t A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
return ((val) << A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_DS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
}
+#define REG_A4XX_SP_DS_OBJ_START 0x00002335
+
+#define REG_A4XX_SP_DS_PVT_MEM_PARAM 0x00002336
+
+#define REG_A4XX_SP_DS_PVT_MEM_ADDR 0x00002337
+
+#define REG_A4XX_SP_DS_LENGTH_REG 0x00002339
+
#define REG_A4XX_SP_GS_OBJ_OFFSET_REG 0x0000235b
#define A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__MASK 0x01ff0000
#define A4XX_SP_GS_OBJ_OFFSET_REG_CONSTOBJECTOFFSET__SHIFT 16
@@ -1296,6 +1506,12 @@ static inline uint32_t A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET(uint32_t val)
return ((val) << A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET__SHIFT) & A4XX_SP_GS_OBJ_OFFSET_REG_SHADEROBJOFFSET__MASK;
}
+#define REG_A4XX_SP_GS_OBJ_START 0x0000235c
+
+#define REG_A4XX_SP_GS_PVT_MEM_PARAM 0x0000235d
+
+#define REG_A4XX_SP_GS_PVT_MEM_ADDR 0x0000235e
+
#define REG_A4XX_SP_GS_LENGTH_REG 0x00002360
#define REG_A4XX_VPC_DEBUG_RAM_SEL 0x00000e60
@@ -1418,6 +1634,10 @@ static inline uint32_t REG_A4XX_VSC_PIPE_DATA_LENGTH_REG(uint32_t i0) { return 0
#define REG_A4XX_VFD_PERFCTR_VFD_SEL_7 0x00000e4a
+#define REG_A4XX_VGT_CL_INITIATOR 0x000021d0
+
+#define REG_A4XX_VGT_EVENT_INITIATOR 0x000021d9
+
#define REG_A4XX_VFD_CONTROL_0 0x00002200
#define A4XX_VFD_CONTROL_0_TOTALATTRTOVS__MASK 0x000000ff
#define A4XX_VFD_CONTROL_0_TOTALATTRTOVS__SHIFT 0
@@ -1554,10 +1774,54 @@ static inline uint32_t A4XX_VFD_DECODE_INSTR_SHIFTCNT(uint32_t val)
#define REG_A4XX_TPL1_DEBUG_ECO_CONTROL 0x00000f00
+#define REG_A4XX_TPL1_TP_MODE_CONTROL 0x00000f03
+
#define REG_A4XX_TPL1_PERFCTR_TP_SEL_7 0x00000f0b
#define REG_A4XX_TPL1_TP_TEX_OFFSET 0x00002380
+#define REG_A4XX_TPL1_TP_TEX_COUNT 0x00002381
+#define A4XX_TPL1_TP_TEX_COUNT_VS__MASK 0x000000ff
+#define A4XX_TPL1_TP_TEX_COUNT_VS__SHIFT 0
+static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_VS(uint32_t val)
+{
+ return ((val) << A4XX_TPL1_TP_TEX_COUNT_VS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_VS__MASK;
+}
+#define A4XX_TPL1_TP_TEX_COUNT_HS__MASK 0x0000ff00
+#define A4XX_TPL1_TP_TEX_COUNT_HS__SHIFT 8
+static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_HS(uint32_t val)
+{
+ return ((val) << A4XX_TPL1_TP_TEX_COUNT_HS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_HS__MASK;
+}
+#define A4XX_TPL1_TP_TEX_COUNT_DS__MASK 0x00ff0000
+#define A4XX_TPL1_TP_TEX_COUNT_DS__SHIFT 16
+static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_DS(uint32_t val)
+{
+ return ((val) << A4XX_TPL1_TP_TEX_COUNT_DS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_DS__MASK;
+}
+#define A4XX_TPL1_TP_TEX_COUNT_GS__MASK 0xff000000
+#define A4XX_TPL1_TP_TEX_COUNT_GS__SHIFT 24
+static inline uint32_t A4XX_TPL1_TP_TEX_COUNT_GS(uint32_t val)
+{
+ return ((val) << A4XX_TPL1_TP_TEX_COUNT_GS__SHIFT) & A4XX_TPL1_TP_TEX_COUNT_GS__MASK;
+}
+
+#define REG_A4XX_TPL1_TP_VS_BORDER_COLOR_BASE_ADDR 0x00002384
+
+#define REG_A4XX_TPL1_TP_HS_BORDER_COLOR_BASE_ADDR 0x00002387
+
+#define REG_A4XX_TPL1_TP_DS_BORDER_COLOR_BASE_ADDR 0x0000238a
+
+#define REG_A4XX_TPL1_TP_GS_BORDER_COLOR_BASE_ADDR 0x0000238d
+
+#define REG_A4XX_TPL1_TP_FS_TEX_COUNT 0x000023a0
+
+#define REG_A4XX_TPL1_TP_FS_BORDER_COLOR_BASE_ADDR 0x000023a1
+
+#define REG_A4XX_TPL1_TP_CS_BORDER_COLOR_BASE_ADDR 0x000023a4
+
+#define REG_A4XX_TPL1_TP_CS_SAMPLER_BASE_ADDR 0x000023a5
+
#define REG_A4XX_TPL1_TP_CS_TEXMEMOBJ_BASE_ADDR 0x000023a6
#define REG_A4XX_GRAS_TSE_STATUS 0x00000c80
@@ -1676,6 +1940,14 @@ static inline uint32_t A4XX_GRAS_SU_POLY_OFFSET_OFFSET(float val)
return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_OFFSET__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_OFFSET__MASK;
}
+#define REG_A4XX_GRAS_SU_POLY_OFFSET_CLAMP 0x00002076
+#define A4XX_GRAS_SU_POLY_OFFSET_CLAMP__MASK 0xffffffff
+#define A4XX_GRAS_SU_POLY_OFFSET_CLAMP__SHIFT 0
+static inline uint32_t A4XX_GRAS_SU_POLY_OFFSET_CLAMP(float val)
+{
+ return ((fui(val)) << A4XX_GRAS_SU_POLY_OFFSET_CLAMP__SHIFT) & A4XX_GRAS_SU_POLY_OFFSET_CLAMP__MASK;
+}
+
#define REG_A4XX_GRAS_DEPTH_CONTROL 0x00002077
#define A4XX_GRAS_DEPTH_CONTROL_FORMAT__MASK 0x00000003
#define A4XX_GRAS_DEPTH_CONTROL_FORMAT__SHIFT 0
@@ -1828,6 +2100,8 @@ static inline uint32_t A4XX_GRAS_SC_EXTENT_WINDOW_TL_Y(uint32_t val)
#define REG_A4XX_HLSQ_DEBUG_ECO_CONTROL 0x00000e04
+#define REG_A4XX_HLSQ_MODE_CONTROL 0x00000e05
+
#define REG_A4XX_HLSQ_PERF_PIPE_MASK 0x00000e0e
#define REG_A4XX_HLSQ_CONTROL_0_REG 0x000023c0
@@ -1867,7 +2141,12 @@ static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_COORDREGID(uint32_t val)
{
return ((val) << A4XX_HLSQ_CONTROL_1_REG_COORDREGID__SHIFT) & A4XX_HLSQ_CONTROL_1_REG_COORDREGID__MASK;
}
-#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORD 0x02000000
+#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__MASK 0xff000000
+#define A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__SHIFT 24
+static inline uint32_t A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID(uint32_t val)
+{
+ return ((val) << A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__SHIFT) & A4XX_HLSQ_CONTROL_1_REG_ZWCOORDREGID__MASK;
+}
#define REG_A4XX_HLSQ_CONTROL_2_REG 0x000023c2
#define A4XX_HLSQ_CONTROL_2_REG_PRIMALLOCTHRESHOLD__MASK 0xfc000000
@@ -1882,6 +2161,18 @@ static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_FACEREGID(uint32_t val)
{
return ((val) << A4XX_HLSQ_CONTROL_2_REG_FACEREGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_FACEREGID__MASK;
}
+#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__MASK 0x0003fc00
+#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__SHIFT 10
+static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID(uint32_t val)
+{
+ return ((val) << A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_SAMPLEID_REGID__MASK;
+}
+#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__MASK 0x03fc0000
+#define A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__SHIFT 18
+static inline uint32_t A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID(uint32_t val)
+{
+ return ((val) << A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__SHIFT) & A4XX_HLSQ_CONTROL_2_REG_SAMPLEMASK_REGID__MASK;
+}
#define REG_A4XX_HLSQ_CONTROL_3_REG 0x000023c3
#define A4XX_HLSQ_CONTROL_3_REG_REGID__MASK 0x000000ff
@@ -1891,6 +2182,8 @@ static inline uint32_t A4XX_HLSQ_CONTROL_3_REG_REGID(uint32_t val)
return ((val) << A4XX_HLSQ_CONTROL_3_REG_REGID__SHIFT) & A4XX_HLSQ_CONTROL_3_REG_REGID__MASK;
}
+#define REG_A4XX_HLSQ_CONTROL_4_REG 0x000023c4
+
#define REG_A4XX_HLSQ_VS_CONTROL_REG 0x000023c5
#define A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__MASK 0x000000ff
#define A4XX_HLSQ_VS_CONTROL_REG_CONSTLENGTH__SHIFT 0
@@ -1904,6 +2197,7 @@ static inline uint32_t A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_VS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
}
+#define A4XX_HLSQ_VS_CONTROL_REG_ENABLED 0x00010000
#define A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00fe0000
#define A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 17
static inline uint32_t A4XX_HLSQ_VS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
@@ -1930,6 +2224,7 @@ static inline uint32_t A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_FS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
}
+#define A4XX_HLSQ_FS_CONTROL_REG_ENABLED 0x00010000
#define A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00fe0000
#define A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 17
static inline uint32_t A4XX_HLSQ_FS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
@@ -1956,6 +2251,7 @@ static inline uint32_t A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_HS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
}
+#define A4XX_HLSQ_HS_CONTROL_REG_ENABLED 0x00010000
#define A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00fe0000
#define A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 17
static inline uint32_t A4XX_HLSQ_HS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
@@ -1982,6 +2278,7 @@ static inline uint32_t A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_DS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
}
+#define A4XX_HLSQ_DS_CONTROL_REG_ENABLED 0x00010000
#define A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00fe0000
#define A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 17
static inline uint32_t A4XX_HLSQ_DS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
@@ -2008,6 +2305,7 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET(uint32_t val)
{
return ((val) << A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__SHIFT) & A4XX_HLSQ_GS_CONTROL_REG_CONSTOBJECTOFFSET__MASK;
}
+#define A4XX_HLSQ_GS_CONTROL_REG_ENABLED 0x00010000
#define A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__MASK 0x00fe0000
#define A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET__SHIFT 17
static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_SHADEROBJOFFSET(uint32_t val)
@@ -2021,6 +2319,36 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
return ((val) << A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH__SHIFT) & A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH__MASK;
}
+#define REG_A4XX_HLSQ_CS_CONTROL 0x000023ca
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_0 0x000023cd
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_1 0x000023ce
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_2 0x000023cf
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_3 0x000023d0
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_4 0x000023d1
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_5 0x000023d2
+
+#define REG_A4XX_HLSQ_CL_NDRANGE_6 0x000023d3
+
+#define REG_A4XX_HLSQ_CL_CONTROL_0 0x000023d4
+
+#define REG_A4XX_HLSQ_CL_CONTROL_1 0x000023d5
+
+#define REG_A4XX_HLSQ_CL_KERNEL_CONST 0x000023d6
+
+#define REG_A4XX_HLSQ_CL_KERNEL_GROUP_X 0x000023d7
+
+#define REG_A4XX_HLSQ_CL_KERNEL_GROUP_Y 0x000023d8
+
+#define REG_A4XX_HLSQ_CL_KERNEL_GROUP_Z 0x000023d9
+
+#define REG_A4XX_HLSQ_CL_WG_OFFSET 0x000023da
+
#define REG_A4XX_HLSQ_UPDATE_CONTROL 0x000023db
#define REG_A4XX_PC_BINNING_COMMAND 0x00000d00
@@ -2035,7 +2363,13 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
#define REG_A4XX_PC_BIN_BASE 0x000021c0
#define REG_A4XX_PC_PRIM_VTX_CNTL 0x000021c4
-#define A4XX_PC_PRIM_VTX_CNTL_VAROUT 0x00000001
+#define A4XX_PC_PRIM_VTX_CNTL_VAROUT__MASK 0x0000000f
+#define A4XX_PC_PRIM_VTX_CNTL_VAROUT__SHIFT 0
+static inline uint32_t A4XX_PC_PRIM_VTX_CNTL_VAROUT(uint32_t val)
+{
+ return ((val) << A4XX_PC_PRIM_VTX_CNTL_VAROUT__SHIFT) & A4XX_PC_PRIM_VTX_CNTL_VAROUT__MASK;
+}
+#define A4XX_PC_PRIM_VTX_CNTL_PRIMITIVE_RESTART 0x00100000
#define A4XX_PC_PRIM_VTX_CNTL_PROVOKING_VTX_LAST 0x02000000
#define A4XX_PC_PRIM_VTX_CNTL_PSIZE 0x04000000
@@ -2044,8 +2378,45 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
#define REG_A4XX_PC_RESTART_INDEX 0x000021c6
#define REG_A4XX_PC_GS_PARAM 0x000021e5
+#define A4XX_PC_GS_PARAM_MAX_VERTICES__MASK 0x000003ff
+#define A4XX_PC_GS_PARAM_MAX_VERTICES__SHIFT 0
+static inline uint32_t A4XX_PC_GS_PARAM_MAX_VERTICES(uint32_t val)
+{
+ return ((val) << A4XX_PC_GS_PARAM_MAX_VERTICES__SHIFT) & A4XX_PC_GS_PARAM_MAX_VERTICES__MASK;
+}
+#define A4XX_PC_GS_PARAM_INVOCATIONS__MASK 0x0000f800
+#define A4XX_PC_GS_PARAM_INVOCATIONS__SHIFT 11
+static inline uint32_t A4XX_PC_GS_PARAM_INVOCATIONS(uint32_t val)
+{
+ return ((val) << A4XX_PC_GS_PARAM_INVOCATIONS__SHIFT) & A4XX_PC_GS_PARAM_INVOCATIONS__MASK;
+}
+#define A4XX_PC_GS_PARAM_PRIMTYPE__MASK 0x01800000
+#define A4XX_PC_GS_PARAM_PRIMTYPE__SHIFT 23
+static inline uint32_t A4XX_PC_GS_PARAM_PRIMTYPE(enum adreno_pa_su_sc_draw val)
+{
+ return ((val) << A4XX_PC_GS_PARAM_PRIMTYPE__SHIFT) & A4XX_PC_GS_PARAM_PRIMTYPE__MASK;
+}
+#define A4XX_PC_GS_PARAM_LAYER 0x80000000
#define REG_A4XX_PC_HS_PARAM 0x000021e7
+#define A4XX_PC_HS_PARAM_VERTICES_OUT__MASK 0x0000003f
+#define A4XX_PC_HS_PARAM_VERTICES_OUT__SHIFT 0
+static inline uint32_t A4XX_PC_HS_PARAM_VERTICES_OUT(uint32_t val)
+{
+ return ((val) << A4XX_PC_HS_PARAM_VERTICES_OUT__SHIFT) & A4XX_PC_HS_PARAM_VERTICES_OUT__MASK;
+}
+#define A4XX_PC_HS_PARAM_SPACING__MASK 0x00600000
+#define A4XX_PC_HS_PARAM_SPACING__SHIFT 21
+static inline uint32_t A4XX_PC_HS_PARAM_SPACING(enum a4xx_tess_spacing val)
+{
+ return ((val) << A4XX_PC_HS_PARAM_SPACING__SHIFT) & A4XX_PC_HS_PARAM_SPACING__MASK;
+}
+#define A4XX_PC_HS_PARAM_PRIMTYPE__MASK 0x01800000
+#define A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT 23
+static inline uint32_t A4XX_PC_HS_PARAM_PRIMTYPE(enum adreno_pa_su_sc_draw val)
+{
+ return ((val) << A4XX_PC_HS_PARAM_PRIMTYPE__SHIFT) & A4XX_PC_HS_PARAM_PRIMTYPE__MASK;
+}
#define REG_A4XX_VBIF_VERSION 0x00003000
@@ -2074,16 +2445,10 @@ static inline uint32_t A4XX_HLSQ_GS_CONTROL_REG_INSTRLENGTH(uint32_t val)
#define REG_A4XX_UNKNOWN_0D01 0x00000d01
-#define REG_A4XX_UNKNOWN_0E05 0x00000e05
-
#define REG_A4XX_UNKNOWN_0E42 0x00000e42
#define REG_A4XX_UNKNOWN_0EC2 0x00000ec2
-#define REG_A4XX_UNKNOWN_0EC3 0x00000ec3
-
-#define REG_A4XX_UNKNOWN_0F03 0x00000f03
-
#define REG_A4XX_UNKNOWN_2001 0x00002001
#define REG_A4XX_UNKNOWN_209B 0x0000209b
@@ -2124,10 +2489,6 @@ static inline uint32_t A4XX_UNKNOWN_20F7(float val)
#define REG_A4XX_UNKNOWN_22D7 0x000022d7
-#define REG_A4XX_UNKNOWN_2381 0x00002381
-
-#define REG_A4XX_UNKNOWN_23A0 0x000023a0
-
#define REG_A4XX_TEX_SAMP_0 0x00000000
#define A4XX_TEX_SAMP_0_MIPFILTER_LINEAR_NEAR 0x00000001
#define A4XX_TEX_SAMP_0_XY_MAG__MASK 0x00000006
@@ -2160,6 +2521,12 @@ static inline uint32_t A4XX_TEX_SAMP_0_WRAP_R(enum a4xx_tex_clamp val)
{
return ((val) << A4XX_TEX_SAMP_0_WRAP_R__SHIFT) & A4XX_TEX_SAMP_0_WRAP_R__MASK;
}
+#define A4XX_TEX_SAMP_0_ANISO__MASK 0x0001c000
+#define A4XX_TEX_SAMP_0_ANISO__SHIFT 14
+static inline uint32_t A4XX_TEX_SAMP_0_ANISO(enum a4xx_tex_aniso val)
+{
+ return ((val) << A4XX_TEX_SAMP_0_ANISO__SHIFT) & A4XX_TEX_SAMP_0_ANISO__MASK;
+}
#define REG_A4XX_TEX_SAMP_1 0x00000001
#define A4XX_TEX_SAMP_1_COMPARE_FUNC__MASK 0x0000000e
@@ -2185,6 +2552,7 @@ static inline uint32_t A4XX_TEX_SAMP_1_MIN_LOD(float val)
#define REG_A4XX_TEX_CONST_0 0x00000000
#define A4XX_TEX_CONST_0_TILED 0x00000001
+#define A4XX_TEX_CONST_0_SRGB 0x00000004
#define A4XX_TEX_CONST_0_SWIZ_X__MASK 0x00000070
#define A4XX_TEX_CONST_0_SWIZ_X__SHIFT 4
static inline uint32_t A4XX_TEX_CONST_0_SWIZ_X(enum a4xx_tex_swiz val)
diff --git a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
index 91221836c5ad..a53f1be05f75 100644
--- a/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/a4xx_gpu.c
@@ -268,6 +268,8 @@ static int a4xx_hw_init(struct msm_gpu *gpu)
static void a4xx_recover(struct msm_gpu *gpu)
{
+ adreno_dump_info(gpu);
+
/* dump registers before resetting gpu, if enabled: */
if (hang_debug)
a4xx_dump(gpu);
@@ -505,7 +507,6 @@ static const unsigned int a4xx_register_offsets[REG_ADRENO_REGISTER_MAX] = {
static void a4xx_dump(struct msm_gpu *gpu)
{
- adreno_dump(gpu);
printk("status: %08x\n",
gpu_read(gpu, REG_A4XX_RBBM_STATUS));
adreno_dump(gpu);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
index 8531beb982e7..9562a1fa552b 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_common.xml.h
@@ -12,9 +12,9 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15085 bytes, from 2014-12-20 21:49:41)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 64344 bytes, from 2014-12-12 20:22:26)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 51069 bytes, from 2014-12-21 15:51:54)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14895 bytes, from 2015-04-19 15:23:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-04-12 18:16:35)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 60633 bytes, from 2015-05-20 14:48:19)
Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index be83dee83d08..1ea2df524fac 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -19,7 +19,7 @@
#include "adreno_gpu.h"
-#if defined(CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)
+#if defined(DOWNSTREAM_CONFIG_MSM_BUS_SCALING) && !defined(CONFIG_OF)
# include <mach/kgsl.h>
#endif
@@ -42,6 +42,14 @@ static const struct adreno_info gpulist[] = {
.gmem = SZ_256K,
.init = a3xx_gpu_init,
}, {
+ .rev = ADRENO_REV(3, 0, 6, 0),
+ .revn = 307, /* because a305c is revn==306 */
+ .name = "A306",
+ .pm4fw = "a300_pm4.fw",
+ .pfpfw = "a300_pfp.fw",
+ .gmem = SZ_128K,
+ .init = a3xx_gpu_init,
+ }, {
.rev = ADRENO_REV(3, 2, ANY_ID, ANY_ID),
.revn = 320,
.name = "A320",
@@ -240,7 +248,7 @@ static int adreno_bind(struct device *dev, struct device *master, void *data)
config.rev = ADRENO_REV(3, 0, 5, 0);
}
-# ifdef CONFIG_MSM_BUS_SCALING
+# ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
config.bus_scale_table = pdata->bus_scale_table;
# endif
#endif
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
index bbdcab0a56c1..a3b54cc76495 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
@@ -176,6 +176,17 @@ int adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
OUT_PKT3(ring, CP_INTERRUPT, 1);
OUT_RING(ring, 0x80000000);
+ /* Workaround for missing irq issue on 8x16/a306. Unsure if the
+ * root cause is a platform issue or some a306 quirk, but this
+ * keeps things humming along:
+ */
+ if (adreno_is_a306(adreno_gpu)) {
+ OUT_PKT3(ring, CP_WAIT_FOR_IDLE, 1);
+ OUT_RING(ring, 0x00000000);
+ OUT_PKT3(ring, CP_INTERRUPT, 1);
+ OUT_RING(ring, 0x80000000);
+ }
+
#if 0
if (adreno_is_a3xx(adreno_gpu)) {
/* Dummy set-constant to trigger context rollover */
@@ -249,8 +260,13 @@ void adreno_show(struct msm_gpu *gpu, struct seq_file *m)
}
#endif
-/* would be nice to not have to duplicate the _show() stuff with printk(): */
-void adreno_dump(struct msm_gpu *gpu)
+/* Dump common gpu status and scratch registers on any hang, to make
+ * the hangcheck logs more useful. The scratch registers seem always
+ * safe to read when GPU has hung (unlike some other regs, depending
+ * on how the GPU hung), and they are useful to match up to cmdstream
+ * dumps when debugging hangs:
+ */
+void adreno_dump_info(struct msm_gpu *gpu)
{
struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
int i;
@@ -266,6 +282,18 @@ void adreno_dump(struct msm_gpu *gpu)
printk("wptr: %d\n", adreno_gpu->memptrs->wptr);
printk("rb wptr: %d\n", get_wptr(gpu->rb));
+ for (i = 0; i < 8; i++) {
+ printk("CP_SCRATCH_REG%d: %u\n", i,
+ gpu_read(gpu, REG_AXXX_CP_SCRATCH_REG0 + i));
+ }
+}
+
+/* would be nice to not have to duplicate the _show() stuff with printk(): */
+void adreno_dump(struct msm_gpu *gpu)
+{
+ struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
+ int i;
+
/* dump these out in a form that can be parsed by demsm: */
printk("IO:region %s 00000000 00020000\n", gpu->name);
for (i = 0; adreno_gpu->registers[i] != ~0; i += 2) {
@@ -317,7 +345,7 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
gpu->fast_rate = config->fast_rate;
gpu->slow_rate = config->slow_rate;
gpu->bus_freq = config->bus_freq;
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
gpu->bus_scale_table = config->bus_scale_table;
#endif
diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.h b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
index a0cc30977e67..0a312e9d3afd 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_gpu.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.h
@@ -167,7 +167,7 @@ struct adreno_gpu {
struct adreno_platform_config {
struct adreno_rev rev;
uint32_t fast_rate, slow_rate, bus_freq;
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
struct msm_bus_scale_pdata *bus_scale_table;
#endif
};
@@ -197,6 +197,12 @@ static inline bool adreno_is_a305(struct adreno_gpu *gpu)
return gpu->revn == 305;
}
+static inline bool adreno_is_a306(struct adreno_gpu *gpu)
+{
+ /* yes, 307, because a305c is 306 */
+ return gpu->revn == 307;
+}
+
static inline bool adreno_is_a320(struct adreno_gpu *gpu)
{
return gpu->revn == 320;
@@ -233,6 +239,7 @@ void adreno_idle(struct msm_gpu *gpu);
#ifdef CONFIG_DEBUG_FS
void adreno_show(struct msm_gpu *gpu, struct seq_file *m);
#endif
+void adreno_dump_info(struct msm_gpu *gpu);
void adreno_dump(struct msm_gpu *gpu);
void adreno_wait_ring(struct msm_gpu *gpu, uint32_t ndwords);
diff --git a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
index 6ffc4f6c8af1..bd5b23bf9041 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
+++ b/drivers/gpu/drm/msm/adreno/adreno_pm4.xml.h
@@ -12,11 +12,11 @@ The rules-ng-ng source files this header was generated from are:
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/a2xx.xml ( 32901 bytes, from 2014-06-02 15:21:30)
- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_common.xml ( 10551 bytes, from 2014-11-13 22:44:30)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 15085 bytes, from 2014-12-20 21:49:41)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 64344 bytes, from 2014-12-12 20:22:26)
-- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 51069 bytes, from 2014-12-21 15:51:54)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/adreno_pm4.xml ( 14895 bytes, from 2015-04-19 15:23:28)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a3xx.xml ( 66709 bytes, from 2015-04-12 18:16:35)
+- /home/robclark/src/freedreno/envytools/rnndb/adreno/a4xx.xml ( 60633 bytes, from 2015-05-20 14:48:19)
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -76,16 +76,11 @@ enum pc_di_primtype {
DI_PT_LINELOOP = 7,
DI_PT_RECTLIST = 8,
DI_PT_POINTLIST_A3XX = 9,
- DI_PT_QUADLIST = 13,
- DI_PT_QUADSTRIP = 14,
- DI_PT_POLYGON = 15,
- DI_PT_2D_COPY_RECT_LIST_V0 = 16,
- DI_PT_2D_COPY_RECT_LIST_V1 = 17,
- DI_PT_2D_COPY_RECT_LIST_V2 = 18,
- DI_PT_2D_COPY_RECT_LIST_V3 = 19,
- DI_PT_2D_FILL_RECT_LIST = 20,
- DI_PT_2D_LINE_STRIP = 21,
- DI_PT_2D_TRI_STRIP = 22,
+ DI_PT_LINE_ADJ = 10,
+ DI_PT_LINESTRIP_ADJ = 11,
+ DI_PT_TRI_ADJ = 12,
+ DI_PT_TRISTRIP_ADJ = 13,
+ DI_PT_PATCHES = 34,
};
enum pc_di_src_sel {
@@ -192,6 +187,7 @@ enum adreno_state_block {
SB_FRAG_TEX = 2,
SB_FRAG_MIPADDR = 3,
SB_VERT_SHADER = 4,
+ SB_GEOM_SHADER = 5,
SB_FRAG_SHADER = 6,
};
@@ -382,12 +378,19 @@ static inline uint32_t CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT(enum pc_di_src_sel va
{
return ((val) << CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__SHIFT) & CP_DRAW_INDX_OFFSET_0_SOURCE_SELECT__MASK;
}
+#define CP_DRAW_INDX_OFFSET_0_TESSELLATE 0x00000100
#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK 0x00000c00
#define CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT 10
static inline uint32_t CP_DRAW_INDX_OFFSET_0_INDEX_SIZE(enum a4xx_index_size val)
{
return ((val) << CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__SHIFT) & CP_DRAW_INDX_OFFSET_0_INDEX_SIZE__MASK;
}
+#define CP_DRAW_INDX_OFFSET_0_TESS_MODE__MASK 0x01f00000
+#define CP_DRAW_INDX_OFFSET_0_TESS_MODE__SHIFT 20
+static inline uint32_t CP_DRAW_INDX_OFFSET_0_TESS_MODE(uint32_t val)
+{
+ return ((val) << CP_DRAW_INDX_OFFSET_0_TESS_MODE__SHIFT) & CP_DRAW_INDX_OFFSET_0_TESS_MODE__MASK;
+}
#define REG_CP_DRAW_INDX_OFFSET_1 0x00000001
#define CP_DRAW_INDX_OFFSET_1_NUM_INSTANCES__MASK 0xffffffff
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index ad50b80225f5..1f2561e2ff71 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -23,12 +23,47 @@ struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi)
msm_dsi->encoders[MSM_DSI_CMD_ENCODER_ID];
}
+static int dsi_get_phy(struct msm_dsi *msm_dsi)
+{
+ struct platform_device *pdev = msm_dsi->pdev;
+ struct platform_device *phy_pdev;
+ struct device_node *phy_node;
+
+ phy_node = of_parse_phandle(pdev->dev.of_node, "qcom,dsi-phy", 0);
+ if (!phy_node) {
+ dev_err(&pdev->dev, "cannot find phy device\n");
+ return -ENXIO;
+ }
+
+ phy_pdev = of_find_device_by_node(phy_node);
+ if (phy_pdev)
+ msm_dsi->phy = platform_get_drvdata(phy_pdev);
+
+ of_node_put(phy_node);
+
+ if (!phy_pdev || !msm_dsi->phy) {
+ dev_err(&pdev->dev, "%s: phy driver is not ready\n", __func__);
+ return -EPROBE_DEFER;
+ }
+
+ msm_dsi->phy_dev = get_device(&phy_pdev->dev);
+
+ return 0;
+}
+
static void dsi_destroy(struct msm_dsi *msm_dsi)
{
if (!msm_dsi)
return;
msm_dsi_manager_unregister(msm_dsi);
+
+ if (msm_dsi->phy_dev) {
+ put_device(msm_dsi->phy_dev);
+ msm_dsi->phy = NULL;
+ msm_dsi->phy_dev = NULL;
+ }
+
if (msm_dsi->host) {
msm_dsi_host_destroy(msm_dsi->host);
msm_dsi->host = NULL;
@@ -43,7 +78,6 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev)
int ret;
if (!pdev) {
- dev_err(&pdev->dev, "no dsi device\n");
ret = -ENXIO;
goto fail;
}
@@ -63,6 +97,11 @@ static struct msm_dsi *dsi_init(struct platform_device *pdev)
if (ret)
goto fail;
+ /* GET dsi PHY */
+ ret = dsi_get_phy(msm_dsi);
+ if (ret)
+ goto fail;
+
/* Register to dsi manager */
ret = msm_dsi_manager_register(msm_dsi);
if (ret)
@@ -142,12 +181,14 @@ static struct platform_driver dsi_driver = {
void __init msm_dsi_register(void)
{
DBG("");
+ msm_dsi_phy_driver_register();
platform_driver_register(&dsi_driver);
}
void __exit msm_dsi_unregister(void)
{
DBG("");
+ msm_dsi_phy_driver_unregister();
platform_driver_unregister(&dsi_driver);
}
diff --git a/drivers/gpu/drm/msm/dsi/dsi.h b/drivers/gpu/drm/msm/dsi/dsi.h
index 10f54d4e379a..92d697de4858 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.h
@@ -14,6 +14,7 @@
#ifndef __DSI_CONNECTOR_H__
#define __DSI_CONNECTOR_H__
+#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include "drm_crtc.h"
@@ -38,6 +39,28 @@
#define DSI_ENCODER_MASTER DSI_1
#define DSI_ENCODER_SLAVE DSI_0
+enum msm_dsi_phy_type {
+ MSM_DSI_PHY_28NM_HPM,
+ MSM_DSI_PHY_28NM_LP,
+ MSM_DSI_PHY_MAX
+};
+
+#define DSI_DEV_REGULATOR_MAX 8
+
+/* Regulators for DSI devices */
+struct dsi_reg_entry {
+ char name[32];
+ int min_voltage;
+ int max_voltage;
+ int enable_load;
+ int disable_load;
+};
+
+struct dsi_reg_config {
+ int num;
+ struct dsi_reg_entry regs[DSI_DEV_REGULATOR_MAX];
+};
+
struct msm_dsi {
struct drm_device *dev;
struct platform_device *pdev;
@@ -49,6 +72,8 @@ struct msm_dsi {
struct msm_dsi_phy *phy;
struct drm_panel *panel;
unsigned long panel_flags;
+
+ struct device *phy_dev;
bool phy_enabled;
/* the encoders we are hooked to (outside of dsi block) */
@@ -73,6 +98,29 @@ void msm_dsi_manager_unregister(struct msm_dsi *msm_dsi);
/* msm dsi */
struct drm_encoder *msm_dsi_get_encoder(struct msm_dsi *msm_dsi);
+/* dsi pll */
+struct msm_dsi_pll;
+#ifdef CONFIG_DRM_MSM_DSI_PLL
+struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
+ enum msm_dsi_phy_type type, int dsi_id);
+void msm_dsi_pll_destroy(struct msm_dsi_pll *pll);
+int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
+ struct clk **byte_clk_provider, struct clk **pixel_clk_provider);
+#else
+static inline struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
+ enum msm_dsi_phy_type type, int id) {
+ return ERR_PTR(-ENODEV);
+}
+static inline void msm_dsi_pll_destroy(struct msm_dsi_pll *pll)
+{
+}
+static inline int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
+ struct clk **byte_clk_provider, struct clk **pixel_clk_provider)
+{
+ return -ENODEV;
+}
+#endif
+
/* dsi host */
int msm_dsi_host_xfer_prepare(struct mipi_dsi_host *host,
const struct mipi_dsi_msg *msg);
@@ -94,6 +142,8 @@ struct drm_panel *msm_dsi_host_get_panel(struct mipi_dsi_host *host,
unsigned long *panel_flags);
int msm_dsi_host_register(struct mipi_dsi_host *host, bool check_defer);
void msm_dsi_host_unregister(struct mipi_dsi_host *host);
+int msm_dsi_host_set_src_pll(struct mipi_dsi_host *host,
+ struct msm_dsi_pll *src_pll);
void msm_dsi_host_destroy(struct mipi_dsi_host *host);
int msm_dsi_host_modeset_init(struct mipi_dsi_host *host,
struct drm_device *dev);
@@ -101,17 +151,14 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi);
/* dsi phy */
struct msm_dsi_phy;
-enum msm_dsi_phy_type {
- MSM_DSI_PHY_UNKNOWN,
- MSM_DSI_PHY_28NM,
- MSM_DSI_PHY_MAX
-};
-struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev,
- enum msm_dsi_phy_type type, int id);
+void msm_dsi_phy_driver_register(void);
+void msm_dsi_phy_driver_unregister(void);
int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel,
const unsigned long bit_rate, const unsigned long esc_rate);
int msm_dsi_phy_disable(struct msm_dsi_phy *phy);
void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
u32 *clk_pre, u32 *clk_post);
+struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy);
+
#endif /* __DSI_CONNECTOR_H__ */
diff --git a/drivers/gpu/drm/msm/dsi/dsi.xml.h b/drivers/gpu/drm/msm/dsi/dsi.xml.h
index 1dcfae265e98..9791ea04bcbc 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.xml.h
+++ b/drivers/gpu/drm/msm/dsi/dsi.xml.h
@@ -8,8 +8,17 @@ 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:
-- /usr2/hali/local/envytools/envytools/rnndb/dsi/dsi.xml ( 18681 bytes, from 2015-03-04 23:08:31)
-- /usr2/hali/local/envytools/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2015-01-28 21:43:22)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2014-12-05 15:34:49)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 22094 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 10416 bytes, from 2015-05-12 12:45:23)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
@@ -394,6 +403,9 @@ static inline uint32_t DSI_CLKOUT_TIMING_CTRL_T_CLK_POST(uint32_t val)
#define DSI_EOT_PACKET_CTRL_TX_EOT_APPEND 0x00000001
#define DSI_EOT_PACKET_CTRL_RX_EOT_IGNORE 0x00000010
+#define REG_DSI_LANE_CTRL 0x000000a8
+#define DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST 0x10000000
+
#define REG_DSI_LANE_SWAP_CTRL 0x000000ac
#define DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL__MASK 0x00000007
#define DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL__SHIFT 0
@@ -835,5 +847,152 @@ static inline uint32_t DSI_28nm_PHY_TIMING_CTRL_11_TRIG3_CMD(uint32_t val)
#define REG_DSI_28nm_PHY_REGULATOR_CAL_PWR_CFG 0x00000018
+#define REG_DSI_28nm_PHY_PLL_REFCLK_CFG 0x00000000
+#define DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR 0x00000001
+
+#define REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG 0x00000004
+
+#define REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG 0x00000008
+
+#define REG_DSI_28nm_PHY_PLL_VCOLPF_CFG 0x0000000c
+
+#define REG_DSI_28nm_PHY_PLL_VREG_CFG 0x00000010
+#define DSI_28nm_PHY_PLL_VREG_CFG_POSTDIV1_BYPASS_B 0x00000002
+
+#define REG_DSI_28nm_PHY_PLL_PWRGEN_CFG 0x00000014
+
+#define REG_DSI_28nm_PHY_PLL_DMUX_CFG 0x00000018
+
+#define REG_DSI_28nm_PHY_PLL_AMUX_CFG 0x0000001c
+
+#define REG_DSI_28nm_PHY_PLL_GLB_CFG 0x00000020
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B 0x00000001
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B 0x00000002
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B 0x00000004
+#define DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE 0x00000008
+
+#define REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG 0x00000024
+
+#define REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG 0x00000028
+
+#define REG_DSI_28nm_PHY_PLL_LPFR_CFG 0x0000002c
+
+#define REG_DSI_28nm_PHY_PLL_LPFC1_CFG 0x00000030
+
+#define REG_DSI_28nm_PHY_PLL_LPFC2_CFG 0x00000034
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG0 0x00000038
+#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__MASK 0x0000003f
+#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__SHIFT 0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(uint32_t val)
+{
+ return ((val) << DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV__MASK;
+}
+#define DSI_28nm_PHY_PLL_SDM_CFG0_BYP 0x00000040
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG1 0x0000003c
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK 0x0000003f
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__SHIFT 0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(uint32_t val)
+{
+ return ((val) << DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;
+}
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__MASK 0x00000040
+#define DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__SHIFT 6
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN(uint32_t val)
+{
+ return ((val) << DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG1_DITHER_EN__MASK;
+}
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG2 0x00000040
+#define DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__MASK 0x000000ff
+#define DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__SHIFT 0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(uint32_t val)
+{
+ return ((val) << DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0__MASK;
+}
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG3 0x00000044
+#define DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__MASK 0x000000ff
+#define DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__SHIFT 0
+static inline uint32_t DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(uint32_t val)
+{
+ return ((val) << DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__SHIFT) & DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8__MASK;
+}
+
+#define REG_DSI_28nm_PHY_PLL_SDM_CFG4 0x00000048
+
+#define REG_DSI_28nm_PHY_PLL_SSC_CFG0 0x0000004c
+
+#define REG_DSI_28nm_PHY_PLL_SSC_CFG1 0x00000050
+
+#define REG_DSI_28nm_PHY_PLL_SSC_CFG2 0x00000054
+
+#define REG_DSI_28nm_PHY_PLL_SSC_CFG3 0x00000058
+
+#define REG_DSI_28nm_PHY_PLL_LKDET_CFG0 0x0000005c
+
+#define REG_DSI_28nm_PHY_PLL_LKDET_CFG1 0x00000060
+
+#define REG_DSI_28nm_PHY_PLL_LKDET_CFG2 0x00000064
+
+#define REG_DSI_28nm_PHY_PLL_TEST_CFG 0x00000068
+#define DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET 0x00000001
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG0 0x0000006c
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG1 0x00000070
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG2 0x00000074
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG3 0x00000078
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG4 0x0000007c
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG5 0x00000080
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG6 0x00000084
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG7 0x00000088
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG8 0x0000008c
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG9 0x00000090
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG10 0x00000094
+
+#define REG_DSI_28nm_PHY_PLL_CAL_CFG11 0x00000098
+
+#define REG_DSI_28nm_PHY_PLL_EFUSE_CFG 0x0000009c
+
+#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS_SEL 0x000000a0
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_42 0x000000a4
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_43 0x000000a8
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_44 0x000000ac
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_45 0x000000b0
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_46 0x000000b4
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_47 0x000000b8
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_48 0x000000bc
+
+#define REG_DSI_28nm_PHY_PLL_STATUS 0x000000c0
+#define DSI_28nm_PHY_PLL_STATUS_PLL_RDY 0x00000001
+
+#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS0 0x000000c4
+
+#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS1 0x000000c8
+
+#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS2 0x000000cc
+
+#define REG_DSI_28nm_PHY_PLL_DEBUG_BUS3 0x000000d0
+
+#define REG_DSI_28nm_PHY_PLL_CTRL_54 0x000000d4
+
#endif /* DSI_XML */
diff --git a/drivers/gpu/drm/msm/dsi/dsi_host.c b/drivers/gpu/drm/msm/dsi/dsi_host.c
index 649d20d29f92..de0400923303 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_host.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_host.c
@@ -15,6 +15,7 @@
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio.h>
+#include <linux/gpio/consumer.h>
#include <linux/interrupt.h>
#include <linux/of_device.h>
#include <linux/of_gpio.h>
@@ -36,35 +37,19 @@
#define DSI_6G_REG_SHIFT 4
-#define DSI_REGULATOR_MAX 8
-struct dsi_reg_entry {
- char name[32];
- int min_voltage;
- int max_voltage;
- int enable_load;
- int disable_load;
-};
-
-struct dsi_reg_config {
- int num;
- struct dsi_reg_entry regs[DSI_REGULATOR_MAX];
-};
-
struct dsi_config {
u32 major;
u32 minor;
u32 io_offset;
- enum msm_dsi_phy_type phy_type;
struct dsi_reg_config reg_cfg;
};
static const struct dsi_config dsi_cfgs[] = {
- {MSM_DSI_VER_MAJOR_V2, 0, 0, MSM_DSI_PHY_UNKNOWN},
+ {MSM_DSI_VER_MAJOR_V2, 0, 0, {0,} },
{ /* 8974 v1 */
.major = MSM_DSI_VER_MAJOR_6G,
.minor = MSM_DSI_6G_VER_MINOR_V1_0,
.io_offset = DSI_6G_REG_SHIFT,
- .phy_type = MSM_DSI_PHY_28NM,
.reg_cfg = {
.num = 4,
.regs = {
@@ -79,7 +64,6 @@ static const struct dsi_config dsi_cfgs[] = {
.major = MSM_DSI_VER_MAJOR_6G,
.minor = MSM_DSI_6G_VER_MINOR_V1_1,
.io_offset = DSI_6G_REG_SHIFT,
- .phy_type = MSM_DSI_PHY_28NM,
.reg_cfg = {
.num = 4,
.regs = {
@@ -94,7 +78,6 @@ static const struct dsi_config dsi_cfgs[] = {
.major = MSM_DSI_VER_MAJOR_6G,
.minor = MSM_DSI_6G_VER_MINOR_V1_1_1,
.io_offset = DSI_6G_REG_SHIFT,
- .phy_type = MSM_DSI_PHY_28NM,
.reg_cfg = {
.num = 4,
.regs = {
@@ -109,7 +92,6 @@ static const struct dsi_config dsi_cfgs[] = {
.major = MSM_DSI_VER_MAJOR_6G,
.minor = MSM_DSI_6G_VER_MINOR_V1_2,
.io_offset = DSI_6G_REG_SHIFT,
- .phy_type = MSM_DSI_PHY_28NM,
.reg_cfg = {
.num = 4,
.regs = {
@@ -124,7 +106,6 @@ static const struct dsi_config dsi_cfgs[] = {
.major = MSM_DSI_VER_MAJOR_6G,
.minor = MSM_DSI_6G_VER_MINOR_V1_3_1,
.io_offset = DSI_6G_REG_SHIFT,
- .phy_type = MSM_DSI_PHY_28NM,
.reg_cfg = {
.num = 4,
.regs = {
@@ -197,7 +178,7 @@ struct msm_dsi_host {
int id;
void __iomem *ctrl_base;
- struct regulator_bulk_data supplies[DSI_REGULATOR_MAX];
+ struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX];
struct clk *mdp_core_clk;
struct clk *ahb_clk;
struct clk *axi_clk;
@@ -205,6 +186,9 @@ struct msm_dsi_host {
struct clk *byte_clk;
struct clk *esc_clk;
struct clk *pixel_clk;
+ struct clk *byte_clk_src;
+ struct clk *pixel_clk_src;
+
u32 byte_clk_rate;
struct gpio_desc *disp_en_gpio;
@@ -273,7 +257,7 @@ static const struct dsi_config *dsi_get_config(struct msm_dsi_host *msm_host)
u32 major = 0, minor = 0;
gdsc_reg = regulator_get(&msm_host->pdev->dev, "gdsc");
- if (IS_ERR_OR_NULL(gdsc_reg)) {
+ if (IS_ERR(gdsc_reg)) {
pr_err("%s: cannot get gdsc\n", __func__);
goto fail;
}
@@ -463,6 +447,22 @@ 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);
+ 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);
+ pr_err("%s: can't find pixel_clk_src. ret=%d\n", __func__, ret);
+ msm_host->pixel_clk_src = NULL;
+ goto exit;
+ }
+
exit:
return ret;
}
@@ -787,6 +787,11 @@ static void dsi_ctrl_config(struct msm_dsi_host *msm_host, bool enable,
dsi_write(msm_host, REG_DSI_LANE_SWAP_CTRL,
DSI_LANE_SWAP_CTRL_DLN_SWAP_SEL(LANE_SWAP_0123));
}
+
+ if (!(flags & MIPI_DSI_CLOCK_NON_CONTINUOUS))
+ dsi_write(msm_host, REG_DSI_LANE_CTRL,
+ DSI_LANE_CTRL_CLKLN_HS_FORCE_REQUEST);
+
data |= DSI_CTRL_ENABLE;
dsi_write(msm_host, REG_DSI_CTRL, data);
@@ -1345,36 +1350,19 @@ static irqreturn_t dsi_host_irq(int irq, void *ptr)
static int dsi_host_init_panel_gpios(struct msm_dsi_host *msm_host,
struct device *panel_device)
{
- int ret;
-
- msm_host->disp_en_gpio = devm_gpiod_get(panel_device,
- "disp-enable");
+ msm_host->disp_en_gpio = devm_gpiod_get_optional(panel_device,
+ "disp-enable",
+ GPIOD_OUT_LOW);
if (IS_ERR(msm_host->disp_en_gpio)) {
DBG("cannot get disp-enable-gpios %ld",
PTR_ERR(msm_host->disp_en_gpio));
- msm_host->disp_en_gpio = NULL;
- }
- if (msm_host->disp_en_gpio) {
- ret = gpiod_direction_output(msm_host->disp_en_gpio, 0);
- if (ret) {
- pr_err("cannot set dir to disp-en-gpios %d\n", ret);
- return ret;
- }
+ return PTR_ERR(msm_host->disp_en_gpio);
}
- msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te");
+ msm_host->te_gpio = devm_gpiod_get(panel_device, "disp-te", GPIOD_IN);
if (IS_ERR(msm_host->te_gpio)) {
DBG("cannot get disp-te-gpios %ld", PTR_ERR(msm_host->te_gpio));
- msm_host->te_gpio = NULL;
- }
-
- if (msm_host->te_gpio) {
- ret = gpiod_direction_input(msm_host->te_gpio);
- if (ret) {
- pr_err("%s: cannot set dir to disp-te-gpios, %d\n",
- __func__, ret);
- return ret;
- }
+ return PTR_ERR(msm_host->te_gpio);
}
return 0;
@@ -1508,13 +1496,6 @@ int msm_dsi_host_init(struct msm_dsi *msm_dsi)
msm_host->workqueue = alloc_ordered_workqueue("dsi_drm_work", 0);
INIT_WORK(&msm_host->err_work, dsi_err_worker);
- msm_dsi->phy = msm_dsi_phy_init(pdev, msm_host->cfg->phy_type,
- msm_host->id);
- if (!msm_dsi->phy) {
- ret = -EINVAL;
- pr_err("%s: phy init failed\n", __func__);
- goto fail;
- }
msm_dsi->host = &msm_host->base;
msm_dsi->id = msm_host->id;
@@ -1824,6 +1805,39 @@ void msm_dsi_host_cmd_xfer_commit(struct mipi_dsi_host *host, u32 iova, u32 len)
wmb();
}
+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);
+ struct clk *byte_clk_provider, *pixel_clk_provider;
+ int ret;
+
+ ret = msm_dsi_pll_get_clk_provider(src_pll,
+ &byte_clk_provider, &pixel_clk_provider);
+ if (ret) {
+ pr_info("%s: can't get provider from pll, don't set parent\n",
+ __func__);
+ return 0;
+ }
+
+ ret = clk_set_parent(msm_host->byte_clk_src, byte_clk_provider);
+ if (ret) {
+ pr_err("%s: can't set parent to byte_clk_src. ret=%d\n",
+ __func__, ret);
+ goto exit;
+ }
+
+ ret = clk_set_parent(msm_host->pixel_clk_src, pixel_clk_provider);
+ if (ret) {
+ pr_err("%s: can't set parent to pixel_clk_src. ret=%d\n",
+ __func__, ret);
+ goto exit;
+ }
+
+exit:
+ return ret;
+}
+
int msm_dsi_host_enable(struct mipi_dsi_host *host)
{
struct msm_dsi_host *msm_host = to_msm_dsi_host(host);
diff --git a/drivers/gpu/drm/msm/dsi/dsi_manager.c b/drivers/gpu/drm/msm/dsi/dsi_manager.c
index 0a40f3c64e8b..87ac6612b6f8 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_manager.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_manager.c
@@ -60,6 +60,53 @@ static int dsi_mgr_parse_dual_panel(struct device_node *np, int id)
return 0;
}
+static int dsi_mgr_host_register(int id)
+{
+ struct msm_dsi *msm_dsi = dsi_mgr_get_dsi(id);
+ struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
+ struct msm_dsi *clk_master_dsi = dsi_mgr_get_dsi(DSI_CLOCK_MASTER);
+ struct msm_dsi_pll *src_pll;
+ int ret;
+
+ if (!IS_DUAL_PANEL()) {
+ ret = msm_dsi_host_register(msm_dsi->host, true);
+ if (ret)
+ return ret;
+
+ src_pll = msm_dsi_phy_get_pll(msm_dsi->phy);
+ ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll);
+ } else if (!other_dsi) {
+ ret = 0;
+ } else {
+ struct msm_dsi *mdsi = IS_MASTER_PANEL(id) ?
+ msm_dsi : other_dsi;
+ struct msm_dsi *sdsi = IS_MASTER_PANEL(id) ?
+ other_dsi : msm_dsi;
+ /* Register slave host first, so that slave DSI device
+ * has a chance to probe, and do not block the master
+ * DSI device's probe.
+ * Also, do not check defer for the slave host,
+ * because only master DSI device adds the panel to global
+ * panel list. The panel's device is the master DSI device.
+ */
+ ret = msm_dsi_host_register(sdsi->host, false);
+ if (ret)
+ return ret;
+ ret = msm_dsi_host_register(mdsi->host, true);
+ if (ret)
+ return ret;
+
+ /* PLL0 is to drive both 2 DSI link clocks in Dual DSI mode. */
+ src_pll = msm_dsi_phy_get_pll(clk_master_dsi->phy);
+ ret = msm_dsi_host_set_src_pll(msm_dsi->host, src_pll);
+ if (ret)
+ return ret;
+ ret = msm_dsi_host_set_src_pll(other_dsi->host, src_pll);
+ }
+
+ return ret;
+}
+
struct dsi_connector {
struct drm_connector base;
int id;
@@ -652,7 +699,6 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
{
struct msm_dsi_manager *msm_dsim = &msm_dsim_glb;
int id = msm_dsi->id;
- struct msm_dsi *other_dsi = dsi_mgr_get_other_dsi(id);
int ret;
if (id > DSI_MAX) {
@@ -670,31 +716,20 @@ int msm_dsi_manager_register(struct msm_dsi *msm_dsi)
ret = dsi_mgr_parse_dual_panel(msm_dsi->pdev->dev.of_node, id);
if (ret) {
pr_err("%s: failed to parse dual panel info\n", __func__);
- return ret;
+ goto fail;
}
- if (!IS_DUAL_PANEL()) {
- ret = msm_dsi_host_register(msm_dsi->host, true);
- } else if (!other_dsi) {
- return 0;
- } else {
- struct msm_dsi *mdsi = IS_MASTER_PANEL(id) ?
- msm_dsi : other_dsi;
- struct msm_dsi *sdsi = IS_MASTER_PANEL(id) ?
- other_dsi : msm_dsi;
- /* Register slave host first, so that slave DSI device
- * has a chance to probe, and do not block the master
- * DSI device's probe.
- * Also, do not check defer for the slave host,
- * because only master DSI device adds the panel to global
- * panel list. The panel's device is the master DSI device.
- */
- ret = msm_dsi_host_register(sdsi->host, false);
- if (ret)
- return ret;
- ret = msm_dsi_host_register(mdsi->host, true);
+ ret = dsi_mgr_host_register(id);
+ if (ret) {
+ pr_err("%s: failed to register mipi dsi host for DSI %d\n",
+ __func__, id);
+ goto fail;
}
+ return 0;
+
+fail:
+ msm_dsim->dsi[id] = NULL;
return ret;
}
diff --git a/drivers/gpu/drm/msm/dsi/dsi_phy.c b/drivers/gpu/drm/msm/dsi/dsi_phy.c
index f0cea8927388..2d3b33ce1cc5 100644
--- a/drivers/gpu/drm/msm/dsi/dsi_phy.c
+++ b/drivers/gpu/drm/msm/dsi/dsi_phy.c
@@ -11,12 +11,27 @@
* GNU General Public License for more details.
*/
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+
#include "dsi.h"
#include "dsi.xml.h"
#define dsi_phy_read(offset) msm_readl((offset))
#define dsi_phy_write(offset, data) msm_writel((data), (offset))
+struct dsi_phy_ops {
+ int (*enable)(struct msm_dsi_phy *phy, bool is_dual_panel,
+ const unsigned long bit_rate, const unsigned long esc_rate);
+ int (*disable)(struct msm_dsi_phy *phy);
+};
+
+struct dsi_phy_cfg {
+ enum msm_dsi_phy_type type;
+ struct dsi_reg_config reg_cfg;
+ struct dsi_phy_ops ops;
+};
+
struct dsi_dphy_timing {
u32 clk_pre;
u32 clk_post;
@@ -34,15 +49,106 @@ struct dsi_dphy_timing {
};
struct msm_dsi_phy {
+ struct platform_device *pdev;
void __iomem *base;
void __iomem *reg_base;
int id;
+
+ struct clk *ahb_clk;
+ struct regulator_bulk_data supplies[DSI_DEV_REGULATOR_MAX];
+
struct dsi_dphy_timing timing;
- int (*enable)(struct msm_dsi_phy *phy, bool is_dual_panel,
- const unsigned long bit_rate, const unsigned long esc_rate);
- int (*disable)(struct msm_dsi_phy *phy);
+ const struct dsi_phy_cfg *cfg;
+
+ struct msm_dsi_pll *pll;
};
+static int dsi_phy_regulator_init(struct msm_dsi_phy *phy)
+{
+ struct regulator_bulk_data *s = phy->supplies;
+ const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
+ struct device *dev = &phy->pdev->dev;
+ int num = phy->cfg->reg_cfg.num;
+ int i, ret;
+
+ for (i = 0; i < num; i++)
+ s[i].supply = regs[i].name;
+
+ ret = devm_regulator_bulk_get(&phy->pdev->dev, num, s);
+ if (ret < 0) {
+ dev_err(dev, "%s: failed to init regulator, ret=%d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ for (i = 0; i < num; i++) {
+ if ((regs[i].min_voltage >= 0) && (regs[i].max_voltage >= 0)) {
+ ret = regulator_set_voltage(s[i].consumer,
+ regs[i].min_voltage, regs[i].max_voltage);
+ if (ret < 0) {
+ dev_err(dev,
+ "regulator %d set voltage failed, %d\n",
+ i, ret);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static void dsi_phy_regulator_disable(struct msm_dsi_phy *phy)
+{
+ struct regulator_bulk_data *s = phy->supplies;
+ const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
+ int num = phy->cfg->reg_cfg.num;
+ int i;
+
+ DBG("");
+ for (i = num - 1; i >= 0; i--)
+ if (regs[i].disable_load >= 0)
+ regulator_set_load(s[i].consumer,
+ regs[i].disable_load);
+
+ regulator_bulk_disable(num, s);
+}
+
+static int dsi_phy_regulator_enable(struct msm_dsi_phy *phy)
+{
+ struct regulator_bulk_data *s = phy->supplies;
+ const struct dsi_reg_entry *regs = phy->cfg->reg_cfg.regs;
+ struct device *dev = &phy->pdev->dev;
+ int num = phy->cfg->reg_cfg.num;
+ int ret, i;
+
+ DBG("");
+ for (i = 0; i < num; i++) {
+ if (regs[i].enable_load >= 0) {
+ ret = regulator_set_load(s[i].consumer,
+ regs[i].enable_load);
+ if (ret < 0) {
+ dev_err(dev,
+ "regulator %d set op mode failed, %d\n",
+ i, ret);
+ goto fail;
+ }
+ }
+ }
+
+ ret = regulator_bulk_enable(num, s);
+ if (ret < 0) {
+ dev_err(dev, "regulator enable failed, %d\n", ret);
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ for (i--; i >= 0; i--)
+ regulator_set_load(s[i].consumer, regs[i].disable_load);
+ return ret;
+}
+
#define S_DIV_ROUND_UP(n, d) \
(((n) >= 0) ? (((n) + (d) - 1) / (d)) : (((n) - (d) + 1) / (d)))
@@ -284,59 +390,200 @@ static int dsi_28nm_phy_disable(struct msm_dsi_phy *phy)
return 0;
}
-#define dsi_phy_func_init(name) \
- do { \
- phy->enable = dsi_##name##_phy_enable; \
- phy->disable = dsi_##name##_phy_disable; \
- } while (0)
+static int dsi_phy_enable_resource(struct msm_dsi_phy *phy)
+{
+ int ret;
+
+ pm_runtime_get_sync(&phy->pdev->dev);
-struct msm_dsi_phy *msm_dsi_phy_init(struct platform_device *pdev,
- enum msm_dsi_phy_type type, int id)
+ ret = clk_prepare_enable(phy->ahb_clk);
+ if (ret) {
+ pr_err("%s: can't enable ahb clk, %d\n", __func__, ret);
+ pm_runtime_put_sync(&phy->pdev->dev);
+ }
+
+ return ret;
+}
+
+static void dsi_phy_disable_resource(struct msm_dsi_phy *phy)
+{
+ clk_disable_unprepare(phy->ahb_clk);
+ pm_runtime_put_sync(&phy->pdev->dev);
+}
+
+static const struct dsi_phy_cfg dsi_phy_cfgs[MSM_DSI_PHY_MAX] = {
+ [MSM_DSI_PHY_28NM_HPM] = {
+ .type = MSM_DSI_PHY_28NM_HPM,
+ .reg_cfg = {
+ .num = 1,
+ .regs = {
+ {"vddio", 1800000, 1800000, 100000, 100},
+ },
+ },
+ .ops = {
+ .enable = dsi_28nm_phy_enable,
+ .disable = dsi_28nm_phy_disable,
+ }
+ },
+ [MSM_DSI_PHY_28NM_LP] = {
+ .type = MSM_DSI_PHY_28NM_LP,
+ .reg_cfg = {
+ .num = 1,
+ .regs = {
+ {"vddio", 1800000, 1800000, 100000, 100},
+ },
+ },
+ .ops = {
+ .enable = dsi_28nm_phy_enable,
+ .disable = dsi_28nm_phy_disable,
+ }
+ },
+};
+
+static const struct of_device_id dsi_phy_dt_match[] = {
+ { .compatible = "qcom,dsi-phy-28nm-hpm",
+ .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_HPM],},
+ { .compatible = "qcom,dsi-phy-28nm-lp",
+ .data = &dsi_phy_cfgs[MSM_DSI_PHY_28NM_LP],},
+ {}
+};
+
+static int dsi_phy_driver_probe(struct platform_device *pdev)
{
struct msm_dsi_phy *phy;
+ const struct of_device_id *match;
+ int ret;
phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL);
if (!phy)
- return NULL;
+ return -ENOMEM;
+
+ match = of_match_node(dsi_phy_dt_match, pdev->dev.of_node);
+ if (!match)
+ return -ENODEV;
+
+ phy->cfg = match->data;
+ phy->pdev = pdev;
+
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "qcom,dsi-phy-index", &phy->id);
+ if (ret) {
+ dev_err(&pdev->dev,
+ "%s: PHY index not specified, ret=%d\n",
+ __func__, ret);
+ goto fail;
+ }
phy->base = msm_ioremap(pdev, "dsi_phy", "DSI_PHY");
- if (IS_ERR_OR_NULL(phy->base)) {
- pr_err("%s: failed to map phy base\n", __func__);
- return NULL;
+ if (IS_ERR(phy->base)) {
+ dev_err(&pdev->dev, "%s: failed to map phy base\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
}
phy->reg_base = msm_ioremap(pdev, "dsi_phy_regulator", "DSI_PHY_REG");
- if (IS_ERR_OR_NULL(phy->reg_base)) {
- pr_err("%s: failed to map phy regulator base\n", __func__);
- return NULL;
+ if (IS_ERR(phy->reg_base)) {
+ dev_err(&pdev->dev,
+ "%s: failed to map phy regulator base\n", __func__);
+ ret = -ENOMEM;
+ goto fail;
}
- switch (type) {
- case MSM_DSI_PHY_28NM:
- dsi_phy_func_init(28nm);
- break;
- default:
- pr_err("%s: unsupported type, %d\n", __func__, type);
- return NULL;
+ ret = dsi_phy_regulator_init(phy);
+ if (ret) {
+ dev_err(&pdev->dev, "%s: failed to init regulator\n", __func__);
+ goto fail;
+ }
+
+ phy->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+ if (IS_ERR(phy->ahb_clk)) {
+ pr_err("%s: Unable to get ahb clk\n", __func__);
+ ret = PTR_ERR(phy->ahb_clk);
+ goto fail;
}
- phy->id = id;
+ /* PLL init will call into clk_register which requires
+ * register access, so we need to enable power and ahb clock.
+ */
+ ret = dsi_phy_enable_resource(phy);
+ if (ret)
+ goto fail;
+
+ phy->pll = msm_dsi_pll_init(pdev, phy->cfg->type, phy->id);
+ if (!phy->pll)
+ dev_info(&pdev->dev,
+ "%s: pll init failed, need separate pll clk driver\n",
+ __func__);
+
+ dsi_phy_disable_resource(phy);
+
+ platform_set_drvdata(pdev, phy);
+
+ return 0;
- return phy;
+fail:
+ return ret;
+}
+
+static int dsi_phy_driver_remove(struct platform_device *pdev)
+{
+ struct msm_dsi_phy *phy = platform_get_drvdata(pdev);
+
+ if (phy && phy->pll) {
+ msm_dsi_pll_destroy(phy->pll);
+ phy->pll = NULL;
+ }
+
+ platform_set_drvdata(pdev, NULL);
+
+ return 0;
+}
+
+static struct platform_driver dsi_phy_platform_driver = {
+ .probe = dsi_phy_driver_probe,
+ .remove = dsi_phy_driver_remove,
+ .driver = {
+ .name = "msm_dsi_phy",
+ .of_match_table = dsi_phy_dt_match,
+ },
+};
+
+void __init msm_dsi_phy_driver_register(void)
+{
+ platform_driver_register(&dsi_phy_platform_driver);
+}
+
+void __exit msm_dsi_phy_driver_unregister(void)
+{
+ platform_driver_unregister(&dsi_phy_platform_driver);
}
int msm_dsi_phy_enable(struct msm_dsi_phy *phy, bool is_dual_panel,
const unsigned long bit_rate, const unsigned long esc_rate)
{
- if (!phy || !phy->enable)
+ int ret;
+
+ if (!phy || !phy->cfg->ops.enable)
return -EINVAL;
- return phy->enable(phy, is_dual_panel, bit_rate, esc_rate);
+
+ ret = dsi_phy_regulator_enable(phy);
+ if (ret) {
+ dev_err(&phy->pdev->dev, "%s: regulator enable failed, %d\n",
+ __func__, ret);
+ return ret;
+ }
+
+ return phy->cfg->ops.enable(phy, is_dual_panel, bit_rate, esc_rate);
}
int msm_dsi_phy_disable(struct msm_dsi_phy *phy)
{
- if (!phy || !phy->disable)
+ if (!phy || !phy->cfg->ops.disable)
return -EINVAL;
- return phy->disable(phy);
+
+ phy->cfg->ops.disable(phy);
+ dsi_phy_regulator_disable(phy);
+
+ return 0;
}
void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
@@ -350,3 +597,11 @@ void msm_dsi_phy_get_clk_pre_post(struct msm_dsi_phy *phy,
*clk_post = phy->timing.clk_post;
}
+struct msm_dsi_pll *msm_dsi_phy_get_pll(struct msm_dsi_phy *phy)
+{
+ if (!phy)
+ return NULL;
+
+ return phy->pll;
+}
+
diff --git a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
index 695f99d4bec2..728152f3ef48 100644
--- a/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
+++ b/drivers/gpu/drm/msm/dsi/mmss_cc.xml.h
@@ -10,15 +10,15 @@ 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 2014-12-05 15:34:49)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 22094 bytes, from 2015-05-12 12:45:23)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 10416 bytes, from 2015-05-12 12:45:23)
Copyright (C) 2013-2014 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
new file mode 100644
index 000000000000..509376fdd112
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.c
@@ -0,0 +1,164 @@
+/*
+ * 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,
+ * 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 "dsi_pll.h"
+
+static int dsi_pll_enable(struct msm_dsi_pll *pll)
+{
+ int i, ret = 0;
+
+ /*
+ * Certain PLLs do not allow VCO rate update when it is on.
+ * Keep track of their status to turn on/off after set rate success.
+ */
+ if (unlikely(pll->pll_on))
+ return 0;
+
+ /* Try all enable sequences until one succeeds */
+ for (i = 0; i < pll->en_seq_cnt; i++) {
+ ret = pll->enable_seqs[i](pll);
+ DBG("DSI PLL %s after sequence #%d",
+ ret ? "unlocked" : "locked", i + 1);
+ if (!ret)
+ break;
+ }
+
+ if (ret) {
+ DRM_ERROR("DSI PLL failed to lock\n");
+ return ret;
+ }
+
+ pll->pll_on = true;
+
+ return 0;
+}
+
+static void dsi_pll_disable(struct msm_dsi_pll *pll)
+{
+ if (unlikely(!pll->pll_on))
+ return;
+
+ pll->disable_seq(pll);
+
+ pll->pll_on = false;
+}
+
+/*
+ * DSI PLL Helper functions
+ */
+long msm_dsi_pll_helper_clk_round_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long *parent_rate)
+{
+ struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+
+ if (rate < pll->min_rate)
+ return pll->min_rate;
+ else if (rate > pll->max_rate)
+ return pll->max_rate;
+ else
+ return rate;
+}
+
+int msm_dsi_pll_helper_clk_prepare(struct clk_hw *hw)
+{
+ struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+ int ret;
+
+ /*
+ * Certain PLLs need to update the same VCO rate and registers
+ * after resume in suspend/resume scenario.
+ */
+ if (pll->restore_state) {
+ ret = pll->restore_state(pll);
+ if (ret)
+ goto error;
+ }
+
+ ret = dsi_pll_enable(pll);
+
+error:
+ return ret;
+}
+
+void msm_dsi_pll_helper_clk_unprepare(struct clk_hw *hw)
+{
+ struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+
+ if (pll->save_state)
+ pll->save_state(pll);
+
+ dsi_pll_disable(pll);
+}
+
+void msm_dsi_pll_helper_unregister_clks(struct platform_device *pdev,
+ struct clk **clks, u32 num_clks)
+{
+ of_clk_del_provider(pdev->dev.of_node);
+
+ if (!num_clks || !clks)
+ return;
+
+ do {
+ clk_unregister(clks[--num_clks]);
+ clks[num_clks] = NULL;
+ } while (num_clks);
+}
+
+/*
+ * DSI PLL API
+ */
+int msm_dsi_pll_get_clk_provider(struct msm_dsi_pll *pll,
+ struct clk **byte_clk_provider, struct clk **pixel_clk_provider)
+{
+ if (pll->get_provider)
+ return pll->get_provider(pll,
+ byte_clk_provider,
+ pixel_clk_provider);
+
+ return -EINVAL;
+}
+
+void msm_dsi_pll_destroy(struct msm_dsi_pll *pll)
+{
+ if (pll->destroy)
+ pll->destroy(pll);
+}
+
+struct msm_dsi_pll *msm_dsi_pll_init(struct platform_device *pdev,
+ enum msm_dsi_phy_type type, int id)
+{
+ struct device *dev = &pdev->dev;
+ struct msm_dsi_pll *pll;
+
+ switch (type) {
+ case MSM_DSI_PHY_28NM_HPM:
+ case MSM_DSI_PHY_28NM_LP:
+ pll = msm_dsi_pll_28nm_init(pdev, type, id);
+ break;
+ default:
+ pll = ERR_PTR(-ENXIO);
+ break;
+ }
+
+ if (IS_ERR(pll)) {
+ dev_err(dev, "%s: failed to init DSI PLL\n", __func__);
+ return NULL;
+ }
+
+ pll->type = type;
+
+ DBG("DSI:%d PLL registered", id);
+
+ return pll;
+}
+
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
new file mode 100644
index 000000000000..5a3bb241c039
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll.h
@@ -0,0 +1,89 @@
+/*
+ * 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,
+ * 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.
+ */
+
+#ifndef __DSI_PLL_H__
+#define __DSI_PLL_H__
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+
+#include "dsi.h"
+
+#define NUM_DSI_CLOCKS_MAX 6
+#define MAX_DSI_PLL_EN_SEQS 10
+
+struct msm_dsi_pll {
+ enum msm_dsi_phy_type type;
+
+ struct clk_hw clk_hw;
+ bool pll_on;
+
+ unsigned long min_rate;
+ unsigned long max_rate;
+ u32 en_seq_cnt;
+
+ int (*enable_seqs[MAX_DSI_PLL_EN_SEQS])(struct msm_dsi_pll *pll);
+ void (*disable_seq)(struct msm_dsi_pll *pll);
+ int (*get_provider)(struct msm_dsi_pll *pll,
+ struct clk **byte_clk_provider,
+ struct clk **pixel_clk_provider);
+ void (*destroy)(struct msm_dsi_pll *pll);
+ void (*save_state)(struct msm_dsi_pll *pll);
+ int (*restore_state)(struct msm_dsi_pll *pll);
+};
+
+#define hw_clk_to_pll(x) container_of(x, struct msm_dsi_pll, clk_hw)
+
+static inline void pll_write(void __iomem *reg, u32 data)
+{
+ msm_writel(data, reg);
+}
+
+static inline u32 pll_read(const void __iomem *reg)
+{
+ return msm_readl(reg);
+}
+
+static inline void pll_write_udelay(void __iomem *reg, u32 data, u32 delay_us)
+{
+ pll_write(reg, data);
+ udelay(delay_us);
+}
+
+static inline void pll_write_ndelay(void __iomem *reg, u32 data, u32 delay_ns)
+{
+ pll_write((reg), data);
+ ndelay(delay_ns);
+}
+
+/*
+ * DSI PLL Helper functions
+ */
+
+/* clock callbacks */
+long msm_dsi_pll_helper_clk_round_rate(struct clk_hw *hw,
+ unsigned long rate, unsigned long *parent_rate);
+int msm_dsi_pll_helper_clk_prepare(struct clk_hw *hw);
+void msm_dsi_pll_helper_clk_unprepare(struct clk_hw *hw);
+/* misc */
+void msm_dsi_pll_helper_unregister_clks(struct platform_device *pdev,
+ struct clk **clks, u32 num_clks);
+
+/*
+ * Initialization for Each PLL Type
+ */
+struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device *pdev,
+ enum msm_dsi_phy_type type, int id);
+
+#endif /* __DSI_PLL_H__ */
+
diff --git a/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
new file mode 100644
index 000000000000..eb8ac3097ff5
--- /dev/null
+++ b/drivers/gpu/drm/msm/dsi/pll/dsi_pll_28nm.c
@@ -0,0 +1,652 @@
+/*
+ * 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,
+ * 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>
+#include <linux/clk-provider.h>
+
+#include "dsi_pll.h"
+#include "dsi.xml.h"
+
+/*
+ * DSI PLL 28nm - clock diagram (eg: DSI0):
+ *
+ * dsi0analog_postdiv_clk
+ * | dsi0indirect_path_div2_clk
+ * | |
+ * +------+ | +----+ | |\ dsi0byte_mux
+ * dsi0vco_clk --o--| DIV1 |--o--| /2 |--o--| \ |
+ * | +------+ +----+ | m| | +----+
+ * | | u|--o--| /4 |-- dsi0pllbyte
+ * | | x| +----+
+ * o--------------------------| /
+ * | |/
+ * | +------+
+ * o----------| DIV3 |------------------------- dsi0pll
+ * +------+
+ */
+
+#define POLL_MAX_READS 10
+#define POLL_TIMEOUT_US 50
+
+#define NUM_PROVIDED_CLKS 2
+
+#define VCO_REF_CLK_RATE 19200000
+#define VCO_MIN_RATE 350000000
+#define VCO_MAX_RATE 750000000
+
+#define DSI_BYTE_PLL_CLK 0
+#define DSI_PIXEL_PLL_CLK 1
+
+#define LPFR_LUT_SIZE 10
+struct lpfr_cfg {
+ unsigned long vco_rate;
+ u32 resistance;
+};
+
+/* Loop filter resistance: */
+static const struct lpfr_cfg lpfr_lut[LPFR_LUT_SIZE] = {
+ { 479500000, 8 },
+ { 480000000, 11 },
+ { 575500000, 8 },
+ { 576000000, 12 },
+ { 610500000, 8 },
+ { 659500000, 9 },
+ { 671500000, 10 },
+ { 672000000, 14 },
+ { 708500000, 10 },
+ { 750000000, 11 },
+};
+
+struct pll_28nm_cached_state {
+ unsigned long vco_rate;
+ u8 postdiv3;
+ u8 postdiv1;
+ u8 byte_mux;
+};
+
+struct dsi_pll_28nm {
+ struct msm_dsi_pll base;
+
+ int id;
+ struct platform_device *pdev;
+ void __iomem *mmio;
+
+ int vco_delay;
+
+ /* private clocks: */
+ struct clk *clks[NUM_DSI_CLOCKS_MAX];
+ u32 num_clks;
+
+ /* clock-provider: */
+ struct clk *provided_clks[NUM_PROVIDED_CLKS];
+ struct clk_onecell_data clk_data;
+
+ struct pll_28nm_cached_state cached_state;
+};
+
+#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)
+{
+ bool pll_locked = false;
+ u32 val;
+
+ while (nb_tries--) {
+ val = pll_read(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_STATUS);
+ pll_locked = !!(val & DSI_28nm_PHY_PLL_STATUS_PLL_RDY);
+
+ if (pll_locked)
+ break;
+
+ udelay(timeout_us);
+ }
+ DBG("DSI PLL is %slocked", pll_locked ? "" : "*not* ");
+
+ return pll_locked;
+}
+
+static void pll_28nm_software_reset(struct dsi_pll_28nm *pll_28nm)
+{
+ void __iomem *base = pll_28nm->mmio;
+
+ /*
+ * Add HW recommended delays after toggling the software
+ * reset bit off and back on.
+ */
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG,
+ DSI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET, 1);
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_TEST_CFG, 0x00, 1);
+}
+
+/*
+ * Clock Callbacks
+ */
+static int dsi_pll_28nm_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+ struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+ struct device *dev = &pll_28nm->pdev->dev;
+ void __iomem *base = pll_28nm->mmio;
+ unsigned long div_fbx1000, gen_vco_clk;
+ u32 refclk_cfg, frac_n_mode, frac_n_value;
+ u32 sdm_cfg0, sdm_cfg1, sdm_cfg2, sdm_cfg3;
+ u32 cal_cfg10, cal_cfg11;
+ u32 rem;
+ int i;
+
+ VERB("rate=%lu, parent's=%lu", rate, parent_rate);
+
+ /* Force postdiv2 to be div-4 */
+ pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV2_CFG, 3);
+
+ /* Configure the Loop filter resistance */
+ for (i = 0; i < LPFR_LUT_SIZE; i++)
+ if (rate <= lpfr_lut[i].vco_rate)
+ break;
+ if (i == LPFR_LUT_SIZE) {
+ dev_err(dev, "unable to get loop filter resistance. vco=%lu\n",
+ rate);
+ return -EINVAL;
+ }
+ pll_write(base + REG_DSI_28nm_PHY_PLL_LPFR_CFG, lpfr_lut[i].resistance);
+
+ /* Loop filter capacitance values : c1 and c2 */
+ pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC1_CFG, 0x70);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_LPFC2_CFG, 0x15);
+
+ rem = rate % VCO_REF_CLK_RATE;
+ if (rem) {
+ refclk_cfg = DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;
+ frac_n_mode = 1;
+ div_fbx1000 = rate / (VCO_REF_CLK_RATE / 500);
+ gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 500);
+ } else {
+ refclk_cfg = 0x0;
+ frac_n_mode = 0;
+ div_fbx1000 = rate / (VCO_REF_CLK_RATE / 1000);
+ gen_vco_clk = div_fbx1000 * (VCO_REF_CLK_RATE / 1000);
+ }
+
+ DBG("refclk_cfg = %d", refclk_cfg);
+
+ rem = div_fbx1000 % 1000;
+ frac_n_value = (rem << 16) / 1000;
+
+ DBG("div_fb = %lu", div_fbx1000);
+ DBG("frac_n_value = %d", frac_n_value);
+
+ DBG("Generated VCO Clock: %lu", gen_vco_clk);
+ rem = 0;
+ sdm_cfg1 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1);
+ sdm_cfg1 &= ~DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET__MASK;
+ if (frac_n_mode) {
+ sdm_cfg0 = 0x0;
+ sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(0);
+ sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(
+ (u32)(((div_fbx1000 / 1000) & 0x3f) - 1));
+ sdm_cfg3 = frac_n_value >> 8;
+ sdm_cfg2 = frac_n_value & 0xff;
+ } else {
+ sdm_cfg0 = DSI_28nm_PHY_PLL_SDM_CFG0_BYP;
+ sdm_cfg0 |= DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV(
+ (u32)(((div_fbx1000 / 1000) & 0x3f) - 1));
+ sdm_cfg1 |= DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET(0);
+ sdm_cfg2 = 0;
+ sdm_cfg3 = 0;
+ }
+
+ DBG("sdm_cfg0=%d", sdm_cfg0);
+ DBG("sdm_cfg1=%d", sdm_cfg1);
+ DBG("sdm_cfg2=%d", sdm_cfg2);
+ DBG("sdm_cfg3=%d", sdm_cfg3);
+
+ cal_cfg11 = (u32)(gen_vco_clk / (256 * 1000000));
+ cal_cfg10 = (u32)((gen_vco_clk % (256 * 1000000)) / 1000000);
+ DBG("cal_cfg10=%d, cal_cfg11=%d", cal_cfg10, cal_cfg11);
+
+ pll_write(base + REG_DSI_28nm_PHY_PLL_CHGPUMP_CFG, 0x02);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG3, 0x2b);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG4, 0x06);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+
+ pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1, sdm_cfg1);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2,
+ DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0(sdm_cfg2));
+ pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3,
+ DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8(sdm_cfg3));
+ pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG4, 0x00);
+
+ /* Add hardware recommended delay for correct PLL configuration */
+ if (pll_28nm->vco_delay)
+ udelay(pll_28nm->vco_delay);
+
+ pll_write(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG, refclk_cfg);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_PWRGEN_CFG, 0x00);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_VCOLPF_CFG, 0x31);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0, sdm_cfg0);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG0, 0x12);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG6, 0x30);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG7, 0x00);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG8, 0x60);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG9, 0x00);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG10, cal_cfg10 & 0xff);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_CAL_CFG11, cal_cfg11 & 0xff);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_EFUSE_CFG, 0x20);
+
+ return 0;
+}
+
+static int dsi_pll_28nm_clk_is_enabled(struct clk_hw *hw)
+{
+ struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+ struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+ return pll_28nm_poll_for_ready(pll_28nm, POLL_MAX_READS,
+ POLL_TIMEOUT_US);
+}
+
+static unsigned long dsi_pll_28nm_clk_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct msm_dsi_pll *pll = hw_clk_to_pll(hw);
+ struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+ void __iomem *base = pll_28nm->mmio;
+ u32 sdm0, doubler, sdm_byp_div;
+ u32 sdm_dc_off, sdm_freq_seed, sdm2, sdm3;
+ u32 ref_clk = VCO_REF_CLK_RATE;
+ unsigned long vco_rate;
+
+ VERB("parent_rate=%lu", parent_rate);
+
+ /* Check to see if the ref clk doubler is enabled */
+ doubler = pll_read(base + REG_DSI_28nm_PHY_PLL_REFCLK_CFG) &
+ DSI_28nm_PHY_PLL_REFCLK_CFG_DBLR;
+ ref_clk += (doubler * VCO_REF_CLK_RATE);
+
+ /* see if it is integer mode or sdm mode */
+ sdm0 = pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0);
+ if (sdm0 & DSI_28nm_PHY_PLL_SDM_CFG0_BYP) {
+ /* integer mode */
+ sdm_byp_div = FIELD(
+ pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG0),
+ DSI_28nm_PHY_PLL_SDM_CFG0_BYP_DIV) + 1;
+ vco_rate = ref_clk * sdm_byp_div;
+ } else {
+ /* sdm mode */
+ sdm_dc_off = FIELD(
+ pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG1),
+ DSI_28nm_PHY_PLL_SDM_CFG1_DC_OFFSET);
+ DBG("sdm_dc_off = %d", sdm_dc_off);
+ sdm2 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG2),
+ DSI_28nm_PHY_PLL_SDM_CFG2_FREQ_SEED_7_0);
+ sdm3 = FIELD(pll_read(base + REG_DSI_28nm_PHY_PLL_SDM_CFG3),
+ DSI_28nm_PHY_PLL_SDM_CFG3_FREQ_SEED_15_8);
+ sdm_freq_seed = (sdm3 << 8) | sdm2;
+ DBG("sdm_freq_seed = %d", sdm_freq_seed);
+
+ vco_rate = (ref_clk * (sdm_dc_off + 1)) +
+ mult_frac(ref_clk, sdm_freq_seed, BIT(16));
+ DBG("vco rate = %lu", vco_rate);
+ }
+
+ DBG("returning vco rate = %lu", vco_rate);
+
+ return vco_rate;
+}
+
+static const struct clk_ops clk_ops_dsi_pll_28nm_vco = {
+ .round_rate = msm_dsi_pll_helper_clk_round_rate,
+ .set_rate = dsi_pll_28nm_clk_set_rate,
+ .recalc_rate = dsi_pll_28nm_clk_recalc_rate,
+ .prepare = msm_dsi_pll_helper_clk_prepare,
+ .unprepare = msm_dsi_pll_helper_clk_unprepare,
+ .is_enabled = dsi_pll_28nm_clk_is_enabled,
+};
+
+/*
+ * PLL Callbacks
+ */
+static int dsi_pll_28nm_enable_seq_hpm(struct msm_dsi_pll *pll)
+{
+ struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+ struct device *dev = &pll_28nm->pdev->dev;
+ void __iomem *base = pll_28nm->mmio;
+ u32 max_reads = 5, timeout_us = 100;
+ bool locked;
+ u32 val;
+ int i;
+
+ DBG("id=%d", pll_28nm->id);
+
+ pll_28nm_software_reset(pll_28nm);
+
+ /*
+ * PLL power up sequence.
+ * Add necessary delays recommended by hardware.
+ */
+ val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+
+ for (i = 0; i < 2; i++) {
+ /* DSI Uniphy lock detect setting */
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2,
+ 0x0c, 100);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x0d);
+
+ /* poll for PLL ready status */
+ locked = pll_28nm_poll_for_ready(pll_28nm,
+ max_reads, timeout_us);
+ if (locked)
+ break;
+
+ pll_28nm_software_reset(pll_28nm);
+
+ /*
+ * PLL power up sequence.
+ * Add necessary delays recommended by hardware.
+ */
+ val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 1);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 250);
+
+ val &= ~DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 200);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B;
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 600);
+ }
+
+ if (unlikely(!locked))
+ dev_err(dev, "DSI PLL lock failed\n");
+ else
+ DBG("DSI PLL Lock success");
+
+ return locked ? 0 : -EINVAL;
+}
+
+static int dsi_pll_28nm_enable_seq_lp(struct msm_dsi_pll *pll)
+{
+ struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+ struct device *dev = &pll_28nm->pdev->dev;
+ void __iomem *base = pll_28nm->mmio;
+ bool locked;
+ u32 max_reads = 10, timeout_us = 50;
+ u32 val;
+
+ DBG("id=%d", pll_28nm->id);
+
+ pll_28nm_software_reset(pll_28nm);
+
+ /*
+ * PLL power up sequence.
+ * Add necessary delays recommended by hardware.
+ */
+ pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_CAL_CFG1, 0x34, 500);
+
+ val = DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B;
+ pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B;
+ pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+ val |= DSI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B |
+ DSI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE;
+ pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_GLB_CFG, val, 500);
+
+ /* DSI PLL toggle lock detect setting */
+ pll_write_ndelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x04, 500);
+ pll_write_udelay(base + REG_DSI_28nm_PHY_PLL_LKDET_CFG2, 0x05, 512);
+
+ locked = pll_28nm_poll_for_ready(pll_28nm, max_reads, timeout_us);
+
+ if (unlikely(!locked))
+ dev_err(dev, "DSI PLL lock failed\n");
+ else
+ DBG("DSI PLL lock success");
+
+ return locked ? 0 : -EINVAL;
+}
+
+static void dsi_pll_28nm_disable_seq(struct msm_dsi_pll *pll)
+{
+ struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+ DBG("id=%d", pll_28nm->id);
+ pll_write(pll_28nm->mmio + REG_DSI_28nm_PHY_PLL_GLB_CFG, 0x00);
+}
+
+static void dsi_pll_28nm_save_state(struct msm_dsi_pll *pll)
+{
+ struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+ struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
+ void __iomem *base = pll_28nm->mmio;
+
+ cached_state->postdiv3 =
+ pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG);
+ cached_state->postdiv1 =
+ pll_read(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG);
+ cached_state->byte_mux = pll_read(base + REG_DSI_28nm_PHY_PLL_VREG_CFG);
+ cached_state->vco_rate = __clk_get_rate(pll->clk_hw.clk);
+}
+
+static int dsi_pll_28nm_restore_state(struct msm_dsi_pll *pll)
+{
+ struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+ struct pll_28nm_cached_state *cached_state = &pll_28nm->cached_state;
+ void __iomem *base = pll_28nm->mmio;
+ int ret;
+
+ if ((cached_state->vco_rate != 0) &&
+ (cached_state->vco_rate == __clk_get_rate(pll->clk_hw.clk))) {
+ ret = dsi_pll_28nm_clk_set_rate(&pll->clk_hw,
+ cached_state->vco_rate, 0);
+ if (ret) {
+ dev_err(&pll_28nm->pdev->dev,
+ "restore vco rate failed. ret=%d\n", ret);
+ return ret;
+ }
+
+ pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
+ cached_state->postdiv3);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
+ cached_state->postdiv1);
+ pll_write(base + REG_DSI_28nm_PHY_PLL_VREG_CFG,
+ cached_state->byte_mux);
+
+ cached_state->vco_rate = 0;
+ }
+
+ return 0;
+}
+
+static int dsi_pll_28nm_get_provider(struct msm_dsi_pll *pll,
+ struct clk **byte_clk_provider,
+ struct clk **pixel_clk_provider)
+{
+ struct dsi_pll_28nm *pll_28nm = to_pll_28nm(pll);
+
+ if (byte_clk_provider)
+ *byte_clk_provider = pll_28nm->provided_clks[DSI_BYTE_PLL_CLK];
+ if (pixel_clk_provider)
+ *pixel_clk_provider =
+ pll_28nm->provided_clks[DSI_PIXEL_PLL_CLK];
+
+ return 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);
+
+ 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;
+}
+
+static int pll_28nm_register(struct dsi_pll_28nm *pll_28nm)
+{
+ char clk_name[32], parent1[32], parent2[32], vco_name[32];
+ struct clk_init_data vco_init = {
+ .parent_names = (const char *[]){ "xo" },
+ .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;
+ int num = 0;
+ int ret;
+
+ DBG("%d", pll_28nm->id);
+
+ 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);
+
+ snprintf(clk_name, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);
+ snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
+ clks[num++] = clk_register_divider(dev, clk_name,
+ parent1, CLK_SET_RATE_PARENT,
+ pll_28nm->mmio +
+ REG_DSI_28nm_PHY_PLL_POSTDIV1_CFG,
+ 0, 4, 0, NULL);
+
+ snprintf(clk_name, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
+ snprintf(parent1, 32, "dsi%danalog_postdiv_clk", pll_28nm->id);
+ clks[num++] = clk_register_fixed_factor(dev, clk_name,
+ parent1, CLK_SET_RATE_PARENT,
+ 1, 2);
+
+ snprintf(clk_name, 32, "dsi%dpll", pll_28nm->id);
+ snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
+ clks[num++] = provided_clks[DSI_PIXEL_PLL_CLK] =
+ clk_register_divider(dev, clk_name,
+ parent1, 0, pll_28nm->mmio +
+ REG_DSI_28nm_PHY_PLL_POSTDIV3_CFG,
+ 0, 8, 0, NULL);
+
+ snprintf(clk_name, 32, "dsi%dbyte_mux", pll_28nm->id);
+ snprintf(parent1, 32, "dsi%dvco_clk", pll_28nm->id);
+ snprintf(parent2, 32, "dsi%dindirect_path_div2_clk", pll_28nm->id);
+ clks[num++] = clk_register_mux(dev, clk_name,
+ (const char *[]){
+ parent1, parent2
+ }, 2, CLK_SET_RATE_PARENT, pll_28nm->mmio +
+ REG_DSI_28nm_PHY_PLL_VREG_CFG, 1, 1, 0, NULL);
+
+ snprintf(clk_name, 32, "dsi%dpllbyte", pll_28nm->id);
+ snprintf(parent1, 32, "dsi%dbyte_mux", pll_28nm->id);
+ clks[num++] = provided_clks[DSI_BYTE_PLL_CLK] =
+ clk_register_fixed_factor(dev, clk_name,
+ parent1, CLK_SET_RATE_PARENT, 1, 4);
+
+ pll_28nm->num_clks = num;
+
+ pll_28nm->clk_data.clk_num = NUM_PROVIDED_CLKS;
+ pll_28nm->clk_data.clks = provided_clks;
+
+ ret = of_clk_add_provider(dev->of_node,
+ of_clk_src_onecell_get, &pll_28nm->clk_data);
+ if (ret) {
+ dev_err(dev, "failed to register clk provider: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+struct msm_dsi_pll *msm_dsi_pll_28nm_init(struct platform_device *pdev,
+ enum msm_dsi_phy_type type, int id)
+{
+ struct dsi_pll_28nm *pll_28nm;
+ struct msm_dsi_pll *pll;
+ int ret;
+
+ if (!pdev)
+ return ERR_PTR(-ENODEV);
+
+ pll_28nm = devm_kzalloc(&pdev->dev, sizeof(*pll_28nm), GFP_KERNEL);
+ if (!pll_28nm)
+ return ERR_PTR(-ENOMEM);
+
+ pll_28nm->pdev = pdev;
+ pll_28nm->id = id;
+
+ pll_28nm->mmio = msm_ioremap(pdev, "dsi_pll", "DSI_PLL");
+ if (IS_ERR_OR_NULL(pll_28nm->mmio)) {
+ dev_err(&pdev->dev, "%s: failed to map pll base\n", __func__);
+ return ERR_PTR(-ENOMEM);
+ }
+
+ pll = &pll_28nm->base;
+ pll->min_rate = VCO_MIN_RATE;
+ pll->max_rate = VCO_MAX_RATE;
+ pll->get_provider = dsi_pll_28nm_get_provider;
+ pll->destroy = dsi_pll_28nm_destroy;
+ pll->disable_seq = dsi_pll_28nm_disable_seq;
+ pll->save_state = dsi_pll_28nm_save_state;
+ pll->restore_state = dsi_pll_28nm_restore_state;
+
+ if (type == MSM_DSI_PHY_28NM_HPM) {
+ pll_28nm->vco_delay = 1;
+
+ pll->en_seq_cnt = 3;
+ pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_hpm;
+ pll->enable_seqs[1] = dsi_pll_28nm_enable_seq_hpm;
+ pll->enable_seqs[2] = dsi_pll_28nm_enable_seq_hpm;
+ } else if (type == MSM_DSI_PHY_28NM_LP) {
+ pll_28nm->vco_delay = 1000;
+
+ pll->en_seq_cnt = 1;
+ pll->enable_seqs[0] = dsi_pll_28nm_enable_seq_lp;
+ } else {
+ dev_err(&pdev->dev, "phy type (%d) is not 28nm\n", type);
+ return ERR_PTR(-EINVAL);
+ }
+
+ ret = pll_28nm_register(pll_28nm);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to register PLL: %d\n", ret);
+ return ERR_PTR(ret);
+ }
+
+ return pll;
+}
+
diff --git a/drivers/gpu/drm/msm/dsi/sfpb.xml.h b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
index 50ff9851d73d..26f268e2dd3d 100644
--- a/drivers/gpu/drm/msm/dsi/sfpb.xml.h
+++ b/drivers/gpu/drm/msm/dsi/sfpb.xml.h
@@ -10,15 +10,15 @@ 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 2014-12-05 15:34:49)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 22094 bytes, from 2015-05-12 12:45:23)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 10416 bytes, from 2015-05-12 12:45:23)
Copyright (C) 2013 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/edp/edp.xml.h b/drivers/gpu/drm/msm/edp/edp.xml.h
index a29f1df15143..f9c71dceb5e2 100644
--- a/drivers/gpu/drm/msm/edp/edp.xml.h
+++ b/drivers/gpu/drm/msm/edp/edp.xml.h
@@ -10,17 +10,17 @@ 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 2014-12-05 15:34:49)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 22094 bytes, from 2015-05-12 12:45:23)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 10416 bytes, from 2015-05-12 12:45:23)
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -288,5 +288,92 @@ static inline uint32_t REG_EDP_PHY_LN_PD_CTL(uint32_t i0) { return 0x00000404 +
#define REG_EDP_PHY_GLB_PHY_STATUS 0x00000598
+#define REG_EDP_28nm_PHY_PLL_REFCLK_CFG 0x00000000
+
+#define REG_EDP_28nm_PHY_PLL_POSTDIV1_CFG 0x00000004
+
+#define REG_EDP_28nm_PHY_PLL_CHGPUMP_CFG 0x00000008
+
+#define REG_EDP_28nm_PHY_PLL_VCOLPF_CFG 0x0000000c
+
+#define REG_EDP_28nm_PHY_PLL_VREG_CFG 0x00000010
+
+#define REG_EDP_28nm_PHY_PLL_PWRGEN_CFG 0x00000014
+
+#define REG_EDP_28nm_PHY_PLL_DMUX_CFG 0x00000018
+
+#define REG_EDP_28nm_PHY_PLL_AMUX_CFG 0x0000001c
+
+#define REG_EDP_28nm_PHY_PLL_GLB_CFG 0x00000020
+#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B 0x00000001
+#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B 0x00000002
+#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B 0x00000004
+#define EDP_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE 0x00000008
+
+#define REG_EDP_28nm_PHY_PLL_POSTDIV2_CFG 0x00000024
+
+#define REG_EDP_28nm_PHY_PLL_POSTDIV3_CFG 0x00000028
+
+#define REG_EDP_28nm_PHY_PLL_LPFR_CFG 0x0000002c
+
+#define REG_EDP_28nm_PHY_PLL_LPFC1_CFG 0x00000030
+
+#define REG_EDP_28nm_PHY_PLL_LPFC2_CFG 0x00000034
+
+#define REG_EDP_28nm_PHY_PLL_SDM_CFG0 0x00000038
+
+#define REG_EDP_28nm_PHY_PLL_SDM_CFG1 0x0000003c
+
+#define REG_EDP_28nm_PHY_PLL_SDM_CFG2 0x00000040
+
+#define REG_EDP_28nm_PHY_PLL_SDM_CFG3 0x00000044
+
+#define REG_EDP_28nm_PHY_PLL_SDM_CFG4 0x00000048
+
+#define REG_EDP_28nm_PHY_PLL_SSC_CFG0 0x0000004c
+
+#define REG_EDP_28nm_PHY_PLL_SSC_CFG1 0x00000050
+
+#define REG_EDP_28nm_PHY_PLL_SSC_CFG2 0x00000054
+
+#define REG_EDP_28nm_PHY_PLL_SSC_CFG3 0x00000058
+
+#define REG_EDP_28nm_PHY_PLL_LKDET_CFG0 0x0000005c
+
+#define REG_EDP_28nm_PHY_PLL_LKDET_CFG1 0x00000060
+
+#define REG_EDP_28nm_PHY_PLL_LKDET_CFG2 0x00000064
+
+#define REG_EDP_28nm_PHY_PLL_TEST_CFG 0x00000068
+#define EDP_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET 0x00000001
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG0 0x0000006c
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG1 0x00000070
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG2 0x00000074
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG3 0x00000078
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG4 0x0000007c
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG5 0x00000080
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG6 0x00000084
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG7 0x00000088
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG8 0x0000008c
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG9 0x00000090
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG10 0x00000094
+
+#define REG_EDP_28nm_PHY_PLL_CAL_CFG11 0x00000098
+
+#define REG_EDP_28nm_PHY_PLL_EFUSE_CFG 0x0000009c
+
+#define REG_EDP_28nm_PHY_PLL_DEBUG_BUS_SEL 0x000000a0
+
#endif /* EDP_XML */
diff --git a/drivers/gpu/drm/msm/edp/edp_aux.c b/drivers/gpu/drm/msm/edp/edp_aux.c
index 208f9d47f82e..82789dd249ee 100644
--- a/drivers/gpu/drm/msm/edp/edp_aux.c
+++ b/drivers/gpu/drm/msm/edp/edp_aux.c
@@ -115,10 +115,12 @@ static int edp_msg_fifo_rx(struct edp_aux *aux, struct drm_dp_aux_msg *msg)
* msm_edp_aux_ctrl() running concurrently in other threads, i.e.
* start transaction only when AUX channel is fully enabled.
*/
-ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg)
+static ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux,
+ struct drm_dp_aux_msg *msg)
{
struct edp_aux *aux = to_edp_aux(drm_aux);
ssize_t ret;
+ unsigned long time_left;
bool native = msg->request & (DP_AUX_NATIVE_WRITE & DP_AUX_NATIVE_READ);
bool read = msg->request & (DP_AUX_I2C_READ & DP_AUX_NATIVE_READ);
@@ -147,15 +149,17 @@ ssize_t edp_aux_transfer(struct drm_dp_aux *drm_aux, struct drm_dp_aux_msg *msg)
goto unlock_exit;
DBG("wait_for_completion");
- ret = wait_for_completion_timeout(&aux->msg_comp, 300);
- if (ret <= 0) {
+ time_left = wait_for_completion_timeout(&aux->msg_comp,
+ msecs_to_jiffies(300));
+ if (!time_left) {
/*
* Clear GO and reset AUX channel
* to cancel the current transaction.
*/
edp_write(aux->base + REG_EDP_AUX_TRANS_CTRL, 0);
msm_edp_aux_ctrl(aux, 1);
- pr_err("%s: aux timeout, %zd\n", __func__, ret);
+ pr_err("%s: aux timeout,\n", __func__);
+ ret = -ETIMEDOUT;
goto unlock_exit;
}
DBG("completion");
diff --git a/drivers/gpu/drm/msm/edp/edp_ctrl.c b/drivers/gpu/drm/msm/edp/edp_ctrl.c
index 29e52d7c61c0..7991069dd492 100644
--- a/drivers/gpu/drm/msm/edp/edp_ctrl.c
+++ b/drivers/gpu/drm/msm/edp/edp_ctrl.c
@@ -1018,7 +1018,7 @@ static void edp_ctrl_off_worker(struct work_struct *work)
{
struct edp_ctrl *ctrl = container_of(
work, struct edp_ctrl, off_work);
- int ret;
+ unsigned long time_left;
mutex_lock(&ctrl->dev_mutex);
@@ -1030,11 +1030,10 @@ static void edp_ctrl_off_worker(struct work_struct *work)
reinit_completion(&ctrl->idle_comp);
edp_state_ctrl(ctrl, EDP_STATE_CTRL_PUSH_IDLE);
- ret = wait_for_completion_timeout(&ctrl->idle_comp,
+ time_left = wait_for_completion_timeout(&ctrl->idle_comp,
msecs_to_jiffies(500));
- if (ret <= 0)
- DBG("%s: idle pattern timedout, %d\n",
- __func__, ret);
+ if (!time_left)
+ DBG("%s: idle pattern timedout\n", __func__);
edp_state_ctrl(ctrl, 0);
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
index 350988740e9f..e6f034808371 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.xml.h
@@ -10,15 +10,15 @@ 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 2014-12-05 15:34:49)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 22094 bytes, from 2015-05-12 12:45:23)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 10416 bytes, from 2015-05-12 12:45:23)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
@@ -750,5 +750,92 @@ static inline uint32_t HDMI_8x60_PHY_REG1_OUTVOL_SWING_CTRL(uint32_t val)
#define REG_HDMI_8x74_BIST_PATN3 0x00000048
+#define REG_HDMI_28nm_PHY_PLL_REFCLK_CFG 0x00000000
+
+#define REG_HDMI_28nm_PHY_PLL_POSTDIV1_CFG 0x00000004
+
+#define REG_HDMI_28nm_PHY_PLL_CHGPUMP_CFG 0x00000008
+
+#define REG_HDMI_28nm_PHY_PLL_VCOLPF_CFG 0x0000000c
+
+#define REG_HDMI_28nm_PHY_PLL_VREG_CFG 0x00000010
+
+#define REG_HDMI_28nm_PHY_PLL_PWRGEN_CFG 0x00000014
+
+#define REG_HDMI_28nm_PHY_PLL_DMUX_CFG 0x00000018
+
+#define REG_HDMI_28nm_PHY_PLL_AMUX_CFG 0x0000001c
+
+#define REG_HDMI_28nm_PHY_PLL_GLB_CFG 0x00000020
+#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_PWRDN_B 0x00000001
+#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_LDO_PWRDN_B 0x00000002
+#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_PWRGEN_PWRDN_B 0x00000004
+#define HDMI_28nm_PHY_PLL_GLB_CFG_PLL_ENABLE 0x00000008
+
+#define REG_HDMI_28nm_PHY_PLL_POSTDIV2_CFG 0x00000024
+
+#define REG_HDMI_28nm_PHY_PLL_POSTDIV3_CFG 0x00000028
+
+#define REG_HDMI_28nm_PHY_PLL_LPFR_CFG 0x0000002c
+
+#define REG_HDMI_28nm_PHY_PLL_LPFC1_CFG 0x00000030
+
+#define REG_HDMI_28nm_PHY_PLL_LPFC2_CFG 0x00000034
+
+#define REG_HDMI_28nm_PHY_PLL_SDM_CFG0 0x00000038
+
+#define REG_HDMI_28nm_PHY_PLL_SDM_CFG1 0x0000003c
+
+#define REG_HDMI_28nm_PHY_PLL_SDM_CFG2 0x00000040
+
+#define REG_HDMI_28nm_PHY_PLL_SDM_CFG3 0x00000044
+
+#define REG_HDMI_28nm_PHY_PLL_SDM_CFG4 0x00000048
+
+#define REG_HDMI_28nm_PHY_PLL_SSC_CFG0 0x0000004c
+
+#define REG_HDMI_28nm_PHY_PLL_SSC_CFG1 0x00000050
+
+#define REG_HDMI_28nm_PHY_PLL_SSC_CFG2 0x00000054
+
+#define REG_HDMI_28nm_PHY_PLL_SSC_CFG3 0x00000058
+
+#define REG_HDMI_28nm_PHY_PLL_LKDET_CFG0 0x0000005c
+
+#define REG_HDMI_28nm_PHY_PLL_LKDET_CFG1 0x00000060
+
+#define REG_HDMI_28nm_PHY_PLL_LKDET_CFG2 0x00000064
+
+#define REG_HDMI_28nm_PHY_PLL_TEST_CFG 0x00000068
+#define HDMI_28nm_PHY_PLL_TEST_CFG_PLL_SW_RESET 0x00000001
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG0 0x0000006c
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG1 0x00000070
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG2 0x00000074
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG3 0x00000078
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG4 0x0000007c
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG5 0x00000080
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG6 0x00000084
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG7 0x00000088
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG8 0x0000008c
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG9 0x00000090
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG10 0x00000094
+
+#define REG_HDMI_28nm_PHY_PLL_CAL_CFG11 0x00000098
+
+#define REG_HDMI_28nm_PHY_PLL_EFUSE_CFG 0x0000009c
+
+#define REG_HDMI_28nm_PHY_PLL_DEBUG_BUS_SEL 0x000000a0
+
#endif /* HDMI_XML */
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
index b62cdb968614..54aa93ff5473 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_connector.c
@@ -16,6 +16,7 @@
*/
#include <linux/gpio.h>
+#include <linux/pinctrl/consumer.h>
#include "msm_kms.h"
#include "hdmi.h"
@@ -29,14 +30,14 @@ struct hdmi_connector {
static int gpio_config(struct hdmi *hdmi, bool on)
{
- struct drm_device *dev = hdmi->dev;
+ struct device *dev = &hdmi->pdev->dev;
const struct hdmi_platform_config *config = hdmi->config;
int ret;
if (on) {
ret = gpio_request(config->ddc_clk_gpio, "HDMI_DDC_CLK");
if (ret) {
- dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+ dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
"HDMI_DDC_CLK", config->ddc_clk_gpio, ret);
goto error1;
}
@@ -44,7 +45,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
ret = gpio_request(config->ddc_data_gpio, "HDMI_DDC_DATA");
if (ret) {
- dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+ dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
"HDMI_DDC_DATA", config->ddc_data_gpio, ret);
goto error2;
}
@@ -52,7 +53,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
ret = gpio_request(config->hpd_gpio, "HDMI_HPD");
if (ret) {
- dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+ dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
"HDMI_HPD", config->hpd_gpio, ret);
goto error3;
}
@@ -62,7 +63,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
if (config->mux_en_gpio != -1) {
ret = gpio_request(config->mux_en_gpio, "HDMI_MUX_EN");
if (ret) {
- dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+ dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
"HDMI_MUX_EN", config->mux_en_gpio, ret);
goto error4;
}
@@ -72,7 +73,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
if (config->mux_sel_gpio != -1) {
ret = gpio_request(config->mux_sel_gpio, "HDMI_MUX_SEL");
if (ret) {
- dev_err(dev->dev, "'%s'(%d) gpio_request failed: %d\n",
+ dev_err(dev, "'%s'(%d) gpio_request failed: %d\n",
"HDMI_MUX_SEL", config->mux_sel_gpio, ret);
goto error5;
}
@@ -83,7 +84,7 @@ static int gpio_config(struct hdmi *hdmi, bool on)
ret = gpio_request(config->mux_lpm_gpio,
"HDMI_MUX_LPM");
if (ret) {
- dev_err(dev->dev,
+ dev_err(dev,
"'%s'(%d) gpio_request failed: %d\n",
"HDMI_MUX_LPM",
config->mux_lpm_gpio, ret);
@@ -136,7 +137,7 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
{
struct hdmi *hdmi = hdmi_connector->hdmi;
const struct hdmi_platform_config *config = hdmi->config;
- struct drm_device *dev = hdmi_connector->base.dev;
+ struct device *dev = &hdmi->pdev->dev;
struct hdmi_phy *phy = hdmi->phy;
uint32_t hpd_ctrl;
int i, ret;
@@ -144,15 +145,21 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
for (i = 0; i < config->hpd_reg_cnt; i++) {
ret = regulator_enable(hdmi->hpd_regs[i]);
if (ret) {
- dev_err(dev->dev, "failed to enable hpd regulator: %s (%d)\n",
+ dev_err(dev, "failed to enable hpd regulator: %s (%d)\n",
config->hpd_reg_names[i], ret);
goto fail;
}
}
+ ret = pinctrl_pm_select_default_state(dev);
+ if (ret) {
+ dev_err(dev, "pinctrl state chg failed: %d\n", ret);
+ goto fail;
+ }
+
ret = gpio_config(hdmi, true);
if (ret) {
- dev_err(dev->dev, "failed to configure GPIOs: %d\n", ret);
+ dev_err(dev, "failed to configure GPIOs: %d\n", ret);
goto fail;
}
@@ -161,13 +168,13 @@ static int hpd_enable(struct hdmi_connector *hdmi_connector)
ret = clk_set_rate(hdmi->hpd_clks[i],
config->hpd_freq[i]);
if (ret)
- dev_warn(dev->dev, "failed to set clk %s (%d)\n",
+ dev_warn(dev, "failed to set clk %s (%d)\n",
config->hpd_clk_names[i], ret);
}
ret = clk_prepare_enable(hdmi->hpd_clks[i]);
if (ret) {
- dev_err(dev->dev, "failed to enable hpd clk: %s (%d)\n",
+ dev_err(dev, "failed to enable hpd clk: %s (%d)\n",
config->hpd_clk_names[i], ret);
goto fail;
}
@@ -204,7 +211,7 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector)
{
struct hdmi *hdmi = hdmi_connector->hdmi;
const struct hdmi_platform_config *config = hdmi->config;
- struct drm_device *dev = hdmi_connector->base.dev;
+ struct device *dev = &hdmi->pdev->dev;
int i, ret = 0;
/* Disable HPD interrupt */
@@ -217,12 +224,16 @@ static void hdp_disable(struct hdmi_connector *hdmi_connector)
ret = gpio_config(hdmi, false);
if (ret)
- dev_warn(dev->dev, "failed to unconfigure GPIOs: %d\n", ret);
+ dev_warn(dev, "failed to unconfigure GPIOs: %d\n", ret);
+
+ ret = pinctrl_pm_select_sleep_state(dev);
+ if (ret)
+ dev_warn(dev, "pinctrl state chg failed: %d\n", ret);
for (i = 0; i < config->hpd_reg_cnt; i++) {
ret = regulator_disable(hdmi->hpd_regs[i]);
if (ret)
- dev_warn(dev->dev, "failed to disable hpd regulator: %s (%d)\n",
+ dev_warn(dev, "failed to disable hpd regulator: %s (%d)\n",
config->hpd_reg_names[i], ret);
}
}
@@ -433,7 +444,7 @@ struct drm_connector *hdmi_connector_init(struct hdmi *hdmi)
ret = hpd_enable(hdmi_connector);
if (ret) {
- dev_err(hdmi->dev->dev, "failed to enable HPD: %d\n", ret);
+ dev_err(&hdmi->pdev->dev, "failed to enable HPD: %d\n", ret);
goto fail;
}
diff --git a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
index 43bb54a9afbf..978c3f70872a 100644
--- a/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
+++ b/drivers/gpu/drm/msm/hdmi/qfprom.xml.h
@@ -10,15 +10,15 @@ 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 2014-12-05 15:34:49)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 22094 bytes, from 2015-05-12 12:45:23)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 10416 bytes, from 2015-05-12 12:45:23)
Copyright (C) 2013 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
index 1d39174d91fb..153fc487d683 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h
@@ -10,17 +10,17 @@ 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 2014-12-05 15:34:49)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 22094 bytes, from 2015-05-12 12:45:23)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 10416 bytes, from 2015-05-12 12:45:23)
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -680,18 +680,18 @@ static inline uint32_t MDP4_PIPE_SRC_STRIDE_B_P3(uint32_t val)
return ((val) << MDP4_PIPE_SRC_STRIDE_B_P3__SHIFT) & MDP4_PIPE_SRC_STRIDE_B_P3__MASK;
}
-static inline uint32_t REG_MDP4_PIPE_FRAME_SIZE(enum mdp4_pipe i0) { return 0x00020048 + 0x10000*i0; }
-#define MDP4_PIPE_FRAME_SIZE_HEIGHT__MASK 0xffff0000
-#define MDP4_PIPE_FRAME_SIZE_HEIGHT__SHIFT 16
-static inline uint32_t MDP4_PIPE_FRAME_SIZE_HEIGHT(uint32_t val)
+static inline uint32_t REG_MDP4_PIPE_SSTILE_FRAME_SIZE(enum mdp4_pipe i0) { return 0x00020048 + 0x10000*i0; }
+#define MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__MASK 0xffff0000
+#define MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__SHIFT 16
+static inline uint32_t MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT(uint32_t val)
{
- return ((val) << MDP4_PIPE_FRAME_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_FRAME_SIZE_HEIGHT__MASK;
+ return ((val) << MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__SHIFT) & MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT__MASK;
}
-#define MDP4_PIPE_FRAME_SIZE_WIDTH__MASK 0x0000ffff
-#define MDP4_PIPE_FRAME_SIZE_WIDTH__SHIFT 0
-static inline uint32_t MDP4_PIPE_FRAME_SIZE_WIDTH(uint32_t val)
+#define MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__MASK 0x0000ffff
+#define MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__SHIFT 0
+static inline uint32_t MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH(uint32_t val)
{
- return ((val) << MDP4_PIPE_FRAME_SIZE_WIDTH__SHIFT) & MDP4_PIPE_FRAME_SIZE_WIDTH__MASK;
+ return ((val) << MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__SHIFT) & MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH__MASK;
}
static inline uint32_t REG_MDP4_PIPE_SRC_FORMAT(enum mdp4_pipe i0) { return 0x00020050 + 0x10000*i0; }
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
index 73afa21822b4..c4bb9d9c7667 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_crtc.c
@@ -51,6 +51,11 @@ struct mdp4_crtc {
/* if there is a pending flip, these will be non-null: */
struct drm_pending_vblank_event *event;
+ /* Bits have been flushed at the last commit,
+ * used to decide if a vsync has happened since last commit.
+ */
+ u32 flushed_mask;
+
#define PENDING_CURSOR 0x1
#define PENDING_FLIP 0x2
atomic_t pending;
@@ -93,6 +98,8 @@ static void crtc_flush(struct drm_crtc *crtc)
DBG("%s: flush=%08x", mdp4_crtc->name, flush);
+ mdp4_crtc->flushed_mask = flush;
+
mdp4_write(mdp4_kms, REG_MDP4_OVERLAY_FLUSH, flush);
}
@@ -537,6 +544,29 @@ static void mdp4_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
crtc_flush(crtc);
}
+static void mdp4_crtc_wait_for_flush_done(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
+ struct mdp4_kms *mdp4_kms = get_kms(crtc);
+ int ret;
+
+ ret = drm_crtc_vblank_get(crtc);
+ if (ret)
+ return;
+
+ ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
+ !(mdp4_read(mdp4_kms, REG_MDP4_OVERLAY_FLUSH) &
+ mdp4_crtc->flushed_mask),
+ msecs_to_jiffies(50));
+ if (ret <= 0)
+ dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp4_crtc->id);
+
+ mdp4_crtc->flushed_mask = 0;
+
+ drm_crtc_vblank_put(crtc);
+}
+
uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc)
{
struct mdp4_crtc *mdp4_crtc = to_mdp4_crtc(crtc);
@@ -600,6 +630,15 @@ void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer)
mdp4_write(mdp4_kms, REG_MDP4_DISP_INTF_SEL, intf_sel);
}
+void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc)
+{
+ /* wait_for_flush_done is the only case for now.
+ * Later we will have command mode CRTC to wait for
+ * other event.
+ */
+ mdp4_crtc_wait_for_flush_done(crtc);
+}
+
static const char *dma_names[] = {
"DMA_P", "DMA_S", "DMA_E",
};
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
index 7896323b2631..89614c6a6c1b 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_dtv_encoder.c
@@ -38,7 +38,7 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
return to_mdp4_kms(to_mdp_kms(priv->kms));
}
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
#include <mach/board.h>
/* not ironically named at all.. no, really.. */
static void bs_init(struct mdp4_dtv_encoder *mdp4_dtv_encoder)
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
index d847b9436194..531e4acc2a87 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.c
@@ -119,6 +119,8 @@ static int mdp4_hw_init(struct msm_kms *kms)
if (mdp4_kms->rev > 1)
mdp4_write(mdp4_kms, REG_MDP4_RESET_STATUS, 1);
+ dev->mode_config.allow_fb_modifiers = true;
+
out:
pm_runtime_put_sync(dev->dev);
@@ -157,6 +159,12 @@ static void mdp4_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s
mdp4_disable(mdp4_kms);
}
+static void mdp4_wait_for_crtc_commit_done(struct msm_kms *kms,
+ struct drm_crtc *crtc)
+{
+ mdp4_crtc_wait_for_commit_done(crtc);
+}
+
static long mdp4_round_pixclk(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder)
{
@@ -195,6 +203,7 @@ static const struct mdp_kms_funcs kms_funcs = {
.disable_vblank = mdp4_disable_vblank,
.prepare_commit = mdp4_prepare_commit,
.complete_commit = mdp4_complete_commit,
+ .wait_for_crtc_commit_done = mdp4_wait_for_crtc_commit_done,
.get_format = mdp_get_format,
.round_pixclk = mdp4_round_pixclk,
.preclose = mdp4_preclose,
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
index 0a5c58bde7a9..c1ecb9d6bdef 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h
@@ -206,6 +206,7 @@ uint32_t mdp4_crtc_vblank(struct drm_crtc *crtc);
void mdp4_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
void mdp4_crtc_set_config(struct drm_crtc *crtc, uint32_t config);
void mdp4_crtc_set_intf(struct drm_crtc *crtc, enum mdp4_intf intf, int mixer);
+void mdp4_crtc_wait_for_commit_done(struct drm_crtc *crtc);
struct drm_crtc *mdp4_crtc_init(struct drm_device *dev,
struct drm_plane *plane, int id, int ovlp_id,
enum mdp4_dma dma_id);
@@ -229,7 +230,7 @@ static inline struct clk *mpd4_lvds_pll_init(struct drm_device *dev)
}
#endif
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
static inline int match_dev_name(struct device *dev, void *data)
{
return !strcmp(dev_name(dev), data);
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
index 60ec8222c9f6..c04843376c54 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_lcdc_encoder.c
@@ -38,7 +38,7 @@ static struct mdp4_kms *get_kms(struct drm_encoder *encoder)
return to_mdp4_kms(to_mdp_kms(priv->kms));
}
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
#include <mach/board.h>
static void bs_init(struct mdp4_lcdc_encoder *mdp4_lcdc_encoder)
{
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
index dbc068988377..0d1dbb737933 100644
--- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
@@ -33,6 +33,21 @@ struct mdp4_plane {
};
#define to_mdp4_plane(x) container_of(x, struct mdp4_plane, base)
+/* MDP format helper functions */
+static inline
+enum mdp4_frame_format mdp4_get_frame_format(struct drm_framebuffer *fb)
+{
+ bool is_tile = false;
+
+ if (fb->modifier[1] == DRM_FORMAT_MOD_SAMSUNG_64_32_TILE)
+ is_tile = true;
+
+ if (fb->pixel_format == DRM_FORMAT_NV12 && is_tile)
+ return FRAME_TILE_YCBCR_420;
+
+ return FRAME_LINEAR;
+}
+
static void mdp4_plane_set_scanout(struct drm_plane *plane,
struct drm_framebuffer *fb);
static int mdp4_plane_mode_set(struct drm_plane *plane,
@@ -205,6 +220,7 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
uint32_t op_mode = 0;
uint32_t phasex_step = MDP4_VG_PHASE_STEP_DEFAULT;
uint32_t phasey_step = MDP4_VG_PHASE_STEP_DEFAULT;
+ enum mdp4_frame_format frame_type = mdp4_get_frame_format(fb);
if (!(crtc && fb)) {
DBG("%s: disabled!", mdp4_plane->name);
@@ -304,6 +320,7 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(format->fetch_type) |
MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample) |
+ MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT(frame_type) |
COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT));
mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe),
@@ -324,6 +341,11 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);
mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step);
+ if (frame_type != FRAME_LINEAR)
+ mdp4_write(mdp4_kms, REG_MDP4_PIPE_SSTILE_FRAME_SIZE(pipe),
+ MDP4_PIPE_SSTILE_FRAME_SIZE_WIDTH(src_w) |
+ MDP4_PIPE_SSTILE_FRAME_SIZE_HEIGHT(src_h));
+
return 0;
}
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
index b9a4ded6e400..50e17527e2e5 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h
@@ -8,9 +8,17 @@ 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:
-- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp5.xml ( 29312 bytes, from 2015-03-23 21:18:48)
-- /local/mnt2/workspace2/sviau/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2014-06-02 18:31:15)
-- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2015-03-23 20:38:49)
+- /home/robclark/src/freedreno/envytools/rnndb/msm.xml ( 676 bytes, from 2014-12-05 15:34:49)
+- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 22094 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 10416 bytes, from 2015-05-12 12:45:23)
Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
@@ -120,6 +128,21 @@ enum mdp5_data_format {
DATA_FORMAT_YUV = 1,
};
+enum mdp5_block_size {
+ BLOCK_SIZE_64 = 0,
+ BLOCK_SIZE_128 = 1,
+};
+
+enum mdp5_rotate_mode {
+ ROTATE_0 = 0,
+ ROTATE_90 = 1,
+};
+
+enum mdp5_chroma_downsample_method {
+ DS_MTHD_NO_PIXEL_DROP = 0,
+ DS_MTHD_PIXEL_DROP = 1,
+};
+
#define MDP5_IRQ_WB_0_DONE 0x00000001
#define MDP5_IRQ_WB_1_DONE 0x00000002
#define MDP5_IRQ_WB_2_DONE 0x00000010
@@ -314,19 +337,19 @@ static inline uint32_t MDP5_MDP_IGC_LUT_REG_VAL(uint32_t val)
#define MDP5_MDP_IGC_LUT_REG_DISABLE_PIPE_1 0x20000000
#define MDP5_MDP_IGC_LUT_REG_DISABLE_PIPE_2 0x40000000
-#define REG_MDP5_SPLIT_DPL_EN 0x000003f4
+static inline uint32_t REG_MDP5_MDP_SPLIT_DPL_EN(uint32_t i0) { return 0x000002f4 + __offset_MDP(i0); }
-#define REG_MDP5_SPLIT_DPL_UPPER 0x000003f8
-#define MDP5_SPLIT_DPL_UPPER_SMART_PANEL 0x00000002
-#define MDP5_SPLIT_DPL_UPPER_SMART_PANEL_FREE_RUN 0x00000004
-#define MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX 0x00000010
-#define MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX 0x00000100
+static inline uint32_t REG_MDP5_MDP_SPLIT_DPL_UPPER(uint32_t i0) { return 0x000002f8 + __offset_MDP(i0); }
+#define MDP5_MDP_SPLIT_DPL_UPPER_SMART_PANEL 0x00000002
+#define MDP5_MDP_SPLIT_DPL_UPPER_SMART_PANEL_FREE_RUN 0x00000004
+#define MDP5_MDP_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX 0x00000010
+#define MDP5_MDP_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX 0x00000100
-#define REG_MDP5_SPLIT_DPL_LOWER 0x000004f0
-#define MDP5_SPLIT_DPL_LOWER_SMART_PANEL 0x00000002
-#define MDP5_SPLIT_DPL_LOWER_SMART_PANEL_FREE_RUN 0x00000004
-#define MDP5_SPLIT_DPL_LOWER_INTF1_TG_SYNC 0x00000010
-#define MDP5_SPLIT_DPL_LOWER_INTF2_TG_SYNC 0x00000100
+static inline uint32_t REG_MDP5_MDP_SPLIT_DPL_LOWER(uint32_t i0) { return 0x000003f0 + __offset_MDP(i0); }
+#define MDP5_MDP_SPLIT_DPL_LOWER_SMART_PANEL 0x00000002
+#define MDP5_MDP_SPLIT_DPL_LOWER_SMART_PANEL_FREE_RUN 0x00000004
+#define MDP5_MDP_SPLIT_DPL_LOWER_INTF1_TG_SYNC 0x00000010
+#define MDP5_MDP_SPLIT_DPL_LOWER_INTF2_TG_SYNC 0x00000100
static inline uint32_t __offset_CTL(uint32_t idx)
{
@@ -782,7 +805,7 @@ static inline uint32_t MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val)
#define MDP5_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB 0x00040000
#define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK 0x00180000
#define MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT 19
-static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(enum mdp_sspp_fetch_type val)
+static inline uint32_t MDP5_PIPE_SRC_FORMAT_NUM_PLANES(enum mdp_fetch_type val)
{
return ((val) << MDP5_PIPE_SRC_FORMAT_NUM_PLANES__SHIFT) & MDP5_PIPE_SRC_FORMAT_NUM_PLANES__MASK;
}
@@ -1234,6 +1257,351 @@ static inline uint32_t REG_MDP5_PP_FBC_BUDGET_CTL(uint32_t i0) { return 0x000000
static inline uint32_t REG_MDP5_PP_FBC_LOSSY_MODE(uint32_t i0) { return 0x0000003c + __offset_PP(i0); }
+static inline uint32_t __offset_WB(uint32_t idx)
+{
+ switch (idx) {
+ default: return INVALID_IDX(idx);
+ }
+}
+static inline uint32_t REG_MDP5_WB(uint32_t i0) { return 0x00000000 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST_FORMAT(uint32_t i0) { return 0x00000000 + __offset_WB(i0); }
+#define MDP5_WB_DST_FORMAT_DSTC0_OUT__MASK 0x00000003
+#define MDP5_WB_DST_FORMAT_DSTC0_OUT__SHIFT 0
+static inline uint32_t MDP5_WB_DST_FORMAT_DSTC0_OUT(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_FORMAT_DSTC0_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC0_OUT__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DSTC1_OUT__MASK 0x0000000c
+#define MDP5_WB_DST_FORMAT_DSTC1_OUT__SHIFT 2
+static inline uint32_t MDP5_WB_DST_FORMAT_DSTC1_OUT(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_FORMAT_DSTC1_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC1_OUT__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DSTC2_OUT__MASK 0x00000030
+#define MDP5_WB_DST_FORMAT_DSTC2_OUT__SHIFT 4
+static inline uint32_t MDP5_WB_DST_FORMAT_DSTC2_OUT(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_FORMAT_DSTC2_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC2_OUT__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DSTC3_OUT__MASK 0x000000c0
+#define MDP5_WB_DST_FORMAT_DSTC3_OUT__SHIFT 6
+static inline uint32_t MDP5_WB_DST_FORMAT_DSTC3_OUT(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_FORMAT_DSTC3_OUT__SHIFT) & MDP5_WB_DST_FORMAT_DSTC3_OUT__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DSTC3_EN 0x00000100
+#define MDP5_WB_DST_FORMAT_DST_BPP__MASK 0x00000600
+#define MDP5_WB_DST_FORMAT_DST_BPP__SHIFT 9
+static inline uint32_t MDP5_WB_DST_FORMAT_DST_BPP(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_FORMAT_DST_BPP__SHIFT) & MDP5_WB_DST_FORMAT_DST_BPP__MASK;
+}
+#define MDP5_WB_DST_FORMAT_PACK_COUNT__MASK 0x00003000
+#define MDP5_WB_DST_FORMAT_PACK_COUNT__SHIFT 12
+static inline uint32_t MDP5_WB_DST_FORMAT_PACK_COUNT(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_FORMAT_PACK_COUNT__SHIFT) & MDP5_WB_DST_FORMAT_PACK_COUNT__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DST_ALPHA_X 0x00004000
+#define MDP5_WB_DST_FORMAT_PACK_TIGHT 0x00020000
+#define MDP5_WB_DST_FORMAT_PACK_ALIGN_MSB 0x00040000
+#define MDP5_WB_DST_FORMAT_WRITE_PLANES__MASK 0x00180000
+#define MDP5_WB_DST_FORMAT_WRITE_PLANES__SHIFT 19
+static inline uint32_t MDP5_WB_DST_FORMAT_WRITE_PLANES(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_FORMAT_WRITE_PLANES__SHIFT) & MDP5_WB_DST_FORMAT_WRITE_PLANES__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DST_DITHER_EN 0x00400000
+#define MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__MASK 0x03800000
+#define MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__SHIFT 23
+static inline uint32_t MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__SHIFT) & MDP5_WB_DST_FORMAT_DST_CHROMA_SAMP__MASK;
+}
+#define MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__MASK 0x3c000000
+#define MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__SHIFT 26
+static inline uint32_t MDP5_WB_DST_FORMAT_DST_CHROMA_SITE(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__SHIFT) & MDP5_WB_DST_FORMAT_DST_CHROMA_SITE__MASK;
+}
+#define MDP5_WB_DST_FORMAT_FRAME_FORMAT__MASK 0xc0000000
+#define MDP5_WB_DST_FORMAT_FRAME_FORMAT__SHIFT 30
+static inline uint32_t MDP5_WB_DST_FORMAT_FRAME_FORMAT(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_FORMAT_FRAME_FORMAT__SHIFT) & MDP5_WB_DST_FORMAT_FRAME_FORMAT__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_DST_OP_MODE(uint32_t i0) { return 0x00000004 + __offset_WB(i0); }
+#define MDP5_WB_DST_OP_MODE_BWC_ENC_EN 0x00000001
+#define MDP5_WB_DST_OP_MODE_BWC_ENC_OP__MASK 0x00000006
+#define MDP5_WB_DST_OP_MODE_BWC_ENC_OP__SHIFT 1
+static inline uint32_t MDP5_WB_DST_OP_MODE_BWC_ENC_OP(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_OP_MODE_BWC_ENC_OP__SHIFT) & MDP5_WB_DST_OP_MODE_BWC_ENC_OP__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_BLOCK_SIZE__MASK 0x00000010
+#define MDP5_WB_DST_OP_MODE_BLOCK_SIZE__SHIFT 4
+static inline uint32_t MDP5_WB_DST_OP_MODE_BLOCK_SIZE(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_OP_MODE_BLOCK_SIZE__SHIFT) & MDP5_WB_DST_OP_MODE_BLOCK_SIZE__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_ROT_MODE__MASK 0x00000020
+#define MDP5_WB_DST_OP_MODE_ROT_MODE__SHIFT 5
+static inline uint32_t MDP5_WB_DST_OP_MODE_ROT_MODE(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_OP_MODE_ROT_MODE__SHIFT) & MDP5_WB_DST_OP_MODE_ROT_MODE__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_ROT_EN 0x00000040
+#define MDP5_WB_DST_OP_MODE_CSC_EN 0x00000100
+#define MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__MASK 0x00000200
+#define MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__SHIFT 9
+static inline uint32_t MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__SHIFT) & MDP5_WB_DST_OP_MODE_CSC_SRC_DATA_FORMAT__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__MASK 0x00000400
+#define MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__SHIFT 10
+static inline uint32_t MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__SHIFT) & MDP5_WB_DST_OP_MODE_CSC_DST_DATA_FORMAT__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_EN 0x00000800
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__MASK 0x00001000
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__SHIFT 12
+static inline uint32_t MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__SHIFT) & MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_FORMAT__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__MASK 0x00002000
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__SHIFT 13
+static inline uint32_t MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__SHIFT) & MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_H_MTHD__MASK;
+}
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__MASK 0x00004000
+#define MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__SHIFT 14
+static inline uint32_t MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__SHIFT) & MDP5_WB_DST_OP_MODE_CHROMA_DWN_SAMPLE_V_MTHD__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_DST_PACK_PATTERN(uint32_t i0) { return 0x00000008 + __offset_WB(i0); }
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT0__MASK 0x00000003
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT0__SHIFT 0
+static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT0(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT0__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT0__MASK;
+}
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT1__MASK 0x00000300
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT1__SHIFT 8
+static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT1(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT1__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT1__MASK;
+}
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT2__MASK 0x00030000
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT2__SHIFT 16
+static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT2(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT2__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT2__MASK;
+}
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT3__MASK 0x03000000
+#define MDP5_WB_DST_PACK_PATTERN_ELEMENT3__SHIFT 24
+static inline uint32_t MDP5_WB_DST_PACK_PATTERN_ELEMENT3(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_PACK_PATTERN_ELEMENT3__SHIFT) & MDP5_WB_DST_PACK_PATTERN_ELEMENT3__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_DST0_ADDR(uint32_t i0) { return 0x0000000c + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST1_ADDR(uint32_t i0) { return 0x00000010 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST2_ADDR(uint32_t i0) { return 0x00000014 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST3_ADDR(uint32_t i0) { return 0x00000018 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST_YSTRIDE0(uint32_t i0) { return 0x0000001c + __offset_WB(i0); }
+#define MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__MASK 0x0000ffff
+#define MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__SHIFT 0
+static inline uint32_t MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE0_DST0_YSTRIDE__MASK;
+}
+#define MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__MASK 0xffff0000
+#define MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__SHIFT 16
+static inline uint32_t MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE0_DST1_YSTRIDE__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_DST_YSTRIDE1(uint32_t i0) { return 0x00000020 + __offset_WB(i0); }
+#define MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__MASK 0x0000ffff
+#define MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__SHIFT 0
+static inline uint32_t MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE1_DST2_YSTRIDE__MASK;
+}
+#define MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__MASK 0xffff0000
+#define MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__SHIFT 16
+static inline uint32_t MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE(uint32_t val)
+{
+ return ((val) << MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__SHIFT) & MDP5_WB_DST_YSTRIDE1_DST3_YSTRIDE__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_DST_DITHER_BITDEPTH(uint32_t i0) { return 0x00000024 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW0(uint32_t i0) { return 0x00000030 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW1(uint32_t i0) { return 0x00000034 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW2(uint32_t i0) { return 0x00000038 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DITHER_MATRIX_ROW3(uint32_t i0) { return 0x0000003c + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_DST_WRITE_CONFIG(uint32_t i0) { return 0x00000048 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_ROTATION_DNSCALER(uint32_t i0) { return 0x00000050 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_X_0_3(uint32_t i0) { return 0x00000060 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_X_1_2(uint32_t i0) { return 0x00000064 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_Y_0_3(uint32_t i0) { return 0x00000068 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_N16_INIT_PHASE_Y_1_2(uint32_t i0) { return 0x0000006c + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_OUT_SIZE(uint32_t i0) { return 0x00000074 + __offset_WB(i0); }
+#define MDP5_WB_OUT_SIZE_DST_W__MASK 0x0000ffff
+#define MDP5_WB_OUT_SIZE_DST_W__SHIFT 0
+static inline uint32_t MDP5_WB_OUT_SIZE_DST_W(uint32_t val)
+{
+ return ((val) << MDP5_WB_OUT_SIZE_DST_W__SHIFT) & MDP5_WB_OUT_SIZE_DST_W__MASK;
+}
+#define MDP5_WB_OUT_SIZE_DST_H__MASK 0xffff0000
+#define MDP5_WB_OUT_SIZE_DST_H__SHIFT 16
+static inline uint32_t MDP5_WB_OUT_SIZE_DST_H(uint32_t val)
+{
+ return ((val) << MDP5_WB_OUT_SIZE_DST_H__SHIFT) & MDP5_WB_OUT_SIZE_DST_H__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_ALPHA_X_VALUE(uint32_t i0) { return 0x00000078 + __offset_WB(i0); }
+
+static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_0(uint32_t i0) { return 0x00000260 + __offset_WB(i0); }
+#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__MASK 0x00001fff
+#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__SHIFT 0
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_11__MASK;
+}
+#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__MASK 0x1fff0000
+#define MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__SHIFT 16
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_0_COEFF_12__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_1(uint32_t i0) { return 0x00000264 + __offset_WB(i0); }
+#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__MASK 0x00001fff
+#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__SHIFT 0
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_13__MASK;
+}
+#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__MASK 0x1fff0000
+#define MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__SHIFT 16
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_1_COEFF_21__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_2(uint32_t i0) { return 0x00000268 + __offset_WB(i0); }
+#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__MASK 0x00001fff
+#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__SHIFT 0
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_22__MASK;
+}
+#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__MASK 0x1fff0000
+#define MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__SHIFT 16
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_2_COEFF_23__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_3(uint32_t i0) { return 0x0000026c + __offset_WB(i0); }
+#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__MASK 0x00001fff
+#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__SHIFT 0
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_31__MASK;
+}
+#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__MASK 0x1fff0000
+#define MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__SHIFT 16
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_3_COEFF_32__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_MATRIX_COEFF_4(uint32_t i0) { return 0x00000270 + __offset_WB(i0); }
+#define MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__MASK 0x00001fff
+#define MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__SHIFT 0
+static inline uint32_t MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__SHIFT) & MDP5_WB_CSC_MATRIX_COEFF_4_COEFF_33__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_PRECLAMP(uint32_t i0, uint32_t i1) { return 0x00000274 + __offset_WB(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_PRECLAMP_REG(uint32_t i0, uint32_t i1) { return 0x00000274 + __offset_WB(i0) + 0x4*i1; }
+#define MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__MASK 0x000000ff
+#define MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__SHIFT 0
+static inline uint32_t MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__SHIFT) & MDP5_WB_CSC_COMP_PRECLAMP_REG_HIGH__MASK;
+}
+#define MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__MASK 0x0000ff00
+#define MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__SHIFT 8
+static inline uint32_t MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__SHIFT) & MDP5_WB_CSC_COMP_PRECLAMP_REG_LOW__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTCLAMP(uint32_t i0, uint32_t i1) { return 0x00000280 + __offset_WB(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTCLAMP_REG(uint32_t i0, uint32_t i1) { return 0x00000280 + __offset_WB(i0) + 0x4*i1; }
+#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__MASK 0x000000ff
+#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__SHIFT 0
+static inline uint32_t MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__SHIFT) & MDP5_WB_CSC_COMP_POSTCLAMP_REG_HIGH__MASK;
+}
+#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__MASK 0x0000ff00
+#define MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__SHIFT 8
+static inline uint32_t MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__SHIFT) & MDP5_WB_CSC_COMP_POSTCLAMP_REG_LOW__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_PREBIAS(uint32_t i0, uint32_t i1) { return 0x0000028c + __offset_WB(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_PREBIAS_REG(uint32_t i0, uint32_t i1) { return 0x0000028c + __offset_WB(i0) + 0x4*i1; }
+#define MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__MASK 0x000001ff
+#define MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__SHIFT 0
+static inline uint32_t MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__SHIFT) & MDP5_WB_CSC_COMP_PREBIAS_REG_VALUE__MASK;
+}
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTBIAS(uint32_t i0, uint32_t i1) { return 0x00000298 + __offset_WB(i0) + 0x4*i1; }
+
+static inline uint32_t REG_MDP5_WB_CSC_COMP_POSTBIAS_REG(uint32_t i0, uint32_t i1) { return 0x00000298 + __offset_WB(i0) + 0x4*i1; }
+#define MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__MASK 0x000001ff
+#define MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__SHIFT 0
+static inline uint32_t MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE(uint32_t val)
+{
+ return ((val) << MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__SHIFT) & MDP5_WB_CSC_COMP_POSTBIAS_REG_VALUE__MASK;
+}
+
static inline uint32_t __offset_INTF(uint32_t idx)
{
switch (idx) {
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
index e4e89567f51d..ee31b16fe7ea 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_cmd_encoder.c
@@ -30,7 +30,7 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
return to_mdp5_kms(to_mdp_kms(priv->kms));
}
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
#include <mach/board.h>
#include <linux/msm-bus.h>
#include <linux/msm-bus-board.h>
@@ -216,16 +216,12 @@ static void mdp5_cmd_encoder_mode_set(struct drm_encoder *encoder,
static void mdp5_cmd_encoder_disable(struct drm_encoder *encoder)
{
struct mdp5_cmd_encoder *mdp5_cmd_enc = to_mdp5_cmd_encoder(encoder);
- struct mdp5_kms *mdp5_kms = get_kms(encoder);
struct mdp5_ctl *ctl = mdp5_crtc_get_ctl(encoder->crtc);
struct mdp5_interface *intf = &mdp5_cmd_enc->intf;
- int lm = mdp5_crtc_get_lm(encoder->crtc);
if (WARN_ON(!mdp5_cmd_enc->enabled))
return;
- /* Wait for the last frame done */
- mdp_irq_wait(&mdp5_kms->base, lm2ppdone(lm));
pingpong_tearcheck_disable(encoder);
mdp5_ctl_set_encoder_state(ctl, false);
@@ -281,22 +277,22 @@ int mdp5_cmd_encoder_set_split_display(struct drm_encoder *encoder,
* start signal for the slave encoder
*/
if (intf_num == 1)
- data |= MDP5_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX;
+ data |= MDP5_MDP_SPLIT_DPL_UPPER_INTF2_SW_TRG_MUX;
else if (intf_num == 2)
- data |= MDP5_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX;
+ data |= MDP5_MDP_SPLIT_DPL_UPPER_INTF1_SW_TRG_MUX;
else
return -EINVAL;
/* Smart Panel, Sync mode */
- data |= MDP5_SPLIT_DPL_UPPER_SMART_PANEL;
+ data |= MDP5_MDP_SPLIT_DPL_UPPER_SMART_PANEL;
/* Make sure clocks are on when connectors calling this function. */
mdp5_enable(mdp5_kms);
- mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, data);
+ mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_UPPER(0), data);
- mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER,
- MDP5_SPLIT_DPL_LOWER_SMART_PANEL);
- mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1);
+ mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_LOWER(0),
+ MDP5_MDP_SPLIT_DPL_LOWER_SMART_PANEL);
+ mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_EN(0), 1);
mdp5_disable(mdp5_kms);
return 0;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
index c1530772187d..dea3d2e559b1 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_crtc.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2015 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@gmail.com>
*
@@ -46,6 +46,11 @@ struct mdp5_crtc {
/* if there is a pending flip, these will be non-null: */
struct drm_pending_vblank_event *event;
+ /* Bits have been flushed at the last commit,
+ * used to decide if a vsync has happened since last commit.
+ */
+ u32 flushed_mask;
+
#define PENDING_CURSOR 0x1
#define PENDING_FLIP 0x2
atomic_t pending;
@@ -55,6 +60,11 @@ struct mdp5_crtc {
struct mdp_irq vblank;
struct mdp_irq err;
+ struct mdp_irq pp_done;
+
+ struct completion pp_completion;
+
+ bool cmd_mode;
struct {
/* protect REG_MDP5_LM_CURSOR* registers and cursor scanout_bo*/
@@ -82,12 +92,18 @@ static void request_pending(struct drm_crtc *crtc, uint32_t pending)
mdp_irq_register(&get_kms(crtc)->base, &mdp5_crtc->vblank);
}
-static void crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
+static void request_pp_done_pending(struct drm_crtc *crtc)
+{
+ struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+ reinit_completion(&mdp5_crtc->pp_completion);
+}
+
+static u32 crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
{
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
DBG("%s: flush=%08x", mdp5_crtc->name, flush_mask);
- mdp5_ctl_commit(mdp5_crtc->ctl, flush_mask);
+ return mdp5_ctl_commit(mdp5_crtc->ctl, flush_mask);
}
/*
@@ -95,7 +111,7 @@ static void crtc_flush(struct drm_crtc *crtc, u32 flush_mask)
* so that we can safely queue unref to current fb (ie. next
* vblank we know hw is done w/ previous scanout_fb).
*/
-static void crtc_flush_all(struct drm_crtc *crtc)
+static u32 crtc_flush_all(struct drm_crtc *crtc)
{
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
struct drm_plane *plane;
@@ -103,7 +119,7 @@ static void crtc_flush_all(struct drm_crtc *crtc)
/* this should not happen: */
if (WARN_ON(!mdp5_crtc->ctl))
- return;
+ return 0;
drm_atomic_crtc_for_each_plane(plane, crtc) {
flush_mask |= mdp5_plane_get_flush(plane);
@@ -111,7 +127,7 @@ static void crtc_flush_all(struct drm_crtc *crtc)
flush_mask |= mdp_ctl_flush_mask_lm(mdp5_crtc->lm);
- crtc_flush(crtc, flush_mask);
+ return crtc_flush(crtc, flush_mask);
}
/* if file!=NULL, this is preclose potential cancel-flip path */
@@ -143,6 +159,8 @@ static void complete_flip(struct drm_crtc *crtc, struct drm_file *file)
}
if (mdp5_crtc->ctl && !crtc->state->enable) {
+ /* set STAGE_UNUSED for all layers */
+ mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000);
mdp5_ctl_release(mdp5_crtc->ctl);
mdp5_crtc->ctl = NULL;
}
@@ -274,8 +292,8 @@ static void mdp5_crtc_disable(struct drm_crtc *crtc)
if (WARN_ON(!mdp5_crtc->enabled))
return;
- /* set STAGE_UNUSED for all layers */
- mdp5_ctl_blend(mdp5_crtc->ctl, mdp5_crtc->lm, 0x00000000);
+ if (mdp5_crtc->cmd_mode)
+ mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->pp_done);
mdp_irq_unregister(&mdp5_kms->base, &mdp5_crtc->err);
mdp5_disable(mdp5_kms);
@@ -296,6 +314,9 @@ static void mdp5_crtc_enable(struct drm_crtc *crtc)
mdp5_enable(mdp5_kms);
mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->err);
+ if (mdp5_crtc->cmd_mode)
+ mdp_irq_register(&mdp5_kms->base, &mdp5_crtc->pp_done);
+
mdp5_crtc->enabled = true;
}
@@ -396,7 +417,18 @@ static void mdp5_crtc_atomic_flush(struct drm_crtc *crtc)
return;
blend_setup(crtc);
- crtc_flush_all(crtc);
+
+ /* PP_DONE irq is only used by command mode for now.
+ * It is better to request pending before FLUSH and START trigger
+ * to make sure no pp_done irq missed.
+ * This is safe because no pp_done will happen before SW trigger
+ * in command mode.
+ */
+ if (mdp5_crtc->cmd_mode)
+ request_pp_done_pending(crtc);
+
+ mdp5_crtc->flushed_mask = crtc_flush_all(crtc);
+
request_pending(crtc, PENDING_FLIP);
}
@@ -601,6 +633,52 @@ static void mdp5_crtc_err_irq(struct mdp_irq *irq, uint32_t irqstatus)
DBG("%s: error: %08x", mdp5_crtc->name, irqstatus);
}
+static void mdp5_crtc_pp_done_irq(struct mdp_irq *irq, uint32_t irqstatus)
+{
+ struct mdp5_crtc *mdp5_crtc = container_of(irq, struct mdp5_crtc,
+ pp_done);
+
+ complete(&mdp5_crtc->pp_completion);
+}
+
+static void mdp5_crtc_wait_for_pp_done(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+ int ret;
+
+ ret = wait_for_completion_timeout(&mdp5_crtc->pp_completion,
+ msecs_to_jiffies(50));
+ if (ret == 0)
+ dev_warn(dev->dev, "pp done time out, lm=%d\n", mdp5_crtc->lm);
+}
+
+static void mdp5_crtc_wait_for_flush_done(struct drm_crtc *crtc)
+{
+ struct drm_device *dev = crtc->dev;
+ struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+ int ret;
+
+ /* Should not call this function if crtc is disabled. */
+ if (!mdp5_crtc->ctl)
+ return;
+
+ ret = drm_crtc_vblank_get(crtc);
+ if (ret)
+ return;
+
+ ret = wait_event_timeout(dev->vblank[drm_crtc_index(crtc)].queue,
+ ((mdp5_ctl_get_commit_status(mdp5_crtc->ctl) &
+ mdp5_crtc->flushed_mask) == 0),
+ msecs_to_jiffies(50));
+ if (ret <= 0)
+ dev_warn(dev->dev, "vblank time out, crtc=%d\n", mdp5_crtc->id);
+
+ mdp5_crtc->flushed_mask = 0;
+
+ drm_crtc_vblank_put(crtc);
+}
+
uint32_t mdp5_crtc_vblank(struct drm_crtc *crtc)
{
struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
@@ -622,16 +700,19 @@ void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf)
/* now that we know what irq's we want: */
mdp5_crtc->err.irqmask = intf2err(intf->num);
+ mdp5_crtc->vblank.irqmask = intf2vblank(lm, intf);
+
+ if ((intf->type == INTF_DSI) &&
+ (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)) {
+ mdp5_crtc->pp_done.irqmask = lm2ppdone(lm);
+ mdp5_crtc->pp_done.irq = mdp5_crtc_pp_done_irq;
+ mdp5_crtc->cmd_mode = true;
+ } else {
+ mdp5_crtc->pp_done.irqmask = 0;
+ mdp5_crtc->pp_done.irq = NULL;
+ mdp5_crtc->cmd_mode = false;
+ }
- /* Register command mode Pingpong done as vblank for now,
- * so that atomic commit should wait for it to finish.
- * Ideally, in the future, we should take rd_ptr done as vblank,
- * and let atomic commit wait for pingpong done for commond mode.
- */
- if (intf->mode == MDP5_INTF_DSI_MODE_COMMAND)
- mdp5_crtc->vblank.irqmask = lm2ppdone(lm);
- else
- mdp5_crtc->vblank.irqmask = intf2vblank(lm, intf);
mdp_irq_update(&mdp5_kms->base);
mdp5_ctl_set_intf(mdp5_crtc->ctl, intf);
@@ -649,6 +730,16 @@ struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc)
return WARN_ON(!crtc) ? NULL : mdp5_crtc->ctl;
}
+void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc)
+{
+ struct mdp5_crtc *mdp5_crtc = to_mdp5_crtc(crtc);
+
+ if (mdp5_crtc->cmd_mode)
+ mdp5_crtc_wait_for_pp_done(crtc);
+ else
+ mdp5_crtc_wait_for_flush_done(crtc);
+}
+
/* initialize crtc */
struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
struct drm_plane *plane, int id)
@@ -667,6 +758,7 @@ struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
spin_lock_init(&mdp5_crtc->lm_lock);
spin_lock_init(&mdp5_crtc->cursor.lock);
+ init_completion(&mdp5_crtc->pp_completion);
mdp5_crtc->vblank.irq = mdp5_crtc_vblank_irq;
mdp5_crtc->err.irq = mdp5_crtc_err_irq;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
index 5488b687c8d1..f2530f224a76 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.c
@@ -392,8 +392,10 @@ static u32 fix_sw_flush(struct mdp5_ctl *ctl, u32 flush_mask)
* CTL registers need to be flushed in some circumstances; if that is the
* case, some trigger bits will be present in both flush mask and
* ctl->pending_ctl_trigger.
+ *
+ * Return H/W flushed bit mask.
*/
-int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)
+u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)
{
struct mdp5_ctl_manager *ctl_mgr = ctl->ctlm;
struct op_mode *pipeline = &ctl->pipeline;
@@ -424,7 +426,12 @@ int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask)
refill_start_mask(ctl);
}
- return 0;
+ return flush_mask;
+}
+
+u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl)
+{
+ return ctl_read(ctl, REG_MDP5_CTL_FLUSH(ctl->id));
}
void mdp5_ctl_release(struct mdp5_ctl *ctl)
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
index 7a62000994a1..4678228c4f14 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_ctl.h
@@ -88,7 +88,8 @@ u32 mdp_ctl_flush_mask_cursor(int cursor_id);
u32 mdp_ctl_flush_mask_encoder(struct mdp5_interface *intf);
/* @flush_mask: see CTL flush masks definitions below */
-int mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask);
+u32 mdp5_ctl_commit(struct mdp5_ctl *ctl, u32 flush_mask);
+u32 mdp5_ctl_get_commit_status(struct mdp5_ctl *ctl);
void mdp5_ctl_release(struct mdp5_ctl *ctl);
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
index 1188f4bf1e60..de97c08f3f1f 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_encoder.c
@@ -36,7 +36,7 @@ static struct mdp5_kms *get_kms(struct drm_encoder *encoder)
return to_mdp5_kms(to_mdp_kms(priv->kms));
}
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
#include <mach/board.h>
#include <mach/msm_bus.h>
#include <mach/msm_bus_board.h>
@@ -144,10 +144,14 @@ static void mdp5_encoder_mode_set(struct drm_encoder *encoder,
mode->type, mode->flags);
ctrl_pol = 0;
- if (mode->flags & DRM_MODE_FLAG_NHSYNC)
- ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
- if (mode->flags & DRM_MODE_FLAG_NVSYNC)
- ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW;
+
+ /* DSI controller cannot handle active-low sync signals. */
+ if (mdp5_encoder->intf.type != INTF_DSI) {
+ if (mode->flags & DRM_MODE_FLAG_NHSYNC)
+ ctrl_pol |= MDP5_INTF_POLARITY_CTL_HSYNC_LOW;
+ if (mode->flags & DRM_MODE_FLAG_NVSYNC)
+ ctrl_pol |= MDP5_INTF_POLARITY_CTL_VSYNC_LOW;
+ }
/* probably need to get DATA_EN polarity from panel.. */
dtv_hsync_skew = 0; /* get this from panel? */
@@ -304,9 +308,9 @@ int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
* to use the master's enable signal for the slave encoder.
*/
if (intf_num == 1)
- data |= MDP5_SPLIT_DPL_LOWER_INTF2_TG_SYNC;
+ data |= MDP5_MDP_SPLIT_DPL_LOWER_INTF2_TG_SYNC;
else if (intf_num == 2)
- data |= MDP5_SPLIT_DPL_LOWER_INTF1_TG_SYNC;
+ data |= MDP5_MDP_SPLIT_DPL_LOWER_INTF1_TG_SYNC;
else
return -EINVAL;
@@ -315,9 +319,9 @@ int mdp5_encoder_set_split_display(struct drm_encoder *encoder,
mdp5_write(mdp5_kms, REG_MDP5_MDP_SPARE_0(0),
MDP5_MDP_SPARE_0_SPLIT_DPL_SINGLE_FLUSH_EN);
/* Dumb Panel, Sync mode */
- mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_UPPER, 0);
- mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_LOWER, data);
- mdp5_write(mdp5_kms, REG_MDP5_SPLIT_DPL_EN, 1);
+ mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_UPPER(0), 0);
+ mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_LOWER(0), data);
+ mdp5_write(mdp5_kms, REG_MDP5_MDP_SPLIT_DPL_EN(0), 1);
mdp5_disable(mdp5_kms);
return 0;
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index bbacf9d2b738..206f758f7d64 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -80,6 +80,12 @@ static void mdp5_complete_commit(struct msm_kms *kms, struct drm_atomic_state *s
mdp5_disable(mdp5_kms);
}
+static void mdp5_wait_for_crtc_commit_done(struct msm_kms *kms,
+ struct drm_crtc *crtc)
+{
+ mdp5_crtc_wait_for_commit_done(crtc);
+}
+
static long mdp5_round_pixclk(struct msm_kms *kms, unsigned long rate,
struct drm_encoder *encoder)
{
@@ -141,6 +147,7 @@ static const struct mdp_kms_funcs kms_funcs = {
.disable_vblank = mdp5_disable_vblank,
.prepare_commit = mdp5_prepare_commit,
.complete_commit = mdp5_complete_commit,
+ .wait_for_crtc_commit_done = mdp5_wait_for_crtc_commit_done,
.get_format = mdp_get_format,
.round_pixclk = mdp5_round_pixclk,
.set_split_display = mdp5_set_split_display,
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
index 2c0de174cc09..e0eb24587c84 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h
@@ -237,6 +237,7 @@ int mdp5_crtc_get_lm(struct drm_crtc *crtc);
struct mdp5_ctl *mdp5_crtc_get_ctl(struct drm_crtc *crtc);
void mdp5_crtc_cancel_pending_flip(struct drm_crtc *crtc, struct drm_file *file);
void mdp5_crtc_set_intf(struct drm_crtc *crtc, struct mdp5_interface *intf);
+void mdp5_crtc_wait_for_commit_done(struct drm_crtc *crtc);
struct drm_crtc *mdp5_crtc_init(struct drm_device *dev,
struct drm_plane *plane, int id);
diff --git a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
index a1d35f162c7f..641d036c5bcb 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_common.xml.h
@@ -10,17 +10,17 @@ 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 2014-12-05 15:34:49)
- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml ( 1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20908 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2357 bytes, from 2014-12-08 16:13:00)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 27208 bytes, from 2015-01-13 23:56:11)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 11712 bytes, from 2013-08-17 17:13:43)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml ( 20915 bytes, from 2015-03-24 22:05:22)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml ( 2352 bytes, from 2015-04-12 15:02:42)
+- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml ( 35083 bytes, from 2015-04-12 15:04:03)
+- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml ( 22094 bytes, from 2015-05-12 12:45:23)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml ( 344 bytes, from 2013-08-11 19:26:32)
- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml ( 1686 bytes, from 2014-10-31 16:48:57)
- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml ( 600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 26848 bytes, from 2015-01-13 23:55:57)
-- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 8253 bytes, from 2014-12-08 16:13:00)
+- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml ( 29012 bytes, from 2015-05-12 12:45:23)
+- /home/robclark/src/freedreno/envytools/rnndb/edp/edp.xml ( 10416 bytes, from 2015-05-12 12:45:23)
-Copyright (C) 2013-2014 by the following authors:
+Copyright (C) 2013-2015 by the following authors:
- Rob Clark <robdclark@gmail.com> (robclark)
Permission is hereby granted, free of charge, to any person obtaining
@@ -52,7 +52,7 @@ enum mdp_chroma_samp_type {
CHROMA_420 = 3,
};
-enum mdp_sspp_fetch_type {
+enum mdp_fetch_type {
MDP_PLANE_INTERLEAVED = 0,
MDP_PLANE_PLANAR = 1,
MDP_PLANE_PSEUDO_PLANAR = 2,
diff --git a/drivers/gpu/drm/msm/mdp/mdp_format.c b/drivers/gpu/drm/msm/mdp/mdp_format.c
index f683433b6727..7b0524dc1872 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_format.c
+++ b/drivers/gpu/drm/msm/mdp/mdp_format.c
@@ -96,6 +96,12 @@ static const struct mdp_format formats[] = {
/* name a r g b e0 e1 e2 e3 alpha tight cpp cnt ... */
FMT(ARGB8888, 8, 8, 8, 8, 1, 0, 2, 3, true, true, 4, 4,
MDP_PLANE_INTERLEAVED, CHROMA_RGB),
+ FMT(ABGR8888, 8, 8, 8, 8, 2, 0, 1, 3, true, true, 4, 4,
+ MDP_PLANE_INTERLEAVED, CHROMA_RGB),
+ FMT(RGBA8888, 8, 8, 8, 8, 3, 1, 0, 2, true, true, 4, 4,
+ MDP_PLANE_INTERLEAVED, CHROMA_RGB),
+ FMT(BGRA8888, 8, 8, 8, 8, 3, 2, 0, 1, true, true, 4, 4,
+ MDP_PLANE_INTERLEAVED, CHROMA_RGB),
FMT(XRGB8888, 8, 8, 8, 8, 1, 0, 2, 3, false, true, 4, 4,
MDP_PLANE_INTERLEAVED, CHROMA_RGB),
FMT(RGB888, 0, 8, 8, 8, 1, 0, 2, 0, false, true, 3, 3,
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index 5ae4039d68e4..2d3428cb74d0 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -88,7 +88,7 @@ struct mdp_format {
uint8_t unpack[4];
bool alpha_enable, unpack_tight;
uint8_t cpp, unpack_count;
- enum mdp_sspp_fetch_type fetch_type;
+ enum mdp_fetch_type fetch_type;
enum mdp_chroma_samp_type chroma_sample;
};
#define to_mdp_format(x) container_of(x, struct mdp_format, base)
diff --git a/drivers/gpu/drm/msm/msm_atomic.c b/drivers/gpu/drm/msm/msm_atomic.c
index 5b192128cda2..1b22d8bfe142 100644
--- a/drivers/gpu/drm/msm/msm_atomic.c
+++ b/drivers/gpu/drm/msm/msm_atomic.c
@@ -84,6 +84,33 @@ static void commit_destroy(struct msm_commit *c)
kfree(c);
}
+static void msm_atomic_wait_for_commit_done(struct drm_device *dev,
+ struct drm_atomic_state *old_state)
+{
+ struct drm_crtc *crtc;
+ struct msm_drm_private *priv = old_state->dev->dev_private;
+ struct msm_kms *kms = priv->kms;
+ int ncrtcs = old_state->dev->mode_config.num_crtc;
+ int i;
+
+ for (i = 0; i < ncrtcs; i++) {
+ crtc = old_state->crtcs[i];
+
+ if (!crtc)
+ continue;
+
+ if (!crtc->state->enable)
+ continue;
+
+ /* Legacy cursor ioctls are completely unsynced, and userspace
+ * relies on that (by doing tons of cursor updates). */
+ if (old_state->legacy_cursor_update)
+ continue;
+
+ kms->funcs->wait_for_crtc_commit_done(kms, crtc);
+ }
+}
+
/* The (potentially) asynchronous part of the commit. At this point
* nothing can fail short of armageddon.
*/
@@ -115,7 +142,7 @@ static void complete_commit(struct msm_commit *c)
* not be critical path)
*/
- drm_atomic_helper_wait_for_vblanks(dev, state);
+ msm_atomic_wait_for_commit_done(dev, state);
drm_atomic_helper_cleanup_planes(dev, state);
@@ -139,7 +166,6 @@ static void add_fb(struct msm_commit *c, struct drm_framebuffer *fb)
c->fence = max(c->fence, msm_gem_fence(to_msm_bo(obj), MSM_PREP_READ));
}
-
int msm_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
@@ -178,7 +204,7 @@ int msm_atomic_commit(struct drm_device *dev,
{
int nplanes = dev->mode_config.num_total_plane;
int ncrtcs = dev->mode_config.num_crtc;
- struct timespec timeout;
+ ktime_t timeout;
struct msm_commit *c;
int i, ret;
@@ -187,8 +213,10 @@ int msm_atomic_commit(struct drm_device *dev,
return ret;
c = commit_init(state);
- if (!c)
- return -ENOMEM;
+ if (!c) {
+ ret = -ENOMEM;
+ goto error;
+ }
/*
* Figure out what crtcs we have:
@@ -221,7 +249,7 @@ int msm_atomic_commit(struct drm_device *dev,
ret = start_atomic(dev->dev_private, c->crtc_mask);
if (ret) {
kfree(c);
- return ret;
+ goto error;
}
/*
@@ -253,7 +281,7 @@ int msm_atomic_commit(struct drm_device *dev,
return 0;
}
- jiffies_to_timespec(jiffies + msecs_to_jiffies(1000), &timeout);
+ timeout = ktime_add_ms(ktime_get(), 1000);
ret = msm_wait_fence_interruptable(dev, c->fence, &timeout);
if (ret) {
@@ -265,4 +293,8 @@ int msm_atomic_commit(struct drm_device *dev,
complete_commit(c);
return 0;
+
+error:
+ drm_atomic_helper_cleanup_planes(dev, state);
+ return ret;
}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index c80a6bee2b18..b7ef56ed8d1c 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -638,7 +638,7 @@ static void msm_debugfs_cleanup(struct drm_minor *minor)
*/
int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
- struct timespec *timeout)
+ ktime_t *timeout)
{
struct msm_drm_private *priv = dev->dev_private;
int ret;
@@ -656,14 +656,16 @@ int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
/* no-wait: */
ret = fence_completed(dev, fence) ? 0 : -EBUSY;
} else {
- unsigned long timeout_jiffies = timespec_to_jiffies(timeout);
- unsigned long start_jiffies = jiffies;
+ ktime_t now = ktime_get();
unsigned long remaining_jiffies;
- if (time_after(start_jiffies, timeout_jiffies))
+ if (ktime_compare(*timeout, now) < 0) {
remaining_jiffies = 0;
- else
- remaining_jiffies = timeout_jiffies - start_jiffies;
+ } else {
+ ktime_t rem = ktime_sub(*timeout, now);
+ struct timespec ts = ktime_to_timespec(rem);
+ remaining_jiffies = timespec_to_jiffies(&ts);
+ }
ret = wait_event_interruptible_timeout(priv->fence_event,
fence_completed(dev, fence),
@@ -772,13 +774,17 @@ static int msm_ioctl_gem_new(struct drm_device *dev, void *data,
args->flags, &args->handle);
}
-#define TS(t) ((struct timespec){ .tv_sec = (t).tv_sec, .tv_nsec = (t).tv_nsec })
+static inline ktime_t to_ktime(struct drm_msm_timespec timeout)
+{
+ return ktime_set(timeout.tv_sec, timeout.tv_nsec);
+}
static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_msm_gem_cpu_prep *args = data;
struct drm_gem_object *obj;
+ ktime_t timeout = to_ktime(args->timeout);
int ret;
if (args->op & ~MSM_PREP_FLAGS) {
@@ -790,7 +796,7 @@ static int msm_ioctl_gem_cpu_prep(struct drm_device *dev, void *data,
if (!obj)
return -ENOENT;
- ret = msm_gem_cpu_prep(obj, args->op, &TS(args->timeout));
+ ret = msm_gem_cpu_prep(obj, args->op, &timeout);
drm_gem_object_unreference_unlocked(obj);
@@ -840,14 +846,14 @@ static int msm_ioctl_wait_fence(struct drm_device *dev, void *data,
struct drm_file *file)
{
struct drm_msm_wait_fence *args = data;
+ ktime_t timeout = to_ktime(args->timeout);
if (args->pad) {
DRM_ERROR("invalid pad: %08x\n", args->pad);
return -EINVAL;
}
- return msm_wait_fence_interruptable(dev, args->fence,
- &TS(args->timeout));
+ return msm_wait_fence_interruptable(dev, args->fence, &timeout);
}
static const struct drm_ioctl_desc msm_ioctls[] = {
@@ -885,6 +891,7 @@ static struct drm_driver msm_driver = {
DRIVER_GEM |
DRIVER_PRIME |
DRIVER_RENDER |
+ DRIVER_ATOMIC |
DRIVER_MODESET,
.load = msm_load,
.unload = msm_unload,
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index 04db4bd1b5b6..e7c5ea125d45 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -165,7 +165,7 @@ int msm_atomic_commit(struct drm_device *dev,
int msm_register_mmu(struct drm_device *dev, struct msm_mmu *mmu);
int msm_wait_fence_interruptable(struct drm_device *dev, uint32_t fence,
- struct timespec *timeout);
+ ktime_t *timeout);
int msm_queue_fence_cb(struct drm_device *dev,
struct msm_fence_cb *cb, uint32_t fence);
void msm_update_fence(struct drm_device *dev, uint32_t fence);
@@ -205,7 +205,7 @@ void msm_gem_move_to_active(struct drm_gem_object *obj,
struct msm_gpu *gpu, bool write, uint32_t fence);
void msm_gem_move_to_inactive(struct drm_gem_object *obj);
int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
- struct timespec *timeout);
+ ktime_t *timeout);
int msm_gem_cpu_fini(struct drm_gem_object *obj);
void msm_gem_free_object(struct drm_gem_object *obj);
int msm_gem_new_handle(struct drm_device *dev, struct drm_file *file,
diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
index 52839769eb6c..f211b80e3a1e 100644
--- a/drivers/gpu/drm/msm/msm_gem.c
+++ b/drivers/gpu/drm/msm/msm_gem.c
@@ -448,8 +448,7 @@ void msm_gem_move_to_inactive(struct drm_gem_object *obj)
list_add_tail(&msm_obj->mm_list, &priv->inactive_list);
}
-int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op,
- struct timespec *timeout)
+int msm_gem_cpu_prep(struct drm_gem_object *obj, uint32_t op, ktime_t *timeout)
{
struct drm_device *dev = obj->dev;
struct msm_gem_object *msm_obj = to_msm_bo(obj);
@@ -540,6 +539,7 @@ void msm_gem_free_object(struct drm_gem_object *obj)
if (msm_obj->pages)
drm_free_large(msm_obj->pages);
+ drm_prime_gem_destroy(obj, msm_obj->sgt);
} else {
vunmap(msm_obj->vaddr);
put_pages(obj);
diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
index 85d481e29276..6fc59bfeedeb 100644
--- a/drivers/gpu/drm/msm/msm_gem.h
+++ b/drivers/gpu/drm/msm/msm_gem.h
@@ -96,6 +96,7 @@ static inline uint32_t msm_gem_fence(struct msm_gem_object *msm_obj,
struct msm_gem_submit {
struct drm_device *dev;
struct msm_gpu *gpu;
+ struct list_head node; /* node in gpu submit_list */
struct list_head bo_list;
struct ww_acquire_ctx ticket;
uint32_t fence;
diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c b/drivers/gpu/drm/msm/msm_gem_submit.c
index cd0554f68316..6d7cd3fe21e7 100644
--- a/drivers/gpu/drm/msm/msm_gem_submit.c
+++ b/drivers/gpu/drm/msm/msm_gem_submit.c
@@ -314,7 +314,6 @@ static void submit_cleanup(struct msm_gem_submit *submit, bool fail)
}
ww_acquire_fini(&submit->ticket);
- kfree(submit);
}
int msm_ioctl_gem_submit(struct drm_device *dev, void *data,
diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
index 4a0dce587745..8f70d9248ac5 100644
--- a/drivers/gpu/drm/msm/msm_gpu.c
+++ b/drivers/gpu/drm/msm/msm_gpu.c
@@ -24,7 +24,7 @@
* Power Management:
*/
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
#include <mach/board.h>
static void bs_init(struct msm_gpu *gpu)
{
@@ -265,6 +265,8 @@ static void inactive_start(struct msm_gpu *gpu)
* Hangcheck detection for locked gpu:
*/
+static void retire_submits(struct msm_gpu *gpu, uint32_t fence);
+
static void recover_worker(struct work_struct *work)
{
struct msm_gpu *gpu = container_of(work, struct msm_gpu, recover_work);
@@ -274,8 +276,19 @@ static void recover_worker(struct work_struct *work)
mutex_lock(&dev->struct_mutex);
if (msm_gpu_active(gpu)) {
+ struct msm_gem_submit *submit;
+ uint32_t fence = gpu->funcs->last_fence(gpu);
+
+ /* retire completed submits, plus the one that hung: */
+ retire_submits(gpu, fence + 1);
+
inactive_cancel(gpu);
gpu->funcs->recover(gpu);
+
+ /* replay the remaining submits after the one that hung: */
+ list_for_each_entry(submit, &gpu->submit_list, node) {
+ gpu->funcs->submit(gpu, submit, NULL);
+ }
}
mutex_unlock(&dev->struct_mutex);
@@ -418,6 +431,27 @@ out:
* Cmdstream submission/retirement:
*/
+static void retire_submits(struct msm_gpu *gpu, uint32_t fence)
+{
+ struct drm_device *dev = gpu->dev;
+
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
+ while (!list_empty(&gpu->submit_list)) {
+ struct msm_gem_submit *submit;
+
+ submit = list_first_entry(&gpu->submit_list,
+ struct msm_gem_submit, node);
+
+ if (submit->fence <= fence) {
+ list_del(&submit->node);
+ kfree(submit);
+ } else {
+ break;
+ }
+ }
+}
+
static void retire_worker(struct work_struct *work)
{
struct msm_gpu *gpu = container_of(work, struct msm_gpu, retire_work);
@@ -428,6 +462,8 @@ static void retire_worker(struct work_struct *work)
mutex_lock(&dev->struct_mutex);
+ retire_submits(gpu, fence);
+
while (!list_empty(&gpu->active_list)) {
struct msm_gem_object *obj;
@@ -467,21 +503,22 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
struct msm_drm_private *priv = dev->dev_private;
int i, ret;
+ WARN_ON(!mutex_is_locked(&dev->struct_mutex));
+
submit->fence = ++priv->next_fence;
gpu->submitted_fence = submit->fence;
inactive_cancel(gpu);
+ list_add_tail(&submit->node, &gpu->submit_list);
+
msm_rd_dump_submit(submit);
gpu->submitted_fence = submit->fence;
update_sw_cntrs(gpu);
- ret = gpu->funcs->submit(gpu, submit, ctx);
- priv->lastctx = ctx;
-
for (i = 0; i < submit->nr_bos; i++) {
struct msm_gem_object *msm_obj = submit->bos[i].obj;
@@ -505,6 +542,10 @@ int msm_gpu_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
if (submit->bos[i].flags & MSM_SUBMIT_BO_WRITE)
msm_gem_move_to_active(&msm_obj->base, gpu, true, submit->fence);
}
+
+ ret = gpu->funcs->submit(gpu, submit, ctx);
+ priv->lastctx = ctx;
+
hangcheck_timer_reset(gpu);
return ret;
@@ -522,6 +563,7 @@ static irqreturn_t irq_handler(int irq, void *data)
static const char *clk_names[] = {
"src_clk", "core_clk", "iface_clk", "mem_clk", "mem_iface_clk",
+ "alt_mem_iface_clk",
};
int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
@@ -544,6 +586,8 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
INIT_WORK(&gpu->inactive_work, inactive_worker);
INIT_WORK(&gpu->recover_work, recover_worker);
+ INIT_LIST_HEAD(&gpu->submit_list);
+
setup_timer(&gpu->inactive_timer, inactive_handler,
(unsigned long)gpu);
setup_timer(&gpu->hangcheck_timer, hangcheck_handler,
diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
index fd1e4b4a6d40..2bbe85a3d6f6 100644
--- a/drivers/gpu/drm/msm/msm_gpu.h
+++ b/drivers/gpu/drm/msm/msm_gpu.h
@@ -100,10 +100,10 @@ struct msm_gpu {
/* Power Control: */
struct regulator *gpu_reg, *gpu_cx;
- struct clk *ebi1_clk, *grp_clks[5];
+ struct clk *ebi1_clk, *grp_clks[6];
uint32_t fast_rate, slow_rate, bus_freq;
-#ifdef CONFIG_MSM_BUS_SCALING
+#ifdef DOWNSTREAM_CONFIG_MSM_BUS_SCALING
struct msm_bus_scale_pdata *bus_scale_table;
uint32_t bsc;
#endif
@@ -119,6 +119,8 @@ struct msm_gpu {
struct timer_list hangcheck_timer;
uint32_t hangcheck_fence;
struct work_struct recover_work;
+
+ struct list_head submit_list;
};
static inline bool msm_gpu_active(struct msm_gpu *gpu)
diff --git a/drivers/gpu/drm/msm/msm_kms.h b/drivers/gpu/drm/msm/msm_kms.h
index a9f17bdb4530..9bcabaada179 100644
--- a/drivers/gpu/drm/msm/msm_kms.h
+++ b/drivers/gpu/drm/msm/msm_kms.h
@@ -43,6 +43,9 @@ struct msm_kms_funcs {
/* modeset, bracketing atomic_commit(): */
void (*prepare_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
void (*complete_commit)(struct msm_kms *kms, struct drm_atomic_state *state);
+ /* functions to wait for atomic commit completed on each CRTC */
+ void (*wait_for_crtc_commit_done)(struct msm_kms *kms,
+ struct drm_crtc *crtc);
/* misc: */
const struct msm_format *(*get_format)(struct msm_kms *kms, uint32_t format);
long (*round_pixclk)(struct msm_kms *kms, unsigned long rate,
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 07735822a28f..2f295cde657e 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -207,4 +207,19 @@
*/
#define I915_FORMAT_MOD_Yf_TILED fourcc_mod_code(INTEL, 3)
+/*
+ * Tiled, NV12MT, grouped in 64 (pixels) x 32 (lines) -sized macroblocks
+ *
+ * Macroblocks are laid in a Z-shape, and each pixel data is following the
+ * standard NV12 style.
+ * As for NV12, an image is the result of two frame buffers: one for Y,
+ * one for the interleaved Cb/Cr components (1/2 the height of the Y buffer).
+ * Alignment requirements are (for each buffer):
+ * - multiple of 128 pixels for the width
+ * - multiple of 32 pixels for the height
+ *
+ * For more information: see http://linuxtv.org/downloads/v4l-dvb-apis/re32.html
+ */
+#define DRM_FORMAT_MOD_SAMSUNG_64_32_TILE fourcc_mod_code(SAMSUNG, 1)
+
#endif /* DRM_FOURCC_H */
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index 0664c31f010c..75a232b9a970 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -23,7 +23,7 @@
/* Please note that modifications to all structs defined here are
* subject to backwards-compatibility constraints:
- * 1) Do not use pointers, use uint64_t instead for 32 bit / 64 bit
+ * 1) Do not use pointers, use __u64 instead for 32 bit / 64 bit
* user/kernel compatibility
* 2) Keep fields aligned to their size
* 3) Because of how drm_ioctl() works, we can add new fields at
@@ -44,8 +44,8 @@
* same as 'struct timespec' but 32/64b ABI safe.
*/
struct drm_msm_timespec {
- int64_t tv_sec; /* seconds */
- int64_t tv_nsec; /* nanoseconds */
+ __s64 tv_sec; /* seconds */
+ __s64 tv_nsec; /* nanoseconds */
};
#define MSM_PARAM_GPU_ID 0x01
@@ -53,9 +53,9 @@ struct drm_msm_timespec {
#define MSM_PARAM_CHIP_ID 0x03
struct drm_msm_param {
- uint32_t pipe; /* in, MSM_PIPE_x */
- uint32_t param; /* in, MSM_PARAM_x */
- uint64_t value; /* out (get_param) or in (set_param) */
+ __u32 pipe; /* in, MSM_PIPE_x */
+ __u32 param; /* in, MSM_PARAM_x */
+ __u64 value; /* out (get_param) or in (set_param) */
};
/*
@@ -77,15 +77,15 @@ struct drm_msm_param {
MSM_BO_UNCACHED)
struct drm_msm_gem_new {
- uint64_t size; /* in */
- uint32_t flags; /* in, mask of MSM_BO_x */
- uint32_t handle; /* out */
+ __u64 size; /* in */
+ __u32 flags; /* in, mask of MSM_BO_x */
+ __u32 handle; /* out */
};
struct drm_msm_gem_info {
- uint32_t handle; /* in */
- uint32_t pad;
- uint64_t offset; /* out, offset to pass to mmap() */
+ __u32 handle; /* in */
+ __u32 pad;
+ __u64 offset; /* out, offset to pass to mmap() */
};
#define MSM_PREP_READ 0x01
@@ -95,13 +95,13 @@ struct drm_msm_gem_info {
#define MSM_PREP_FLAGS (MSM_PREP_READ | MSM_PREP_WRITE | MSM_PREP_NOSYNC)
struct drm_msm_gem_cpu_prep {
- uint32_t handle; /* in */
- uint32_t op; /* in, mask of MSM_PREP_x */
+ __u32 handle; /* in */
+ __u32 op; /* in, mask of MSM_PREP_x */
struct drm_msm_timespec timeout; /* in */
};
struct drm_msm_gem_cpu_fini {
- uint32_t handle; /* in */
+ __u32 handle; /* in */
};
/*
@@ -120,11 +120,11 @@ struct drm_msm_gem_cpu_fini {
* otherwise EINVAL.
*/
struct drm_msm_gem_submit_reloc {
- uint32_t submit_offset; /* in, offset from submit_bo */
- uint32_t or; /* in, value OR'd with result */
- int32_t shift; /* in, amount of left shift (can be negative) */
- uint32_t reloc_idx; /* in, index of reloc_bo buffer */
- uint64_t reloc_offset; /* in, offset from start of reloc_bo */
+ __u32 submit_offset; /* in, offset from submit_bo */
+ __u32 or; /* in, value OR'd with result */
+ __s32 shift; /* in, amount of left shift (can be negative) */
+ __u32 reloc_idx; /* in, index of reloc_bo buffer */
+ __u64 reloc_offset; /* in, offset from start of reloc_bo */
};
/* submit-types:
@@ -139,13 +139,13 @@ struct drm_msm_gem_submit_reloc {
#define MSM_SUBMIT_CMD_IB_TARGET_BUF 0x0002
#define MSM_SUBMIT_CMD_CTX_RESTORE_BUF 0x0003
struct drm_msm_gem_submit_cmd {
- uint32_t type; /* in, one of MSM_SUBMIT_CMD_x */
- uint32_t submit_idx; /* in, index of submit_bo cmdstream buffer */
- uint32_t submit_offset; /* in, offset into submit_bo */
- uint32_t size; /* in, cmdstream size */
- uint32_t pad;
- uint32_t nr_relocs; /* in, number of submit_reloc's */
- uint64_t __user relocs; /* in, ptr to array of submit_reloc's */
+ __u32 type; /* in, one of MSM_SUBMIT_CMD_x */
+ __u32 submit_idx; /* in, index of submit_bo cmdstream buffer */
+ __u32 submit_offset; /* in, offset into submit_bo */
+ __u32 size; /* in, cmdstream size */
+ __u32 pad;
+ __u32 nr_relocs; /* in, number of submit_reloc's */
+ __u64 __user relocs; /* in, ptr to array of submit_reloc's */
};
/* Each buffer referenced elsewhere in the cmdstream submit (ie. the
@@ -165,9 +165,9 @@ struct drm_msm_gem_submit_cmd {
#define MSM_SUBMIT_BO_FLAGS (MSM_SUBMIT_BO_READ | MSM_SUBMIT_BO_WRITE)
struct drm_msm_gem_submit_bo {
- uint32_t flags; /* in, mask of MSM_SUBMIT_BO_x */
- uint32_t handle; /* in, GEM handle */
- uint64_t presumed; /* in/out, presumed buffer address */
+ __u32 flags; /* in, mask of MSM_SUBMIT_BO_x */
+ __u32 handle; /* in, GEM handle */
+ __u64 presumed; /* in/out, presumed buffer address */
};
/* Each cmdstream submit consists of a table of buffers involved, and
@@ -175,12 +175,12 @@ struct drm_msm_gem_submit_bo {
* (context-restore), and IB buffers needed for per tile/bin draw cmds.
*/
struct drm_msm_gem_submit {
- uint32_t pipe; /* in, MSM_PIPE_x */
- uint32_t fence; /* out */
- uint32_t nr_bos; /* in, number of submit_bo's */
- uint32_t nr_cmds; /* in, number of submit_cmd's */
- uint64_t __user bos; /* in, ptr to array of submit_bo's */
- uint64_t __user cmds; /* in, ptr to array of submit_cmd's */
+ __u32 pipe; /* in, MSM_PIPE_x */
+ __u32 fence; /* out */
+ __u32 nr_bos; /* in, number of submit_bo's */
+ __u32 nr_cmds; /* in, number of submit_cmd's */
+ __u64 __user bos; /* in, ptr to array of submit_bo's */
+ __u64 __user cmds; /* in, ptr to array of submit_cmd's */
};
/* The normal way to synchronize with the GPU is just to CPU_PREP on
@@ -191,8 +191,8 @@ struct drm_msm_gem_submit {
* APIs without requiring a dummy bo to synchronize on.
*/
struct drm_msm_wait_fence {
- uint32_t fence; /* in */
- uint32_t pad;
+ __u32 fence; /* in */
+ __u32 pad;
struct drm_msm_timespec timeout; /* in */
};