Merge "msm: kgsl: Do not return error if there is no GMU" into msm-4.9
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc-vmem.txt b/Documentation/devicetree/bindings/media/video/msm-vidc-vmem.txt
deleted file mode 100644
index 84a8765..0000000
--- a/Documentation/devicetree/bindings/media/video/msm-vidc-vmem.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-* Qualcomm Technologies Inc MSM VIDC VMEM
-
-Required properties:
-- compatible : "qcom,msm-vmem".
-- interrupts : Contains the interrupt that maps to the VMEM module.
-- reg : A set of 2 start address and size pairs that describe the hardware
-register address space and mappable memory address space.
-- reg-names : Strings that describe the pairs in "reg". The register address
-space should be called "reg-base" and the memory space should be called "mem-base".
-- clocks : A set of clocks that correspond to the AHB and MAXI clocks that the
-hardware uses.
-- clock-names : A string that describes the "clocks" property. The AHB clock
-should be named "ahb" and the MAXI clock should be named "maxi".
-- qcom,bank-size : The size of each memory bank, in bytes.
-- vdd-supply: phandle to a regulator that is considered to be the footswitch for vmem.
-- qcom,msm-bus,(name|num-cases,num-paths,vectors-KBps) - Bus to be voted for prior to
- issuing any IO transactions to vmem. Refer to Documentation/devicetree/bindings/arm/\
- msm/msm_bus_adhoc.txt for further details.
-
-Example:
-
-qcom,vmem@880000 {
- compatible = "qcom,msm-vmem";
- interrupts = <0 429 0>;
- reg = <0x880000 0x800>,
- <0x6800000 0x100000>;
- reg-names = "reg-base", "mem-base";
-
- vdd-supply = <&gdsc_mmagic_video>;
- clocks = <&clock_mmss clk_vmem_ahb_clk>,
- <&clock_mmss clk_vmem_maxi_clk>;
- clock-names = "ahb", "maxi";
-
- qcom,bank-size = <131072>;
-
- qcom,msm-bus,name = "vmem";
- qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,num-paths = <1>;
- qcom,msm-bus,vectors-KBps =
- <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_VMEM_CFG 0 0>,
- <MSM_BUS_MASTER_AMPSS_M0 MSM_BUS_SLAVE_VMEM_CFG 500 800>;
-};
diff --git a/Documentation/devicetree/bindings/media/video/msm-vidc.txt b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
index bdc0eba..53f419c 100644
--- a/Documentation/devicetree/bindings/media/video/msm-vidc.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-vidc.txt
@@ -104,6 +104,9 @@
memory, performance etc.
- qcom,debug-timeout = A bool indicating that FW errors such as SYS_ERROR,
SESSION_ERROR and timeouts will be treated as Fatal.
+- cache-slice-names = An array of supported cache slice names by llcc
+- cache-slices = An array of supported cache slice ids corresponding
+ to cache-slice-names by llcc
[Second level nodes]
Context Banks
@@ -149,7 +152,7 @@
Optional properties:
- qcom,bus-governor : governor to use when scaling bus, generally any commonly
found devfreq governor might be used. In addition to those governors, the
- custom Venus governors, "msm-vidc-ddr" or "msm-vidc-vmem" are also
+ custom Venus governors, "msm-vidc-ddr" or "msm-vidc-llcc" are also
acceptable values.
In the absence of this property the "performance" governor is used.
- qcom,bus-rage-kbps : an array of two items (<min max>) that indicate the
diff --git a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
index 5d0499c..803df6f 100644
--- a/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/gdsc-regulator.txt
@@ -59,6 +59,8 @@
- qcom,poll-cfg-gdscr: Poll the CFG register of the GDSC to determine if the
GDSC is enabled/disabled. This flag should not be set
in conjunction with "hw-ctrl-addr".
+ - qcom,toggle-sw-collapse-in-disable: If set, SW_COLLAPSE bit is toggled
+ in disable call.
Example:
gdsc_oxili_gx: qcom,gdsc@fd8c4024 {
diff --git a/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi b/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
index 84a6a84..2194a42 100644
--- a/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-gdsc-sdm845.dtsi
@@ -217,6 +217,7 @@
sw-reset = <&gpu_gx_sw_reset>;
qcom,reset-aon-logic;
qcom,poll-cfg-gdscr;
+ qcom,toggle-sw-collapse-in-disable;
status = "disabled";
};
diff --git a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
index f6493ac..9b7865f 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-coresight.dtsi
@@ -767,6 +767,15 @@
<&tpdm_lpass_out_funnel_lpass>;
};
};
+
+ port@2 {
+ reg = <1>;
+ funnel_lpass_in_audio_etm0: endpoint {
+ slave-mode;
+ remote-endpoint =
+ <&audio_etm0_out_funnel_lpass>;
+ };
+ };
};
};
@@ -1731,7 +1740,7 @@
compatible = "qcom,coresight-remote-etm";
coresight-name = "coresight-turing-etm0";
- qcom,inst-id = <1>;
+ qcom,inst-id = <13>;
port{
turing_etm0_out_funnel_turing: endpoint {
@@ -1770,6 +1779,19 @@
};
};
+ audio_etm0 {
+ compatible = "qcom,coresight-remote-etm";
+
+ coresight-name = "coresight-audio-etm0";
+ qcom,inst-id = <5>;
+
+ port {
+ audio_etm0_out_funnel_lpass: endpoint {
+ remote-endpoint = <&funnel_lpass_in_audio_etm0>;
+ };
+ };
+ };
+
funnel_apss_merg: funnel@7810000 {
compatible = "arm,primecell";
arm,primecell-periphid = <0x0003b908>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
index 9056569..b51996d 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-qrd.dtsi
@@ -142,6 +142,7 @@
qcom,panel-mode-gpio = <&tlmm 52 0>;
qcom,platform-te-gpio = <&tlmm 10 0>;
qcom,platform-reset-gpio = <&tlmm 6 0>;
+ qcom,mdss-dsi-panel-orientation = "180";
};
&dsi_sharp_4k_dsc_video_display {
diff --git a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
index df2e0c7..6d9e321 100644
--- a/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845-sde.dtsi
@@ -14,9 +14,11 @@
mdss_mdp: qcom,mdss_mdp@ae00000 {
compatible = "qcom,sde-kms";
reg = <0x0ae00000 0x81d40>,
- <0x0aeb0000 0x2008>;
+ <0x0aeb0000 0x2008>,
+ <0x0aeac000 0xf0>;
reg-names = "mdp_phys",
- "vbif_phys";
+ "vbif_phys",
+ "regdma_phys";
clocks =
<&clock_gcc GCC_DISP_AHB_CLK>,
@@ -56,7 +58,7 @@
qcom,sde-mixer-size = <0x320>;
qcom,sde-dspp-off = <0x55000 0x57000 0x59000 0x5b000>;
- qcom,sde-dspp-size = <0x4>;
+ qcom,sde-dspp-size = <0x17e0>;
qcom,sde-wb-off = <0x66000>;
qcom,sde-wb-size = <0x2c8>;
@@ -97,6 +99,8 @@
1 5 9 13>;
qcom,sde-sspp-excl-rect = <1 1 1 1
1 1 1 1>;
+ qcom,sde-sspp-smart-dma-priority = <5 6 7 8 1 2 3 4>;
+ qcom,sde-smart-dma-rev = "smart_dma_v2";
qcom,sde-mixer-pair-mask = <2 1 6 0 0 3>;
@@ -133,12 +137,22 @@
qcom,sde-inline-rotator = <&mdss_rotator 0>;
+ qcom,sde-reg-dma-off = <0>;
+ qcom,sde-reg-dma-version = <0x1>;
+ qcom,sde-reg-dma-trigger-off = <0x119c>;
+
qcom,sde-sspp-vig-blocks {
qcom,sde-vig-csc-off = <0x1a00>;
qcom,sde-vig-qseed-off = <0xa00>;
qcom,sde-vig-qseed-size = <0xa0>;
};
+ qcom,sde-dspp-blocks {
+ qcom,sde-dspp-vlut = <0xa00 0x00010008>;
+ qcom,sde-dspp-gamut = <0x1000 0x00040000>;
+ qcom,sde-dspp-gc = <0x17c0 0x00010008>;
+ };
+
qcom,platform-supply-entries {
#address-cells = <1>;
#size-cells = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index dddd241..6038b6e 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -69,11 +69,14 @@
};
L1_I_0: l1-icache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x9000>;
+ qcom,dump-size = <0xa000>;
};
L1_D_0: l1-dcache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x9000>;
+ qcom,dump-size = <0xa000>;
+ };
+ L1_TLB_0: l1-tlb {
+ qcom,dump-size = <0x3000>;
};
};
@@ -97,11 +100,14 @@
};
L1_I_100: l1-icache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x9000>;
+ qcom,dump-size = <0xa000>;
};
L1_D_100: l1-dcache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x9000>;
+ qcom,dump-size = <0xa000>;
+ };
+ L1_TLB_100: l1-tlb {
+ qcom,dump-size = <0x3000>;
};
};
@@ -125,11 +131,14 @@
};
L1_I_200: l1-icache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x9000>;
+ qcom,dump-size = <0xa000>;
};
L1_D_200: l1-dcache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x9000>;
+ qcom,dump-size = <0xa000>;
+ };
+ L1_TLB_200: l1-tlb {
+ qcom,dump-size = <0x3000>;
};
};
@@ -153,11 +162,14 @@
};
L1_I_300: l1-icache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x9000>;
+ qcom,dump-size = <0xa000>;
};
L1_D_300: l1-dcache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x9000>;
+ qcom,dump-size = <0xa000>;
+ };
+ L1_TLB_300: l1-tlb {
+ qcom,dump-size = <0x3000>;
};
};
@@ -181,11 +193,14 @@
};
L1_I_400: l1-icache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x12000>;
+ qcom,dump-size = <0x14000>;
};
L1_D_400: l1-dcache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x12000>;
+ qcom,dump-size = <0x14000>;
+ };
+ L1_TLB_400: l1-tlb {
+ qcom,dump-size = <0x3c000>;
};
};
@@ -209,11 +224,14 @@
};
L1_I_500: l1-icache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x12000>;
+ qcom,dump-size = <0x14000>;
};
L1_D_500: l1-dcache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x12000>;
+ qcom,dump-size = <0x14000>;
+ };
+ L1_TLB_500: l1-tlb {
+ qcom,dump-size = <0x3c000>;
};
};
@@ -237,11 +255,14 @@
};
L1_I_600: l1-icache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x12000>;
+ qcom,dump-size = <0x14000>;
};
L1_D_600: l1-dcache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x12000>;
+ qcom,dump-size = <0x14000>;
+ };
+ L1_TLB_600: l1-tlb {
+ qcom,dump-size = <0x3c000>;
};
};
@@ -265,11 +286,14 @@
};
L1_I_700: l1-icache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x12000>;
+ qcom,dump-size = <0x14000>;
};
L1_D_700: l1-dcache {
compatible = "arm,arch-cache";
- qcom,dump-size = <0x12000>;
+ qcom,dump-size = <0x14000>;
+ };
+ L1_TLB_700: l1-tlb {
+ qcom,dump-size = <0x3c000>;
};
};
@@ -428,6 +452,13 @@
soc: soc { };
+ vendor: vendor {
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges = <0 0 0 0xffffffff>;
+ compatible = "simple-bus";
+ };
+
reserved-memory {
#address-cells = <2>;
#size-cells = <2>;
@@ -2036,6 +2067,38 @@
qcom,dump-node = <&LLCC_4>;
qcom,dump-id = <0x124>;
};
+ qcom,l1_tlb_dump0 {
+ qcom,dump-node = <&L1_TLB_0>;
+ qcom,dump-id = <0x20>;
+ };
+ qcom,l1_tlb_dump100 {
+ qcom,dump-node = <&L1_TLB_100>;
+ qcom,dump-id = <0x21>;
+ };
+ qcom,l1_tlb_dump200 {
+ qcom,dump-node = <&L1_TLB_200>;
+ qcom,dump-id = <0x22>;
+ };
+ qcom,l1_tlb_dump300 {
+ qcom,dump-node = <&L1_TLB_300>;
+ qcom,dump-id = <0x23>;
+ };
+ qcom,l1_tlb_dump400 {
+ qcom,dump-node = <&L1_TLB_400>;
+ qcom,dump-id = <0x24>;
+ };
+ qcom,l1_tlb_dump500 {
+ qcom,dump-node = <&L1_TLB_500>;
+ qcom,dump-id = <0x25>;
+ };
+ qcom,l1_tlb_dump600 {
+ qcom,dump-node = <&L1_TLB_600>;
+ qcom,dump-id = <0x26>;
+ };
+ qcom,l1_tlb_dump700 {
+ qcom,dump-node = <&L1_TLB_700>;
+ qcom,dump-id = <0x27>;
+ };
};
kryo3xx-erp {
@@ -2797,7 +2860,7 @@
thermal-sensors = <&tsens0 0>;
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2811,7 +2874,7 @@
thermal-sensors = <&tsens0 1>;
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2825,7 +2888,7 @@
thermal-sensors = <&tsens0 2>;
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2839,7 +2902,7 @@
thermal-sensors = <&tsens0 3>;
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2853,7 +2916,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2867,7 +2930,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2881,7 +2944,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2895,7 +2958,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2909,7 +2972,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2923,7 +2986,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2937,7 +3000,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2951,7 +3014,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2965,7 +3028,7 @@
thermal-sensors = <&tsens0 12>;
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2979,7 +3042,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -2993,7 +3056,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -3009,7 +3072,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -3023,7 +3086,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -3037,7 +3100,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -3051,7 +3114,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -3065,7 +3128,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -3079,7 +3142,7 @@
thermal-governor = "user_space";
trips {
active-config0 {
- temperature = <65000>;
+ temperature = <125000>;
hysteresis = <1000>;
type = "passive";
};
@@ -3811,6 +3874,38 @@
interrupt-names = "tsens-upper-lower", "tsens-critical";
#thermal-sensor-cells = <1>;
};
+
+ gpi_dma0: qcom,gpi-dma@0x800000 {
+ #dma-cells = <6>;
+ compatible = "qcom,gpi-dma";
+ reg = <0x800000 0x60000>;
+ reg-names = "gpi-top";
+ interrupts = <0 244 0>, <0 245 0>, <0 246 0>, <0 247 0>,
+ <0 248 0>, <0 249 0>, <0 250 0>, <0 251 0>,
+ <0 252 0>, <0 253 0>, <0 254 0>, <0 255 0>,
+ <0 256 0>;
+ qcom,max-num-gpii = <13>;
+ qcom,gpii-mask = <0xfa>;
+ qcom,ev-factor = <2>;
+ iommus = <&apps_smmu 0x0016 0x0>;
+ status = "ok";
+ };
+
+ gpi_dma1: qcom,gpi-dma@0xa00000 {
+ #dma-cells = <6>;
+ compatible = "qcom,gpi-dma";
+ reg = <0xa00000 0x60000>;
+ reg-names = "gpi-top";
+ interrupts = <0 279 0>, <0 280 0>, <0 281 0>, <0 282 0>,
+ <0 283 0>, <0 284 0>, <0 293 0>, <0 294 0>,
+ <0 295 0>, <0 296 0>, <0 297 0>, <0 298 0>,
+ <0 299 0>;
+ qcom,max-num-gpii = <13>;
+ qcom,gpii-mask = <0xfa>;
+ qcom,ev-factor = <2>;
+ iommus = <&apps_smmu 0x06d6 0x0>;
+ status = "ok";
+ };
};
&clock_cpucc {
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 837bbab..75088c00 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -943,6 +943,8 @@
.sync_single_for_device = __iommu_sync_single_for_device,
.sync_sg_for_cpu = __iommu_sync_sg_for_cpu,
.sync_sg_for_device = __iommu_sync_sg_for_device,
+ .map_resource = iommu_dma_map_resource,
+ .unmap_resource = iommu_dma_unmap_resource,
.dma_supported = iommu_dma_supported,
.mapping_error = iommu_dma_mapping_error,
};
@@ -1847,6 +1849,45 @@
__dma_page_cpu_to_dev(page, offset, size, dir);
}
+static dma_addr_t arm_iommu_dma_map_resource(
+ struct device *dev, phys_addr_t phys_addr,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs)
+{
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+ size_t offset = phys_addr & ~PAGE_MASK;
+ size_t len = PAGE_ALIGN(size + offset);
+ dma_addr_t dma_addr;
+ int prot;
+
+ dma_addr = __alloc_iova(mapping, len);
+ if (dma_addr == DMA_ERROR_CODE)
+ return dma_addr;
+
+ prot = __dma_direction_to_prot(dir);
+ prot |= IOMMU_MMIO;
+
+ if (iommu_map(mapping->domain, dma_addr, phys_addr - offset,
+ len, prot)) {
+ __free_iova(mapping, dma_addr, len);
+ return DMA_ERROR_CODE;
+ }
+ return dma_addr + offset;
+}
+
+static void arm_iommu_dma_unmap_resource(
+ struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs)
+{
+ struct dma_iommu_mapping *mapping = dev->archdata.mapping;
+ size_t offset = addr & ~PAGE_MASK;
+ size_t len = PAGE_ALIGN(size + offset);
+
+ iommu_unmap(mapping->domain, addr - offset, len);
+ __free_iova(mapping, addr - offset, len);
+}
+
static int arm_iommu_mapping_error(struct device *dev,
dma_addr_t dma_addr)
{
@@ -1869,6 +1910,9 @@
.sync_sg_for_cpu = arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
+ .map_resource = arm_iommu_dma_map_resource,
+ .unmap_resource = arm_iommu_dma_unmap_resource,
+
.set_dma_mask = arm_dma_set_mask,
.mapping_error = arm_iommu_mapping_error,
};
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index ee847d9f..3f2ce31 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -2470,7 +2470,7 @@
int srcVM[1] = {VMID_HLOS};
int destVM[4] = {VMID_HLOS, VMID_MSS_MSA, VMID_SSC_Q6,
VMID_ADSP_Q6};
- int destVMperm[4] = {PERM_READ | PERM_WRITE,
+ int destVMperm[4] = {PERM_READ | PERM_WRITE | PERM_EXEC,
PERM_READ | PERM_WRITE | PERM_EXEC,
PERM_READ | PERM_WRITE | PERM_EXEC,
PERM_READ | PERM_WRITE | PERM_EXEC,
diff --git a/drivers/clk/qcom/gdsc-regulator.c b/drivers/clk/qcom/gdsc-regulator.c
index 3bb7c04..90c76e6 100644
--- a/drivers/clk/qcom/gdsc-regulator.c
+++ b/drivers/clk/qcom/gdsc-regulator.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2012-2016, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2017, 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
@@ -54,6 +54,9 @@
/* Timeout Delay */
#define TIMEOUT_US 100
+/* TOGGLE SW COLLAPSE */
+#define TOGGLE_SW_COLLAPSE_IN_DISABLE BIT(0)
+
struct gdsc {
struct regulator_dev *rdev;
struct regulator_desc rdesc;
@@ -79,6 +82,7 @@
int reset_count;
int root_clk_idx;
u32 gds_timeout;
+ u32 flags;
};
enum gdscr_status {
@@ -378,6 +382,13 @@
regval |= SW_COLLAPSE_MASK;
regmap_write(sc->regmap, REG_OFFSET, regval);
+ if (sc->flags & TOGGLE_SW_COLLAPSE_IN_DISABLE) {
+ regval &= ~SW_COLLAPSE_MASK;
+ regmap_write(sc->regmap, REG_OFFSET, regval);
+ regval |= SW_COLLAPSE_MASK;
+ regmap_write(sc->regmap, REG_OFFSET, regval);
+ }
+
/* Wait for 8 XO cycles before polling the status bit. */
mb();
udelay(1);
@@ -522,7 +533,7 @@
struct resource *res;
struct gdsc *sc;
uint32_t regval, clk_dis_wait_val = 0;
- bool retain_mem, retain_periph, support_hw_trigger;
+ bool retain_mem, retain_periph, support_hw_trigger, prop_val;
int i, ret;
u32 timeout;
@@ -613,6 +624,11 @@
sc->force_root_en = of_property_read_bool(pdev->dev.of_node,
"qcom,force-enable-root-clk");
+ prop_val = of_property_read_bool(pdev->dev.of_node,
+ "qcom,toggle-sw-collapse-in-disable");
+ if (prop_val)
+ sc->flags |= TOGGLE_SW_COLLAPSE_IN_DISABLE;
+
for (i = 0; i < sc->clock_count; i++) {
const char *clock_name;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
index 53f0098..37ed411 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_drm.c
@@ -357,6 +357,10 @@
case DSI_PANEL_ROTATE_V_FLIP:
sde_kms_info_add_keystr(info, "panel orientation", "vert flip");
break;
+ case DSI_PANEL_ROTATE_HV_FLIP:
+ sde_kms_info_add_keystr(info, "panel orientation",
+ "horz & vert flip");
+ break;
default:
pr_debug("invalid panel rotation:%d\n",
panel->phy_props.rotation);
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index 79b39bd..d5207b9 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -1164,7 +1164,7 @@
sde_cp_create_local_blob(crtc, SDE_CP_CRTC_DSPP_AD_CFG,
sizeof(struct drm_msm_ad4_cfg));
sde_cp_crtc_install_range_property(crtc,
- "SDE_DSPP_AD_V4_ASSERTIVNESS",
+ "SDE_DSPP_AD_V4_ASSERTIVENESS",
SDE_CP_CRTC_DSPP_AD_ASSERTIVENESS, 0, (BIT(8) - 1), 0);
sde_cp_crtc_install_range_property(crtc, "SDE_DSPP_AD_V4_INPUT",
SDE_CP_CRTC_DSPP_AD_INPUT, 0, U16_MAX, 0);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 02d6009..dcf3c08 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -731,7 +731,6 @@
struct sde_crtc *sde_crtc;
struct sde_crtc_state *crtc_state;
struct sde_rect *crtc_roi;
- struct drm_clip_rect crtc_clip, *user_rect;
int i, num_attached_conns = 0;
if (!crtc || !state)
@@ -741,12 +740,6 @@
crtc_state = to_sde_crtc_state(state);
crtc_roi = &crtc_state->crtc_roi;
- /* init to invalid range maxes */
- crtc_clip.x1 = ~0;
- crtc_clip.y1 = ~0;
- crtc_clip.x2 = 0;
- crtc_clip.y2 = 0;
-
for_each_connector_in_state(state->state, conn, conn_state, i) {
struct sde_connector_state *sde_conn_state;
@@ -771,36 +764,7 @@
}
}
- /* aggregate all clipping rectangles together for overall crtc roi */
- for (i = 0; i < crtc_state->user_roi_list.num_rects; i++) {
- user_rect = &crtc_state->user_roi_list.roi[i];
-
- crtc_clip.x1 = min(crtc_clip.x1, user_rect->x1);
- crtc_clip.y1 = min(crtc_clip.y1, user_rect->y1);
- crtc_clip.x2 = max(crtc_clip.x2, user_rect->x2);
- crtc_clip.y2 = max(crtc_clip.y2, user_rect->y2);
-
- SDE_DEBUG(
- "%s: conn%d roi%d (%d,%d),(%d,%d) -> crtc (%d,%d),(%d,%d)\n",
- sde_crtc->name, DRMID(crtc), i,
- user_rect->x1, user_rect->y1,
- user_rect->x2, user_rect->y2,
- crtc_clip.x1, crtc_clip.y1,
- crtc_clip.x2, crtc_clip.y2);
-
- }
-
- if (crtc_clip.x2 && crtc_clip.y2) {
- crtc_roi->x = crtc_clip.x1;
- crtc_roi->y = crtc_clip.y1;
- crtc_roi->w = crtc_clip.x2 - crtc_clip.x1;
- crtc_roi->h = crtc_clip.y2 - crtc_clip.y1;
- } else {
- crtc_roi->x = 0;
- crtc_roi->y = 0;
- crtc_roi->w = 0;
- crtc_roi->h = 0;
- }
+ sde_kms_rect_merge_rectangles(&crtc_state->user_roi_list, crtc_roi);
SDE_DEBUG("%s: crtc roi (%d,%d,%d,%d)\n", sde_crtc->name,
crtc_roi->x, crtc_roi->y, crtc_roi->w, crtc_roi->h);
@@ -1066,6 +1030,10 @@
if (sde_kms_rect_is_null(lm_roi))
continue;
+ hw_lm->cfg.out_width = lm_roi->w;
+ hw_lm->cfg.out_height = lm_roi->h;
+ hw_lm->cfg.right_mixer = lm_horiz_position;
+
cfg.out_width = lm_roi->w;
cfg.out_height = lm_roi->h;
cfg.right_mixer = lm_horiz_position++;
@@ -2563,11 +2531,14 @@
}
for (i = 1; i < SSPP_MAX; i++) {
- if (pipe_staged[i] &&
- is_sde_plane_virtual(pipe_staged[i]->plane)) {
- SDE_ERROR("invalid use of virtual plane: %d\n",
+ if (pipe_staged[i]) {
+ sde_plane_clear_multirect(pipe_staged[i]);
+
+ if (is_sde_plane_virtual(pipe_staged[i]->plane)) {
+ SDE_ERROR("invalid use of virtual plane: %d\n",
pipe_staged[i]->plane->base.id);
- goto end;
+ goto end;
+ }
}
}
@@ -3081,6 +3052,8 @@
seq_printf(s, "\tdst x:%4d dst_y:%4d dst_w:%4d dst_h:%4d\n",
state->crtc_x, state->crtc_y, state->crtc_w,
state->crtc_h);
+ seq_printf(s, "\tmultirect: mode: %d index: %d\n",
+ pstate->multirect_mode, pstate->multirect_index);
seq_puts(s, "\n");
}
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_ad4.c b/drivers/gpu/drm/msm/sde/sde_hw_ad4.c
index 7d2f67d..b02cc06 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_ad4.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_ad4.c
@@ -17,8 +17,8 @@
#include "sde_ad4.h"
#define IDLE_2_RUN(x) ((x) == (ad4_init | ad4_cfg | ad4_mode | ad4_input))
-#define MERGE_WIDTH_RIGHT 4
-#define MERGE_WIDTH_LEFT 3
+#define MERGE_WIDTH_RIGHT 6
+#define MERGE_WIDTH_LEFT 5
enum ad4_ops_bitmask {
ad4_init = BIT(AD_INIT),
@@ -179,7 +179,7 @@
cfg->hw_cfg->displayh, cfg->hw_cfg->displayv);
return -EINVAL;
} else if (hw_lm->cfg.out_height != cfg->hw_cfg->displayv &&
- hw_lm->cfg.out_width != (cfg->hw_cfg->displayh >> 2)) {
+ hw_lm->cfg.out_width != (cfg->hw_cfg->displayh >> 1)) {
DRM_ERROR("dual_lm lmh %d lmw %d displayh %d displayw %d\n",
hw_lm->cfg.out_height, hw_lm->cfg.out_width,
cfg->hw_cfg->displayh, cfg->hw_cfg->displayv);
@@ -250,6 +250,7 @@
MERGE_WIDTH_LEFT;
proc_start = 0;
proc_end = (cfg->hw_cfg->displayh >> 1) - 1;
+ tile_ctl |= 0x10;
}
}
@@ -769,7 +770,8 @@
(cfg->hw_cfg->payload));
info[dspp->idx].completed_ops_mask |= ad4_mode;
- if (IDLE_2_RUN(info[dspp->idx].completed_ops_mask))
+ if (IDLE_2_RUN(info[dspp->idx].completed_ops_mask) ||
+ info[dspp->idx].cached_mode == AD4_OFF)
ad4_mode_setup(dspp, info[dspp->idx].cached_mode);
return 0;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
index c33e520..5719c51 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
@@ -529,16 +529,36 @@
REG_DMA_SETUP_OPS(dma_write_cfg,
ctx->cap->sblk->gc.base + GC_C0_OFF +
(i * sizeof(u32) * 2),
- lut_cfg->c0 + ARRAY_SIZE(lut_cfg->c0),
+ lut_cfg->c0 + (ARRAY_SIZE(lut_cfg->c0) * i),
PGC_TBL_LEN * sizeof(u32),
REG_BLK_WRITE_INC, 0, 0);
rc = dma_ops->setup_payload(&dma_write_cfg);
if (rc) {
- DRM_ERROR("index init failed ret %d\n", rc);
+ DRM_ERROR("lut write failed ret %d\n", rc);
return;
}
}
+ reg = BIT(0);
+ REG_DMA_SETUP_OPS(dma_write_cfg,
+ ctx->cap->sblk->gc.base + GC_LUT_SWAP_OFF,
+ ®, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+ rc = dma_ops->setup_payload(&dma_write_cfg);
+ if (rc) {
+ DRM_ERROR("setting swap offset failed ret %d\n", rc);
+ return;
+ }
+
+ reg = GC_EN | ((lut_cfg->flags & PGC_8B_ROUND) ? GC_8B_ROUND_EN : 0);
+ REG_DMA_SETUP_OPS(dma_write_cfg,
+ ctx->cap->sblk->gc.base,
+ ®, sizeof(reg), REG_SINGLE_WRITE, 0, 0);
+ rc = dma_ops->setup_payload(&dma_write_cfg);
+ if (rc) {
+ DRM_ERROR("enabling gamma correction failed ret %d\n", rc);
+ return;
+ }
+
REG_DMA_SETUP_KICKOFF(kick_off, hw_cfg->ctl, dspp_buf[GC][ctx->idx],
REG_DMA_WRITE, DMA_CTL_QUEUE0, WRITE_IMMEDIATE);
kick_off.last_command = hw_cfg->last_feature;
@@ -547,11 +567,6 @@
DRM_ERROR("failed to kick off ret %d\n", rc);
return;
}
-
- reg = GC_EN | ((lut_cfg->flags & PGC_8B_ROUND) ? GC_8B_ROUND_EN : 0);
- SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base + GC_LUT_SWAP_OFF,
- BIT(0));
- SDE_REG_WRITE(&ctx->hw, ctx->cap->sblk->gc.base, reg);
}
int reg_dmav1_deinit_dspp_ops(enum sde_dspp idx)
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index c045067..a1f5cee 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -299,7 +299,7 @@
{
struct sde_hw_blk_reg_map *c;
u32 chroma_samp, unpack, src_format;
- u32 secure = 0;
+ u32 secure = 0, secure_bit_mask;
u32 opmode = 0;
u32 op_mode_off, unpack_pat_off, format_off;
u32 idx;
@@ -311,10 +311,12 @@
op_mode_off = SSPP_SRC_OP_MODE;
unpack_pat_off = SSPP_SRC_UNPACK_PATTERN;
format_off = SSPP_SRC_FORMAT;
+ secure_bit_mask = (rect_mode == SDE_SSPP_RECT_SOLO) ? 0xF : 0x5;
} else {
op_mode_off = SSPP_SRC_OP_MODE_REC1;
unpack_pat_off = SSPP_SRC_UNPACK_PATTERN_REC1;
format_off = SSPP_SRC_FORMAT_REC1;
+ secure_bit_mask = 0xA;
}
c = &ctx->hw;
@@ -322,16 +324,11 @@
opmode &= ~(MDSS_MDP_OP_FLIP_LR | MDSS_MDP_OP_FLIP_UD |
MDSS_MDP_OP_BWC_EN | MDSS_MDP_OP_PE_OVERRIDE);
- if (flags & SDE_SSPP_SECURE_OVERLAY_SESSION) {
- secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
-
- if (rect_mode == SDE_SSPP_RECT_SOLO)
- secure |= 0xF;
- else if (rect_mode == SDE_SSPP_RECT_0)
- secure |= 0x5;
- else if (rect_mode == SDE_SSPP_RECT_1)
- secure |= 0xA;
- }
+ secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
+ if (flags & SDE_SSPP_SECURE_OVERLAY_SESSION)
+ secure |= secure_bit_mask;
+ else
+ secure &= ~secure_bit_mask;
if (flags & SDE_SSPP_FLIP_LR)
opmode |= MDSS_MDP_OP_FLIP_LR;
@@ -803,11 +800,17 @@
ystride1 = SDE_REG_READ(c, SSPP_SRC_YSTRIDE1 + idx);
if (rect_index == SDE_SSPP_RECT_0) {
- ystride0 |= cfg->layout.plane_pitch[0];
- ystride1 |= cfg->layout.plane_pitch[2];
- } else {
- ystride0 |= cfg->layout.plane_pitch[0] << 16;
- ystride1 |= cfg->layout.plane_pitch[2] << 16;
+ ystride0 = (ystride0 & 0xFFFF0000) |
+ (cfg->layout.plane_pitch[0] & 0x0000FFFF);
+ ystride1 = (ystride1 & 0xFFFF0000)|
+ (cfg->layout.plane_pitch[2] & 0x0000FFFF);
+ } else {
+ ystride0 = (ystride0 & 0x0000FFFF) |
+ ((cfg->layout.plane_pitch[0] << 16) &
+ 0xFFFF0000);
+ ystride1 = (ystride1 & 0x0000FFFF) |
+ ((cfg->layout.plane_pitch[2] << 16) &
+ 0xFFFF0000);
}
}
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.h b/drivers/gpu/drm/msm/sde/sde_kms.h
index 01a5535..1f56d73 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.h
+++ b/drivers/gpu/drm/msm/sde/sde_kms.h
@@ -407,6 +407,14 @@
struct sde_rect *result);
/**
+ * sde_kms_rect_merge_rectangles - merge a rectangle list into one rect
+ * @rois: pointer to the list of rois
+ * @result: output rectangle, all 0 on error
+ */
+void sde_kms_rect_merge_rectangles(const struct msm_roi_list *rois,
+ struct sde_rect *result);
+
+/**
* sde_kms_rect_is_equal - compares two rects
* @r1: rect value to compare
* @r2: rect value to compare
diff --git a/drivers/gpu/drm/msm/sde/sde_kms_utils.c b/drivers/gpu/drm/msm/sde/sde_kms_utils.c
index b956be5..dcc0bd5 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms_utils.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms_utils.c
@@ -175,3 +175,46 @@
result->h = b - t;
}
}
+
+void sde_kms_rect_merge_rectangles(const struct msm_roi_list *rois,
+ struct sde_rect *result)
+{
+ struct drm_clip_rect clip;
+ const struct drm_clip_rect *roi_rect;
+ int i;
+
+ if (!rois || !result)
+ return;
+
+ memset(result, 0, sizeof(*result));
+
+ /* init to invalid range maxes */
+ clip.x1 = ~0;
+ clip.y1 = ~0;
+ clip.x2 = 0;
+ clip.y2 = 0;
+
+ /* aggregate all clipping rectangles together for overall roi */
+ for (i = 0; i < rois->num_rects; i++) {
+ roi_rect = &rois->roi[i];
+
+ clip.x1 = min(clip.x1, roi_rect->x1);
+ clip.y1 = min(clip.y1, roi_rect->y1);
+ clip.x2 = max(clip.x2, roi_rect->x2);
+ clip.y2 = max(clip.y2, roi_rect->y2);
+
+ SDE_DEBUG("roi%d (%d,%d),(%d,%d) -> crtc (%d,%d),(%d,%d)\n", i,
+ roi_rect->x1, roi_rect->y1,
+ roi_rect->x2, roi_rect->y2,
+ clip.x1, clip.y1,
+ clip.x2, clip.y2);
+ }
+
+ if (clip.x2 && clip.y2) {
+ result->x = clip.x1;
+ result->y = clip.y1;
+ result->w = clip.x2 - clip.x1;
+ result->h = clip.y2 - clip.y1;
+ }
+}
+
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index deca83e..3a6de75 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -2208,274 +2208,17 @@
DRM_MODE_PROP_IMMUTABLE, PLANE_PROP_ROT_CAPS_V1);
}
-static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
- struct drm_plane_state *state)
+void sde_plane_clear_multirect(const struct drm_plane_state *drm_state)
{
- uint32_t nplanes, src_flags;
- struct sde_plane *psde;
struct sde_plane_state *pstate;
- struct sde_plane_rot_state *rstate;
- const struct sde_format *fmt;
- struct drm_crtc *crtc;
- struct drm_framebuffer *fb;
- struct sde_rect src, dst;
- const struct sde_rect *crtc_roi;
- bool q16_data = true;
- int idx;
- if (!plane) {
- SDE_ERROR("invalid plane\n");
- return -EINVAL;
- } else if (!plane->state) {
- SDE_ERROR("invalid plane state\n");
- return -EINVAL;
- }
+ if (!drm_state)
+ return;
- psde = to_sde_plane(plane);
- pstate = to_sde_plane_state(plane->state);
- rstate = &pstate->rot;
+ pstate = to_sde_plane_state(drm_state);
- crtc = state->crtc;
- fb = rstate->out_fb;
- if (!crtc || !fb) {
- SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
- crtc != 0, fb != 0);
- return -EINVAL;
- }
- fmt = to_sde_format(msm_framebuffer_format(fb));
- nplanes = fmt->num_planes;
-
- SDE_DEBUG(
- "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
- plane->base.id, rstate->sequence_id,
- rstate->out_fb_width, rstate->out_fb_height,
- (char *) &rstate->out_fb_pixel_format,
- rstate->out_fb_modifier[0],
- rstate->out_src_w >> 16, rstate->out_src_h >> 16,
- rstate->out_src_x >> 16, rstate->out_src_y >> 16,
- rstate->out_rotation,
- state->crtc_w, state->crtc_h,
- state->crtc_x, state->crtc_y);
-
- /* force reprogramming of all the parameters, if the flag is set */
- if (psde->revalidate) {
- SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
- plane->base.id);
- pstate->dirty = SDE_PLANE_DIRTY_ALL;
- psde->revalidate = false;
- }
-
- /* determine what needs to be refreshed */
- while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
- switch (idx) {
- case PLANE_PROP_SCALER_V1:
- case PLANE_PROP_SCALER_V2:
- case PLANE_PROP_H_DECIMATE:
- case PLANE_PROP_V_DECIMATE:
- case PLANE_PROP_SRC_CONFIG:
- case PLANE_PROP_ZPOS:
- case PLANE_PROP_EXCL_RECT_V1:
- pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
- break;
- case PLANE_PROP_CSC_V1:
- pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
- break;
- case PLANE_PROP_COLOR_FILL:
- /* potentially need to refresh everything */
- pstate->dirty = SDE_PLANE_DIRTY_ALL;
- break;
- case PLANE_PROP_ROTATION:
- pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
- break;
- case PLANE_PROP_INFO:
- case PLANE_PROP_ALPHA:
- case PLANE_PROP_INPUT_FENCE:
- case PLANE_PROP_BLEND_OP:
- /* no special action required */
- break;
- case PLANE_PROP_ROT_DST_X:
- case PLANE_PROP_ROT_DST_Y:
- case PLANE_PROP_ROT_DST_W:
- case PLANE_PROP_ROT_DST_H:
- /* handled by rotator atomic update */
- break;
- default:
- /* unknown property, refresh everything */
- pstate->dirty |= SDE_PLANE_DIRTY_ALL;
- SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
- break;
- }
- }
-
- /* re-program the output rects always in the case of partial update */
- sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
- if (!sde_kms_rect_is_null(crtc_roi))
- pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
-
- if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
- memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
-
- _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
-
- /* early out if nothing dirty */
- if (!pstate->dirty)
- return 0;
- pstate->pending = true;
-
- psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
- _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
-
- /* update roi config */
- if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
- POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
- rstate->out_src_w, rstate->out_src_h, q16_data);
- POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
- state->crtc_w, state->crtc_h, !q16_data);
-
- SDE_DEBUG_PLANE(psde,
- "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
- fb->base.id, src.x, src.y, src.w, src.h,
- crtc->base.id, dst.x, dst.y, dst.w, dst.h,
- (char *)&fmt->base.pixel_format,
- SDE_FORMAT_IS_UBWC(fmt));
-
- if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
- BIT(SDE_DRM_DEINTERLACE)) {
- SDE_DEBUG_PLANE(psde, "deinterlace\n");
- for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
- psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
- src.h /= 2;
- src.y = DIV_ROUND_UP(src.y, 2);
- src.y &= ~0x1;
- }
-
- /*
- * adjust layer mixer position of the sspp in the presence
- * of a partial update to the active lm origin
- */
- dst.x -= crtc_roi->x;
- dst.y -= crtc_roi->y;
-
- psde->pipe_cfg.src_rect = src;
- psde->pipe_cfg.dst_rect = dst;
-
- _sde_plane_setup_scaler(psde, fmt, pstate);
-
- /* check for color fill */
- psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
- PLANE_PROP_COLOR_FILL);
- if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
- /* skip remaining processing on color fill */
- pstate->dirty = 0x0;
- } else if (psde->pipe_hw->ops.setup_rects) {
- psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
- &psde->pipe_cfg,
- pstate->multirect_index);
- }
-
- if (psde->pipe_hw->ops.setup_pe)
- psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
- &psde->pixel_ext);
-
- if (psde->pipe_hw->ops.setup_scaler)
- psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
- &psde->pipe_cfg, &psde->pixel_ext,
- psde->scaler3_cfg);
-
- /* update excl rect */
- if (psde->pipe_hw->ops.setup_excl_rect)
- psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
- &pstate->excl_rect,
- pstate->multirect_index);
-
- if (psde->pipe_hw->ops.setup_multirect)
- psde->pipe_hw->ops.setup_multirect(
- psde->pipe_hw,
- pstate->multirect_index,
- pstate->multirect_mode);
- }
-
- if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
- psde->pipe_hw->ops.setup_format) {
- src_flags = 0x0;
- SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
- if (rstate->out_rotation & DRM_REFLECT_X)
- src_flags |= SDE_SSPP_FLIP_LR;
- if (rstate->out_rotation & DRM_REFLECT_Y)
- src_flags |= SDE_SSPP_FLIP_UD;
-
- /* update format */
- psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
- pstate->multirect_index);
-
- if (psde->pipe_hw->ops.setup_sys_cache) {
- if (rstate->out_sbuf) {
- if (rstate->nplane < 2)
- pstate->sc_cfg.op_mode =
- SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
- else if (rstate->out_xpos == 0)
- pstate->sc_cfg.op_mode =
- SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
- else
- pstate->sc_cfg.op_mode =
- SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
-
- pstate->sc_cfg.rd_en = true;
- pstate->sc_cfg.rd_scid =
- rstate->rot_hw->caps->scid;
- pstate->sc_cfg.rd_noallocate = true;
- pstate->sc_cfg.rd_op_type =
- SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
- } else {
- pstate->sc_cfg.op_mode =
- SDE_PIPE_SC_OP_MODE_OFFLINE;
- pstate->sc_cfg.rd_en = false;
- pstate->sc_cfg.rd_scid = 0;
- pstate->sc_cfg.rd_noallocate = false;
- pstate->sc_cfg.rd_op_type =
- SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
- }
-
- psde->pipe_hw->ops.setup_sys_cache(
- psde->pipe_hw, &pstate->sc_cfg);
- }
-
- /* update csc */
- if (SDE_FORMAT_IS_YUV(fmt))
- _sde_plane_setup_csc(psde);
- else
- psde->csc_ptr = 0;
- }
-
- sde_color_process_plane_setup(plane);
-
- /* update sharpening */
- if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
- psde->pipe_hw->ops.setup_sharpening) {
- psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
- psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
- psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
- psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
-
- psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
- &psde->sharp_cfg);
- }
-
- _sde_plane_set_qos_lut(plane, fb);
- _sde_plane_set_danger_lut(plane, fb);
-
- if (plane->type != DRM_PLANE_TYPE_CURSOR) {
- _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
- _sde_plane_set_ot_limit(plane, crtc);
- }
-
- /* clear dirty */
- pstate->dirty = 0x0;
-
- /* clear multirect mode*/
pstate->multirect_index = SDE_SSPP_RECT_SOLO;
pstate->multirect_mode = SDE_SSPP_MULTIRECT_NONE;
- return 0;
}
int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane)
@@ -2486,11 +2229,12 @@
struct sde_plane *sde_plane[R_MAX];
const struct sde_format *fmt[R_MAX];
bool q16_data = true;
- int i, max_sspp_linewidth;
- int buffer_lines = TX_MODE_BUFFER_LINE_THRES;
+ int i, buffer_lines = TX_MODE_BUFFER_LINE_THRES;
+ bool parallel_fetch_qualified = true;
for (i = 0; i < R_MAX; i++) {
const struct msm_format *msm_fmt;
+ int width_threshold;
drm_state[i] = i ? plane->r1 : plane->r0;
pstate[i] = to_sde_plane_state(drm_state[i]);
@@ -2521,15 +2265,27 @@
"Unsupported format for multirect mode\n");
return -EINVAL;
}
- }
- max_sspp_linewidth = sde_plane[R0]->pipe_sblk->maxlinewidth;
+ /**
+ * SSPP PD_MEM is split half - one for each RECT.
+ * Tiled formats need 5 lines of buffering while fetching
+ * whereas linear formats need only 2 lines.
+ * So we cannot support more than half of the supported SSPP
+ * width for tiled formats.
+ */
+ width_threshold = sde_plane[i]->pipe_sblk->maxlinewidth;
+ if (SDE_FORMAT_IS_UBWC(fmt[i]))
+ width_threshold /= 2;
+
+ if (parallel_fetch_qualified && src[i].w > width_threshold)
+ parallel_fetch_qualified = false;
+
+ }
/* Validate RECT's and set the mode */
/* Prefer PARALLEL FETCH Mode over TIME_MX Mode */
- if (src[R0].w <= max_sspp_linewidth/2 &&
- src[R1].w <= max_sspp_linewidth/2) {
+ if (parallel_fetch_qualified) {
if (dst[R0].x <= dst[R1].x) {
pstate[R0]->multirect_index = SDE_SSPP_RECT_0;
pstate[R1]->multirect_index = SDE_SSPP_RECT_1;
@@ -2564,6 +2320,10 @@
pstate[R0]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
pstate[R1]->multirect_mode = SDE_SSPP_MULTIRECT_TIME_MX;
done:
+ SDE_DEBUG_PLANE(sde_plane[R0], "R0: %d - %d\n",
+ pstate[R0]->multirect_mode, pstate[R0]->multirect_index);
+ SDE_DEBUG_PLANE(sde_plane[R1], "R1: %d - %d\n",
+ pstate[R1]->multirect_mode, pstate[R1]->multirect_index);
return 0;
}
@@ -2667,6 +2427,10 @@
} else if (to_sde_plane_state(old_state)->pending) {
SDE_DEBUG_PLANE(psde, "still pending\n");
pstate->dirty |= SDE_PLANE_DIRTY_ALL;
+ } else if (pstate->multirect_index != old_pstate->multirect_index ||
+ pstate->multirect_mode != old_pstate->multirect_mode) {
+ SDE_DEBUG_PLANE(psde, "multirect config updated\n");
+ pstate->dirty |= SDE_PLANE_DIRTY_ALL;
} else if (rstate->out_src_w != old_rstate->out_src_w ||
rstate->out_src_h != old_rstate->out_src_h ||
rstate->out_src_x != old_rstate->out_src_x ||
@@ -2685,10 +2449,6 @@
pstate->excl_rect.y != old_pstate->excl_rect.y) {
SDE_DEBUG_PLANE(psde, "excl rect updated\n");
pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
- } else if (pstate->multirect_index != old_pstate->multirect_index ||
- pstate->multirect_mode != old_pstate->multirect_mode) {
- SDE_DEBUG_PLANE(psde, "multirect config updated\n");
- pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
}
fb = rstate->out_fb;
@@ -2976,6 +2736,299 @@
to_sde_plane_state(plane->state)->pending = false;
}
+static int sde_plane_sspp_atomic_update(struct drm_plane *plane,
+ struct drm_plane_state *old_state)
+{
+ uint32_t nplanes, src_flags;
+ struct sde_plane *psde;
+ struct drm_plane_state *state;
+ struct sde_plane_state *pstate;
+ struct sde_plane_state *old_pstate;
+ struct sde_plane_rot_state *rstate;
+ const struct sde_format *fmt;
+ struct drm_crtc *crtc;
+ struct drm_framebuffer *fb;
+ struct sde_rect src, dst;
+ const struct sde_rect *crtc_roi;
+ bool q16_data = true;
+ int idx;
+
+ if (!plane) {
+ SDE_ERROR("invalid plane\n");
+ return -EINVAL;
+ } else if (!plane->state) {
+ SDE_ERROR("invalid plane state\n");
+ return -EINVAL;
+ } else if (!old_state) {
+ SDE_ERROR("invalid old state\n");
+ return -EINVAL;
+ }
+
+ psde = to_sde_plane(plane);
+ state = plane->state;
+
+ pstate = to_sde_plane_state(state);
+ rstate = &pstate->rot;
+
+ old_pstate = to_sde_plane_state(old_state);
+
+ crtc = state->crtc;
+ fb = rstate->out_fb;
+ if (!crtc || !fb) {
+ SDE_ERROR_PLANE(psde, "invalid crtc %d or fb %d\n",
+ crtc != 0, fb != 0);
+ return -EINVAL;
+ }
+ fmt = to_sde_format(msm_framebuffer_format(fb));
+ nplanes = fmt->num_planes;
+
+ SDE_DEBUG(
+ "plane%d.%d sspp:%dx%d/%4.4s/%llx/%dx%d+%d+%d/%x crtc:%dx%d+%d+%d\n",
+ plane->base.id, rstate->sequence_id,
+ rstate->out_fb_width, rstate->out_fb_height,
+ (char *) &rstate->out_fb_pixel_format,
+ rstate->out_fb_modifier[0],
+ rstate->out_src_w >> 16, rstate->out_src_h >> 16,
+ rstate->out_src_x >> 16, rstate->out_src_y >> 16,
+ rstate->out_rotation,
+ state->crtc_w, state->crtc_h,
+ state->crtc_x, state->crtc_y);
+
+ /* force reprogramming of all the parameters, if the flag is set */
+ if (psde->revalidate) {
+ SDE_DEBUG("plane:%d - reconfigure all the parameters\n",
+ plane->base.id);
+ pstate->dirty = SDE_PLANE_DIRTY_ALL;
+ psde->revalidate = false;
+ }
+
+ /* determine what needs to be refreshed */
+ while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
+ switch (idx) {
+ case PLANE_PROP_SCALER_V1:
+ case PLANE_PROP_SCALER_V2:
+ case PLANE_PROP_H_DECIMATE:
+ case PLANE_PROP_V_DECIMATE:
+ case PLANE_PROP_SRC_CONFIG:
+ case PLANE_PROP_ZPOS:
+ case PLANE_PROP_EXCL_RECT_V1:
+ pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
+ break;
+ case PLANE_PROP_CSC_V1:
+ pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
+ break;
+ case PLANE_PROP_COLOR_FILL:
+ /* potentially need to refresh everything */
+ pstate->dirty = SDE_PLANE_DIRTY_ALL;
+ break;
+ case PLANE_PROP_ROTATION:
+ pstate->dirty |= SDE_PLANE_DIRTY_FORMAT;
+ break;
+ case PLANE_PROP_INFO:
+ case PLANE_PROP_ALPHA:
+ case PLANE_PROP_INPUT_FENCE:
+ case PLANE_PROP_BLEND_OP:
+ /* no special action required */
+ break;
+ case PLANE_PROP_ROT_DST_X:
+ case PLANE_PROP_ROT_DST_Y:
+ case PLANE_PROP_ROT_DST_W:
+ case PLANE_PROP_ROT_DST_H:
+ /* handled by rotator atomic update */
+ break;
+ default:
+ /* unknown property, refresh everything */
+ pstate->dirty |= SDE_PLANE_DIRTY_ALL;
+ SDE_ERROR("executing full mode set, prp_idx %d\n", idx);
+ break;
+ }
+ }
+
+ /**
+ * since plane_atomic_check is invoked before crtc_atomic_check
+ * in the commit sequence, all the parameters for updating the
+ * plane dirty flag will not be available during
+ * plane_atomic_check as some features params are updated
+ * in crtc_atomic_check (eg.:sDMA). So check for mode_change
+ * before sspp update.
+ */
+ _sde_plane_sspp_atomic_check_mode_changed(psde, state,
+ old_state);
+
+ /* re-program the output rects always in the case of partial update */
+ sde_crtc_get_crtc_roi(crtc->state, &crtc_roi);
+ if (!sde_kms_rect_is_null(crtc_roi))
+ pstate->dirty |= SDE_PLANE_DIRTY_RECTS;
+
+ if (pstate->dirty & SDE_PLANE_DIRTY_RECTS)
+ memset(&(psde->pipe_cfg), 0, sizeof(struct sde_hw_pipe_cfg));
+
+ _sde_plane_set_scanout(plane, pstate, &psde->pipe_cfg, fb);
+
+ /* early out if nothing dirty */
+ if (!pstate->dirty)
+ return 0;
+ pstate->pending = true;
+
+ psde->is_rt_pipe = (sde_crtc_get_client_type(crtc) != NRT_CLIENT);
+ _sde_plane_set_qos_ctrl(plane, false, SDE_PLANE_QOS_PANIC_CTRL);
+
+ /* update roi config */
+ if (pstate->dirty & SDE_PLANE_DIRTY_RECTS) {
+ POPULATE_RECT(&src, rstate->out_src_x, rstate->out_src_y,
+ rstate->out_src_w, rstate->out_src_h, q16_data);
+ POPULATE_RECT(&dst, state->crtc_x, state->crtc_y,
+ state->crtc_w, state->crtc_h, !q16_data);
+
+ SDE_DEBUG_PLANE(psde,
+ "FB[%u] %u,%u,%ux%u->crtc%u %d,%d,%ux%u, %4.4s ubwc %d\n",
+ fb->base.id, src.x, src.y, src.w, src.h,
+ crtc->base.id, dst.x, dst.y, dst.w, dst.h,
+ (char *)&fmt->base.pixel_format,
+ SDE_FORMAT_IS_UBWC(fmt));
+
+ if (sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
+ BIT(SDE_DRM_DEINTERLACE)) {
+ SDE_DEBUG_PLANE(psde, "deinterlace\n");
+ for (idx = 0; idx < SDE_MAX_PLANES; ++idx)
+ psde->pipe_cfg.layout.plane_pitch[idx] <<= 1;
+ src.h /= 2;
+ src.y = DIV_ROUND_UP(src.y, 2);
+ src.y &= ~0x1;
+ }
+
+ /*
+ * adjust layer mixer position of the sspp in the presence
+ * of a partial update to the active lm origin
+ */
+ dst.x -= crtc_roi->x;
+ dst.y -= crtc_roi->y;
+
+ psde->pipe_cfg.src_rect = src;
+ psde->pipe_cfg.dst_rect = dst;
+
+ _sde_plane_setup_scaler(psde, fmt, pstate);
+
+ /* check for color fill */
+ psde->color_fill = (uint32_t)sde_plane_get_property(pstate,
+ PLANE_PROP_COLOR_FILL);
+ if (psde->color_fill & SDE_PLANE_COLOR_FILL_FLAG) {
+ /* skip remaining processing on color fill */
+ pstate->dirty = 0x0;
+ } else if (psde->pipe_hw->ops.setup_rects) {
+ psde->pipe_hw->ops.setup_rects(psde->pipe_hw,
+ &psde->pipe_cfg,
+ pstate->multirect_index);
+ }
+
+ if (psde->pipe_hw->ops.setup_pe)
+ psde->pipe_hw->ops.setup_pe(psde->pipe_hw,
+ &psde->pixel_ext);
+
+ /**
+ * when programmed in multirect mode, scalar block will be
+ * bypassed. Still we need to update alpha and bitwidth
+ * ONLY for RECT0
+ */
+ if (psde->pipe_hw->ops.setup_scaler &&
+ pstate->multirect_index != SDE_SSPP_RECT_1)
+ psde->pipe_hw->ops.setup_scaler(psde->pipe_hw,
+ &psde->pipe_cfg, &psde->pixel_ext,
+ psde->scaler3_cfg);
+
+ /* update excl rect */
+ if (psde->pipe_hw->ops.setup_excl_rect)
+ psde->pipe_hw->ops.setup_excl_rect(psde->pipe_hw,
+ &pstate->excl_rect,
+ pstate->multirect_index);
+
+ if (psde->pipe_hw->ops.setup_multirect)
+ psde->pipe_hw->ops.setup_multirect(
+ psde->pipe_hw,
+ pstate->multirect_index,
+ pstate->multirect_mode);
+ }
+
+ if ((pstate->dirty & SDE_PLANE_DIRTY_FORMAT) &&
+ psde->pipe_hw->ops.setup_format) {
+ src_flags = 0x0;
+ SDE_DEBUG_PLANE(psde, "rotation 0x%X\n", rstate->out_rotation);
+ if (rstate->out_rotation & DRM_REFLECT_X)
+ src_flags |= SDE_SSPP_FLIP_LR;
+ if (rstate->out_rotation & DRM_REFLECT_Y)
+ src_flags |= SDE_SSPP_FLIP_UD;
+
+ /* update format */
+ psde->pipe_hw->ops.setup_format(psde->pipe_hw, fmt, src_flags,
+ pstate->multirect_index);
+
+ if (psde->pipe_hw->ops.setup_sys_cache) {
+ if (rstate->out_sbuf) {
+ if (rstate->nplane < 2)
+ pstate->sc_cfg.op_mode =
+ SDE_PIPE_SC_OP_MODE_INLINE_SINGLE;
+ else if (rstate->out_xpos == 0)
+ pstate->sc_cfg.op_mode =
+ SDE_PIPE_SC_OP_MODE_INLINE_LEFT;
+ else
+ pstate->sc_cfg.op_mode =
+ SDE_PIPE_SC_OP_MODE_INLINE_RIGHT;
+
+ pstate->sc_cfg.rd_en = true;
+ pstate->sc_cfg.rd_scid =
+ rstate->rot_hw->caps->scid;
+ pstate->sc_cfg.rd_noallocate = true;
+ pstate->sc_cfg.rd_op_type =
+ SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
+ } else {
+ pstate->sc_cfg.op_mode =
+ SDE_PIPE_SC_OP_MODE_OFFLINE;
+ pstate->sc_cfg.rd_en = false;
+ pstate->sc_cfg.rd_scid = 0;
+ pstate->sc_cfg.rd_noallocate = false;
+ pstate->sc_cfg.rd_op_type =
+ SDE_PIPE_SC_RD_OP_TYPE_CACHEABLE;
+ }
+
+ psde->pipe_hw->ops.setup_sys_cache(
+ psde->pipe_hw, &pstate->sc_cfg);
+ }
+
+ /* update csc */
+ if (SDE_FORMAT_IS_YUV(fmt))
+ _sde_plane_setup_csc(psde);
+ else
+ psde->csc_ptr = 0;
+ }
+
+ sde_color_process_plane_setup(plane);
+
+ /* update sharpening */
+ if ((pstate->dirty & SDE_PLANE_DIRTY_SHARPEN) &&
+ psde->pipe_hw->ops.setup_sharpening) {
+ psde->sharp_cfg.strength = SHARP_STRENGTH_DEFAULT;
+ psde->sharp_cfg.edge_thr = SHARP_EDGE_THR_DEFAULT;
+ psde->sharp_cfg.smooth_thr = SHARP_SMOOTH_THR_DEFAULT;
+ psde->sharp_cfg.noise_thr = SHARP_NOISE_THR_DEFAULT;
+
+ psde->pipe_hw->ops.setup_sharpening(psde->pipe_hw,
+ &psde->sharp_cfg);
+ }
+
+ _sde_plane_set_qos_lut(plane, fb);
+ _sde_plane_set_danger_lut(plane, fb);
+
+ if (plane->type != DRM_PLANE_TYPE_CURSOR) {
+ _sde_plane_set_qos_ctrl(plane, true, SDE_PLANE_QOS_PANIC_CTRL);
+ _sde_plane_set_ot_limit(plane, crtc);
+ }
+
+ /* clear dirty */
+ pstate->dirty = 0x0;
+
+ return 0;
+}
+
static void sde_plane_atomic_update(struct drm_plane *plane,
struct drm_plane_state *old_state)
{
@@ -3007,7 +3060,7 @@
} else {
int ret;
- ret = sde_plane_sspp_atomic_update(plane, state);
+ ret = sde_plane_sspp_atomic_update(plane, old_state);
/* atomic_check should have ensured that this doesn't fail */
WARN_ON(ret < 0);
}
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index ac70542..2056a70 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -207,10 +207,15 @@
* against hw limitations
* @plane: drm plate states of the multirect pair
*/
-
int sde_plane_validate_multirect_v2(struct sde_multirect_plane_states *plane);
/**
+ * sde_plane_clear_multirect - clear multirect bits for the given pipe
+ * @drm_state: Pointer to DRM plane state
+ */
+void sde_plane_clear_multirect(const struct drm_plane_state *drm_state);
+
+/**
* sde_plane_wait_input_fence - wait for input fence object
* @plane: Pointer to DRM plane object
* @wait_ms: Wait timeout value
diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h
index da68139..38bf21f 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.h
+++ b/drivers/gpu/drm/msm/sde_power_handle.h
@@ -16,9 +16,9 @@
#define MAX_CLIENT_NAME_LEN 128
-#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA 2000000
+#define SDE_POWER_HANDLE_ENABLE_BUS_AB_QUOTA 6000000000
#define SDE_POWER_HANDLE_DISABLE_BUS_AB_QUOTA 0
-#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 2000000
+#define SDE_POWER_HANDLE_ENABLE_BUS_IB_QUOTA 6000000000
#define SDE_POWER_HANDLE_DISABLE_BUS_IB_QUOTA 0
#include <linux/sde_io_util.h>
diff --git a/drivers/gpu/drm/msm/sde_rsc.c b/drivers/gpu/drm/msm/sde_rsc.c
index 3413ee7..50710cd 100644
--- a/drivers/gpu/drm/msm/sde_rsc.c
+++ b/drivers/gpu/drm/msm/sde_rsc.c
@@ -416,6 +416,11 @@
if (config)
sde_rsc_timer_calculate(rsc, config);
+ if (rsc->current_state == SDE_RSC_CMD_STATE) {
+ rc = 0;
+ goto vsync_wait;
+ }
+
/* any one client in video state blocks the cmd state switch */
list_for_each_entry(client, &rsc->client_list, list)
if (client->current_state == SDE_RSC_VID_STATE)
@@ -427,8 +432,10 @@
rpmh_mode_solver_set(rsc->disp_rsc, true);
}
- /* wait for vsync for vid to cmd state switch */
- if (!rc && (rsc->current_state == SDE_RSC_VID_STATE))
+vsync_wait:
+ /* wait for vsync for vid to cmd state switch and config update */
+ if (!rc && (rsc->current_state == SDE_RSC_VID_STATE ||
+ rsc->current_state == SDE_RSC_CMD_STATE))
drm_wait_one_vblank(rsc->master_drm,
rsc->primary_client->crtc_id);
end:
@@ -470,6 +477,10 @@
if (config && (caller_client == rsc->primary_client))
sde_rsc_timer_calculate(rsc, config);
+ /* early exit without vsync wait for vid state */
+ if (rsc->current_state == SDE_RSC_VID_STATE)
+ goto end;
+
/* video state switch should be done immediately */
if (rsc->hw_ops.state_update) {
rc = rsc->hw_ops.state_update(rsc, SDE_RSC_VID_STATE);
@@ -482,6 +493,8 @@
(rsc->current_state == SDE_RSC_CMD_STATE))
drm_wait_one_vblank(rsc->master_drm,
rsc->primary_client->crtc_id);
+
+end:
return rc;
}
diff --git a/drivers/gpu/msm/a6xx_reg.h b/drivers/gpu/msm/a6xx_reg.h
index 6db0111..e5cfd69 100644
--- a/drivers/gpu/msm/a6xx_reg.h
+++ b/drivers/gpu/msm/a6xx_reg.h
@@ -381,6 +381,7 @@
#define A6XX_RBBM_PERFCTR_RBBM_SEL_1 0x508
#define A6XX_RBBM_PERFCTR_RBBM_SEL_2 0x509
#define A6XX_RBBM_PERFCTR_RBBM_SEL_3 0x50A
+#define A6XX_RBBM_PERFCTR_GPU_BUSY_MASKED 0x50B
#define A6XX_RBBM_ISDB_CNT 0x533
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 98ca77f..24b5faa 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -385,6 +385,10 @@
adreno_vbif_start(adreno_dev, a6xx_vbif_platforms,
ARRAY_SIZE(a6xx_vbif_platforms));
+
+ /* Make all blocks contribute to the GPU BUSY perf counter */
+ kgsl_regwrite(device, A6XX_RBBM_PERFCTR_GPU_BUSY_MASKED, 0xFFFFFFFF);
+
/*
* Set UCHE_WRITE_THRU_BASE to the UCHE_TRAP_BASE effectively
* disabling L2 bypass
diff --git a/drivers/gpu/msm/adreno_a6xx_snapshot.c b/drivers/gpu/msm/adreno_a6xx_snapshot.c
index 63dbde0..17ee6e6 100644
--- a/drivers/gpu/msm/adreno_a6xx_snapshot.c
+++ b/drivers/gpu/msm/adreno_a6xx_snapshot.c
@@ -640,6 +640,9 @@
unsigned int *data = (unsigned int *)(buf + sizeof(*header));
int i, j;
+ if (!device->snapshot_legacy)
+ return 0;
+
if (remain < sizeof(*header)) {
SNAPSHOT_ERR_NOMEM(device, "REGISTERS");
return 0;
@@ -748,6 +751,9 @@
unsigned int read_sel;
int i, j;
+ if (!device->snapshot_legacy)
+ return 0;
+
/* Figure out how many registers we are going to dump */
for (i = 0; i < regs->num_sets; i++) {
int start = regs->regs[i * 2];
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 876b668..be379e3 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -291,6 +291,8 @@
/* Use CP Crash dumper to get GPU snapshot*/
bool snapshot_crashdumper;
+ /* Use HOST side register reads to get GPU snapshot*/
+ bool snapshot_legacy;
struct kobject snapshot_kobj;
diff --git a/drivers/gpu/msm/kgsl_hfi.c b/drivers/gpu/msm/kgsl_hfi.c
index 30e1d7c..b05e18d 100644
--- a/drivers/gpu/msm/kgsl_hfi.c
+++ b/drivers/gpu/msm/kgsl_hfi.c
@@ -573,44 +573,41 @@
if (result)
return result;
- if (boot_state == GMU_COLD_BOOT) {
- major = adreno_dev->gpucore->gpmu_major;
- minor = adreno_dev->gpucore->gpmu_minor;
+ major = adreno_dev->gpucore->gpmu_major;
+ minor = adreno_dev->gpucore->gpmu_minor;
+ result = hfi_get_fw_version(gmu,
+ FW_VERSION(major, minor), &ver);
+ if (result)
+ dev_err(dev, "Failed to get FW version via HFI\n");
- result = hfi_get_fw_version(gmu,
- FW_VERSION(major, minor), &ver);
- if (result)
- dev_err(dev, "Failed to get FW version via HFI\n");
+ gmu->ver = ver;
+ if (major != FW_VER_MAJOR(ver))
+ dev_err(dev, "FW version major %d error (expect %d)\n",
+ FW_VER_MAJOR(ver),
+ adreno_dev->gpucore->gpmu_major);
- gmu->ver = ver;
- if (major != FW_VER_MAJOR(ver))
- dev_err(dev, "FW version major %d error (expect %d)\n",
- FW_VER_MAJOR(ver),
- adreno_dev->gpucore->gpmu_major);
+ if (minor > FW_VER_MINOR(ver))
+ dev_err(dev, "FW version minor %d error (expect %d)\n",
+ FW_VER_MINOR(ver),
+ adreno_dev->gpucore->gpmu_minor);
- if (minor > FW_VER_MINOR(ver))
- dev_err(dev, "FW version minor %d error (expect %d)\n",
- FW_VER_MINOR(ver),
- adreno_dev->gpucore->gpmu_minor);
+ result = hfi_send_perftbl(gmu);
+ if (result)
+ return result;
- result = hfi_send_perftbl(gmu);
- if (result)
- return result;
+ result = hfi_send_bwtbl(gmu);
+ if (result)
+ return result;
- result = hfi_send_bwtbl(gmu);
- if (result)
- return result;
-
- /*
- * FW is not ready for LM configuration
- * without powering on GPU.
- */
- /*
- * result = hfi_send_lmconfig(gmu);
- * if (result)
- * return result;
- */
- }
+ /*
+ * FW is not ready for LM configuration
+ * without powering on GPU.
+ */
+ /*
+ * result = hfi_send_lmconfig(gmu);
+ * if (result)
+ * return result;
+ */
set_bit(GMU_HFI_ON, &gmu->flags);
return 0;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 40d239c..7cbda72 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -875,6 +875,25 @@
return snprintf(buf, PAGE_SIZE, "%lu\n", timestamp);
}
+static ssize_t snapshot_legacy_show(struct kgsl_device *device, char *buf)
+{
+ return snprintf(buf, PAGE_SIZE, "%d\n", device->snapshot_legacy);
+}
+
+static ssize_t snapshot_legacy_store(struct kgsl_device *device,
+ const char *buf, size_t count)
+{
+ unsigned int val = 0;
+ int ret;
+
+ ret = kgsl_sysfs_store(buf, &val);
+
+ if (!ret && device)
+ device->snapshot_legacy = (bool)val;
+
+ return (ssize_t) ret < 0 ? ret : count;
+}
+
static struct bin_attribute snapshot_attr = {
.attr.name = "dump",
.attr.mode = 0444,
@@ -894,6 +913,8 @@
static SNAPSHOT_ATTR(force_panic, 0644, force_panic_show, force_panic_store);
static SNAPSHOT_ATTR(snapshot_crashdumper, 0644, snapshot_crashdumper_show,
snapshot_crashdumper_store);
+static SNAPSHOT_ATTR(snapshot_legacy, 0644, snapshot_legacy_show,
+ snapshot_legacy_store);
static ssize_t snapshot_sysfs_show(struct kobject *kobj,
struct attribute *attr, char *buf)
@@ -975,6 +996,7 @@
device->snapshot_faultcount = 0;
device->force_panic = 0;
device->snapshot_crashdumper = 1;
+ device->snapshot_legacy = 0;
ret = kobject_init_and_add(&device->snapshot_kobj, &ktype_snapshot,
&device->dev->kobj, "snapshot");
@@ -1000,6 +1022,12 @@
ret = sysfs_create_file(&device->snapshot_kobj,
&attr_snapshot_crashdumper.attr);
+ if (ret)
+ goto done;
+
+ ret = sysfs_create_file(&device->snapshot_kobj,
+ &attr_snapshot_legacy.attr);
+
done:
return ret;
}
diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index c5ab866..2db0d64 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -432,13 +432,12 @@
return ret;
}
-dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size, int prot)
+static dma_addr_t __iommu_dma_map(struct device *dev, phys_addr_t phys,
+ size_t size, int prot)
{
dma_addr_t dma_addr;
struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
struct iova_domain *iovad = cookie_iovad(domain);
- phys_addr_t phys = page_to_phys(page) + offset;
size_t iova_off = iova_offset(iovad, phys);
size_t len = iova_align(iovad, size + iova_off);
struct iova *iova = __alloc_iova(domain, len, dma_get_mask(dev));
@@ -454,6 +453,12 @@
return dma_addr + iova_off;
}
+dma_addr_t iommu_dma_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size, int prot)
+{
+ return __iommu_dma_map(dev, page_to_phys(page) + offset, size, prot);
+}
+
void iommu_dma_unmap_page(struct device *dev, dma_addr_t handle, size_t size,
enum dma_data_direction dir, unsigned long attrs)
{
@@ -624,6 +629,19 @@
__iommu_dma_unmap(iommu_get_domain_for_dev(dev), sg_dma_address(sg));
}
+dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+ return __iommu_dma_map(dev, phys, size,
+ dma_direction_to_prot(dir, false) | IOMMU_MMIO);
+}
+
+void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
+ size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+ __iommu_dma_unmap(iommu_get_domain_for_dev(dev), handle);
+}
+
int iommu_dma_supported(struct device *dev, u64 mask)
{
/*
diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c
index 8ba6da4..ac3059d 100644
--- a/drivers/iommu/dma-mapping-fast.c
+++ b/drivers/iommu/dma-mapping-fast.c
@@ -611,6 +611,55 @@
return ret;
}
+static dma_addr_t fast_smmu_dma_map_resource(
+ struct device *dev, phys_addr_t phys_addr,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs)
+{
+ struct dma_fast_smmu_mapping *mapping = dev->archdata.mapping->fast;
+ size_t offset = phys_addr & ~FAST_PAGE_MASK;
+ size_t len = round_up(size + offset, FAST_PAGE_SIZE);
+ dma_addr_t dma_addr;
+ int prot;
+ unsigned long flags;
+
+ spin_lock_irqsave(&mapping->lock, flags);
+ dma_addr = __fast_smmu_alloc_iova(mapping, attrs, len);
+ spin_unlock_irqrestore(&mapping->lock, flags);
+
+ if (dma_addr == DMA_ERROR_CODE)
+ return dma_addr;
+
+ prot = __fast_dma_direction_to_prot(dir);
+ prot |= IOMMU_MMIO;
+
+ if (iommu_map(mapping->domain, dma_addr, phys_addr - offset,
+ len, prot)) {
+ spin_lock_irqsave(&mapping->lock, flags);
+ __fast_smmu_free_iova(mapping, dma_addr, len);
+ spin_unlock_irqrestore(&mapping->lock, flags);
+ return DMA_ERROR_CODE;
+ }
+ return dma_addr + offset;
+}
+
+static void fast_smmu_dma_unmap_resource(
+ struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ unsigned long attrs)
+{
+ struct dma_fast_smmu_mapping *mapping = dev->archdata.mapping->fast;
+ size_t offset = addr & ~FAST_PAGE_MASK;
+ size_t len = round_up(size + offset, FAST_PAGE_SIZE);
+ unsigned long flags;
+
+ iommu_unmap(mapping->domain, addr - offset, len);
+ spin_lock_irqsave(&mapping->lock, flags);
+ __fast_smmu_free_iova(mapping, addr, len);
+ spin_unlock_irqrestore(&mapping->lock, flags);
+}
+
+
static int fast_smmu_dma_supported(struct device *dev, u64 mask)
{
return mask <= 0xffffffff;
@@ -667,6 +716,8 @@
.unmap_sg = fast_smmu_unmap_sg,
.sync_sg_for_cpu = fast_smmu_sync_sg_for_cpu,
.sync_sg_for_device = fast_smmu_sync_sg_for_device,
+ .map_resource = fast_smmu_dma_map_resource,
+ .unmap_resource = fast_smmu_dma_unmap_resource,
.dma_supported = fast_smmu_dma_supported,
.mapping_error = fast_smmu_mapping_error,
};
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index 7a03bdc..c837232 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -974,7 +974,7 @@
del_req_id, rc);
}
} else {
- pr_err("%s:%d Invalid/NOP request to apply: %lld\n",
+ CDBG("%s:%d Invalid/NOP request to apply: %lld\n",
__func__, __LINE__, req_id);
}
}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c
index 1709fd3..40a69ef 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_cci_i2c.c
@@ -146,11 +146,9 @@
for (i = 0; i < delay_ms; i++) {
rc = cam_cci_i2c_compare(client,
addr, data, data_mask, data_type, addr_type);
- if (!rc) {
- pr_err("%s:%d Fail in comparing the data in poll\n",
- __func__, __LINE__);
+ if (!rc)
return rc;
- }
+
usleep_range(1000, 1010);
}
diff --git a/drivers/media/platform/msm/vidc/Kconfig b/drivers/media/platform/msm/vidc/Kconfig
index db12cae..d6297d4 100644
--- a/drivers/media/platform/msm/vidc/Kconfig
+++ b/drivers/media/platform/msm/vidc/Kconfig
@@ -7,5 +7,4 @@
depends on ARCH_QCOM && VIDEO_V4L2
select VIDEOBUF2_CORE
-source "drivers/media/platform/msm/vidc/vmem/Kconfig"
source "drivers/media/platform/msm/vidc/governors/Kconfig"
diff --git a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
index 12b5b04..f7ce757 100644
--- a/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
+++ b/drivers/media/platform/msm/vidc/governors/msm_vidc_dyn_gov.c
@@ -22,8 +22,7 @@
enum governor_mode {
GOVERNOR_DDR,
- GOVERNOR_VMEM,
- GOVERNOR_VMEM_PLUS,
+ GOVERNOR_LLCC,
};
struct governor {
@@ -275,38 +274,6 @@
}
}
-static unsigned long __calculate_vmem_plus_ab(struct vidc_bus_vote_data *d)
-{
- unsigned long i = 0, vmem_plus = 0;
-
- if (!d->imem_ab_tbl || !d->imem_ab_tbl_size) {
- vmem_plus = 1; /* Vote for the min ab value */
- goto exit;
- }
-
- /* Pick up vmem frequency based on venus core frequency */
- for (i = 0; i < d->imem_ab_tbl_size; i++) {
- if (d->imem_ab_tbl[i].core_freq == d->core_freq) {
- vmem_plus = d->imem_ab_tbl[i].imem_ab;
- break;
- }
- }
-
- /*
- * Incase we get an unsupported freq throw a warning
- * and set ab to the minimum value.
- */
- if (!vmem_plus) {
- vmem_plus = 1;
- dprintk(VIDC_WARN,
- "could not calculate vmem ab value due to core freq mismatch\n");
- WARN_ON(1);
- }
-
-exit:
- return vmem_plus;
-}
-
static unsigned long __calculate_decoder(struct vidc_bus_vote_data *d,
enum governor_mode gm) {
/*
@@ -611,12 +578,9 @@
case GOVERNOR_DDR:
ret = kbps(fp_round(ddr.total));
break;
- case GOVERNOR_VMEM:
+ case GOVERNOR_LLCC:
ret = kbps(fp_round(vmem.total));
break;
- case GOVERNOR_VMEM_PLUS:
- ret = __calculate_vmem_plus_ab(d);
- break;
default:
dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
}
@@ -1016,12 +980,9 @@
case GOVERNOR_DDR:
ret = kbps(fp_round(ddr.total));
break;
- case GOVERNOR_VMEM:
+ case GOVERNOR_LLCC:
ret = kbps(fp_round(vmem.total));
break;
- case GOVERNOR_VMEM_PLUS:
- ret = __calculate_vmem_plus_ab(d);
- break;
default:
dprintk(VIDC_ERR, "%s - Unknown governor\n", __func__);
}
@@ -1107,17 +1068,9 @@
},
},
{
- .mode = GOVERNOR_VMEM,
+ .mode = GOVERNOR_LLCC,
.devfreq_gov = {
- .name = "msm-vidc-vmem",
- .get_target_freq = __get_target_freq,
- .event_handler = __event_handler,
- },
- },
- {
- .mode = GOVERNOR_VMEM_PLUS,
- .devfreq_gov = {
- .name = "msm-vidc-vmem+",
+ .name = "msm-vidc-llcc",
.get_target_freq = __get_target_freq,
.event_handler = __event_handler,
},
diff --git a/drivers/media/platform/msm/vidc/hfi_packetization.c b/drivers/media/platform/msm/vidc/hfi_packetization.c
index 9331c94..a477340 100644
--- a/drivers/media/platform/msm/vidc/hfi_packetization.c
+++ b/drivers/media/platform/msm/vidc/hfi_packetization.c
@@ -332,37 +332,56 @@
int create_pkt_cmd_sys_set_resource(
struct hfi_cmd_sys_set_resource_packet *pkt,
- struct vidc_resource_hdr *resource_hdr,
- void *resource_value)
+ struct vidc_resource_hdr *res_hdr,
+ void *res_value)
{
int rc = 0;
+ u32 i = 0;
- if (!pkt || !resource_hdr || !resource_value)
+ if (!pkt || !res_hdr || !res_value) {
+ dprintk(VIDC_ERR,
+ "Invalid paramas pkt %pK res_hdr %pK res_value %pK\n",
+ pkt, res_hdr, res_value);
return -EINVAL;
+ }
pkt->packet_type = HFI_CMD_SYS_SET_RESOURCE;
pkt->size = sizeof(struct hfi_cmd_sys_set_resource_packet);
- pkt->resource_handle = hash32_ptr(resource_hdr->resource_handle);
+ pkt->resource_handle = hash32_ptr(res_hdr->resource_handle);
- switch (resource_hdr->resource_id) {
- case VIDC_RESOURCE_OCMEM:
- case VIDC_RESOURCE_VMEM:
+ switch (res_hdr->resource_id) {
+ case VIDC_RESOURCE_SYSCACHE:
{
- struct hfi_resource_ocmem *hfioc_mem =
- (struct hfi_resource_ocmem *)
- &pkt->rg_resource_data[0];
+ struct hfi_resource_syscache_info_type *res_sc_info =
+ (struct hfi_resource_syscache_info_type *) res_value;
+ struct hfi_resource_subcache_type *res_sc =
+ (struct hfi_resource_subcache_type *)
+ &(res_sc_info->rg_subcache_entries[0]);
- phys_addr_t imem_addr = (phys_addr_t)resource_value;
+ struct hfi_resource_syscache_info_type *hfi_sc_info =
+ (struct hfi_resource_syscache_info_type *)
+ &pkt->rg_resource_data[0];
- pkt->resource_type = HFI_RESOURCE_OCMEM;
- pkt->size += sizeof(struct hfi_resource_ocmem) - sizeof(u32);
- hfioc_mem->size = (u32)resource_hdr->size;
- hfioc_mem->mem = imem_addr;
+ struct hfi_resource_subcache_type *hfi_sc =
+ (struct hfi_resource_subcache_type *)
+ &(hfi_sc_info->rg_subcache_entries[0]);
+
+ pkt->resource_type = HFI_RESOURCE_SYSCACHE;
+ hfi_sc_info->num_entries = res_sc_info->num_entries;
+
+ pkt->size += (sizeof(struct hfi_resource_subcache_type))
+ * hfi_sc_info->num_entries;
+
+ for (i = 0; i < hfi_sc_info->num_entries; i++) {
+ hfi_sc[i] = res_sc[i];
+ dprintk(VIDC_DBG, "entry hfi#%d, sc_id %d, size %d\n",
+ i, hfi_sc[i].sc_id, hfi_sc[i].size);
+ }
break;
}
default:
- dprintk(VIDC_ERR, "Invalid resource_id %d\n",
- resource_hdr->resource_id);
+ dprintk(VIDC_ERR,
+ "Invalid resource_id %d\n", res_hdr->resource_id);
rc = -ENOTSUPP;
}
@@ -371,28 +390,35 @@
int create_pkt_cmd_sys_release_resource(
struct hfi_cmd_sys_release_resource_packet *pkt,
- struct vidc_resource_hdr *resource_hdr)
+ struct vidc_resource_hdr *res_hdr)
{
int rc = 0;
- if (!pkt)
+ if (!pkt || !res_hdr) {
+ dprintk(VIDC_ERR,
+ "Invalid paramas pkt %pK res_hdr %pK\n",
+ pkt, res_hdr);
return -EINVAL;
+ }
pkt->size = sizeof(struct hfi_cmd_sys_release_resource_packet);
pkt->packet_type = HFI_CMD_SYS_RELEASE_RESOURCE;
- pkt->resource_handle = hash32_ptr(resource_hdr->resource_handle);
+ pkt->resource_handle = hash32_ptr(res_hdr->resource_handle);
- switch (resource_hdr->resource_id) {
- case VIDC_RESOURCE_OCMEM:
- case VIDC_RESOURCE_VMEM:
- pkt->resource_type = HFI_RESOURCE_OCMEM;
+ switch (res_hdr->resource_id) {
+ case VIDC_RESOURCE_SYSCACHE:
+ pkt->resource_type = HFI_RESOURCE_SYSCACHE;
break;
default:
- dprintk(VIDC_ERR, "Invalid resource_id %d\n",
- resource_hdr->resource_id);
+ dprintk(VIDC_ERR,
+ "Invalid resource_id %d\n", res_hdr->resource_id);
rc = -ENOTSUPP;
}
+ dprintk(VIDC_DBG,
+ "rel_res: pkt_type 0x%x res_type 0x%x prepared\n",
+ pkt->packet_type, pkt->resource_type);
+
return rc;
}
@@ -1837,6 +1863,14 @@
pkt->size += sizeof(u32) + sizeof(*work_mode);
break;
}
+ case HAL_PARAM_USE_SYS_CACHE:
+ {
+ create_pkt_enable(pkt->rg_property_data,
+ HFI_PROPERTY_PARAM_USE_SYS_CACHE,
+ (((struct hal_enable *) pdata)->enable));
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
/* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
case HAL_CONFIG_BUFFER_REQUIREMENTS:
case HAL_CONFIG_PRIORITY:
diff --git a/drivers/media/platform/msm/vidc/msm_smem.c b/drivers/media/platform/msm/vidc/msm_smem.c
index 19a1e3f..3d3d567 100644
--- a/drivers/media/platform/msm/vidc/msm_smem.c
+++ b/drivers/media/platform/msm/vidc/msm_smem.c
@@ -94,9 +94,11 @@
trace_msm_smem_buffer_iommu_op_start("MAP", 0, 0,
align, *iova, *buffer_size);
- /* Map a scatterlist into an SMMU */
- rc = msm_dma_map_sg_lazy(cb->dev, table->sgl, table->nents,
- DMA_BIDIRECTIONAL, buf);
+ /* Map a scatterlist into an SMMU with system cacheability */
+ rc = msm_dma_map_sg_attrs(cb->dev, table->sgl,
+ table->nents, DMA_BIDIRECTIONAL,
+ buf, DMA_ATTR_IOMMU_USE_UPSTREAM_HINT);
+
if (rc != table->nents) {
dprintk(VIDC_ERR,
"Mapping failed with rc(%d), expected rc(%d)\n",
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 89da0a1..2289b23 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1449,6 +1449,8 @@
}
}
+ msm_comm_set_use_sys_cache(inst);
+
/*
* For seq_changed_insufficient, driver should set session_continue
* to firmware after the following sequence
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 25cc1e4..a52fe05 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -968,6 +968,8 @@
decision_done:
core_info.video_core_enable_mask = inst->clk_data.core_id;
+ dprintk(VIDC_DBG,
+ "Core Enable Mask %d\n", core_info.video_core_enable_mask);
rc = call_hfi_op(hdev, session_set_property,
(void *)inst->session,
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 7b75d70..c0bbfbb 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -5553,3 +5553,41 @@
{
return VENUS_BUFFER_SIZE(COLOR_FMT_NV12_BPP10_UBWC, width, height);
}
+
+void msm_comm_set_use_sys_cache(struct msm_vidc_inst *inst)
+{
+ struct hal_enable syscache_use;
+ int rc = 0;
+
+
+ if (!inst->core->resources.sys_cache_enabled)
+ goto exit;
+
+ syscache_use.enable = false;
+ inst->clk_data.use_sys_cache = false;
+
+ if (inst->flags & VIDC_REALTIME)
+ syscache_use.enable = true;
+
+ if (inst->flags & VIDC_THUMBNAIL)
+ syscache_use.enable = false;
+
+ dprintk(VIDC_DBG,
+ "set_use_sys_cache: enable = %d inst = %pK flags =%d\n",
+ syscache_use.enable, inst, inst->flags);
+ rc = msm_comm_try_set_prop(inst, HAL_PARAM_USE_SYS_CACHE,
+ &syscache_use);
+ if (rc) {
+ dprintk(VIDC_ERR, "set_use_sys_cache: failed!!\n");
+ inst->clk_data.use_sys_cache = false;
+ goto exit;
+ }
+
+ inst->clk_data.use_sys_cache = syscache_use.enable;
+
+ return;
+
+exit:
+ return;
+}
+
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.h b/drivers/media/platform/msm/vidc/msm_vidc_common.h
index 61df652..7534593 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.h
@@ -103,4 +103,5 @@
u32 get_frame_size_rgba(int plane, u32 height, u32 width);
u32 get_frame_size_nv21(int plane, u32 height, u32 width);
u32 get_frame_size_tp10_ubwc(int plane, u32 height, u32 width);
+void msm_comm_set_use_sys_cache(struct msm_vidc_inst *inst);
#endif
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_internal.h b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
index 37bccbd..17c3045 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_internal.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_internal.h
@@ -224,6 +224,7 @@
u32 core_id;
enum hal_work_mode work_mode;
bool low_latency_mode;
+ bool use_sys_cache;
};
struct profile_data {
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
index 0a6de41..5cf4628 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_res_parse.c
@@ -59,19 +59,6 @@
return 0;
}
-static inline enum imem_type read_imem_type(struct platform_device *pdev)
-{
- bool is_compatible(char *compat)
- {
- return !!of_find_compatible_node(NULL, NULL, compat);
- }
-
- return is_compatible("qcom,msm-ocmem") ? IMEM_OCMEM :
- is_compatible("qcom,msm-vmem") ? IMEM_VMEM :
- IMEM_NONE;
-
-}
-
static inline void msm_vidc_free_allowed_clocks_table(
struct msm_vidc_platform_resources *res)
{
@@ -90,12 +77,6 @@
res->pf_ver_tbl = NULL;
}
-static inline void msm_vidc_free_imem_ab_table(
- struct msm_vidc_platform_resources *res)
-{
- res->imem_ab_tbl = NULL;
-}
-
static inline void msm_vidc_free_reg_table(
struct msm_vidc_platform_resources *res)
{
@@ -262,43 +243,48 @@
return rc;
}
-static int msm_vidc_load_imem_ab_table(struct msm_vidc_platform_resources *res)
+static int msm_vidc_load_subcache_info(struct msm_vidc_platform_resources *res)
{
- int num_elements = 0;
+ int rc = 0, num_subcaches = 0, c;
struct platform_device *pdev = res->pdev;
+ struct subcache_set *subcaches = &res->subcache_set;
- if (!of_find_property(pdev->dev.of_node, "qcom,imem-ab-tbl", NULL)) {
- /* optional property */
- dprintk(VIDC_DBG, "qcom,imem-freq-tbl not found\n");
- return 0;
+ num_subcaches = of_property_count_strings(pdev->dev.of_node,
+ "cache-slice-names");
+ if (num_subcaches <= 0) {
+ dprintk(VIDC_DBG, "No subcaches found\n");
+ goto err_load_subcache_table_fail;
}
- num_elements = get_u32_array_num_elements(pdev->dev.of_node,
- "qcom,imem-ab-tbl");
- num_elements /= (sizeof(*res->imem_ab_tbl) / sizeof(u32));
- if (!num_elements) {
- dprintk(VIDC_ERR, "no elements in imem ab table\n");
- return -EINVAL;
+ subcaches->subcache_tbl = devm_kzalloc(&pdev->dev,
+ sizeof(*subcaches->subcache_tbl) * num_subcaches, GFP_KERNEL);
+ if (!subcaches->subcache_tbl) {
+ dprintk(VIDC_ERR,
+ "Failed to allocate memory for subcache tbl\n");
+ rc = -ENOMEM;
+ goto err_load_subcache_table_fail;
}
- res->imem_ab_tbl = devm_kzalloc(&pdev->dev, num_elements *
- sizeof(*res->imem_ab_tbl), GFP_KERNEL);
- if (!res->imem_ab_tbl) {
- dprintk(VIDC_ERR, "Failed to alloc imem_ab_tbl\n");
- return -ENOMEM;
+ subcaches->count = num_subcaches;
+ dprintk(VIDC_DBG, "Found %d subcaches\n", num_subcaches);
+
+ for (c = 0; c < num_subcaches; ++c) {
+ struct subcache_info *vsc = &res->subcache_set.subcache_tbl[c];
+
+ of_property_read_string_index(pdev->dev.of_node,
+ "cache-slice-names", c, &vsc->name);
}
- if (of_property_read_u32_array(pdev->dev.of_node,
- "qcom,imem-ab-tbl", (u32 *)res->imem_ab_tbl,
- num_elements * sizeof(*res->imem_ab_tbl) / sizeof(u32))) {
- dprintk(VIDC_ERR, "Failed to read imem_ab_tbl\n");
- msm_vidc_free_imem_ab_table(res);
- return -EINVAL;
- }
-
- res->imem_ab_tbl_size = num_elements;
+ res->sys_cache_enabled = true;
return 0;
+
+err_load_subcache_table_fail:
+ res->sys_cache_enabled = false;
+ subcaches->count = 0;
+ subcaches->subcache_tbl = NULL;
+
+ return rc;
}
/**
@@ -856,10 +842,6 @@
kres = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
res->irq = kres ? kres->start : -1;
- of_property_read_u32(pdev->dev.of_node,
- "qcom,imem-size", &res->imem_size);
- res->imem_type = read_imem_type(pdev);
-
res->sys_idle_indicator = of_property_read_bool(pdev->dev.of_node,
"qcom,enable-idle-indicator");
@@ -884,9 +866,9 @@
if (rc)
dprintk(VIDC_ERR, "Failed to load pf version table: %d\n", rc);
- rc = msm_vidc_load_imem_ab_table(res);
+ rc = msm_vidc_load_subcache_info(res);
if (rc)
- dprintk(VIDC_WARN, "Failed to load freq table: %d\n", rc);
+ dprintk(VIDC_WARN, "Failed to load subcache info: %d\n", rc);
rc = msm_vidc_load_qdss_table(res);
if (rc)
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_resources.h b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
index 20b0ffc..d76985e 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_resources.h
+++ b/drivers/media/platform/msm/vidc/msm_vidc_resources.h
@@ -17,6 +17,8 @@
#include <linux/devfreq.h>
#include <linux/platform_device.h>
#include <media/msm_vidc.h>
+#include <linux/soc/qcom/llcc-qcom.h>
+
#define MAX_BUFFER_TYPES 32
struct platform_version_table {
@@ -36,11 +38,6 @@
u32 fps;
};
-struct imem_ab_table {
- u32 core_freq;
- u32 imem_ab;
-};
-
struct reg_value_pair {
u32 reg;
u32 value;
@@ -122,13 +119,6 @@
u32 count;
};
-enum imem_type {
- IMEM_NONE,
- IMEM_OCMEM,
- IMEM_VMEM,
- IMEM_MAX,
-};
-
struct allowed_clock_rates_table {
u32 clock_rate;
};
@@ -145,6 +135,18 @@
u32 count;
};
+struct subcache_info {
+ const char *name;
+ bool isactive;
+ bool isset;
+ struct llcc_slice_desc *subcache;
+};
+
+struct subcache_set {
+ struct subcache_info *subcache_tbl;
+ u32 count;
+};
+
struct msm_vidc_platform_resources {
phys_addr_t firmware_base;
phys_addr_t register_base;
@@ -157,13 +159,11 @@
struct dcvs_table *dcvs_tbl;
uint32_t dcvs_tbl_size;
struct dcvs_limit *dcvs_limit;
- struct imem_ab_table *imem_ab_tbl;
- u32 imem_ab_tbl_size;
+ bool sys_cache_enabled;
+ struct subcache_set subcache_set;
struct reg_set reg_set;
struct addr_set qdss_addr_set;
struct buffer_usage_set buffer_usage_set;
- uint32_t imem_size;
- enum imem_type imem_type;
uint32_t max_load;
uint32_t max_hq_mbs_per_frame;
uint32_t max_hq_fps;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.c b/drivers/media/platform/msm/vidc/venus_hfi.c
index 1a1078d..5a8dd26 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.c
+++ b/drivers/media/platform/msm/vidc/venus_hfi.c
@@ -27,6 +27,8 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/soc/qcom/llcc-qcom.h>
#include <soc/qcom/scm.h>
#include <soc/qcom/smem.h>
#include <soc/qcom/subsystem_restart.h>
@@ -72,7 +74,6 @@
const struct msm_vidc_gov_data DEFAULT_BUS_VOTE = {
.data = NULL,
.data_count = 0,
- .imem_size = 0,
};
const int max_packets = 1000;
@@ -95,6 +96,8 @@
static int __load_fw(struct venus_hfi_device *device);
static void __unload_fw(struct venus_hfi_device *device);
static int __tzbsp_set_video_state(enum tzbsp_video_state state);
+static int __enable_subcaches(struct venus_hfi_device *device);
+static int __disable_subcaches(struct venus_hfi_device *device);
/**
@@ -875,7 +878,6 @@
kfree(device->bus_vote.data);
device->bus_vote.data = new_data;
device->bus_vote.data_count = num_data;
- device->bus_vote.imem_size = device->res->imem_size;
venus_hfi_for_each_bus(device, bus) {
if (bus && bus->devfreq) {
@@ -939,140 +941,33 @@
return rc;
}
-static int __alloc_imem(struct venus_hfi_device *device, unsigned long size)
+static int __core_release_resource(struct venus_hfi_device *device,
+ struct vidc_resource_hdr *resource_hdr)
{
- struct imem *imem = NULL;
+ struct hfi_cmd_sys_release_resource_packet *pkt;
+ u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
int rc = 0;
- if (!device)
- return -EINVAL;
-
- imem = &device->resources.imem;
- if (imem->type) {
- dprintk(VIDC_ERR, "IMEM of type %d already allocated\n",
- imem->type);
- return -ENOMEM;
- }
-
- switch (device->res->imem_type) {
- case IMEM_VMEM:
- {
- phys_addr_t vmem_buffer = 0;
-
- rc = vmem_allocate(size, &vmem_buffer);
- if (rc) {
- if (rc == -ENOTSUPP) {
- dprintk(VIDC_DBG,
- "Target does not support vmem\n");
- rc = 0;
- }
- goto imem_alloc_failed;
- } else if (!vmem_buffer) {
- rc = -ENOMEM;
- goto imem_alloc_failed;
- }
-
- imem->vmem = vmem_buffer;
- break;
- }
- case IMEM_NONE:
- rc = 0;
- break;
-
- default:
- rc = -ENOTSUPP;
- goto imem_alloc_failed;
- }
-
- imem->type = device->res->imem_type;
- dprintk(VIDC_DBG, "Allocated %ld bytes of IMEM of type %d\n", size,
- imem->type);
- return 0;
-imem_alloc_failed:
- imem->type = IMEM_NONE;
- return rc;
-}
-
-static int __free_imem(struct venus_hfi_device *device)
-{
- struct imem *imem = NULL;
- int rc = 0;
-
- if (!device)
- return -EINVAL;
-
- imem = &device->resources.imem;
- switch (imem->type) {
- case IMEM_NONE:
- /* Follow the semantics of free(NULL), which is a no-op. */
- break;
- case IMEM_VMEM:
- vmem_free(imem->vmem);
- break;
- default:
- rc = -ENOTSUPP;
- goto imem_free_failed;
- }
-
- imem->type = IMEM_NONE;
- return 0;
-
-imem_free_failed:
- return rc;
-}
-
-static int __set_imem(struct venus_hfi_device *device, struct imem *imem)
-{
- struct vidc_resource_hdr rhdr;
- phys_addr_t addr = 0;
- int rc = 0;
-
- if (!device || !device->res || !imem) {
- dprintk(VIDC_ERR, "Invalid params, core: %pK, imem: %pK\n",
- device, imem);
+ if (!device || !resource_hdr) {
+ dprintk(VIDC_ERR, "release_res: Invalid Params\n");
return -EINVAL;
}
- rhdr.resource_handle = imem; /* cookie */
- rhdr.size = device->res->imem_size;
- rhdr.resource_id = VIDC_RESOURCE_NONE;
+ pkt = (struct hfi_cmd_sys_release_resource_packet *) packet;
- switch (imem->type) {
- case IMEM_VMEM:
- rhdr.resource_id = VIDC_RESOURCE_VMEM;
- addr = imem->vmem;
- break;
- case IMEM_NONE:
- dprintk(VIDC_DBG, "%s Target does not support IMEM", __func__);
- rc = 0;
- goto imem_set_failed;
- default:
- dprintk(VIDC_ERR, "IMEM of type %d unsupported\n", imem->type);
- rc = -ENOTSUPP;
- goto imem_set_failed;
- }
+ rc = call_hfi_pkt_op(device, sys_release_resource,
+ pkt, resource_hdr);
- MSM_VIDC_ERROR(!addr);
-
- rc = __core_set_resource(device, &rhdr, (void *)addr);
if (rc) {
- dprintk(VIDC_ERR, "Failed to set IMEM on driver\n");
- goto imem_set_failed;
+ dprintk(VIDC_ERR, "release_res: failed to create packet\n");
+ goto err_create_pkt;
}
- dprintk(VIDC_DBG,
- "Managed to set IMEM buffer of type %d sized %d bytes at %pa\n",
- rhdr.resource_id, rhdr.size, &addr);
+ rc = __iface_cmdq_write(device, pkt);
+ if (rc)
+ rc = -ENOTEMPTY;
- rc = __vote_buses(device, device->bus_vote.data,
- device->bus_vote.data_count);
- if (rc) {
- dprintk(VIDC_ERR,
- "Failed to vote for buses after setting imem: %d\n",
- rc);
- }
-
-imem_set_failed:
+err_create_pkt:
return rc;
}
@@ -1931,6 +1826,12 @@
if (rc || __iface_cmdq_write(dev, &version_pkt))
dprintk(VIDC_WARN, "Failed to send image version pkt to f/w\n");
+ rc = __enable_subcaches(device);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed to enable subcaches, err = %d\n", rc);
+ }
+
if (dev->res->pm_qos_latency_us) {
#ifdef CONFIG_SMP
dev->qos.type = PM_QOS_REQ_AFFINE_IRQ;
@@ -2848,6 +2749,8 @@
return;
}
+ dprintk(VIDC_PROF,
+ "Entering venus_hfi_pm_handler\n");
/*
* It is ok to check this variable outside the lock since
* it is being updated in this context only
@@ -3094,12 +2997,7 @@
break;
case HAL_SYS_INIT_DONE:
dprintk(VIDC_DBG, "Received SYS_INIT_DONE\n");
- /* Video driver intentionally does not unset
- * IMEM on venus to simplify power collapse.
- */
- if (__set_imem(device, &device->resources.imem))
- dprintk(VIDC_WARN,
- "Failed to set IMEM. Performance will be impacted\n");
+
sys_init_done.capabilities =
device->sys_init_capabilities;
hfi_process_sys_init_done_prop_read(
@@ -3584,6 +3482,68 @@
return rc;
}
+static void __deinit_subcaches(struct venus_hfi_device *device)
+{
+ struct subcache_info *sinfo = NULL;
+
+ if (!device) {
+ dprintk(VIDC_ERR, "deinit_subcaches: invalid device %pK\n",
+ device);
+ goto exit;
+ }
+
+ if (!device->res->sys_cache_enabled)
+ goto exit;
+
+ venus_hfi_for_each_subcache_reverse(device, sinfo) {
+ if (sinfo->subcache) {
+ dprintk(VIDC_DBG, "deinit_subcaches: %s\n",
+ sinfo->name);
+ llcc_slice_putd(sinfo->subcache);
+ sinfo->subcache = NULL;
+ }
+ }
+
+exit:
+ return;
+}
+
+static int __init_subcaches(struct venus_hfi_device *device)
+{
+ int rc = 0;
+ struct subcache_info *sinfo = NULL;
+
+ if (!device) {
+ dprintk(VIDC_ERR, "init_subcaches: invalid device %pK\n",
+ device);
+ return -EINVAL;
+ }
+
+ if (!device->res->sys_cache_enabled)
+ return 0;
+
+ venus_hfi_for_each_subcache(device, sinfo) {
+ sinfo->subcache = llcc_slice_getd(&device->res->pdev->dev,
+ sinfo->name);
+ if (IS_ERR_OR_NULL(sinfo->subcache)) {
+ rc = PTR_ERR(sinfo->subcache) ? : -EBADHANDLE;
+ dprintk(VIDC_ERR,
+ "init_subcaches: invalid subcache: %s rc %d\n",
+ sinfo->name, rc);
+ sinfo->subcache = NULL;
+ goto err_subcache_get;
+ }
+ dprintk(VIDC_DBG, "init_subcaches: %s\n",
+ sinfo->name);
+ }
+
+ return 0;
+
+err_subcache_get:
+ __deinit_subcaches(device);
+ return rc;
+}
+
static int __init_resources(struct venus_hfi_device *device,
struct msm_vidc_platform_resources *res)
{
@@ -3608,6 +3568,10 @@
goto err_init_bus;
}
+ rc = __init_subcaches(device);
+ if (rc)
+ dprintk(VIDC_WARN, "Failed to init subcaches: %d\n", rc);
+
device->sys_init_capabilities =
kzalloc(sizeof(struct msm_vidc_capability)
* VIDC_MAX_SESSIONS, GFP_TEMPORARY);
@@ -3623,6 +3587,7 @@
static void __deinit_resources(struct venus_hfi_device *device)
{
+ __deinit_subcaches(device);
__deinit_bus(device);
__deinit_clocks(device);
__deinit_regulators(device);
@@ -3789,6 +3754,132 @@
return rc;
}
+static int __enable_subcaches(struct venus_hfi_device *device)
+{
+ int rc = 0;
+ u32 c = 0;
+ struct subcache_info *sinfo;
+ u32 resource[VIDC_MAX_SUBCACHE_SIZE];
+ struct hfi_resource_syscache_info_type *sc_res_info;
+ struct hfi_resource_subcache_type *sc_res;
+ struct vidc_resource_hdr rhdr;
+
+ if (!device->res->sys_cache_enabled)
+ return 0;
+
+ memset((void *)resource, 0x0, (sizeof(u32) * VIDC_MAX_SUBCACHE_SIZE));
+
+ sc_res_info = (struct hfi_resource_syscache_info_type *)resource;
+ sc_res = &(sc_res_info->rg_subcache_entries[0]);
+
+ /* Activate subcaches */
+ venus_hfi_for_each_subcache(device, sinfo) {
+ rc = llcc_slice_activate(sinfo->subcache);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to activate %s: %d\n",
+ sinfo->name, rc);
+ continue;
+ }
+ sinfo->isactive = true;
+
+ /* Update the entry */
+ sc_res[c].size = sinfo->subcache->llcc_slice_size;
+ sc_res[c].sc_id = sinfo->subcache->llcc_slice_id;
+ dprintk(VIDC_DBG, "Activate subcache %s\n", sinfo->name);
+ c++;
+ }
+
+ /* Set resource to Venus for activated subcaches */
+ if (c) {
+ dprintk(VIDC_DBG, "Setting Subcaches\n");
+
+ rhdr.resource_handle = sc_res_info; /* cookie */
+ rhdr.resource_id = VIDC_RESOURCE_SYSCACHE;
+
+ sc_res_info->num_entries = c;
+
+ rc = __core_set_resource(device, &rhdr, (void *)sc_res_info);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to set subcaches %d\n", rc);
+ goto err_fail_set_subacaches;
+ }
+ }
+
+ venus_hfi_for_each_subcache(device, sinfo) {
+ if (sinfo->isactive == true)
+ sinfo->isset = true;
+ }
+
+ dprintk(VIDC_DBG, "Activated & Set Subcaches to Venus\n");
+
+ return 0;
+
+err_fail_set_subacaches:
+ __disable_subcaches(device);
+
+ return rc;
+}
+
+static int __disable_subcaches(struct venus_hfi_device *device)
+{
+ struct subcache_info *sinfo;
+ int rc = 0;
+ u32 c = 0;
+ u32 resource[VIDC_MAX_SUBCACHE_SIZE];
+ struct hfi_resource_syscache_info_type *sc_res_info;
+ struct hfi_resource_subcache_type *sc_res;
+ struct vidc_resource_hdr rhdr;
+
+ if (!device->res->sys_cache_enabled)
+ return 0;
+
+ dprintk(VIDC_DBG, "Disabling Subcaches\n");
+
+ memset((void *)resource, 0x0, (sizeof(u32) * VIDC_MAX_SUBCACHE_SIZE));
+
+ sc_res_info = (struct hfi_resource_syscache_info_type *)resource;
+ sc_res = &(sc_res_info->rg_subcache_entries[0]);
+
+ /* Release resource command to Venus */
+ venus_hfi_for_each_subcache_reverse(device, sinfo) {
+ if (sinfo->isset == true) {
+ /* Update the entry */
+ sc_res[c].size = sinfo->subcache->llcc_slice_size;
+ sc_res[c].sc_id = sinfo->subcache->llcc_slice_id;
+ c++;
+ sinfo->isset = false;
+ }
+ }
+
+ if (c > 0) {
+ rhdr.resource_handle = sc_res_info; /* cookie */
+ rhdr.resource_id = VIDC_RESOURCE_SYSCACHE;
+
+ rc = __core_release_resource(device, &rhdr);
+ if (rc)
+ dprintk(VIDC_ERR, "Failed to release subcaches\n");
+
+ dprintk(VIDC_DBG, "Release %d subcaches\n", c);
+ }
+
+ /* De-activate subcaches */
+ venus_hfi_for_each_subcache_reverse(device, sinfo) {
+ if (sinfo->isactive == true) {
+ dprintk(VIDC_DBG, "De-activate subcache %s\n",
+ sinfo->name);
+ rc = llcc_slice_deactivate(sinfo->subcache);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Failed to de-activate %s: %d\n",
+ sinfo->name, rc);
+ }
+ sinfo->isactive = false;
+ }
+ }
+
+ return rc;
+}
+
static int __venus_power_on(struct venus_hfi_device *device)
{
int rc = 0;
@@ -3805,12 +3896,6 @@
goto fail_vote_buses;
}
- rc = __alloc_imem(device, device->res->imem_size);
- if (rc) {
- dprintk(VIDC_ERR, "Failed to allocate IMEM\n");
- goto fail_alloc_imem;
- }
-
rc = __enable_regulators(device);
if (rc) {
dprintk(VIDC_ERR, "Failed to enable GDSC, err = %d\n", rc);
@@ -3855,8 +3940,6 @@
fail_enable_clks:
__disable_regulators(device);
fail_enable_gdsc:
- __free_imem(device);
-fail_alloc_imem:
__unvote_buses(device);
fail_vote_buses:
device->power_enabled = false;
@@ -3876,8 +3959,6 @@
if (__disable_regulators(device))
dprintk(VIDC_WARN, "Failed to disable regulators\n");
- __free_imem(device);
-
if (__unvote_buses(device))
dprintk(VIDC_WARN, "Failed to unvote for buses\n");
device->power_enabled = false;
@@ -3897,6 +3978,9 @@
dprintk(VIDC_PROF, "Entering power collapse\n");
+ if (__disable_subcaches(device))
+ dprintk(VIDC_ERR, "Failed to disable subcaches\n");
+
if (device->res->pm_qos_latency_us &&
pm_qos_request_active(&device->qos))
pm_qos_remove_request(&device->qos);
@@ -3966,6 +4050,15 @@
pm_qos_add_request(&device->qos, PM_QOS_CPU_DMA_LATENCY,
device->res->pm_qos_latency_us);
}
+
+ __sys_set_debug(device, msm_vidc_fw_debug);
+
+ rc = __enable_subcaches(device);
+ if (rc) {
+ dprintk(VIDC_WARN,
+ "Failed to enable subcaches, err = %d\n", rc);
+ }
+
dprintk(VIDC_PROF, "Resumed from power collapse\n");
exit:
device->skip_pc_count = 0;
diff --git a/drivers/media/platform/msm/vidc/venus_hfi.h b/drivers/media/platform/msm/vidc/venus_hfi.h
index 76ede70..925918c 100644
--- a/drivers/media/platform/msm/vidc/venus_hfi.h
+++ b/drivers/media/platform/msm/vidc/venus_hfi.h
@@ -19,7 +19,6 @@
#include <linux/platform_device.h>
#include <linux/pm_qos.h>
#include <linux/spinlock.h>
-#include "vmem/vmem.h"
#include "vidc_hfi_api.h"
#include "vidc_hfi_helper.h"
#include "vidc_hfi_api.h"
@@ -48,6 +47,9 @@
#define VIDC_MAX_NAME_LENGTH 64
#define VIDC_MAX_PC_SKIP_COUNT 10
+#define VIDC_MAX_SUBCACHES 4
+#define VIDC_MAX_SUBCACHE_SIZE 52
+
struct hfi_queue_table_header {
u32 qtbl_version;
u32 qtbl_size;
@@ -198,6 +200,11 @@
#define venus_hfi_for_each_bus_reverse(__device, __binfo) \
venus_hfi_for_each_thing_reverse(__device, __binfo, bus)
+/* Subcache set helpers */
+#define venus_hfi_for_each_subcache(__device, __sinfo) \
+ venus_hfi_for_each_thing(__device, __sinfo, subcache)
+#define venus_hfi_for_each_subcache_reverse(__device, __sinfo) \
+ venus_hfi_for_each_thing_reverse(__device, __sinfo, subcache)
/* Internal data used in vidc_hal not exposed to msm_vidc*/
struct hal_data {
@@ -207,16 +214,8 @@
u32 register_size;
};
-struct imem {
- enum imem_type type;
- union {
- phys_addr_t vmem;
- };
-};
-
struct venus_resources {
struct msm_vidc_fw fw;
- struct imem imem;
};
enum venus_hfi_state {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_api.h b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
index 537a1c6..bcc29c0 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_api.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_api.h
@@ -224,6 +224,7 @@
HAL_PARAM_VIDEO_CORES_USAGE,
HAL_PARAM_VIDEO_WORK_MODE,
HAL_PARAM_SECURE,
+ HAL_PARAM_USE_SYS_CACHE,
};
enum hal_domain {
@@ -870,15 +871,13 @@
enum vidc_resource_id {
VIDC_RESOURCE_NONE,
- VIDC_RESOURCE_OCMEM,
- VIDC_RESOURCE_VMEM,
+ VIDC_RESOURCE_SYSCACHE,
VIDC_UNUSED_RESOURCE = 0x10000000,
};
struct vidc_resource_hdr {
enum vidc_resource_id resource_id;
void *resource_handle;
- u32 size;
};
struct vidc_buffer_addr_info {
@@ -1293,7 +1292,6 @@
struct msm_vidc_gov_data {
struct vidc_bus_vote_data *data;
u32 data_count;
- int imem_size;
};
enum msm_vidc_power_mode {
@@ -1309,9 +1307,6 @@
int num_formats; /* 1 = DPB-OPB unified; 2 = split */
int height, width, fps;
enum msm_vidc_power_mode power_mode;
- struct imem_ab_table *imem_ab_tbl;
- u32 imem_ab_tbl_size;
- unsigned long core_freq;
};
struct vidc_clk_scale_data {
diff --git a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
index eaba920..fc638f0 100644
--- a/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
+++ b/drivers/media/platform/msm/vidc/vidc_hfi_helper.h
@@ -220,6 +220,8 @@
(HFI_PROPERTY_PARAM_COMMON_START + 0x010)
#define HFI_PROPERTY_PARAM_SECURE_SESSION \
(HFI_PROPERTY_PARAM_COMMON_START + 0x011)
+#define HFI_PROPERTY_PARAM_USE_SYS_CACHE \
+ (HFI_PROPERTY_PARAM_COMMON_START + 0x012)
#define HFI_PROPERTY_PARAM_WORK_MODE \
(HFI_PROPERTY_PARAM_COMMON_START + 0x015)
@@ -718,23 +720,16 @@
u32 flip;
};
-#define HFI_RESOURCE_OCMEM 0x00000001
+#define HFI_RESOURCE_SYSCACHE 0x00000002
-struct hfi_resource_ocmem {
+struct hfi_resource_subcache_type {
u32 size;
- u32 mem;
+ u32 sc_id;
};
-struct hfi_resource_ocmem_requirement {
- u32 session_domain;
- u32 width;
- u32 height;
- u32 size;
-};
-
-struct hfi_resource_ocmem_requirement_info {
+struct hfi_resource_syscache_info_type {
u32 num_entries;
- struct hfi_resource_ocmem_requirement rg_requirements[1];
+ struct hfi_resource_subcache_type rg_subcache_entries[1];
};
struct hfi_property_sys_image_version_info_type {
diff --git a/drivers/media/platform/msm/vidc/vmem/Kconfig b/drivers/media/platform/msm/vidc/vmem/Kconfig
deleted file mode 100644
index 99260a9..0000000
--- a/drivers/media/platform/msm/vidc/vmem/Kconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-menuconfig MSM_VIDC_VMEM
- tristate "Qualcomm Technologies, Inc. MSM VMEM driver"
- depends on ARCH_QCOM && MSM_VIDC_V4L2
diff --git a/drivers/media/platform/msm/vidc/vmem/Makefile b/drivers/media/platform/msm/vidc/vmem/Makefile
deleted file mode 100644
index a56ad95..0000000
--- a/drivers/media/platform/msm/vidc/vmem/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-ccflags-y += -I$(srctree)/drivers/media/platform/msm/vidc/
-ccflags-y += -I$(srctree)/drivers/media/platform/msm/vidc/vmem/
-
-msm-vidc-vmem-objs := vmem.o \
- vmem_debugfs.o
-
-obj-$(CONFIG_MSM_VIDC_VMEM) := msm-vidc-vmem.o
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.c b/drivers/media/platform/msm/vidc/vmem/vmem.c
deleted file mode 100644
index c75f02d..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem.c
+++ /dev/null
@@ -1,738 +0,0 @@
-/*
- * Copyright (c) 2014-2017, 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/bitops.h>
-#include <linux/clk.h>
-#include <linux/clk/qcom.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/msm-bus.h>
-#include <linux/of.h>
-#include <linux/platform_device.h>
-#include <linux/regulator/consumer.h>
-#include <linux/slab.h>
-#include <linux/workqueue.h>
-#include "vmem.h"
-#include "vmem_debugfs.h"
-
-/* Registers */
-#define OCIMEM_BASE(v) ((uint8_t *)(v)->reg.base)
-#define OCIMEM_HW_VERSION(v) (OCIMEM_BASE(v) + 0x00)
-#define OCIMEM_HW_PROFILE(v) (OCIMEM_BASE(v) + 0x04)
-#define OCIMEM_GEN_CTL(v) (OCIMEM_BASE(v) + 0x08)
-#define OCIMEM_GEN_STAT(v) (OCIMEM_BASE(v) + 0x0C)
-#define OCIMEM_INTC_CLR(v) (OCIMEM_BASE(v) + 0x10)
-#define OCIMEM_INTC_MASK(v) (OCIMEM_BASE(v) + 0x14)
-#define OCIMEM_INTC_STAT(v) (OCIMEM_BASE(v) + 0x18)
-#define OCIMEM_OSW_STATUS(v) (OCIMEM_BASE(v) + 0x1C)
-#define OCIMEM_PSCGC_TIMERS(v) (OCIMEM_BASE(v) + 0x34)
-#define OCIMEM_PSCGC_STAT(v) (OCIMEM_BASE(v) + 0x38)
-#define OCIMEM_PSCGC_M0_M7_CTL(v) (OCIMEM_BASE(v) + 0x3C)
-#define OCIMEM_ERR_ADDRESS(v) (OCIMEM_BASE(v) + 0x60)
-#define OCIMEM_AXI_ERR_SYNDROME(v) (OCIMEM_BASE(v) + 0x64)
-#define OCIMEM_DEBUG_CTL(v) (OCIMEM_BASE(v) + 0x68)
-
-/*
- * Helper macro to help out with masks and shifts for values packed into
- * registers.
- */
-#define DECLARE_TYPE(__type, __end, __start) \
- static const unsigned int __type##_BITS = (__end) - (__start) + 1; \
- static const unsigned int __type##_SHIFT = (__start); \
- static const unsigned int __type##_MASK = GENMASK((__end), (__start)); \
- static inline unsigned int __type(uint32_t val) \
- { \
- return (val & __type##_MASK) >> __type##_SHIFT; \
- } \
- static inline uint32_t __type##_UPDATE(unsigned int val) \
- { \
- return (val << __type##_SHIFT) & __type##_MASK; \
- }
-
-/* Register masks */
-/* OCIMEM_PSCGC_M0_M7_CTL */
-DECLARE_TYPE(BANK0_STATE, 3, 0);
-DECLARE_TYPE(BANK1_STATE, 7, 4);
-DECLARE_TYPE(BANK2_STATE, 11, 8);
-DECLARE_TYPE(BANK3_STATE, 15, 12);
-/* OCIMEM_PSCGC_TIMERS */
-DECLARE_TYPE(TIMERS_WAKEUP, 3, 0);
-DECLARE_TYPE(TIMERS_SLEEP, 11, 8);
-/* OCIMEM_HW_VERSION */
-DECLARE_TYPE(VERSION_STEP, 15, 0);
-DECLARE_TYPE(VERSION_MINOR, 27, 16);
-DECLARE_TYPE(VERSION_MAJOR, 31, 28);
-/* OCIMEM_HW_PROFILE */
-DECLARE_TYPE(PROFILE_BANKS, 16, 12);
-/* OCIMEM_AXI_ERR_SYNDROME */
-DECLARE_TYPE(ERR_SYN_ATID, 14, 8);
-DECLARE_TYPE(ERR_SYN_AMID, 23, 16);
-DECLARE_TYPE(ERR_SYN_APID, 28, 24);
-DECLARE_TYPE(ERR_SYN_ABID, 31, 29);
-/* OCIMEM_INTC_MASK */
-DECLARE_TYPE(AXI_ERR_INT, 0, 0);
-
-/* Internal stuff */
-#define MAX_BANKS 4
-
-enum bank_state {
- BANK_STATE_NORM_PASSTHRU = 0x000,
- BANK_STATE_NORM_FORCE_CORE_ON = 0x002,
- BANK_STATE_NORM_FORCE_PERIPH_ON = 0x001,
- BANK_STATE_NORM_FORCE_ALL_ON = 0x03,
- BANK_STATE_SLEEP_RET = 0x6,
- BANK_STATE_SLEEP_RET_PERIPH_ON = 0x7,
- BANK_STATE_SLEEP_NO_RET = 0x4,
-};
-
-struct vmem {
- int irq;
- int num_banks;
- int bank_size;
- struct {
- struct resource *resource;
- void __iomem *base;
- } reg, mem;
- struct regulator *vdd;
- struct {
- const char *name;
- struct clk *clk;
- bool has_mem_retention;
- } *clocks;
- int num_clocks;
- struct {
- struct msm_bus_scale_pdata *pdata;
- uint32_t priv;
- } bus;
- atomic_t alloc_count;
- struct dentry *debugfs_root;
-};
-
-static struct vmem *vmem;
-
-static inline u32 __readl(void * __iomem addr)
-{
- u32 value = 0;
-
- pr_debug("read %pK ", addr);
- value = readl_relaxed(addr);
- pr_debug("-> %08x\n", value);
-
- return value;
-}
-
-static inline void __writel(u32 val, void * __iomem addr)
-{
- pr_debug("write %08x -> %pK\n", val, addr);
- writel_relaxed(val, addr);
- /*
- * Commit all writes via a mem barrier, as subsequent __readl()
- * will depend on the state that's set via __writel().
- */
- mb();
-}
-
-static inline void __wait_timer(struct vmem *v, bool wakeup)
-{
- uint32_t ticks = 0;
- unsigned int (*timer)(uint32_t) = wakeup ?
- TIMERS_WAKEUP : TIMERS_SLEEP;
-
- ticks = timer(__readl(OCIMEM_PSCGC_TIMERS(v)));
-
- /* Sleep for `ticks` nanoseconds as per h/w spec */
- ndelay(ticks);
-}
-
-static inline void __wait_wakeup(struct vmem *v)
-{
- return __wait_timer(v, true);
-}
-
-static inline void __wait_sleep(struct vmem *v)
-{
- return __wait_timer(v, false);
-}
-
-static inline int __power_on(struct vmem *v)
-{
- int rc = 0, c = 0;
-
- rc = msm_bus_scale_client_update_request(v->bus.priv, 1);
- if (rc) {
- pr_err("Failed to vote for buses (%d)\n", rc);
- goto exit;
- }
- pr_debug("Voted for buses\n");
-
- rc = regulator_enable(v->vdd);
- if (rc) {
- pr_err("Failed to power on gdsc (%d)", rc);
- goto unvote_bus;
- }
- pr_debug("Enabled regulator vdd\n");
-
- for (c = 0; c < v->num_clocks; ++c) {
- if (v->clocks[c].has_mem_retention) {
- rc = clk_set_flags(v->clocks[c].clk,
- CLKFLAG_NORETAIN_PERIPH);
- if (rc) {
- pr_warn("Failed set flag NORETAIN_PERIPH %s\n",
- v->clocks[c].name);
- }
- rc = clk_set_flags(v->clocks[c].clk,
- CLKFLAG_NORETAIN_MEM);
- if (rc) {
- pr_warn("Failed set flag NORETAIN_MEM %s\n",
- v->clocks[c].name);
- }
- }
-
- rc = clk_prepare_enable(v->clocks[c].clk);
- if (rc) {
- pr_err("Failed to enable %s clock (%d)\n",
- v->clocks[c].name, rc);
- goto disable_clocks;
- }
-
- pr_debug("Enabled clock %s\n", v->clocks[c].name);
- }
-
- return 0;
-disable_clocks:
- for (--c; c >= 0; c--)
- clk_disable_unprepare(v->clocks[c].clk);
- regulator_disable(v->vdd);
-unvote_bus:
- msm_bus_scale_client_update_request(v->bus.priv, 0);
-exit:
- return rc;
-}
-
-static inline int __power_off(struct vmem *v)
-{
- int c = v->num_clocks;
-
- for (c--; c >= 0; --c) {
- clk_disable_unprepare(v->clocks[c].clk);
- pr_debug("Disabled clock %s\n", v->clocks[c].name);
- }
-
- regulator_disable(v->vdd);
- pr_debug("Disabled regulator vdd\n");
-
- msm_bus_scale_client_update_request(v->bus.priv, 0);
- pr_debug("Unvoted for buses\n");
-
- return 0;
-}
-
-static inline enum bank_state __bank_get_state(struct vmem *v,
- unsigned int bank)
-{
- unsigned int (*func[MAX_BANKS])(uint32_t) = {
- BANK0_STATE, BANK1_STATE, BANK2_STATE, BANK3_STATE
- };
-
- VMEM_ERROR(bank >= ARRAY_SIZE(func));
- return func[bank](__readl(OCIMEM_PSCGC_M0_M7_CTL(v)));
-}
-
-static inline void __bank_set_state(struct vmem *v, unsigned int bank,
- enum bank_state state)
-{
- uint32_t bank_state = 0;
- struct {
- uint32_t (*update)(unsigned int);
- uint32_t mask;
- } banks[MAX_BANKS] = {
- {BANK0_STATE_UPDATE, BANK0_STATE_MASK},
- {BANK1_STATE_UPDATE, BANK1_STATE_MASK},
- {BANK2_STATE_UPDATE, BANK2_STATE_MASK},
- {BANK3_STATE_UPDATE, BANK3_STATE_MASK},
- };
-
- VMEM_ERROR(bank >= ARRAY_SIZE(banks));
-
- bank_state = __readl(OCIMEM_PSCGC_M0_M7_CTL(v));
- bank_state &= ~banks[bank].mask;
- bank_state |= banks[bank].update(state);
-
- __writel(bank_state, OCIMEM_PSCGC_M0_M7_CTL(v));
-}
-
-static inline void __toggle_interrupts(struct vmem *v, bool enable)
-{
- uint32_t ints = __readl(OCIMEM_INTC_MASK(v)),
- mask = AXI_ERR_INT_MASK,
- update = AXI_ERR_INT_UPDATE(!enable);
-
- ints &= ~mask;
- ints |= update;
-
- __writel(ints, OCIMEM_INTC_MASK(v));
-}
-
-static void __enable_interrupts(struct vmem *v)
-{
- pr_debug("Enabling interrupts\n");
- enable_irq(v->irq);
- __toggle_interrupts(v, true);
-}
-
-static void __disable_interrupts(struct vmem *v)
-{
- pr_debug("Disabling interrupts\n");
- __toggle_interrupts(v, false);
- disable_irq_nosync(v->irq);
-}
-
-/**
- * vmem_allocate: - Allocates memory from VMEM. Allocations have a few
- * restrictions: only allocations of the entire VMEM memory are allowed, and
- * , as a result, only single outstanding allocations are allowed.
- *
- * @size: amount of bytes to allocate
- * @addr: A pointer to phys_addr_t where the physical address of the memory
- * allocated is stored.
- *
- * Return: 0 in case of successful allocation (i.e. *addr != NULL). -ENOTSUPP,
- * if platform doesn't support VMEM. -EEXIST, if there are outstanding VMEM
- * allocations. -ENOMEM, if platform can't support allocation of `size` bytes.
- * -EAGAIN, if `size` does not allocate the entire VMEM region. -EIO in case of
- * internal errors.
- */
-int vmem_allocate(size_t size, phys_addr_t *addr)
-{
- int rc = 0, c = 0;
- resource_size_t max_size = 0;
-
- if (!vmem) {
- pr_err("No vmem, try rebooting your device\n");
- rc = -ENOTSUPP;
- goto exit;
- }
- if (!size) {
- pr_err("%s Invalid size %zu\n", __func__, size);
- rc = -EINVAL;
- goto exit;
- }
-
- max_size = resource_size(vmem->mem.resource);
-
- if (atomic_read(&vmem->alloc_count)) {
- pr_err("Only single allocations allowed for vmem\n");
- rc = -EEXIST;
- goto exit;
- } else if (size > max_size) {
- pr_err("Out of memory, have max %pa\n", &max_size);
- rc = -ENOMEM;
- goto exit;
- } else if (size != max_size) {
- pr_err("Only support allocations of size %pa\n", &max_size);
- rc = -EAGAIN;
- goto exit;
- }
-
- rc = __power_on(vmem);
- if (rc) {
- pr_err("Failed power on (%d)\n", rc);
- goto exit;
- }
-
- VMEM_ERROR(vmem->num_banks != DIV_ROUND_UP(size, vmem->bank_size));
-
- /* Turn on the necessary banks */
- for (c = 0; c < vmem->num_banks; ++c) {
- __bank_set_state(vmem, c, BANK_STATE_NORM_FORCE_CORE_ON);
- __wait_wakeup(vmem);
- }
-
- /* Enable interrupts to detect faults */
- __enable_interrupts(vmem);
-
- atomic_inc(&vmem->alloc_count);
- *addr = (phys_addr_t)vmem->mem.resource->start;
- return 0;
-exit:
- return rc;
-}
-EXPORT_SYMBOL(vmem_allocate);
-
-/**
- * vmem_free: - Frees the memory allocated via vmem_allocate. Undefined
- * behaviour if to_free is a not a pointer returned via vmem_allocate
- */
-void vmem_free(phys_addr_t to_free)
-{
- int c = 0;
-
- if (!to_free || !vmem)
- return;
-
- VMEM_ERROR(atomic_read(&vmem->alloc_count) == 0);
-
- for (c = 0; c < vmem->num_banks; ++c) {
- enum bank_state curr_state = __bank_get_state(vmem, c);
-
- if (curr_state != BANK_STATE_NORM_FORCE_CORE_ON) {
- pr_warn("When freeing, expected bank state to be %d, was instead %d\n",
- BANK_STATE_NORM_FORCE_CORE_ON,
- curr_state);
- }
-
- __bank_set_state(vmem, c, BANK_STATE_SLEEP_NO_RET);
- }
-
- __disable_interrupts(vmem);
- __power_off(vmem);
- atomic_dec(&vmem->alloc_count);
-}
-EXPORT_SYMBOL(vmem_free);
-
-struct vmem_interrupt_cookie {
- struct vmem *vmem;
- struct work_struct work;
-};
-
-static void __irq_helper(struct work_struct *work)
-{
- struct vmem_interrupt_cookie *cookie = container_of(work,
- struct vmem_interrupt_cookie, work);
- struct vmem *v = cookie->vmem;
- unsigned int stat, gen_stat, pscgc_stat, err_addr_abs,
- err_addr_rel, err_syn;
-
- stat = __readl(OCIMEM_INTC_STAT(v));
- gen_stat = __readl(OCIMEM_GEN_CTL(v));
- pscgc_stat = __readl(OCIMEM_PSCGC_STAT(v));
-
- err_addr_abs = __readl(OCIMEM_ERR_ADDRESS(v));
- err_addr_rel = v->mem.resource->start - err_addr_abs;
-
- err_syn = __readl(OCIMEM_AXI_ERR_SYNDROME(v));
-
- pr_crit("Detected a fault on VMEM:\n");
- pr_cont("\tinterrupt status: %x\n", stat);
- pr_cont("\tgeneral status: %x\n", gen_stat);
- pr_cont("\tmemory status: %x\n", pscgc_stat);
- pr_cont("\tfault address: %x (absolute), %x (relative)\n",
- err_addr_abs, err_addr_rel);
- pr_cont("\tfault bank: %x\n", err_addr_rel / v->bank_size);
- pr_cont("\tfault core: %u (mid), %u (pid), %u (bid)\n",
- ERR_SYN_AMID(err_syn), ERR_SYN_APID(err_syn),
- ERR_SYN_ABID(err_syn));
-
- /* Clear the interrupt */
- __writel(0, OCIMEM_INTC_CLR(v));
-
- __enable_interrupts(v);
-}
-
-static struct vmem_interrupt_cookie interrupt_cookie;
-
-static irqreturn_t __irq_handler(int irq, void *cookie)
-{
- struct vmem *v = cookie;
- irqreturn_t status = __readl(OCIMEM_INTC_STAT(vmem)) ?
- IRQ_HANDLED : IRQ_NONE;
-
- if (status != IRQ_NONE) {
- /* Mask further interrupts while handling this one */
- __disable_interrupts(v);
-
- interrupt_cookie.vmem = v;
- INIT_WORK(&interrupt_cookie.work, __irq_helper);
- schedule_work(&interrupt_cookie.work);
- }
-
- return status;
-}
-
-static inline int __init_resources(struct vmem *v,
- struct platform_device *pdev)
-{
- int rc = 0, c = 0;
- int *clock_props = NULL;
-
- v->irq = platform_get_irq(pdev, 0);
- if (v->irq < 0) {
- rc = v->irq;
- pr_err("Failed to get irq (%d)\n", rc);
- v->irq = 0;
- goto exit;
- }
-
- /* Registers and memory */
- v->reg.resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "reg-base");
- if (!v->reg.resource) {
- pr_err("Failed to find register base\n");
- rc = -ENOENT;
- goto exit;
- }
-
- v->reg.base = devm_ioremap_resource(&pdev->dev, v->reg.resource);
- if (IS_ERR_OR_NULL(v->reg.base)) {
- rc = PTR_ERR(v->reg.base) ?: -EIO;
- pr_err("Failed to map register base into kernel (%d)\n", rc);
- v->reg.base = NULL;
- goto exit;
- }
-
- pr_debug("Register range: %pa -> %pa\n", &v->reg.resource->start,
- &v->reg.resource->end);
-
- v->mem.resource = platform_get_resource_byname(pdev, IORESOURCE_MEM,
- "mem-base");
- if (!v->mem.resource) {
- pr_err("Failed to find memory base\n");
- rc = -ENOENT;
- goto exit;
- }
-
- v->mem.base = NULL;
- pr_debug("Memory range: %pa -> %pa\n", &v->mem.resource->start,
- &v->mem.resource->end);
-
- /* Buses, Clocks & Regulators*/
- v->num_clocks = of_property_count_strings(pdev->dev.of_node,
- "clock-names");
- if (v->num_clocks <= 0) {
- pr_err("Can't find any clocks\n");
- goto exit;
- }
-
- v->clocks = devm_kzalloc(&pdev->dev, sizeof(*v->clocks) * v->num_clocks,
- GFP_KERNEL);
- if (!v->clocks) {
- rc = -ENOMEM;
- goto exit;
- }
-
- clock_props = devm_kzalloc(&pdev->dev,
- v->num_clocks * sizeof(*clock_props),
- GFP_KERNEL);
- if (!clock_props) {
- pr_err("Failed to allocate clock config table\n");
- goto exit;
- }
-
- rc = of_property_read_u32_array(pdev->dev.of_node, "clock-config",
- clock_props, v->num_clocks);
- if (rc) {
- pr_err("Failed to read clock config\n");
- goto exit;
- }
-
- for (c = 0; c < v->num_clocks; ++c) {
- const char *name = NULL;
- struct clk *temp = NULL;
-
- of_property_read_string_index(pdev->dev.of_node, "clock-names",
- c, &name);
- temp = devm_clk_get(&pdev->dev, name);
- if (IS_ERR_OR_NULL(temp)) {
- rc = PTR_ERR(temp) ?: -ENOENT;
- pr_err("Failed to find %s (%d)\n", name, rc);
- goto exit;
- }
-
- v->clocks[c].clk = temp;
- v->clocks[c].name = name;
- v->clocks[c].has_mem_retention = clock_props[c];
- }
-
- v->vdd = devm_regulator_get(&pdev->dev, "vdd");
- if (IS_ERR_OR_NULL(v->vdd)) {
- rc = PTR_ERR(v->vdd) ?: -ENOENT;
- pr_err("Failed to find regulator (vdd) (%d)\n", rc);
- goto exit;
- }
-
- v->bus.pdata = msm_bus_cl_get_pdata(pdev);
- if (IS_ERR_OR_NULL(v->bus.pdata)) {
- rc = PTR_ERR(v->bus.pdata) ?: -ENOENT;
- pr_err("Failed to find bus vectors (%d)\n", rc);
- goto exit;
- }
-
- v->bus.priv = msm_bus_scale_register_client(v->bus.pdata);
- if (!v->bus.priv) {
- rc = -EBADHANDLE;
- pr_err("Failed to register bus client\n");
- goto free_pdata;
- }
-
- /* Misc. */
- rc = of_property_read_u32(pdev->dev.of_node, "qcom,bank-size",
- &v->bank_size);
- if (rc || !v->bank_size) {
- pr_err("Failed reading (or found invalid) qcom,bank-size in %s (%d)\n",
- of_node_full_name(pdev->dev.of_node), rc);
- rc = -ENOENT;
- goto free_pdata;
- }
-
- v->num_banks = resource_size(v->mem.resource) / v->bank_size;
-
- pr_debug("Found configuration with %d banks with size %d\n",
- v->num_banks, v->bank_size);
-
- return 0;
-free_pdata:
- msm_bus_cl_clear_pdata(v->bus.pdata);
-exit:
- return rc;
-}
-
-static inline void __uninit_resources(struct vmem *v,
- struct platform_device *pdev)
-{
- int c = 0;
-
- msm_bus_cl_clear_pdata(v->bus.pdata);
- v->bus.pdata = NULL;
- v->bus.priv = 0;
-
- for (c = 0; c < v->num_clocks; ++c) {
- v->clocks[c].clk = NULL;
- v->clocks[c].name = NULL;
- }
-
- v->vdd = NULL;
-}
-
-static int vmem_probe(struct platform_device *pdev)
-{
- uint32_t version = 0, num_banks = 0, rc = 0;
- struct vmem *v = NULL;
-
- if (vmem) {
- pr_err("Only one instance of %s allowed", pdev->name);
- return -EEXIST;
- }
-
- v = devm_kzalloc(&pdev->dev, sizeof(*v), GFP_KERNEL);
- if (!v)
- return -ENOMEM;
-
-
- rc = __init_resources(v, pdev);
- if (rc) {
- pr_err("Failed to read resources\n");
- goto exit;
- }
-
- /*
- * For now, only support up to 4 banks. It's unrealistic that VMEM has
- * more banks than that (even in the future).
- */
- if (v->num_banks > MAX_BANKS) {
- pr_err("Number of banks (%d) exceeds what's supported (%d)\n",
- v->num_banks, MAX_BANKS);
- rc = -ENOTSUPP;
- goto exit;
- }
-
- /* Cross check the platform resources with what's available on chip */
- rc = __power_on(v);
- if (rc) {
- pr_err("Failed to power on (%d)\n", rc);
- goto exit;
- }
-
- version = __readl(OCIMEM_HW_VERSION(v));
- pr_debug("v%d.%d.%d\n", VERSION_MAJOR(version), VERSION_MINOR(version),
- VERSION_STEP(version));
-
- num_banks = PROFILE_BANKS(__readl(OCIMEM_HW_PROFILE(v)));
- pr_debug("Found %d banks on chip\n", num_banks);
- if (v->num_banks != num_banks) {
- pr_err("Platform configuration of %d banks differs from what's available on chip (%d)\n",
- v->num_banks, num_banks);
- rc = -EINVAL;
- goto disable_clocks;
- }
-
- rc = devm_request_irq(&pdev->dev, v->irq, __irq_handler,
- IRQF_TRIGGER_HIGH, "vmem", v);
- if (rc) {
- pr_err("Failed to setup irq (%d)\n", rc);
- goto disable_clocks;
- }
-
- __disable_interrupts(v);
-
- /* Everything good so far, set up the global context and debug hooks */
- pr_info("Up and running with %d banks of memory from %pR\n",
- v->num_banks, &v->mem.resource);
- v->debugfs_root = vmem_debugfs_init(pdev);
- platform_set_drvdata(pdev, v);
- vmem = v;
-
-disable_clocks:
- __power_off(v);
-exit:
- return rc;
-}
-
-static int vmem_remove(struct platform_device *pdev)
-{
- struct vmem *v = platform_get_drvdata(pdev);
-
- VMEM_ERROR(v != vmem);
-
- __uninit_resources(v, pdev);
- vmem_debugfs_deinit(v->debugfs_root);
- vmem = NULL;
-
- return 0;
-}
-
-static const struct of_device_id vmem_of_match[] = {
- {.compatible = "qcom,msm-vmem"},
- {}
-};
-
-MODULE_DEVICE_TABLE(of, vmem_of_match);
-
-static struct platform_driver vmem_driver = {
- .probe = vmem_probe,
- .remove = vmem_remove,
- .driver = {
- .name = "msm_vidc_vmem",
- .owner = THIS_MODULE,
- .of_match_table = vmem_of_match,
- },
-};
-
-static int __init vmem_init(void)
-{
- return platform_driver_register(&vmem_driver);
-}
-
-static void __exit vmem_exit(void)
-{
- platform_driver_unregister(&vmem_driver);
-}
-
-module_init(vmem_init);
-module_exit(vmem_exit);
-
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem.h b/drivers/media/platform/msm/vidc/vmem/vmem.h
deleted file mode 100644
index 0376427..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 2014, 2016-2017, 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 __VMEM_H__
-#define __VMEM_H__
-
-#define VMEM_ERROR(value) \
- do { \
- pr_info("%s : Fatal Level = %d\n", KBUILD_MODNAME, value);\
- BUG_ON(value); \
- } while (0)
-
-#if (defined CONFIG_MSM_VIDC_VMEM) || (defined CONFIG_MSM_VIDC_VMEM_MODULE)
-
-int vmem_allocate(size_t size, phys_addr_t *addr);
-void vmem_free(phys_addr_t to_free);
-
-#else
-
-static inline int vmem_allocate(size_t size, phys_addr_t *addr)
-{
- return -ENODEV;
-}
-
-static inline void vmem_free(phys_addr_t to_free)
-{
-}
-
-#endif
-
-#endif /* __VMEM_H__ */
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.c b/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.c
deleted file mode 100644
index 7d2d524..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.c
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) 2014, 2017 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/debugfs.h>
-#include <linux/fs.h>
-#include <linux/platform_device.h>
-#include "vmem.h"
-
-struct vmem_debugfs_cookie {
- phys_addr_t addr;
- size_t size;
-};
-
-static int __vmem_alloc_get(void *priv, u64 *val)
-{
- struct vmem_debugfs_cookie *cookie = priv;
-
- *val = cookie->size;
- return 0;
-}
-
-static int __vmem_alloc_set(void *priv, u64 val)
-{
- struct vmem_debugfs_cookie *cookie = priv;
- int rc = 0;
-
- switch (val) {
- case 0: /* free */
- vmem_free(cookie->addr);
- cookie->size = 0;
- break;
- default:
- rc = vmem_allocate(val, &cookie->addr);
- cookie->size = val;
- break;
- }
-
- return rc;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(fops_vmem_alloc, __vmem_alloc_get,
- __vmem_alloc_set, "%llu");
-
-struct dentry *vmem_debugfs_init(struct platform_device *pdev)
-{
- struct vmem_debugfs_cookie *alloc_cookie = NULL;
- struct dentry *debugfs_root = NULL;
-
- alloc_cookie = devm_kzalloc(&pdev->dev, sizeof(*alloc_cookie),
- GFP_KERNEL);
- if (!alloc_cookie)
- goto exit;
-
- debugfs_root = debugfs_create_dir("vmem", NULL);
- if (IS_ERR_OR_NULL(debugfs_root)) {
- pr_warn("Failed to create '<debugfs>/vmem'\n");
- debugfs_root = NULL;
- goto exit;
- }
-
- debugfs_create_file("alloc", 0600, debugfs_root,
- alloc_cookie, &fops_vmem_alloc);
-
-exit:
- return debugfs_root;
-}
-
-void vmem_debugfs_deinit(struct dentry *debugfs_root)
-{
- debugfs_remove_recursive(debugfs_root);
-}
-
diff --git a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.h b/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.h
deleted file mode 100644
index 8b716cc..0000000
--- a/drivers/media/platform/msm/vidc/vmem/vmem_debugfs.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/*
- * Copyright (c) 2014, 2017 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 __VMEM_DEBUGFS_H__
-#define __VMEM_DEBUGFS_H__
-
-#include <linux/debugfs.h>
-
-struct dentry *vmem_debugfs_init(struct platform_device *pdev);
-void vmem_debugfs_deinit(struct dentry *debugfs_root);
-
-#endif /* __VMEM_DEBUGFS_H__ */
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index f8a7555..64e1f43 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -677,7 +677,7 @@
rc = smblib_get_prop_fcc_delta(chg, val);
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
- val->intval = get_effective_result(chg->usb_icl_votable);
+ rc = smblib_get_icl_current(chg, &val->intval);
break;
default:
pr_debug("get prop %d is not supported in usb-main\n", psp);
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index f4ae415..6eb7009 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -812,6 +812,28 @@
return rc;
}
+static int get_sdp_current(struct smb_charger *chg, int *icl_ua)
+{
+ int rc;
+ u8 icl_options;
+ bool usb3 = false;
+
+ rc = smblib_read(chg, USBIN_ICL_OPTIONS_REG, &icl_options);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get ICL options rc=%d\n", rc);
+ return rc;
+ }
+
+ usb3 = (icl_options & CFG_USB3P0_SEL_BIT);
+
+ if (icl_options & USB51_MODE_BIT)
+ *icl_ua = usb3 ? USBIN_900MA : USBIN_500MA;
+ else
+ *icl_ua = usb3 ? USBIN_150MA : USBIN_100MA;
+
+ return rc;
+}
+
int smblib_set_icl_current(struct smb_charger *chg, int icl_ua)
{
int rc = 0;
@@ -889,6 +911,48 @@
return rc;
}
+int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua)
+{
+ int rc = 0;
+ u8 load_cfg;
+ bool override;
+ union power_supply_propval pval;
+
+ rc = smblib_get_prop_typec_mode(chg, &pval);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get typeC mode rc = %d\n", rc);
+ return rc;
+ }
+
+ if ((pval.intval == POWER_SUPPLY_TYPEC_SOURCE_DEFAULT
+ || chg->micro_usb_mode)
+ && (chg->usb_psy_desc.type == POWER_SUPPLY_TYPE_USB)) {
+ rc = get_sdp_current(chg, icl_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get SDP ICL rc=%d\n", rc);
+ return rc;
+ }
+ } else {
+ rc = smblib_read(chg, USBIN_LOAD_CFG_REG, &load_cfg);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get load cfg rc=%d\n", rc);
+ return rc;
+ }
+ override = load_cfg & ICL_OVERRIDE_AFTER_APSD_BIT;
+ if (!override)
+ return INT_MAX;
+
+ /* override is set */
+ rc = smblib_get_charge_param(chg, &chg->param.usb_icl, icl_ua);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't get HC ICL rc=%d\n", rc);
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
/*********************
* VOTABLE CALLBACKS *
*********************/
@@ -2822,7 +2886,7 @@
int smblib_get_charge_current(struct smb_charger *chg,
int *total_current_ua)
{
- const struct apsd_result *apsd_result = smblib_update_usb_type(chg);
+ const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
union power_supply_propval val = {0, };
int rc = 0, typec_source_rd, current_ua;
bool non_compliant;
@@ -3094,12 +3158,28 @@
}
}
-static void smblib_typec_usb_plugin(struct smb_charger *chg, bool vbus_rising)
+void smblib_usb_plugin_hard_reset_locked(struct smb_charger *chg)
{
+ int rc;
+ u8 stat;
+ bool vbus_rising;
+
+ rc = smblib_read(chg, USBIN_BASE + INT_RT_STS_OFFSET, &stat);
+ if (rc < 0) {
+ smblib_err(chg, "Couldn't read USB_INT_RT_STS rc=%d\n", rc);
+ return;
+ }
+
+ vbus_rising = (bool)(stat & USBIN_PLUGIN_RT_STS_BIT);
+
if (vbus_rising)
smblib_cc2_sink_removal_exit(chg);
else
smblib_cc2_sink_removal_enter(chg);
+
+ power_supply_changed(chg->usb_psy);
+ smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
+ vbus_rising ? "attached" : "detached");
}
#define PL_DELAY_MS 30000
@@ -3158,8 +3238,6 @@
if (chg->micro_usb_mode)
smblib_micro_usb_plugin(chg, vbus_rising);
- else
- smblib_typec_usb_plugin(chg, vbus_rising);
power_supply_changed(chg->usb_psy);
smblib_dbg(chg, PR_INTERRUPT, "IRQ: usbin-plugin %s\n",
@@ -3172,7 +3250,10 @@
struct smb_charger *chg = irq_data->parent_data;
mutex_lock(&chg->lock);
- smblib_usb_plugin_locked(chg);
+ if (chg->pd_hard_reset)
+ smblib_usb_plugin_hard_reset_locked(chg);
+ else
+ smblib_usb_plugin_locked(chg);
mutex_unlock(&chg->lock);
return IRQ_HANDLED;
}
@@ -3336,7 +3417,7 @@
static void smblib_handle_hvdcp_check_timeout(struct smb_charger *chg,
bool rising, bool qc_charger)
{
- const struct apsd_result *apsd_result = smblib_update_usb_type(chg);
+ const struct apsd_result *apsd_result = smblib_get_apsd_result(chg);
/* Hold off PD only until hvdcp 2.0 detection timeout */
if (rising) {
diff --git a/drivers/power/supply/qcom/smb-lib.h b/drivers/power/supply/qcom/smb-lib.h
index 5409166..e4679f4 100644
--- a/drivers/power/supply/qcom/smb-lib.h
+++ b/drivers/power/supply/qcom/smb-lib.h
@@ -495,6 +495,7 @@
int smblib_dp_dm(struct smb_charger *chg, int val);
int smblib_rerun_aicl(struct smb_charger *chg);
int smblib_set_icl_current(struct smb_charger *chg, int icl_ua);
+int smblib_get_icl_current(struct smb_charger *chg, int *icl_ua);
int smblib_get_charge_current(struct smb_charger *chg, int *total_current_ua);
int smblib_init(struct smb_charger *chg);
diff --git a/drivers/power/supply/qcom/smb138x-charger.c b/drivers/power/supply/qcom/smb138x-charger.c
index a29871b..8725590 100644
--- a/drivers/power/supply/qcom/smb138x-charger.c
+++ b/drivers/power/supply/qcom/smb138x-charger.c
@@ -598,6 +598,26 @@
POWER_SUPPLY_PROP_CHARGER_TEMP_MAX,
};
+static int smb138x_get_parallel_charging(struct smb138x *chip, int *disabled)
+{
+ struct smb_charger *chg = &chip->chg;
+ int rc = 0;
+ u8 cfg2;
+
+ rc = smblib_read(chg, CHGR_CFG2_REG, &cfg2);
+ if (rc < 0) {
+ pr_err("Couldn't read en_cmg_reg rc=%d\n", rc);
+ return rc;
+ }
+
+ if (cfg2 & CHG_EN_SRC_BIT)
+ *disabled = 0;
+ else
+ *disabled = 1;
+
+ return 0;
+}
+
static int smb138x_parallel_get_prop(struct power_supply *psy,
enum power_supply_property prop,
union power_supply_propval *val)
@@ -624,7 +644,7 @@
val->intval = !(temp & DISABLE_CHARGING_BIT);
break;
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
- rc = smblib_get_usb_suspend(chg, &val->intval);
+ rc = smb138x_get_parallel_charging(chip, &val->intval);
break;
case POWER_SUPPLY_PROP_INPUT_CURRENT_LIMITED:
if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
@@ -694,28 +714,33 @@
return rc;
}
-static int smb138x_set_parallel_suspend(struct smb138x *chip, bool suspend)
+static int smb138x_set_parallel_charging(struct smb138x *chip, bool disable)
{
struct smb_charger *chg = &chip->chg;
int rc = 0;
rc = smblib_masked_write(chg, WD_CFG_REG, WDOG_TIMER_EN_BIT,
- suspend ? 0 : WDOG_TIMER_EN_BIT);
+ disable ? 0 : WDOG_TIMER_EN_BIT);
if (rc < 0) {
pr_err("Couldn't %s watchdog rc=%d\n",
- suspend ? "disable" : "enable", rc);
- suspend = true;
+ disable ? "disable" : "enable", rc);
+ disable = true;
}
- rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT,
- suspend ? USBIN_SUSPEND_BIT : 0);
+ /*
+ * Configure charge enable for high polarity and
+ * When disabling charging set it to cmd register control(cmd bit=0)
+ * When enabling charging set it to pin control
+ */
+ rc = smblib_masked_write(chg, CHGR_CFG2_REG,
+ CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT,
+ disable ? 0 : CHG_EN_SRC_BIT);
if (rc < 0) {
- pr_err("Couldn't %s parallel charger rc=%d\n",
- suspend ? "suspend" : "resume", rc);
+ pr_err("Couldn't configure charge enable source rc=%d\n", rc);
return rc;
}
- return rc;
+ return 0;
}
static int smb138x_parallel_set_prop(struct power_supply *psy,
@@ -728,7 +753,7 @@
switch (prop) {
case POWER_SUPPLY_PROP_INPUT_SUSPEND:
- rc = smb138x_set_parallel_suspend(chip, (bool)val->intval);
+ rc = smb138x_set_parallel_charging(chip, (bool)val->intval);
break;
case POWER_SUPPLY_PROP_CURRENT_MAX:
if ((chip->dt.pl_mode == POWER_SUPPLY_PL_USBIN_USBIN)
@@ -946,10 +971,25 @@
return rc;
}
- /* suspend parallel charging */
- rc = smb138x_set_parallel_suspend(chip, true);
+ /* disable the charging path when under s/w control */
+ rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG,
+ CHARGING_ENABLE_CMD_BIT, 0);
if (rc < 0) {
- pr_err("Couldn't suspend parallel charging rc=%d\n", rc);
+ pr_err("Couldn't disable charging rc=%d\n", rc);
+ return rc;
+ }
+
+ /* disable parallel charging path */
+ rc = smb138x_set_parallel_charging(chip, true);
+ if (rc < 0) {
+ pr_err("Couldn't disable parallel path rc=%d\n", rc);
+ return rc;
+ }
+
+ /* unsuspend parallel charging */
+ rc = smblib_masked_write(chg, USBIN_CMD_IL_REG, USBIN_SUSPEND_BIT, 0);
+ if (rc < 0) {
+ pr_err("Couldn't unsuspend parallel charging rc=%d\n", rc);
return rc;
}
@@ -960,24 +1000,6 @@
return rc;
}
- /* enable the charging path */
- rc = smblib_masked_write(chg, CHARGING_ENABLE_CMD_REG,
- CHARGING_ENABLE_CMD_BIT,
- CHARGING_ENABLE_CMD_BIT);
- if (rc < 0) {
- pr_err("Couldn't enable charging rc=%d\n", rc);
- return rc;
- }
-
- /* configure charge enable for software control; active high */
- rc = smblib_masked_write(chg, CHGR_CFG2_REG,
- CHG_EN_POLARITY_BIT | CHG_EN_SRC_BIT, 0);
- if (rc < 0) {
- pr_err("Couldn't configure charge enable source rc=%d\n",
- rc);
- return rc;
- }
-
/* enable parallel current sensing */
rc = smblib_masked_write(chg, CFG_REG,
VCHG_EN_CFG_BIT, VCHG_EN_CFG_BIT);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index dc74484..2f6cd95 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -10054,7 +10054,8 @@
mb();
/* IRQ registration */
- err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED, UFSHCD, hba);
+ err = devm_request_irq(dev, irq, ufshcd_intr, IRQF_SHARED,
+ dev_name(dev), hba);
if (err) {
dev_err(hba->dev, "request irq failed\n");
goto exit_gating;
diff --git a/drivers/soc/qcom/llcc-sdm845.c b/drivers/soc/qcom/llcc-sdm845.c
index 0a28ee0..be2b7da 100644
--- a/drivers/soc/qcom/llcc-sdm845.c
+++ b/drivers/soc/qcom/llcc-sdm845.c
@@ -65,20 +65,15 @@
SCT_ENTRY("audio", 6, 6, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
SCT_ENTRY("modemhp_grow", 7, 7, 1024, 2, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
SCT_ENTRY("modem", 8, 8, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
- SCT_ENTRY("modemhw", 9, 9, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
SCT_ENTRY("compute", 10, 10, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
- SCT_ENTRY("gpuhtw", 11, 11, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
- SCT_ENTRY("gpu", 12, 12, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
+ SCT_ENTRY("gpuhtw", 11, 11, 515, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
+ SCT_ENTRY("gpu", 12, 12, 2560, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
SCT_ENTRY("mmuhwt", 13, 13, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 1),
- SCT_ENTRY("sensor", 14, 14, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
SCT_ENTRY("compute_dma", 15, 15, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
SCT_ENTRY("display", 16, 16, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
- SCT_ENTRY("videofw", 17, 17, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
- SCT_ENTRY("camerafw", 18, 18, 256, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
- SCT_ENTRY("mss_tcm", 19, 19, 1024, 0, 0, 0x0, 0xf, 1, 0, 1, 1, 0),
SCT_ENTRY("modemhp_fix", 20, 20, 1024, 2, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
SCT_ENTRY("modem_paging", 21, 21, 1024, 0, 1, 0xF, 0x0, 0, 0, 0, 1, 0),
- SCT_ENTRY("audiohw", 22, 22, 3072, 1, 0, 0xFFF, 0x0, 0, 0, 0, 1, 0),
+ SCT_ENTRY("audiohw", 22, 22, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 1, 0),
};
static int sdm845_qcom_llcc_probe(struct platform_device *pdev)
diff --git a/include/linux/dma-iommu.h b/include/linux/dma-iommu.h
index 32c5890..7f7e9a7 100644
--- a/include/linux/dma-iommu.h
+++ b/include/linux/dma-iommu.h
@@ -61,6 +61,10 @@
enum dma_data_direction dir, unsigned long attrs);
void iommu_dma_unmap_sg(struct device *dev, struct scatterlist *sg, int nents,
enum dma_data_direction dir, unsigned long attrs);
+dma_addr_t iommu_dma_map_resource(struct device *dev, phys_addr_t phys,
+ size_t size, enum dma_data_direction dir, unsigned long attrs);
+void iommu_dma_unmap_resource(struct device *dev, dma_addr_t handle,
+ size_t size, enum dma_data_direction dir, unsigned long attrs);
int iommu_dma_supported(struct device *dev, u64 mask);
int iommu_dma_mapping_error(struct device *dev, dma_addr_t dma_addr);
diff --git a/sound/soc/msm/qdsp6v2/msm-lsm-client.c b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
index 37dd31f..421769e 100644
--- a/sound/soc/msm/qdsp6v2/msm-lsm-client.c
+++ b/sound/soc/msm/qdsp6v2/msm-lsm-client.c
@@ -1165,28 +1165,27 @@
break;
case SNDRV_LSM_SET_FWK_MODE_CONFIG: {
- u32 *mode = NULL;
+ u32 mode;
- if (!arg) {
- dev_err(rtd->dev,
- "%s: Invalid param arg for ioctl %s session %d\n",
- __func__, "SNDRV_LSM_SET_FWK_MODE_CONFIG",
- prtd->lsm_client->session);
- rc = -EINVAL;
- break;
+ if (copy_from_user(&mode, arg, sizeof(mode))) {
+ dev_err(rtd->dev, "%s: %s: copy_frm_user failed\n",
+ __func__, "LSM_SET_FWK_MODE_CONFIG");
+ return -EFAULT;
}
- mode = (u32 *)arg;
- if (prtd->lsm_client->event_mode == *mode) {
+
+ dev_dbg(rtd->dev, "%s: ioctl %s, enable = %d\n",
+ __func__, "SNDRV_LSM_SET_FWK_MODE_CONFIG", mode);
+ if (prtd->lsm_client->event_mode == mode) {
dev_dbg(rtd->dev,
"%s: mode for %d already set to %d\n",
- __func__, prtd->lsm_client->session, *mode);
+ __func__, prtd->lsm_client->session, mode);
rc = 0;
} else {
dev_dbg(rtd->dev, "%s: Event mode = %d\n",
- __func__, *mode);
- rc = q6lsm_set_fwk_mode_cfg(prtd->lsm_client, *mode);
+ __func__, mode);
+ rc = q6lsm_set_fwk_mode_cfg(prtd->lsm_client, mode);
if (!rc)
- prtd->lsm_client->event_mode = *mode;
+ prtd->lsm_client->event_mode = mode;
else
dev_err(rtd->dev,
"%s: set event mode failed %d\n",