summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinux Build Service Account <lnxbuild@localhost>2016-08-17 11:20:38 -0600
committerLinux Build Service Account <lnxbuild@localhost>2016-08-17 11:20:39 -0600
commitd0c25e98778cc543ecbd51e24bd21376ada1466d (patch)
tree4b6f5d9e1cd45dae760b6ab6cda5e0e8ca3945d1
parentd1a3280d68d7f442142eda95fd2592ff3afada89 (diff)
parent008f057bbab6dd6629b7e1a3b8c67b650a6b9ef1 (diff)
Promotion of kernel.lnx.4.4-160817.
CRs Change ID Subject -------------------------------------------------------------------------------------------------------------- 1053499 I1c54b6ab1c27c9b1a7601f809184d27b78ac6e8b tty: serial: msm: Move header file into driver 1053499 Ic480a989bb65b1924f3bd6d38927d1fe54eaaeee tty: serial: msm: Support more bauds 1054373 I12d3a22362b965c7d302976c83ab0e757c98d3c6 Revert "arm64: Add support for app specific settings" 1053499 I893ebd28a3e4e7afe8080bcc3e000970fe1fa36b earlycon: Use common framework for earlycon declarations 1049617 I1697139a0c7cf84e20d3a8c3747a1e96f765139a msm: vidc: Delay output buffer setting to FW 1051284 Icd3aedb9efc702d6bec0d4966d87f10c235d83e9 defconfig: msm: enable IRQ off and preempt off tracers 1046094 I521059ab1c1d95df95fdede84512e73c5d9b2329 usb: pd: Always request maximum available current from P 1054373 I8f21787f0a45dd9f7be8986b4f332f498add3203 Revert "arm64: fpsimd: Enable FP(floating-point) setting 886063 I3c56dffb4ca197e8fc23d54a44282a60254dd001 ASoC: soundwire: fix out of boundary access issues 1048345 I5eb1318d1e3a62619869033b36479c4e68f1602f soc: qcom: Fix compilation warning/error 1053499 I0a336cc928bbff5bba253281ff7deca52414ba9d tty: serial: msm: Only configure MND registers on hw tha 1054373 I8d11c596d61f0435f4ee2d1007f4903843650aed Revert "arm64: fpsimd: add support to enable/disable fps 997062 I1fde78158af71d57c958ac9f5668d4b65c9a7a3f ASoC: wcd: set pointer to null after kfree 1053687 Ib704bfa6c6ca9fc3d90ab76a2e4aef02dc48822a msm: mdss: update voltage level configuration for CX sup 1047362 1047365 I632c1dc7136a49c07b587a03181b5b4da42bdd4b ARM: dts: msm: define pinctrl for MI2S and PCM devices f 1050304 I4ef01c7bdb9af770ea3014bd6e63d3c17b0cfa47 msm: mdss: add aux read/write support for hdcp 1052513 I8df74307d4c3461198de0a58f6b8ec7c8bef1f12 ion_page_pool: Remove prealloc tracking 1051156 I15a01a772198e0383b1b73052e2d0c4160bf389f ARM: dts: msm: Add QoS clocks to MDP nodes for msmcobalt 1052513 Ia9030bcb6b404b080cb8bebb91ca7bf03c5f3e05 ion: Remove "FIXME" comment 1054226 I33e5ddb318200535c3563f5670059144e0f5eba8 sched/fair: Don't check for migration for a pinned task 997062 Ifa27a21cb76688101b758a34eddf69b160c27c79 ASoC: msm: set pointer to null after kfree 1028059 I7e57a4d6c67a58728bb3ef7f3ea0312380f84486 msm: camera: sensor: Detect flash_driver_type from dtsi 997062 I18bd73397173187f87af28c78564835eed6d6a10 swr-wcd-ctrl: set pointer to null after kfree 1054474 Iadaafa64d2c1908b04498d0a88dd612dbc36dae8 msm: mdss: remove always source split quirk setting 1054447 Ia0bd3026025c1215c595219a19cc164bc3758363 defconfig: msm: enable GIC_V3_ACL access control on msmc 1053808 I5d0cb3fcc711d22eada0983b6b660da7be1d9a3e ARM: dts: msm: Add PSCI support for msmfalcon 1052513 I5ab82f717bb003e074124e1ffae3f112c405bc2b ion_page_pool: Remove GFP_COMP from page allocation mask 1050517 Ia8f5e0b9e86b49077f15db8da2dc7a3cda6b1748 ARM: dts: msm: Add support for reset clocks for MSM8996 1009284 I4aa64724a912ae1df07d382d3eb346424b50cf36 msm: mdss: validate codec operations during HPD process 1049420 Ifda5783f7bf33ba20a3ee3749410560f7864a4f3 msm: vidc: fix CONSTRAINED_INTRA_PRED setting 1053538 Ic7523e68d65634f28babac6d17e0b02311d7ad79 ARM: dts: msm: Add bus bandwidth entry for ICNSS 1053499 Ib6da8e064171dffe5a8652e49a51c9b7bed96170 tty: serial: msm: Cleanup include usage 1009284 I93b43be6c2ca50796148898f5210c5b4d13b6f24 mdss: display-port: add support for edid read 1051435 I65f854e184606684ce2ca711f19cf61d26c1ecb5 soc: qcom: Initialize message pointer with NULL 1054373 I9464305f6cac6aedb3e5763979dba4cba92e050b Revert "defconfig: arm64: Enable app specific setting on 1048727 I093e494800dacefda447b27da4fc2ea9c0cdeda6 msm: mdss: disable scaler for pipes with solid_fill 1053499 Icea65c8df570eb4d8cb22a421b89fa03dc33f659 tty: serial: msm: fix definition of msm_stop_dma 1050304 I16bf5ecbc237294e99ce6710c6b759e3346011a5 msm: mdss: add display-port hdcp's register set 1053538 I5e300cf81bd8b653e9a5611ed60b2b770e94a863 icnss: Vote aggre2_noc_clk through bus bandwidth framewo 1050304 I62738697e91549fe44ef09b0a3aa905b37c00389 msm: mdss: generalize the hdcp 1.x registers programming 1053499 Ib05d8a73a516d7591868c87fd60ff227835d8609 tty:serial:msm:Do not restore Rx interrupts in DMA 1051287 I99fdc57e1d0cde48ac5192d83ced96848232eb41 defconfig: msmcortex: Enable CONFIG_MSM_AVTIMER 1001194 I52e6978b1c104fd78bc42e4600ceb111b47b3e11 perf: add hotplug support so that perf continues after h 1050304 I8be206dbc53fd7c757f244dc544241f1d8e1dd1c msm: mdss: add support for hdcp 1.x interrupt handler 1053499 I029ac3c7a20fdce9b5dfd0bbde8a049ff47dc4bd tty: msm_serial: remove static clk rate setting in probe 1041251 1050177 I9014831c92a6ba16450f48d7f6eb831e47b5e0ab msm: camera: sensor: Add META10 fourcc 1046456 Ifaa687b036eeab22ab4cf0238abdfbe7b2311ed3 msm: kgsl: Add sparse memory support 1001194 I61f7a7474856abf67ac6dfd9e531702072e108a5 perf: Add support for exclude_idle attribute 1051170 I4d6547d95bd76d8ca6f4d729009d8b4a78716d5b clk: msm: clock: Update clock frequencies on MSMCOBALT 1051959 Id2e764210e3ca9e12a3d8299bf0c585958bbd7c8 ARM: dts: msm: Update qusb2 phy init sequence for msmcob 1048743 Icff3c15a4f1d26f43274465063259f06737fe495 ASoC: msmcobalt: remove custom PM QoS for Low-latency pl 1052522 Ibf1f086be4c6692479c11cb4585954c5d3c91707 iommu: dma-mapping-fast: Add mmap support 1051287 Ia646ddb1ae550a8b604f41545f738771204ac48e soc: qcom: add apr_glink as dependency for AVTimer kconf 1053499 Ia6127c3a18e8909171c4b24c633e361245d1ed72 tty: serial: msm: Don't read off end of tx fifo 1054373 I0d2c9bc8f27c2ac938754ab97b4bdc7feb6325b1 Revert "defconfig: arm64: Enable FP settings for msm8996 1052522 I88ddd98a76b39e3e9126d78da8e725491f2a5b32 arm/arm64: dma-mapping: Fix iova region size 997062 I5dd4a9dd8f757d0850d75575d7e522e2a22f46f3 ASoC: wcd9xxx: set pointer to null after kfree 1052513 I1353c5d9bdfd5c525c0c781c524630577c84b95e ion: system_heap: Add a new allocation method Change-Id: I46358c9ab9b5e47c56df9998e03f30b851eb318c CRs-Fixed: 1052522, 1028059, 1009284, 1050177, 1048345, 1054474, 1047362, 1051959, 1054373, 1047365, 1053687, 1051170, 1046094, 1050304, 997062, 1001194, 1051156, 1049617, 886063, 1053499, 1051435, 1052513, 1048743, 1050517, 1046456, 1051287, 1048727, 1053538, 1054447, 1041251, 1049420, 1053808, 1054226, 1051284
-rw-r--r--Documentation/devicetree/bindings/fb/mdss-mdp.txt6
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-bus.dtsi21
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi937
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi23
-rw-r--r--arch/arm/boot/dts/qcom/msmcobalt.dtsi7
-rw-r--r--arch/arm/boot/dts/qcom/msmfalcon.dtsi5
-rw-r--r--arch/arm/boot/dts/qcom/msmhamster.dtsi16
-rw-r--r--arch/arm/mm/dma-mapping.c2
-rw-r--r--arch/arm64/Kconfig31
-rw-r--r--arch/arm64/configs/msm-perf_defconfig2
-rw-r--r--arch/arm64/configs/msm_defconfig2
-rw-r--r--arch/arm64/configs/msmcortex-perf_defconfig2
-rw-r--r--arch/arm64/configs/msmcortex_defconfig4
-rw-r--r--arch/arm64/include/asm/app_api.h42
-rw-r--r--arch/arm64/include/asm/elf.h7
-rw-r--r--arch/arm64/include/asm/fpsimd.h8
-rw-r--r--arch/arm64/kernel/Makefile2
-rw-r--r--arch/arm64/kernel/app_api.c75
-rw-r--r--arch/arm64/kernel/app_setting.c120
-rw-r--r--arch/arm64/kernel/entry-fpsimd.S16
-rw-r--r--arch/arm64/kernel/entry.S13
-rw-r--r--arch/arm64/kernel/fpsimd.c49
-rw-r--r--arch/arm64/kernel/perf_event.c65
-rw-r--r--arch/arm64/mm/dma-mapping.c2
-rw-r--r--drivers/base/regmap/regmap-swr.c23
-rw-r--r--drivers/clk/msm/clock-gpu-cobalt.c80
-rw-r--r--drivers/clk/msm/clock-mmss-cobalt.c73
-rw-r--r--drivers/gpu/msm/kgsl.c602
-rw-r--r--drivers/gpu/msm/kgsl.h37
-rw-r--r--drivers/gpu/msm/kgsl_compat.c12
-rw-r--r--drivers/gpu/msm/kgsl_debugfs.c81
-rw-r--r--drivers/gpu/msm/kgsl_ioctl.c12
-rw-r--r--drivers/gpu/msm/kgsl_iommu.c165
-rw-r--r--drivers/gpu/msm/kgsl_mmu.c93
-rw-r--r--drivers/gpu/msm/kgsl_mmu.h6
-rw-r--r--drivers/gpu/msm/kgsl_sharedmem.h34
-rw-r--r--drivers/gpu/msm/kgsl_snapshot.c7
-rw-r--r--drivers/gpu/msm/kgsl_trace.h94
-rw-r--r--drivers/iommu/dma-mapping-fast.c29
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c3
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c15
-rw-r--r--drivers/media/platform/msm/vidc/msm_vdec.c128
-rw-r--r--drivers/media/platform/msm/vidc/msm_venc.c2
-rw-r--r--drivers/media/platform/msm/vidc/msm_vidc_common.c6
-rw-r--r--drivers/mfd/wcd9xxx-irq.c1
-rw-r--r--drivers/of/fdt.c14
-rw-r--r--drivers/perf/arm_pmu.c128
-rw-r--r--drivers/soc/qcom/Kconfig2
-rw-r--r--drivers/soc/qcom/icnss.c92
-rw-r--r--drivers/soc/qcom/service-locator.c4
-rw-r--r--drivers/soundwire/swr-wcd-ctrl.c5
-rw-r--r--drivers/staging/android/ion/ion_page_pool.c60
-rw-r--r--drivers/staging/android/ion/ion_priv.h6
-rw-r--r--drivers/staging/android/ion/ion_system_heap.c123
-rw-r--r--drivers/staging/android/ion/ion_system_secure_heap.c3
-rw-r--r--drivers/staging/android/uapi/msm_ion.h3
-rw-r--r--drivers/tty/serial/amba-pl011.c1
-rw-r--r--drivers/tty/serial/arc_uart.c1
-rw-r--r--drivers/tty/serial/earlycon.c10
-rw-r--r--drivers/tty/serial/msm_serial.c300
-rw-r--r--drivers/tty/serial/msm_serial.h184
-rw-r--r--drivers/tty/serial/samsung.c6
-rw-r--r--drivers/tty/serial/sprd_serial.c2
-rw-r--r--drivers/usb/pd/policy_engine.c16
-rw-r--r--drivers/video/fbdev/msm/mdss.h2
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.c69
-rw-r--r--drivers/video/fbdev/msm/mdss_dp.h13
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_aux.c92
-rw-r--r--drivers/video/fbdev/msm/mdss_dp_util.h39
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_hdcp.c1006
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_hdcp.h10
-rw-r--r--drivers/video/fbdev/msm/mdss_hdmi_tx.c1
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp.c27
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_layer.c5
-rw-r--r--drivers/video/fbdev/msm/mdss_mdp_pipe.c16
-rw-r--r--drivers/video/fbdev/msm/msm_ext_display.c24
-rw-r--r--include/asm-generic/vmlinux.lds.h6
-rw-r--r--include/dt-bindings/clock/msm-clocks-cobalt.h4
-rw-r--r--include/dt-bindings/clock/msm-clocks-hwio-cobalt.h2
-rw-r--r--include/linux/mm_types.h4
-rw-r--r--include/linux/serial_core.h22
-rw-r--r--include/soc/qcom/service-locator.h2
-rw-r--r--include/soc/qcom/service-notifier.h2
-rw-r--r--include/uapi/linux/msm_kgsl.h99
-rw-r--r--include/uapi/media/msm_cam_sensor.h1
-rw-r--r--include/uapi/media/msmb_isp.h1
-rw-r--r--kernel/events/core.c30
-rw-r--r--kernel/sched/core.c8
-rw-r--r--kernel/sched/fair.c3
-rw-r--r--mm/mmap.c9
-rw-r--r--sound/soc/codecs/wcd9330.c8
-rw-r--r--sound/soc/codecs/wcd9335.c8
-rw-r--r--sound/soc/codecs/wcd934x/wcd934x.c4
-rw-r--r--sound/soc/msm/msm-audio-pinctrl.c26
-rw-r--r--sound/soc/msm/msmcobalt.c27
97 files changed, 3748 insertions, 1745 deletions
diff --git a/Documentation/devicetree/bindings/fb/mdss-mdp.txt b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
index 93cacc07e623..c8cf395d5669 100644
--- a/Documentation/devicetree/bindings/fb/mdss-mdp.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-mdp.txt
@@ -243,6 +243,12 @@ Bus Scaling Data:
Optional properties:
- batfet-supply : Phandle for battery FET regulator device node.
- vdd-cx-supply : Phandle for vdd CX regulator device node.
+- vdd-cx-min-uV : The minimum voltage level in uV for the CX rail
+ whenever the display is on. If vdd-cx-supply is
+ specified, then this binding is mandatory.
+- vdd-cx-max-uV : The maximum voltage level in uV for the CX rail
+ whenever the display is on. If vdd-cx-supply is
+ specified, then this binding is mandatory.
- qcom,vbif-settings : Array with key-value pairs of constant VBIF register
settings used to setup MDSS QoS for optimum performance.
The key used should be offset from "vbif_phys" register
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index bc8f998d197b..aa973e4ee3d6 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -808,6 +808,7 @@
<&mdss_dsi1_pll clk_dsi1pll_byte_clk_mux>,
<&mdss_hdmi_pll clk_hdmi_vco_clk>;
#clock-cells = <1>;
+ #reset-cells = <1>;
};
clock_gpu: qcom,gpucc@8c0000 {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-bus.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-bus.dtsi
index 86decf438430..edf7e7b9cbb0 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-bus.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-bus.dtsi
@@ -131,10 +131,6 @@
clock-names = "bus_clk", "bus_a_clk";
clocks = <&clock_gcc clk_mmssnoc_axi_clk>,
<&clock_gcc clk_mmssnoc_axi_a_clk>;
- clk-mdss-axi-no-rate-supply =
- <&gdsc_mdss>;
- clk-mdss-ahb-no-rate-supply =
- <&gdsc_mdss>;
clk-camss-ahb-no-rate-supply =
<&gdsc_camss_top>;
clk-video-ahb-no-rate-supply =
@@ -145,8 +141,6 @@
clock-names =
"clk-noc-cfg-ahb-no-rate",
"clk-mnoc-ahb-no-rate",
- "clk-mdss-ahb-no-rate",
- "clk-mdss-axi-no-rate",
"clk-camss-ahb-no-rate",
"clk-video-ahb-no-rate",
"clk-video-axi-no-rate";
@@ -154,8 +148,6 @@
<&clock_gcc clk_mmssnoc_axi_clk>,
<&clock_gcc clk_gcc_mmss_noc_cfg_ahb_clk>,
<&clock_mmss clk_mmss_mnoc_ahb_clk>,
- <&clock_mmss clk_mmss_mdss_ahb_clk>,
- <&clock_mmss clk_mmss_mdss_axi_clk>,
<&clock_mmss clk_mmss_camss_ahb_clk>,
<&clock_mmss clk_mmss_video_ahb_clk>,
<&clock_mmss clk_mmss_video_axi_clk>;
@@ -535,6 +527,19 @@
qcom,bus-dev = <&fab_mnoc>;
qcom,vrail-comp = <25>;
qcom,mas-rpm-id = <ICBID_MASTER_MDP0>;
+ clk-mdss-axi-no-rate-supply =
+ <&gdsc_mdss>;
+ clk-mdss-ahb-no-rate-supply =
+ <&gdsc_mdss>;
+ qcom,node-qos-clks {
+ clock-names =
+ "clk-mdss-ahb-no-rate",
+ "clk-mdss-axi-no-rate";
+ clocks =
+ <&clock_mmss clk_mmss_mdss_ahb_clk>,
+ <&clock_mmss clk_mmss_mdss_axi_clk>;
+ };
+
};
mas_mdp_p1: mas-mdp-p1 {
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
index 24e23d00d697..c0f465b0eba5 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-pinctrl.dtsi
@@ -1778,5 +1778,942 @@
bias-pull-up;
};
};
+
+ pri_aux_pcm_clk {
+ pri_aux_pcm_clk_sleep: pri_aux_pcm_clk_sleep {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio65";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_aux_pcm_clk_active: pri_aux_pcm_clk_active {
+ mux {
+ pins = "gpio65";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio65";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_aux_pcm_sync {
+ pri_aux_pcm_sync_sleep: pri_aux_pcm_sync_sleep {
+ mux {
+ pins = "gpio66";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio66";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_aux_pcm_sync_active: pri_aux_pcm_sync_active {
+ mux {
+ pins = "gpio66";
+ function = "pri_mi2s_ws";
+ };
+
+ config {
+ pins = "gpio66";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_aux_pcm_din {
+ pri_aux_pcm_din_sleep: pri_aux_pcm_din_sleep {
+ mux {
+ pins = "gpio67";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_aux_pcm_din_active: pri_aux_pcm_din_active {
+ mux {
+ pins = "gpio67";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ pri_aux_pcm_dout {
+ pri_aux_pcm_dout_sleep: pri_aux_pcm_dout_sleep {
+ mux {
+ pins = "gpio68";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio68";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_aux_pcm_dout_active: pri_aux_pcm_dout_active {
+ mux {
+ pins = "gpio68";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio68";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_aux_pcm {
+ sec_aux_pcm_sleep: sec_aux_pcm_sleep {
+ mux {
+ pins = "gpio80", "gpio81";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio80", "gpio81";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_aux_pcm_active: sec_aux_pcm_active {
+ mux {
+ pins = "gpio80", "gpio81";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio80", "gpio81";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_aux_pcm_din {
+ sec_aux_pcm_din_sleep: sec_aux_pcm_din_sleep {
+ mux {
+ pins = "gpio82";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio82";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_aux_pcm_din_active: sec_aux_pcm_din_active {
+ mux {
+ pins = "gpio82";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio82";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_aux_pcm_dout {
+ sec_aux_pcm_dout_sleep: sec_aux_pcm_dout_sleep {
+ mux {
+ pins = "gpio83";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio83";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_aux_pcm_dout_active: sec_aux_pcm_dout_active {
+ mux {
+ pins = "gpio83";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio83";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ tert_aux_pcm {
+ tert_aux_pcm_sleep: tert_aux_pcm_sleep {
+ mux {
+ pins = "gpio75", "gpio76";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio75", "gpio76";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_aux_pcm_active: tert_aux_pcm_active {
+ mux {
+ pins = "gpio75", "gpio76";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio75", "gpio76";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ tert_aux_pcm_din {
+ tert_aux_pcm_din_sleep: tert_aux_pcm_din_sleep {
+ mux {
+ pins = "gpio77";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio77";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_aux_pcm_din_active: tert_aux_pcm_din_active {
+ mux {
+ pins = "gpio77";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio77";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ tert_aux_pcm_dout {
+ tert_aux_pcm_dout_sleep: tert_aux_pcm_dout_sleep {
+ mux {
+ pins = "gpio78";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_aux_pcm_dout_active: tert_aux_pcm_dout_active {
+ mux {
+ pins = "gpio78";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_aux_pcm {
+ quat_aux_pcm_sleep: quat_aux_pcm_sleep {
+ mux {
+ pins = "gpio58", "gpio59";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio58", "gpio59";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_aux_pcm_active: quat_aux_pcm_active {
+ mux {
+ pins = "gpio58", "gpio59";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio58", "gpio59";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ quat_aux_pcm_din {
+ quat_aux_pcm_din_sleep: quat_aux_pcm_din_sleep {
+ mux {
+ pins = "gpio60";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio60";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_aux_pcm_din_active: quat_aux_pcm_din_active {
+ mux {
+ pins = "gpio60";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio60";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_aux_pcm_dout {
+ quat_aux_pcm_dout_sleep: quat_aux_pcm_dout_sleep {
+ mux {
+ pins = "gpio61";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio61";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_aux_pcm_dout_active: quat_aux_pcm_dout_active {
+ mux {
+ pins = "gpio61";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio61";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ pri_mi2s_mclk {
+ pri_mi2s_mclk_sleep: pri_mi2s_mclk_sleep {
+ mux {
+ pins = "gpio64";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio64";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_mclk_active: pri_mi2s_mclk_active {
+ mux {
+ pins = "gpio64";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio64";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_mi2s_sck {
+ pri_mi2s_sck_sleep: pri_mi2s_sck_sleep {
+ mux {
+ pins = "gpio65";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio65";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_sck_active: pri_mi2s_sck_active {
+ mux {
+ pins = "gpio65";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio65";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_mi2s_ws {
+ pri_mi2s_ws_sleep: pri_mi2s_ws_sleep {
+ mux {
+ pins = "gpio66";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio66";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_ws_active: pri_mi2s_ws_active {
+ mux {
+ pins = "gpio66";
+ function = "pri_mi2s_ws";
+ };
+
+ config {
+ pins = "gpio66";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ pri_mi2s_sd0 {
+ pri_mi2s_sd0_sleep: pri_mi2s_sd0_sleep {
+ mux {
+ pins = "gpio67";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_sd0_active: pri_mi2s_sd0_active {
+ mux {
+ pins = "gpio67";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio67";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ pri_mi2s_sd1 {
+ pri_mi2s_sd1_sleep: pri_mi2s_sd1_sleep {
+ mux {
+ pins = "gpio68";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio68";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ pri_mi2s_sd1_active: pri_mi2s_sd1_active {
+ mux {
+ pins = "gpio68";
+ function = "pri_mi2s";
+ };
+
+ config {
+ pins = "gpio68";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_mi2s_mclk {
+ sec_mi2s_mclk_sleep: sec_mi2s_mclk_sleep {
+ mux {
+ pins = "gpio79";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio79";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_mi2s_mclk_active: sec_mi2s_mclk_active {
+ mux {
+ pins = "gpio79";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio79";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_mi2s {
+ sec_mi2s_sleep: sec_mi2s_sleep {
+ mux {
+ pins = "gpio80", "gpio81";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio80", "gpio81";
+ drive-strength = <2>; /* 2 mA */
+ bias-disable; /* NO PULL */
+ input-enable;
+ };
+ };
+
+ sec_mi2s_active: sec_mi2s_active {
+ mux {
+ pins = "gpio80", "gpio81";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio80", "gpio81";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_mi2s_sd0 {
+ sec_mi2s_sd0_sleep: sec_mi2s_sd0_sleep {
+ mux {
+ pins = "gpio82";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio82";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_mi2s_sd0_active: sec_mi2s_sd0_active {
+ mux {
+ pins = "gpio82";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio82";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ sec_mi2s_sd1 {
+ sec_mi2s_sd1_sleep: sec_mi2s_sd1_sleep {
+ mux {
+ pins = "gpio83";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio83";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ sec_mi2s_sd1_active: sec_mi2s_sd1_active {
+ mux {
+ pins = "gpio83";
+ function = "sec_mi2s";
+ };
+
+ config {
+ pins = "gpio83";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ tert_mi2s_mclk {
+ tert_mi2s_mclk_sleep: tert_mi2s_mclk_sleep {
+ mux {
+ pins = "gpio74";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio74";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_mi2s_mclk_active: tert_mi2s_mclk_active {
+ mux {
+ pins = "gpio74";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio74";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ tert_mi2s {
+ tert_mi2s_sleep: tert_mi2s_sleep {
+ mux {
+ pins = "gpio75", "gpio76";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio75", "gpio76";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_mi2s_active: tert_mi2s_active {
+ mux {
+ pins = "gpio75", "gpio76";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio75", "gpio76";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ tert_mi2s_sd0 {
+ tert_mi2s_sd0_sleep: tert_mi2s_sd0_sleep {
+ mux {
+ pins = "gpio77";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio77";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_mi2s_sd0_active: tert_mi2s_sd0_active {
+ mux {
+ pins = "gpio77";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio77";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ tert_mi2s_sd1 {
+ tert_mi2s_sd1_sleep: tert_mi2s_sd1_sleep {
+ mux {
+ pins = "gpio78";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ tert_mi2s_sd1_active: tert_mi2s_sd1_active {
+ mux {
+ pins = "gpio78";
+ function = "ter_mi2s";
+ };
+
+ config {
+ pins = "gpio78";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_mi2s_mclk {
+ quat_mi2s_mclk_sleep: quat_mi2s_mclk_sleep {
+ mux {
+ pins = "gpio57";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio57";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_mclk_active: quat_mi2s_mclk_active {
+ mux {
+ pins = "gpio57";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio57";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_mi2s {
+ quat_mi2s_sleep: quat_mi2s_sleep {
+ mux {
+ pins = "gpio58", "gpio59";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio58", "gpio59";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_active: quat_mi2s_active {
+ mux {
+ pins = "gpio58", "gpio59";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio58", "gpio59";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ output-high;
+ };
+ };
+ };
+
+ quat_mi2s_sd0 {
+ quat_mi2s_sd0_sleep: quat_mi2s_sd0_sleep {
+ mux {
+ pins = "gpio60";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio60";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_sd0_active: quat_mi2s_sd0_active {
+ mux {
+ pins = "gpio60";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio60";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_mi2s_sd1 {
+ quat_mi2s_sd1_sleep: quat_mi2s_sd1_sleep {
+ mux {
+ pins = "gpio61";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio61";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_sd1_active: quat_mi2s_sd1_active {
+ mux {
+ pins = "gpio61";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio61";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_mi2s_sd2 {
+ quat_mi2s_sd2_sleep: quat_mi2s_sd2_sleep {
+ mux {
+ pins = "gpio62";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio62";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_sd2_active: quat_mi2s_sd2_active {
+ mux {
+ pins = "gpio62";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio62";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
+
+ quat_mi2s_sd3 {
+ quat_mi2s_sd3_sleep: quat_mi2s_sd3_sleep {
+ mux {
+ pins = "gpio63";
+ function = "gpio";
+ };
+
+ config {
+ pins = "gpio63";
+ drive-strength = <2>; /* 2 mA */
+ bias-pull-down; /* PULL DOWN */
+ input-enable;
+ };
+ };
+
+ quat_mi2s_sd3_active: quat_mi2s_sd3_active {
+ mux {
+ pins = "gpio63";
+ function = "qua_mi2s";
+ };
+
+ config {
+ pins = "gpio63";
+ drive-strength = <8>; /* 8 mA */
+ bias-disable; /* NO PULL */
+ };
+ };
+ };
};
};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
index 238d68efaba7..c909c23774b5 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt-v2.dtsi
@@ -165,21 +165,21 @@
compatible = "qcom,gfxcc-cobalt-v2";
qcom,gfxfreq-speedbin0 =
< 0 0 0 >,
- < 189000000 1 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 264000000 2 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 180000000 1 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 257000000 2 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 342000000 3 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 414000000 4 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 520000000 5 RPM_SMD_REGULATOR_LEVEL_NOM >,
+ < 515000000 5 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 596000000 6 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 670000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >,
< 710000000 8 RPM_SMD_REGULATOR_LEVEL_TURBO >;
qcom,gfxfreq-mx-speedbin0 =
< 0 0 >,
- < 189000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 264000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 180000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 257000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 342000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 414000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 520000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
+ < 515000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 596000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >,
< 710000000 RPM_SMD_REGULATOR_LEVEL_TURBO >;
@@ -357,3 +357,14 @@
qcom,allow-quotient-interpolation;
qcom,cpr-scaled-open-loop-voltage-as-ceiling;
};
+
+&qusb_phy0 {
+ qcom,qusb-phy-init-seq =
+ /* <value reg_offset> */
+ <0x13 0x04
+ 0x7c 0x18c
+ 0x80 0x2c
+ 0x0a 0x184
+ 0x00 0x240
+ 0x19 0xb4>;
+};
diff --git a/arch/arm/boot/dts/qcom/msmcobalt.dtsi b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
index 683110415d5e..4675a374ef01 100644
--- a/arch/arm/boot/dts/qcom/msmcobalt.dtsi
+++ b/arch/arm/boot/dts/qcom/msmcobalt.dtsi
@@ -2762,8 +2762,6 @@
<0xb0000000 0x10000>;
reg-names = "membase", "mpm_config",
"smmu_iova_base", "smmu_iova_ipa";
- clocks = <&clock_gcc clk_aggre2_noc_clk>;
- clock-names = "smmu_aggre2_noc_clk";
iommus = <&anoc2_smmu 0x1900>,
<&anoc2_smmu 0x1901>;
interrupts = <0 413 0 /* CE0 */ >,
@@ -2781,6 +2779,11 @@
qcom,wlan-msa-memory = <0x100000>;
vdd-io-supply = <&pmcobalt_l5>;
qcom,vdd-io-voltage-level = <800000 800000>;
+ qcom,msm-bus,name = "msm-icnss";
+ qcom,msm-bus,num-cases = <2>;
+ qcom,msm-bus,num-paths = <1>;
+ qcom,msm-bus,vectors-KBps = <81 10065 0 0>,
+ <81 10065 0 16000>;
};
wil6210: qcom,wil6210 {
diff --git a/arch/arm/boot/dts/qcom/msmfalcon.dtsi b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
index 21fda2e6fce6..e46041cdd501 100644
--- a/arch/arm/boot/dts/qcom/msmfalcon.dtsi
+++ b/arch/arm/boot/dts/qcom/msmfalcon.dtsi
@@ -30,6 +30,11 @@
stdout-path = "serial0";
};
+ psci {
+ compatible = "arm,psci-1.0";
+ method = "smc";
+ };
+
cpus {
#address-cells = <2>;
#size-cells = <0>;
diff --git a/arch/arm/boot/dts/qcom/msmhamster.dtsi b/arch/arm/boot/dts/qcom/msmhamster.dtsi
index e87cf7c153ea..4669fa519f5d 100644
--- a/arch/arm/boot/dts/qcom/msmhamster.dtsi
+++ b/arch/arm/boot/dts/qcom/msmhamster.dtsi
@@ -39,24 +39,24 @@
compatible = "qcom,gfxcc-hamster";
qcom,gfxfreq-speedbin0 =
< 0 0 0 >,
- < 185000000 1 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 285000000 2 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 180000000 1 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 265000000 2 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 358000000 3 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 434000000 4 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 542000000 5 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 630000000 6 RPM_SMD_REGULATOR_LEVEL_NOM >,
- < 670000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >,
- < 710000000 8 RPM_SMD_REGULATOR_LEVEL_TURBO >;
+ < 700000000 7 RPM_SMD_REGULATOR_LEVEL_TURBO >,
+ < 750000000 8 RPM_SMD_REGULATOR_LEVEL_TURBO >;
qcom,gfxfreq-mx-speedbin0 =
< 0 0 >,
- < 185000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
- < 285000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 180000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
+ < 265000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 358000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 434000000 RPM_SMD_REGULATOR_LEVEL_SVS >,
< 542000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
< 630000000 RPM_SMD_REGULATOR_LEVEL_NOM >,
- < 670000000 RPM_SMD_REGULATOR_LEVEL_TURBO >,
- < 710000000 RPM_SMD_REGULATOR_LEVEL_TURBO >;
+ < 700000000 RPM_SMD_REGULATOR_LEVEL_TURBO >,
+ < 750000000 RPM_SMD_REGULATOR_LEVEL_TURBO >;
};
&tsens0 {
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index d41957eae6ef..f5dab4e9fb4b 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -2078,7 +2078,7 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, u64 size)
mapping->nr_bitmaps = 1;
mapping->extensions = extensions;
mapping->base = base;
- mapping->bits = BITS_PER_BYTE * bitmap_size;
+ mapping->bits = bits;
spin_lock_init(&mapping->lock);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 69c9b84b367b..0314b80695ca 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -513,37 +513,6 @@ config ARM64_64K_PAGES
endchoice
-config MSM_APP_API
- bool "API support to enable / disable app settings for MSM8996"
- depends on ARCH_MSM8996 && (ENABLE_FP_SIMD_SETTINGS || MSM_APP_SETTINGS)
- help
- Add API support to enable / disable the app settings to be used
- at runtime. These APIs are used to enable / disable app setting
- when specific aarch32 or aarch64 processes are running.
-
- If you are not sure what to do, select 'N' here.
-
-config ENABLE_FP_SIMD_SETTINGS
- bool "Enable FP(Floating Point) Settings for Qualcomm MSM8996"
- depends on ARCH_MSM8996
- select MSM_APP_API
- help
- Enable FP(Floating Point) and SIMD settings for the MSM8996 during
- the execution of the aarch32 processes and disable these settings
- when you switch to the aarch64 processes.
-
- If you are not sure what to do, select 'N' here.
-
-config MSM_APP_SETTINGS
- bool "Support to enable / disable app settings for MSM8996"
- depends on ARCH_MSM8996
- select MSM_APP_API
- help
- Expose an interface used by the userspace at runtime to
- enable / disable the app specific settings.
-
- If you are not sure what to do, select 'N' here.
-
choice
prompt "Virtual address space size"
default ARM64_VA_BITS_39 if ARM64_4K_PAGES
diff --git a/arch/arm64/configs/msm-perf_defconfig b/arch/arm64/configs/msm-perf_defconfig
index 210017d4467e..9ded3e3d5ff4 100644
--- a/arch/arm64/configs/msm-perf_defconfig
+++ b/arch/arm64/configs/msm-perf_defconfig
@@ -44,8 +44,6 @@ CONFIG_ARCH_QCOM=y
CONFIG_ARCH_MSM8996=y
CONFIG_PCI=y
CONFIG_PCI_MSM=y
-CONFIG_ENABLE_FP_SIMD_SETTINGS=y
-CONFIG_MSM_APP_SETTINGS=y
CONFIG_SCHED_MC=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT=y
diff --git a/arch/arm64/configs/msm_defconfig b/arch/arm64/configs/msm_defconfig
index 18a4322d9f9f..f4b10dcd45cb 100644
--- a/arch/arm64/configs/msm_defconfig
+++ b/arch/arm64/configs/msm_defconfig
@@ -41,8 +41,6 @@ CONFIG_ARCH_QCOM=y
CONFIG_ARCH_MSM8996=y
CONFIG_PCI=y
CONFIG_PCI_MSM=y
-CONFIG_ENABLE_FP_SIMD_SETTINGS=y
-CONFIG_MSM_APP_SETTINGS=y
CONFIG_SCHED_MC=y
CONFIG_NR_CPUS=8
CONFIG_PREEMPT=y
diff --git a/arch/arm64/configs/msmcortex-perf_defconfig b/arch/arm64/configs/msmcortex-perf_defconfig
index 1f9740b86e43..46755ce99619 100644
--- a/arch/arm64/configs/msmcortex-perf_defconfig
+++ b/arch/arm64/configs/msmcortex-perf_defconfig
@@ -518,6 +518,7 @@ CONFIG_TRACER_PKT=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_MSM_MPM_OF=y
CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
CONFIG_MSM_CORE_CTL_HELPER=y
CONFIG_QCOM_REMOTEQDSS=y
CONFIG_MSM_RPM_RBCPR_STATS_V2_LOG=y
@@ -537,6 +538,7 @@ CONFIG_IIO=y
CONFIG_QCOM_RRADC=y
CONFIG_PWM=y
CONFIG_PWM_QPNP=y
+CONFIG_ARM_GIC_V3_ACL=y
CONFIG_ANDROID=y
CONFIG_ANDROID_BINDER_IPC=y
CONFIG_SENSORS_SSC=y
diff --git a/arch/arm64/configs/msmcortex_defconfig b/arch/arm64/configs/msmcortex_defconfig
index ba867a7573e6..fd55c0e72e20 100644
--- a/arch/arm64/configs/msmcortex_defconfig
+++ b/arch/arm64/configs/msmcortex_defconfig
@@ -538,6 +538,7 @@ CONFIG_TRACER_PKT=y
CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
CONFIG_MSM_MPM_OF=y
CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
CONFIG_MSM_CORE_CTL_HELPER=y
CONFIG_QCOM_REMOTEQDSS=y
CONFIG_MSM_SERVICE_NOTIFIER=y
@@ -621,7 +622,8 @@ CONFIG_IPC_LOGGING=y
CONFIG_QCOM_RTB=y
CONFIG_QCOM_RTB_SEPARATE_CPUS=y
CONFIG_FUNCTION_TRACER=y
-CONFIG_TRACER_SNAPSHOT=y
+CONFIG_IRQSOFF_TRACER=y
+CONFIG_PREEMPT_TRACER=y
CONFIG_BLK_DEV_IO_TRACE=y
CONFIG_CPU_FREQ_SWITCH_PROFILER=y
CONFIG_MEMTEST=y
diff --git a/arch/arm64/include/asm/app_api.h b/arch/arm64/include/asm/app_api.h
deleted file mode 100644
index 2162400fde13..000000000000
--- a/arch/arm64/include/asm/app_api.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* Copyright (c) 2016, 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 __ASM_APP_API_H
-#define __ASM_APP_API_H
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/fs.h>
-
-#define APP_SETTING_BIT 30
-#define MAX_ENTRIES 10
-
-/*
- * APIs to set / clear the app setting bits
- * in the register.
- */
-#ifdef CONFIG_MSM_APP_API
-extern void set_app_setting_bit(uint32_t bit);
-extern void clear_app_setting_bit(uint32_t bit);
-#else
-static inline void set_app_setting_bit(uint32_t bit) {}
-static inline void clear_app_setting_bit(uint32_t bit) {}
-#endif
-
-#ifdef CONFIG_MSM_APP_SETTINGS
-extern void switch_app_setting_bit(struct task_struct *prev,
- struct task_struct *next);
-extern void apply_app_setting_bit(struct file *file);
-extern bool use_app_setting;
-#endif
-
-#endif
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 99733665be07..faad6df49e5b 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -23,7 +23,6 @@
*/
#include <asm/ptrace.h>
#include <asm/user.h>
-#include <asm/fpsimd.h>
typedef unsigned long elf_greg_t;
@@ -178,11 +177,7 @@ typedef compat_elf_greg_t compat_elf_gregset_t[COMPAT_ELF_NGREG];
((x)->e_flags & EF_ARM_EABI_MASK))
#define compat_start_thread compat_start_thread
-#define COMPAT_SET_PERSONALITY(ex) \
-do { \
- set_thread_flag(TIF_32BIT); \
-} while (0)
-
+#define COMPAT_SET_PERSONALITY(ex) set_thread_flag(TIF_32BIT);
#define COMPAT_ARCH_DLINFO
extern int aarch32_setup_vectors_page(struct linux_binprm *bprm,
int uses_interp);
diff --git a/arch/arm64/include/asm/fpsimd.h b/arch/arm64/include/asm/fpsimd.h
index 3efaa5cebc03..50f559f574fe 100644
--- a/arch/arm64/include/asm/fpsimd.h
+++ b/arch/arm64/include/asm/fpsimd.h
@@ -81,14 +81,6 @@ extern void fpsimd_save_partial_state(struct fpsimd_partial_state *state,
u32 num_regs);
extern void fpsimd_load_partial_state(struct fpsimd_partial_state *state);
-#ifdef CONFIG_ENABLE_FP_SIMD_SETTINGS
-extern void fpsimd_disable_trap(void);
-extern void fpsimd_enable_trap(void);
-#else
-static inline void fpsimd_disable_trap(void) {}
-static inline void fpsimd_enable_trap(void) {}
-#endif
-
#endif
#endif
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 57e55e4d5fcc..9f7794c5743f 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -43,8 +43,6 @@ arm64-obj-$(CONFIG_EFI) += efi.o efi-entry.stub.o
arm64-obj-$(CONFIG_PCI) += pci.o
arm64-obj-$(CONFIG_ARMV8_DEPRECATED) += armv8_deprecated.o
arm64-obj-$(CONFIG_ACPI) += acpi.o
-arm64-obj-$(CONFIG_MSM_APP_API) += app_api.o
-arm64-obj-$(CONFIG_MSM_APP_SETTINGS) += app_setting.o
obj-y += $(arm64-obj-y) vdso/
obj-m += $(arm64-obj-m)
diff --git a/arch/arm64/kernel/app_api.c b/arch/arm64/kernel/app_api.c
deleted file mode 100644
index 39eeee1a9029..000000000000
--- a/arch/arm64/kernel/app_api.c
+++ /dev/null
@@ -1,75 +0,0 @@
-/* Copyright (c) 2016, 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/bitops.h>
-#include <linux/spinlock.h>
-#include <linux/cpu.h>
-#include <linux/export.h>
-
-#include <asm/app_api.h>
-
-static spinlock_t spinlock;
-static DEFINE_PER_CPU(int, app_config_applied);
-static unsigned long app_config_set[NR_CPUS];
-static unsigned long app_config_clear[NR_CPUS];
-
-void set_app_setting_bit(uint32_t bit)
-{
- unsigned long flags;
- uint64_t reg;
- int cpu;
-
- spin_lock_irqsave(&spinlock, flags);
- asm volatile("mrs %0, S3_1_C15_C15_0" : "=r" (reg));
- reg = reg | BIT(bit);
- isb();
- asm volatile("msr S3_1_C15_C15_0, %0" : : "r" (reg));
- isb();
- if (bit == APP_SETTING_BIT) {
- cpu = raw_smp_processor_id();
- app_config_set[cpu]++;
-
- this_cpu_write(app_config_applied, 1);
- }
- spin_unlock_irqrestore(&spinlock, flags);
-
-}
-EXPORT_SYMBOL(set_app_setting_bit);
-
-void clear_app_setting_bit(uint32_t bit)
-{
- unsigned long flags;
- uint64_t reg;
- int cpu;
-
- spin_lock_irqsave(&spinlock, flags);
- asm volatile("mrs %0, S3_1_C15_C15_0" : "=r" (reg));
- reg = reg & ~BIT(bit);
- isb();
- asm volatile("msr S3_1_C15_C15_0, %0" : : "r" (reg));
- isb();
- if (bit == APP_SETTING_BIT) {
- cpu = raw_smp_processor_id();
- app_config_clear[cpu]++;
-
- this_cpu_write(app_config_applied, 0);
- }
- spin_unlock_irqrestore(&spinlock, flags);
-}
-EXPORT_SYMBOL(clear_app_setting_bit);
-
-static int __init init_app_api(void)
-{
- spin_lock_init(&spinlock);
- return 0;
-}
-early_initcall(init_app_api);
diff --git a/arch/arm64/kernel/app_setting.c b/arch/arm64/kernel/app_setting.c
deleted file mode 100644
index 6b4eb28d0e24..000000000000
--- a/arch/arm64/kernel/app_setting.c
+++ /dev/null
@@ -1,120 +0,0 @@
-/* Copyright (c) 2016, 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/module.h>
-#include <linux/cpu.h>
-#include <linux/slab.h>
-#include <linux/notifier.h>
-
-#include <asm/app_api.h>
-
-#define MAX_LEN 100
-
-static char *lib_names[MAX_ENTRIES];
-static unsigned int count;
-static struct mutex mutex;
-
-static char lib_str[MAX_LEN] = "";
-static struct kparam_string kps = {
- .string = lib_str,
- .maxlen = MAX_LEN,
-};
-static int set_name(const char *str, struct kernel_param *kp);
-module_param_call(lib_name, set_name, param_get_string, &kps, S_IWUSR);
-
-bool use_app_setting = true;
-module_param(use_app_setting, bool, 0644);
-MODULE_PARM_DESC(use_app_setting, "control use of app specific settings");
-
-static int set_name(const char *str, struct kernel_param *kp)
-{
- int len = strlen(str);
- char *name;
-
- if (len >= MAX_LEN) {
- pr_err("app_setting: name string too long\n");
- return -ENOSPC;
- }
-
- /*
- * echo adds '\n' which we need to chop off later
- */
- name = kzalloc(len + 1, GFP_KERNEL);
- if (!name)
- return -ENOMEM;
-
- strlcpy(name, str, len + 1);
-
- if (name[len - 1] == '\n')
- name[len - 1] = '\0';
-
- mutex_lock(&mutex);
- if (count < MAX_ENTRIES) {
- lib_names[count] = name;
- /*
- * mb to ensure that the new lib_names entry is present
- * before updating the view presented by get_lib_names
- */
- mb();
- count++;
- } else {
- pr_err("app_setting: set name failed. Max entries reached\n");
- kfree(name);
- mutex_unlock(&mutex);
- return -EPERM;
- }
- mutex_unlock(&mutex);
-
- return 0;
-}
-
-void switch_app_setting_bit(struct task_struct *prev, struct task_struct *next)
-{
- if (prev->mm && unlikely(prev->mm->app_setting))
- clear_app_setting_bit(APP_SETTING_BIT);
-
- if (next->mm && unlikely(next->mm->app_setting))
- set_app_setting_bit(APP_SETTING_BIT);
-}
-EXPORT_SYMBOL(switch_app_setting_bit);
-
-void apply_app_setting_bit(struct file *file)
-{
- bool found = false;
- int i;
-
- if (file && file->f_path.dentry) {
- const char *name = file->f_path.dentry->d_name.name;
-
- for (i = 0; i < count; i++) {
- if (unlikely(!strcmp(name, lib_names[i]))) {
- found = true;
- break;
- }
- }
- if (found) {
- preempt_disable();
- set_app_setting_bit(APP_SETTING_BIT);
- /* This will take care of child processes as well */
- current->mm->app_setting = 1;
- preempt_enable();
- }
- }
-}
-EXPORT_SYMBOL(apply_app_setting_bit);
-
-static int __init app_setting_init(void)
-{
- mutex_init(&mutex);
- return 0;
-}
-module_init(app_setting_init);
diff --git a/arch/arm64/kernel/entry-fpsimd.S b/arch/arm64/kernel/entry-fpsimd.S
index 1ffe15459c92..c44a82f146b1 100644
--- a/arch/arm64/kernel/entry-fpsimd.S
+++ b/arch/arm64/kernel/entry-fpsimd.S
@@ -64,20 +64,4 @@ ENTRY(fpsimd_load_partial_state)
ret
ENDPROC(fpsimd_load_partial_state)
-#ifdef CONFIG_ENABLE_FP_SIMD_SETTINGS
-ENTRY(fpsimd_enable_trap)
- mrs x0, cpacr_el1
- bic x0, x0, #(3 << 20)
- orr x0, x0, #(1 << 20)
- msr cpacr_el1, x0
- ret
-ENDPROC(fpsimd_enable_trap)
-ENTRY(fpsimd_disable_trap)
- mrs x0, cpacr_el1
- orr x0, x0, #(3 << 20)
- msr cpacr_el1, x0
- ret
-ENDPROC(fpsimd_disable_trap)
-#endif
-
#endif
diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
index 485186bff022..e3131b39fbf2 100644
--- a/arch/arm64/kernel/entry.S
+++ b/arch/arm64/kernel/entry.S
@@ -427,7 +427,7 @@ el0_sync_compat:
cmp x24, #ESR_ELx_EC_IABT_LOW // instruction abort in EL0
b.eq el0_ia
cmp x24, #ESR_ELx_EC_FP_ASIMD // FP/ASIMD access
- b.eq el0_fpsimd_acc_compat
+ b.eq el0_fpsimd_acc
cmp x24, #ESR_ELx_EC_FP_EXC32 // FP/ASIMD exception
b.eq el0_fpsimd_exc
cmp x24, #ESR_ELx_EC_PC_ALIGN // pc alignment exception
@@ -498,17 +498,6 @@ el0_fpsimd_acc:
mov x1, sp
bl do_fpsimd_acc
b ret_to_user
-el0_fpsimd_acc_compat:
- /*
- * Floating Point or Advanced SIMD access
- */
- enable_dbg
- ct_user_exit
- mov x0, x25
- mov x1, sp
- bl do_fpsimd_acc_compat
- b ret_to_user
-
el0_fpsimd_exc:
/*
* Floating Point or Advanced SIMD exception
diff --git a/arch/arm64/kernel/fpsimd.c b/arch/arm64/kernel/fpsimd.c
index 2ed553f3a4ae..4c46c54a3ad7 100644
--- a/arch/arm64/kernel/fpsimd.c
+++ b/arch/arm64/kernel/fpsimd.c
@@ -20,7 +20,6 @@
#include <linux/cpu.h>
#include <linux/cpu_pm.h>
#include <linux/kernel.h>
-#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
#include <linux/signal.h>
@@ -28,7 +27,6 @@
#include <asm/fpsimd.h>
#include <asm/cputype.h>
-#include <asm/app_api.h>
#define FPEXC_IOF (1 << 0)
#define FPEXC_DZF (1 << 1)
@@ -37,8 +35,6 @@
#define FPEXC_IXF (1 << 4)
#define FPEXC_IDF (1 << 7)
-#define FP_SIMD_BIT 31
-
/*
* In order to reduce the number of times the FPSIMD state is needlessly saved
* and restored, we need to keep track of two things:
@@ -92,42 +88,14 @@
* whatever is in the FPSIMD registers is not saved to memory, but discarded.
*/
static DEFINE_PER_CPU(struct fpsimd_state *, fpsimd_last_state);
-static DEFINE_PER_CPU(int, fpsimd_stg_enable);
-
-static int fpsimd_settings = 0x1; /* default = 0x1 */
-module_param(fpsimd_settings, int, 0644);
-
-void fpsimd_settings_enable(void)
-{
- set_app_setting_bit(FP_SIMD_BIT);
-}
-
-void fpsimd_settings_disable(void)
-{
- clear_app_setting_bit(FP_SIMD_BIT);
-}
/*
* Trapped FP/ASIMD access.
*/
void do_fpsimd_acc(unsigned int esr, struct pt_regs *regs)
{
- if (!fpsimd_settings)
- return;
-
- fpsimd_disable_trap();
- fpsimd_settings_disable();
- this_cpu_write(fpsimd_stg_enable, 0);
-}
-
-void do_fpsimd_acc_compat(unsigned int esr, struct pt_regs *regs)
-{
- if (!fpsimd_settings)
- return;
-
- fpsimd_disable_trap();
- fpsimd_settings_enable();
- this_cpu_write(fpsimd_stg_enable, 1);
+ /* TODO: implement lazy context saving/restoring */
+ WARN_ON(1);
}
/*
@@ -167,11 +135,6 @@ void fpsimd_thread_switch(struct task_struct *next)
if (current->mm && !test_thread_flag(TIF_FOREIGN_FPSTATE))
fpsimd_save_state(&current->thread.fpsimd_state);
- if (fpsimd_settings && __this_cpu_read(fpsimd_stg_enable)) {
- fpsimd_settings_disable();
- this_cpu_write(fpsimd_stg_enable, 0);
- }
-
if (next->mm) {
/*
* If we are switching to a task whose most recent userland
@@ -189,14 +152,6 @@ void fpsimd_thread_switch(struct task_struct *next)
else
set_ti_thread_flag(task_thread_info(next),
TIF_FOREIGN_FPSTATE);
-
- if (!fpsimd_settings)
- return;
-
- if (test_ti_thread_flag(task_thread_info(next), TIF_32BIT))
- fpsimd_enable_trap();
- else
- fpsimd_disable_trap();
}
}
diff --git a/arch/arm64/kernel/perf_event.c b/arch/arm64/kernel/perf_event.c
index 52d046b6a920..10db9cbaf49e 100644
--- a/arch/arm64/kernel/perf_event.c
+++ b/arch/arm64/kernel/perf_event.c
@@ -232,6 +232,11 @@ static const unsigned armv8_a57_perf_cache_map[PERF_COUNT_HW_CACHE_MAX]
#define ARMV8_EXCLUDE_EL0 (1 << 30)
#define ARMV8_INCLUDE_EL2 (1 << 27)
+struct arm_pmu_and_idle_nb {
+ struct arm_pmu *cpu_pmu;
+ struct notifier_block perf_cpu_idle_nb;
+};
+
static inline u32 armv8pmu_pmcr_read(void)
{
u32 val;
@@ -541,8 +546,6 @@ static int armv8pmu_set_event_filter(struct hw_perf_event *event,
{
unsigned long config_base = 0;
- if (attr->exclude_idle)
- return -EPERM;
if (attr->exclude_user)
config_base |= ARMV8_EXCLUDE_EL0;
if (attr->exclude_kernel)
@@ -575,6 +578,33 @@ static inline void armv8pmu_init_usermode(void)
}
#endif
+
+static void armv8pmu_idle_update(struct arm_pmu *cpu_pmu)
+{
+ struct pmu_hw_events *hw_events;
+ struct perf_event *event;
+ int idx;
+
+ if (!cpu_pmu)
+ return;
+
+ hw_events = this_cpu_ptr(cpu_pmu->hw_events);
+
+ for (idx = 0; idx < cpu_pmu->num_events; ++idx) {
+
+ if (!test_bit(idx, hw_events->used_mask))
+ continue;
+
+ event = hw_events->events[idx];
+
+ if (!event || !event->attr.exclude_idle ||
+ event->state != PERF_EVENT_STATE_ACTIVE)
+ continue;
+
+ cpu_pmu->pmu.read(event);
+ }
+}
+
static void armv8pmu_reset(void *info)
{
struct arm_pmu *cpu_pmu = (struct arm_pmu *)info;
@@ -624,11 +654,40 @@ static void armv8pmu_read_num_pmnc_events(void *info)
*nb_cnt += 1;
}
+static int perf_cpu_idle_notifier(struct notifier_block *nb,
+ unsigned long action, void *data)
+{
+ struct arm_pmu_and_idle_nb *pmu_nb = container_of(nb,
+ struct arm_pmu_and_idle_nb, perf_cpu_idle_nb);
+
+ if (action == IDLE_START)
+ armv8pmu_idle_update(pmu_nb->cpu_pmu);
+
+ return NOTIFY_OK;
+}
+
int armv8pmu_probe_num_events(struct arm_pmu *arm_pmu)
{
- return smp_call_function_any(&arm_pmu->supported_cpus,
+ int ret;
+ struct arm_pmu_and_idle_nb *pmu_idle_nb;
+
+ pmu_idle_nb = devm_kzalloc(&arm_pmu->plat_device->dev,
+ sizeof(*pmu_idle_nb), GFP_KERNEL);
+ if (!pmu_idle_nb)
+ return -ENOMEM;
+
+ pmu_idle_nb->cpu_pmu = arm_pmu;
+ pmu_idle_nb->perf_cpu_idle_nb.notifier_call = perf_cpu_idle_notifier;
+ idle_notifier_register(&pmu_idle_nb->perf_cpu_idle_nb);
+
+ ret = smp_call_function_any(&arm_pmu->supported_cpus,
armv8pmu_read_num_pmnc_events,
&arm_pmu->num_events, 1);
+ if (!ret)
+ idle_notifier_unregister(&pmu_idle_nb->perf_cpu_idle_nb);
+ return ret;
+
+
}
void armv8_pmu_init(struct arm_pmu *cpu_pmu)
diff --git a/arch/arm64/mm/dma-mapping.c b/arch/arm64/mm/dma-mapping.c
index 06f9ffccd562..196c73e2cf9c 100644
--- a/arch/arm64/mm/dma-mapping.c
+++ b/arch/arm64/mm/dma-mapping.c
@@ -2064,7 +2064,7 @@ arm_iommu_create_mapping(struct bus_type *bus, dma_addr_t base, size_t size)
goto err2;
mapping->base = base;
- mapping->bits = BITS_PER_BYTE * bitmap_size;
+ mapping->bits = bits;
spin_lock_init(&mapping->lock);
mapping->domain = iommu_domain_alloc(bus);
diff --git a/drivers/base/regmap/regmap-swr.c b/drivers/base/regmap/regmap-swr.c
index 5ea67421ed85..027cbfc505ab 100644
--- a/drivers/base/regmap/regmap-swr.c
+++ b/drivers/base/regmap/regmap-swr.c
@@ -23,15 +23,15 @@
static int regmap_swr_gather_write(void *context,
const void *reg, size_t reg_size,
- const void *val, size_t val_size)
+ const void *val, size_t val_len)
{
struct device *dev = context;
struct swr_device *swr = to_swr_device(dev);
struct regmap *map = dev_get_regmap(dev, NULL);
size_t addr_bytes = map->format.reg_bytes;
- int ret = 0;
- int i;
- u32 reg_addr = 0;
+ size_t val_bytes;
+ int i, ret = 0;
+ u16 reg_addr = 0;
if (swr == NULL) {
dev_err(dev, "%s: swr device is NULL\n", __func__);
@@ -43,12 +43,15 @@ static int regmap_swr_gather_write(void *context,
return -EINVAL;
}
reg_addr = *(u16 *)reg;
- for (i = 0; i < val_size; i++) {
- ret = swr_write(swr, swr->dev_num, (reg_addr+i),
- (u32 *)(val+i));
+ val_bytes = map->format.val_bytes;
+ /* val_len = val_bytes * val_count */
+ for (i = 0; i < (val_len / val_bytes); i++) {
+ reg_addr = reg_addr + i;
+ val = (u8 *)val + (val_bytes * i);
+ ret = swr_write(swr, swr->dev_num, reg_addr, val);
if (ret < 0) {
dev_err(dev, "%s: write reg 0x%x failed, err %d\n",
- __func__, (reg_addr+i), ret);
+ __func__, reg_addr, ret);
break;
}
}
@@ -153,7 +156,7 @@ static int regmap_swr_read(void *context,
struct regmap *map = dev_get_regmap(dev, NULL);
size_t addr_bytes = map->format.reg_bytes;
int ret = 0;
- u32 reg_addr = 0;
+ u16 reg_addr = 0;
if (swr == NULL) {
dev_err(dev, "%s: swr is NULL\n", __func__);
@@ -164,7 +167,7 @@ static int regmap_swr_read(void *context,
__func__, reg_size);
return -EINVAL;
}
- reg_addr = *(u32 *)reg;
+ reg_addr = *(u16 *)reg;
ret = swr_read(swr, swr->dev_num, reg_addr, val, val_size);
if (ret < 0)
dev_err(dev, "%s: codec reg 0x%x read failed %d\n",
diff --git a/drivers/clk/msm/clock-gpu-cobalt.c b/drivers/clk/msm/clock-gpu-cobalt.c
index 7230c7a2bc04..7cec9be1f42c 100644
--- a/drivers/clk/msm/clock-gpu-cobalt.c
+++ b/drivers/clk/msm/clock-gpu-cobalt.c
@@ -39,8 +39,6 @@ static void __iomem *virt_base_gfx;
#define gpucc_gpll0_source_val 5
#define gpu_pll0_pll_out_even_source_val 1
#define gpu_pll0_pll_out_odd_source_val 2
-#define gpu_pll1_pll_out_even_source_val 3
-#define gpu_pll1_pll_out_odd_source_val 4
#define SW_COLLAPSE_MASK BIT(0)
#define GPU_CX_GDSCR_OFFSET 0x1004
@@ -157,65 +155,6 @@ static struct div_clk gpu_pll0_pll_out_odd = {
},
};
-static struct alpha_pll_clk gpu_pll1_pll = {
- .masks = &pll_masks_p,
- .base = &virt_base_gfx,
- .offset = GPUCC_GPU_PLL1_PLL_MODE,
- .enable_config = 0x1,
- .is_fabia = true,
- .c = {
- .rate = 0,
- .parent = &gpucc_xo.c,
- .dbg_name = "gpu_pll1_pll",
- .ops = &clk_ops_fabia_alpha_pll,
- VDD_GPU_PLL_FMAX_MAP1(MIN, 1300000500),
- CLK_INIT(gpu_pll1_pll.c),
- },
-};
-
-static struct div_clk gpu_pll1_pll_out_even = {
- .base = &virt_base_gfx,
- .offset = GPUCC_GPU_PLL1_USER_CTL_MODE,
- .mask = 0xf,
- .shift = 8,
- .data = {
- .max_div = 8,
- .min_div = 1,
- .skip_odd_div = true,
- .allow_div_one = true,
- .rate_margin = 500,
- },
- .ops = &postdiv_reg_ops,
- .c = {
- .parent = &gpu_pll1_pll.c,
- .dbg_name = "gpu_pll1_pll_out_even",
- .ops = &clk_ops_div,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(gpu_pll1_pll_out_even.c),
- },
-};
-
-static struct div_clk gpu_pll1_pll_out_odd = {
- .base = &virt_base_gfx,
- .offset = GPUCC_GPU_PLL0_USER_CTL_MODE,
- .mask = 0xf,
- .shift = 12,
- .data = {
- .max_div = 7,
- .min_div = 3,
- .skip_even_div = true,
- .rate_margin = 500,
- },
- .ops = &postdiv_reg_ops,
- .c = {
- .parent = &gpu_pll1_pll.c,
- .dbg_name = "gpu_pll1_pll_out_odd",
- .ops = &clk_ops_div,
- .flags = CLKFLAG_NO_RATE_CACHE,
- CLK_INIT(gpu_pll1_pll_out_odd.c),
- },
-};
-
static struct clk_freq_tbl ftbl_gfx3d_clk_src[] = {
F_SLEW( 171000000, 342000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 251000000, 502000000, gpu_pll0_pll_out_even, 1, 0, 0),
@@ -227,11 +166,11 @@ static struct clk_freq_tbl ftbl_gfx3d_clk_src[] = {
};
static struct clk_freq_tbl ftbl_gfx3d_clk_src_v2[] = {
- F_SLEW( 189000000, 378000000, gpu_pll0_pll_out_even, 1, 0, 0),
- F_SLEW( 264000000, 528000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 180000000, 360000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 257000000, 514000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 342000000, 684000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 414000000, 828000000, gpu_pll0_pll_out_even, 1, 0, 0),
- F_SLEW( 520000000, 1040000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 515000000, 1030000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 596000000, 1192000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 670000000, 1340000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 710000000, 1420000000, gpu_pll0_pll_out_even, 1, 0, 0),
@@ -239,14 +178,14 @@ static struct clk_freq_tbl ftbl_gfx3d_clk_src_v2[] = {
};
static struct clk_freq_tbl ftbl_gfx3d_clk_src_vq[] = {
- F_SLEW( 185000000, 370000000, gpu_pll0_pll_out_even, 1, 0, 0),
- F_SLEW( 285000000, 570000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 180000000, 360000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 265000000, 530000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 358000000, 716000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 434000000, 868000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 542000000, 1084000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_SLEW( 630000000, 1260000000, gpu_pll0_pll_out_even, 1, 0, 0),
- F_SLEW( 670000000, 1340000000, gpu_pll1_pll_out_even, 1, 0, 0),
- F_SLEW( 710000000, 1420000000, gpu_pll1_pll_out_even, 1, 0, 0),
+ F_SLEW( 700000000, 1400000000, gpu_pll0_pll_out_even, 1, 0, 0),
+ F_SLEW( 750000000, 1500000000, gpu_pll0_pll_out_even, 1, 0, 0),
F_END
};
@@ -659,9 +598,6 @@ static struct clk_lookup msm_clocks_gfxcc_cobalt[] = {
CLK_LIST(gpu_pll0_pll),
CLK_LIST(gpu_pll0_pll_out_even),
CLK_LIST(gpu_pll0_pll_out_odd),
- CLK_LIST(gpu_pll1_pll),
- CLK_LIST(gpu_pll1_pll_out_even),
- CLK_LIST(gpu_pll1_pll_out_odd),
CLK_LIST(gfx3d_clk_src),
CLK_LIST(gpucc_gfx3d_clk),
CLK_LIST(gpucc_mx_clk),
@@ -671,14 +607,12 @@ static struct clk_lookup msm_clocks_gfxcc_cobalt[] = {
static void msm_gfxcc_hamster_fixup(void)
{
gpu_pll0_pll.c.fmax[VDD_DIG_MIN] = 1420000500;
- gpu_pll1_pll.c.fmax[VDD_DIG_MIN] = 1420000500;
gfx3d_clk_src.freq_tbl = ftbl_gfx3d_clk_src_vq;
}
static void msm_gfxcc_cobalt_v2_fixup(void)
{
gpu_pll0_pll.c.fmax[VDD_DIG_MIN] = 1420000500;
- gpu_pll1_pll.c.fmax[VDD_DIG_MIN] = 1420000500;
gfx3d_clk_src.freq_tbl = ftbl_gfx3d_clk_src_v2;
}
diff --git a/drivers/clk/msm/clock-mmss-cobalt.c b/drivers/clk/msm/clock-mmss-cobalt.c
index 288abb133743..2da10a2e4780 100644
--- a/drivers/clk/msm/clock-mmss-cobalt.c
+++ b/drivers/clk/msm/clock-mmss-cobalt.c
@@ -274,7 +274,7 @@ static struct rcg_clk csi0_clk_src = {
.c = {
.dbg_name = "csi0_clk_src",
.ops = &clk_ops_rcg,
- VDD_DIG_FMAX_MAP4(LOWER, 164570000, LOW, 256000000,
+ VDD_DIG_FMAX_MAP4(LOWER, 164571429, LOW, 256000000,
NOMINAL, 384000000, HIGH, 576000000),
CLK_INIT(csi0_clk_src.c),
},
@@ -292,6 +292,9 @@ static struct clk_freq_tbl ftbl_vfe_clk_src[] = {
static struct clk_freq_tbl ftbl_vfe_clk_src_vq[] = {
F_MM( 200000000, mmsscc_gpll0, 3, 0, 0),
+ F_MM( 300000000, mmsscc_gpll0, 2, 0, 0),
+ F_MM( 320000000, mmpll7_pll_out, 3, 0, 0),
+ F_MM( 384000000, mmpll4_pll_out, 2, 0, 0),
F_MM( 404000000, mmpll0_pll_out, 2, 0, 0),
F_MM( 480000000, mmpll7_pll_out, 2, 0, 0),
F_MM( 576000000, mmpll10_pll_out, 1, 0, 0),
@@ -367,16 +370,6 @@ static struct clk_freq_tbl ftbl_maxi_clk_src[] = {
F_END
};
-static struct clk_freq_tbl ftbl_maxi_clk_src_vq[] = {
- F_MM( 19200000, mmsscc_xo, 1, 0, 0),
- F_MM( 75000000, mmsscc_gpll0_div, 4, 0, 0),
- F_MM( 171428571, mmsscc_gpll0, 3.5, 0, 0),
- F_MM( 240000000, mmsscc_gpll0, 2.5, 0, 0),
- F_MM( 323200000, mmpll0_pll_out, 2.5, 0, 0),
- F_MM( 406000000, mmpll1_pll_out, 2, 0, 0),
- F_END
-};
-
static struct rcg_clk maxi_clk_src = {
.cmd_rcgr_reg = MMSS_MAXI_CMD_RCGR,
.set_rate = set_rate_hid,
@@ -592,18 +585,11 @@ static struct clk_freq_tbl ftbl_fd_core_clk_src[] = {
F_END
};
-static struct clk_freq_tbl ftbl_fd_core_clk_src_v2[] = {
- F_MM( 100000000, mmsscc_gpll0, 6, 0, 0),
- F_MM( 404000000, mmpll0_pll_out, 2, 0, 0),
- F_MM( 480000000, mmpll7_pll_out, 2, 0, 0),
- F_MM( 576000000, mmpll10_pll_out, 1, 0, 0),
- F_END
-};
-
static struct clk_freq_tbl ftbl_fd_core_clk_src_vq[] = {
F_MM( 100000000, mmsscc_gpll0, 6, 0, 0),
F_MM( 200000000, mmsscc_gpll0, 3, 0, 0),
- F_MM( 400000000, mmsscc_gpll0, 1.5, 0, 0),
+ F_MM( 404000000, mmpll0_pll_out, 2, 0, 0),
+ F_MM( 480000000, mmpll7_pll_out, 2, 0, 0),
F_MM( 576000000, mmpll10_pll_out, 1, 0, 0),
F_END
};
@@ -2677,60 +2663,81 @@ static void msm_mmsscc_hamster_fixup(void)
vfe1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 480000000;
csi0_clk_src.freq_tbl = ftbl_csi_clk_src_vq;
- csi0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi0_clk_src.c.fmax[VDD_DIG_LOW] = 274290000;
+ csi0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 320000000;
csi1_clk_src.freq_tbl = ftbl_csi_clk_src_vq;
- csi1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi1_clk_src.c.fmax[VDD_DIG_LOW] = 274290000;
+ csi1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 320000000;
csi2_clk_src.freq_tbl = ftbl_csi_clk_src_vq;
- csi2_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi2_clk_src.c.fmax[VDD_DIG_LOW] = 274290000;
+ csi2_clk_src.c.fmax[VDD_DIG_LOW_L1] = 320000000;
csi3_clk_src.freq_tbl = ftbl_csi_clk_src_vq;
- csi3_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi3_clk_src.c.fmax[VDD_DIG_LOW] = 274290000;
+ csi3_clk_src.c.fmax[VDD_DIG_LOW_L1] = 320000000;
cpp_clk_src.freq_tbl = ftbl_cpp_clk_src_vq;
- cpp_clk_src.c.fmax[VDD_DIG_LOW_L1] = 480000000;
+ cpp_clk_src.c.fmax[VDD_DIG_LOW] = 384000000;
+ cpp_clk_src.c.fmax[VDD_DIG_LOW_L1] = 404000000;
jpeg0_clk_src.freq_tbl = ftbl_jpeg0_clk_src_vq;
jpeg0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 320000000;
csiphy_clk_src.freq_tbl = ftbl_csiphy_clk_src_vq;
+ csiphy_clk_src.c.fmax[VDD_DIG_LOW] = 274290000;
csiphy_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
fd_core_clk_src.freq_tbl = ftbl_fd_core_clk_src_vq;
- fd_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 400000000;
+ fd_core_clk_src.c.fmax[VDD_DIG_LOW] = 404000000;
+ fd_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 480000000;
csi0phytimer_clk_src.c.fmax[VDD_DIG_LOW_L1] = 269333333;
csi1phytimer_clk_src.c.fmax[VDD_DIG_LOW_L1] = 269333333;
csi2phytimer_clk_src.c.fmax[VDD_DIG_LOW_L1] = 269333333;
mdp_clk_src.c.fmax[VDD_DIG_LOW_L1] = 330000000;
+ dp_pixel_clk_src.c.fmax[VDD_DIG_LOWER] = 154000000;
extpclk_clk_src.c.fmax[VDD_DIG_LOW] = 312500000;
extpclk_clk_src.c.fmax[VDD_DIG_LOW_L1] = 375000000;
rot_clk_src.c.fmax[VDD_DIG_LOW_L1] = 330000000;
- maxi_clk_src.freq_tbl = ftbl_maxi_clk_src_vq;
video_core_clk_src.freq_tbl = ftbl_video_core_clk_src_vq;
video_core_clk_src.c.fmax[VDD_DIG_LOWER] = 200000000;
video_core_clk_src.c.fmax[VDD_DIG_LOW] = 269330000;
- video_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 404000000;
+ video_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
video_core_clk_src.c.fmax[VDD_DIG_NOMINAL] = 444000000;
video_core_clk_src.c.fmax[VDD_DIG_HIGH] = 533000000;
video_subcore0_clk_src.freq_tbl = ftbl_video_subcore_clk_src_vq;
video_subcore0_clk_src.c.fmax[VDD_DIG_LOWER] = 200000000;
video_subcore0_clk_src.c.fmax[VDD_DIG_LOW] = 269330000;
- video_subcore0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 404000000;
+ video_subcore0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
video_subcore0_clk_src.c.fmax[VDD_DIG_NOMINAL] = 444000000;
video_subcore0_clk_src.c.fmax[VDD_DIG_HIGH] = 533000000;
video_subcore1_clk_src.freq_tbl = ftbl_video_subcore_clk_src_vq;
video_subcore1_clk_src.c.fmax[VDD_DIG_LOWER] = 200000000;
video_subcore1_clk_src.c.fmax[VDD_DIG_LOW] = 269330000;
- video_subcore1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 404000000;
+ video_subcore1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
video_subcore1_clk_src.c.fmax[VDD_DIG_NOMINAL] = 444000000;
video_subcore1_clk_src.c.fmax[VDD_DIG_HIGH] = 533000000;
};
static void msm_mmsscc_v2_fixup(void)
{
- fd_core_clk_src.freq_tbl = ftbl_fd_core_clk_src_v2;
- fd_core_clk_src.c.fmax[VDD_DIG_LOW] = 404000000;
- fd_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 480000000;
+ cpp_clk_src.c.fmax[VDD_DIG_LOW] = 200000000;
+ cpp_clk_src.c.fmax[VDD_DIG_LOW_L1] = 480000000;
+ csi0_clk_src.c.fmax[VDD_DIG_LOW] = 256000000;
+ csi0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi1_clk_src.c.fmax[VDD_DIG_LOW] = 256000000;
+ csi1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi2_clk_src.c.fmax[VDD_DIG_LOW] = 256000000;
+ csi2_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csi3_clk_src.c.fmax[VDD_DIG_LOW] = 256000000;
+ csi3_clk_src.c.fmax[VDD_DIG_LOW_L1] = 300000000;
+ csiphy_clk_src.c.fmax[VDD_DIG_LOW] = 256000000;
+
+ dp_pixel_clk_src.c.fmax[VDD_DIG_LOWER] = 148380000;
+
+ video_subcore0_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
+ video_subcore1_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
+ video_core_clk_src.c.fmax[VDD_DIG_LOW_L1] = 355200000;
}
int msm_mmsscc_cobalt_probe(struct platform_device *pdev)
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index c203ac7bfe8c..24005a1fda72 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -78,6 +78,16 @@ struct kgsl_dma_buf_meta {
struct sg_table *table;
};
+static inline struct kgsl_pagetable *_get_memdesc_pagetable(
+ struct kgsl_pagetable *pt, struct kgsl_mem_entry *entry)
+{
+ /* if a secured buffer, map it to secure global pagetable */
+ if (kgsl_memdesc_is_secured(&entry->memdesc))
+ return pt->mmu->securepagetable;
+
+ return pt;
+}
+
static void kgsl_mem_entry_detach_process(struct kgsl_mem_entry *entry);
static const struct file_operations kgsl_fops;
@@ -445,14 +455,17 @@ kgsl_mem_entry_attach_process(struct kgsl_mem_entry *entry,
/* map the memory after unlocking if gpuaddr has been assigned */
if (entry->memdesc.gpuaddr) {
- /* if a secured buffer map it to secure global pagetable */
+ pagetable = process->pagetable;
if (kgsl_memdesc_is_secured(&entry->memdesc))
- pagetable = process->pagetable->mmu->securepagetable;
- else
- pagetable = process->pagetable;
+ pagetable = pagetable->mmu->securepagetable;
entry->memdesc.pagetable = pagetable;
- ret = kgsl_mmu_map(pagetable, &entry->memdesc);
+
+ if (entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_VIRT)
+ ret = kgsl_mmu_sparse_dummy_map(pagetable,
+ &entry->memdesc, 0, entry->memdesc.size);
+ else if (entry->memdesc.gpuaddr)
+ ret = kgsl_mmu_map(pagetable, &entry->memdesc);
if (ret)
kgsl_mem_entry_detach_process(entry);
}
@@ -1270,6 +1283,24 @@ kgsl_sharedmem_find(struct kgsl_process_private *private, uint64_t gpuaddr)
}
EXPORT_SYMBOL(kgsl_sharedmem_find);
+struct kgsl_mem_entry * __must_check
+kgsl_sharedmem_find_id_flags(struct kgsl_process_private *process,
+ unsigned int id, uint64_t flags)
+{
+ int count = 0;
+ struct kgsl_mem_entry *entry;
+
+ spin_lock(&process->mem_lock);
+ entry = idr_find(&process->mem_idr, id);
+ if (entry)
+ if (!entry->pending_free &&
+ (flags & entry->memdesc.flags) == flags)
+ count = kgsl_mem_entry_get(entry);
+ spin_unlock(&process->mem_lock);
+
+ return (count == 0) ? NULL : entry;
+}
+
/**
* kgsl_sharedmem_find_id() - find a memory entry by id
* @process: the owning process
@@ -1283,19 +1314,7 @@ EXPORT_SYMBOL(kgsl_sharedmem_find);
struct kgsl_mem_entry * __must_check
kgsl_sharedmem_find_id(struct kgsl_process_private *process, unsigned int id)
{
- int result;
- struct kgsl_mem_entry *entry;
-
- drain_workqueue(kgsl_driver.mem_workqueue);
-
- spin_lock(&process->mem_lock);
- entry = idr_find(&process->mem_idr, id);
- result = kgsl_mem_entry_get(entry);
- spin_unlock(&process->mem_lock);
-
- if (result == 0)
- return NULL;
- return entry;
+ return kgsl_sharedmem_find_id_flags(process, id, 0);
}
/**
@@ -3121,6 +3140,546 @@ long kgsl_ioctl_gpumem_get_info(struct kgsl_device_private *dev_priv,
return result;
}
+static inline int _sparse_alloc_param_sanity_check(uint64_t size,
+ uint64_t pagesize)
+{
+ if (size == 0 || pagesize == 0)
+ return -EINVAL;
+
+ if (pagesize != PAGE_SIZE && pagesize != SZ_64K)
+ return -EINVAL;
+
+ if (pagesize > size || !IS_ALIGNED(size, pagesize))
+ return -EINVAL;
+
+ return 0;
+}
+
+long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_sparse_phys_alloc *param = data;
+ struct kgsl_mem_entry *entry;
+ int ret;
+ int id;
+
+ ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
+ if (ret)
+ return ret;
+
+ entry = kgsl_mem_entry_create();
+ if (entry == NULL)
+ return -ENOMEM;
+
+ ret = kgsl_process_private_get(process);
+ if (!ret) {
+ ret = -EBADF;
+ goto err_free_entry;
+ }
+
+ idr_preload(GFP_KERNEL);
+ spin_lock(&process->mem_lock);
+ /* Allocate the ID but don't attach the pointer just yet */
+ id = idr_alloc(&process->mem_idr, NULL, 1, 0, GFP_NOWAIT);
+ spin_unlock(&process->mem_lock);
+ idr_preload_end();
+
+ if (id < 0) {
+ ret = id;
+ goto err_put_proc_priv;
+ }
+
+ entry->id = id;
+ entry->priv = process;
+
+ entry->memdesc.flags = KGSL_MEMFLAGS_SPARSE_PHYS;
+ kgsl_memdesc_set_align(&entry->memdesc, ilog2(param->pagesize));
+
+ ret = kgsl_allocate_user(dev_priv->device, &entry->memdesc,
+ process->pagetable, param->size, entry->memdesc.flags);
+ if (ret)
+ goto err_remove_idr;
+
+ /* Sanity check to verify we got correct pagesize */
+ if (param->pagesize != PAGE_SIZE && entry->memdesc.sgt != NULL) {
+ struct scatterlist *s;
+ int i;
+
+ for_each_sg(entry->memdesc.sgt->sgl, s,
+ entry->memdesc.sgt->nents, i) {
+ if (!IS_ALIGNED(s->length, param->pagesize))
+ goto err_invalid_pages;
+ }
+ }
+
+ param->id = entry->id;
+ param->flags = entry->memdesc.flags;
+
+ trace_sparse_phys_alloc(entry->id, param->size, param->pagesize);
+ kgsl_mem_entry_commit_process(entry);
+
+ return 0;
+
+err_invalid_pages:
+ kgsl_sharedmem_free(&entry->memdesc);
+err_remove_idr:
+ spin_lock(&process->mem_lock);
+ idr_remove(&process->mem_idr, entry->id);
+ spin_unlock(&process->mem_lock);
+err_put_proc_priv:
+ kgsl_process_private_put(process);
+err_free_entry:
+ kfree(entry);
+
+ return ret;
+}
+
+long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_sparse_phys_free *param = data;
+ struct kgsl_mem_entry *entry;
+
+ entry = kgsl_sharedmem_find_id_flags(process, param->id,
+ KGSL_MEMFLAGS_SPARSE_PHYS);
+ if (entry == NULL)
+ return -EINVAL;
+
+ if (entry->memdesc.cur_bindings != 0) {
+ kgsl_mem_entry_put(entry);
+ return -EINVAL;
+ }
+
+ trace_sparse_phys_free(entry->id);
+
+ /* One put for find_id(), one put for the kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_put(entry);
+
+ return 0;
+}
+
+long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_sparse_virt_alloc *param = data;
+ struct kgsl_mem_entry *entry;
+ int ret;
+
+ ret = _sparse_alloc_param_sanity_check(param->size, param->pagesize);
+ if (ret)
+ return ret;
+
+ entry = kgsl_mem_entry_create();
+ if (entry == NULL)
+ return -ENOMEM;
+
+ entry->memdesc.flags = KGSL_MEMFLAGS_SPARSE_VIRT;
+ entry->memdesc.size = param->size;
+ entry->memdesc.cur_bindings = 0;
+ kgsl_memdesc_set_align(&entry->memdesc, ilog2(param->pagesize));
+
+ spin_lock_init(&entry->bind_lock);
+ entry->bind_tree = RB_ROOT;
+
+ ret = kgsl_mem_entry_attach_process(entry, dev_priv);
+ if (ret) {
+ kfree(entry);
+ return ret;
+ }
+
+ param->id = entry->id;
+ param->gpuaddr = entry->memdesc.gpuaddr;
+ param->flags = entry->memdesc.flags;
+
+ trace_sparse_virt_alloc(entry->id, param->size, param->pagesize);
+ kgsl_mem_entry_commit_process(entry);
+
+ return 0;
+}
+
+long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_process_private *process = dev_priv->process_priv;
+ struct kgsl_sparse_virt_free *param = data;
+ struct kgsl_mem_entry *entry = NULL;
+
+ entry = kgsl_sharedmem_find_id_flags(process, param->id,
+ KGSL_MEMFLAGS_SPARSE_VIRT);
+ if (entry == NULL)
+ return -EINVAL;
+
+ if (entry->bind_tree.rb_node != NULL) {
+ kgsl_mem_entry_put(entry);
+ return -EINVAL;
+ }
+
+ trace_sparse_virt_free(entry->id);
+
+ /* One put for find_id(), one put for the kgsl_mem_entry_create() */
+ kgsl_mem_entry_put(entry);
+ kgsl_mem_entry_put(entry);
+
+ return 0;
+}
+
+static int _sparse_add_to_bind_tree(struct kgsl_mem_entry *entry,
+ uint64_t v_offset,
+ struct kgsl_memdesc *memdesc,
+ uint64_t p_offset,
+ uint64_t size,
+ uint64_t flags)
+{
+ struct sparse_bind_object *new;
+ struct rb_node **node, *parent = NULL;
+
+ new = kzalloc(sizeof(*new), GFP_KERNEL);
+ if (new == NULL)
+ return -ENOMEM;
+
+ new->v_off = v_offset;
+ new->p_off = p_offset;
+ new->p_memdesc = memdesc;
+ new->size = size;
+ new->flags = flags;
+
+ node = &entry->bind_tree.rb_node;
+
+ while (*node != NULL) {
+ struct sparse_bind_object *this;
+
+ parent = *node;
+ this = rb_entry(parent, struct sparse_bind_object, node);
+
+ if (new->v_off < this->v_off)
+ node = &parent->rb_left;
+ else if (new->v_off > this->v_off)
+ node = &parent->rb_right;
+ }
+
+ rb_link_node(&new->node, parent, node);
+ rb_insert_color(&new->node, &entry->bind_tree);
+
+ return 0;
+}
+
+static int _sparse_rm_from_bind_tree(struct kgsl_mem_entry *entry,
+ struct sparse_bind_object *obj,
+ uint64_t v_offset, uint64_t size)
+{
+ spin_lock(&entry->bind_lock);
+ if (v_offset == obj->v_off && size >= obj->size) {
+ /*
+ * We are all encompassing, remove the entry and free
+ * things up
+ */
+ rb_erase(&obj->node, &entry->bind_tree);
+ kfree(obj);
+ } else if (v_offset == obj->v_off) {
+ /*
+ * We are the front of the node, adjust the front of
+ * the node
+ */
+ obj->v_off += size;
+ obj->p_off += size;
+ obj->size -= size;
+ } else if ((v_offset + size) == (obj->v_off + obj->size)) {
+ /*
+ * We are at the end of the obj, adjust the beginning
+ * points
+ */
+ obj->size -= size;
+ } else {
+ /*
+ * We are in the middle of a node, split it up and
+ * create a new mini node. Adjust this node's bounds
+ * and add the new node to the list.
+ */
+ uint64_t tmp_size = obj->size;
+ int ret;
+
+ obj->size = v_offset - obj->v_off;
+
+ spin_unlock(&entry->bind_lock);
+ ret = _sparse_add_to_bind_tree(entry, v_offset + size,
+ obj->p_memdesc,
+ obj->p_off + (v_offset - obj->v_off) + size,
+ tmp_size - (v_offset - obj->v_off) - size,
+ obj->flags);
+
+ return ret;
+ }
+
+ spin_unlock(&entry->bind_lock);
+
+ return 0;
+}
+
+static struct sparse_bind_object *_find_containing_bind_obj(
+ struct kgsl_mem_entry *entry,
+ uint64_t offset, uint64_t size)
+{
+ struct sparse_bind_object *obj = NULL;
+ struct rb_node *node = entry->bind_tree.rb_node;
+
+ spin_lock(&entry->bind_lock);
+
+ while (node != NULL) {
+ obj = rb_entry(node, struct sparse_bind_object, node);
+
+ if (offset == obj->v_off) {
+ break;
+ } else if (offset < obj->v_off) {
+ if (offset + size > obj->v_off)
+ break;
+ node = node->rb_left;
+ obj = NULL;
+ } else if (offset > obj->v_off) {
+ if (offset < obj->v_off + obj->size)
+ break;
+ node = node->rb_right;
+ obj = NULL;
+ }
+ }
+
+ spin_unlock(&entry->bind_lock);
+
+ return obj;
+}
+
+static int _sparse_unbind(struct kgsl_mem_entry *entry,
+ struct sparse_bind_object *bind_obj,
+ uint64_t offset, uint64_t size)
+{
+ struct kgsl_memdesc *memdesc = bind_obj->p_memdesc;
+ struct kgsl_pagetable *pt = memdesc->pagetable;
+ int ret;
+
+ if (memdesc->cur_bindings < (size / PAGE_SIZE))
+ return -EINVAL;
+
+ memdesc->cur_bindings -= size / PAGE_SIZE;
+
+ ret = kgsl_mmu_unmap_offset(pt, memdesc,
+ entry->memdesc.gpuaddr, offset, size);
+ if (ret)
+ return ret;
+
+ ret = kgsl_mmu_sparse_dummy_map(pt, &entry->memdesc, offset, size);
+ if (ret)
+ return ret;
+
+ ret = _sparse_rm_from_bind_tree(entry, bind_obj, offset, size);
+ if (ret == 0) {
+ atomic_long_sub(size, &kgsl_driver.stats.mapped);
+ trace_sparse_unbind(entry->id, offset, size);
+ }
+
+ return ret;
+}
+
+static long sparse_unbind_range(struct kgsl_sparse_binding_object *obj,
+ struct kgsl_mem_entry *virt_entry)
+{
+ struct sparse_bind_object *bind_obj;
+ int ret = 0;
+ uint64_t size = obj->size;
+ uint64_t tmp_size = obj->size;
+ uint64_t offset = obj->virtoffset;
+
+ while (size > 0 && ret == 0) {
+ tmp_size = size;
+ bind_obj = _find_containing_bind_obj(virt_entry, offset, size);
+ if (bind_obj == NULL)
+ return 0;
+
+ if (bind_obj->v_off > offset) {
+ tmp_size = size - bind_obj->v_off - offset;
+ if (tmp_size > bind_obj->size)
+ tmp_size = bind_obj->size;
+ offset = bind_obj->v_off;
+ } else if (bind_obj->v_off < offset) {
+ uint64_t diff = offset - bind_obj->v_off;
+
+ if (diff + size > bind_obj->size)
+ tmp_size = bind_obj->size - diff;
+ } else {
+ if (tmp_size > bind_obj->size)
+ tmp_size = bind_obj->size;
+ }
+
+ ret = _sparse_unbind(virt_entry, bind_obj, offset, tmp_size);
+ if (ret == 0) {
+ offset += tmp_size;
+ size -= tmp_size;
+ }
+ }
+
+ return ret;
+}
+
+static inline bool _is_phys_bindable(struct kgsl_mem_entry *phys_entry,
+ uint64_t offset, uint64_t size, uint64_t flags)
+{
+ struct kgsl_memdesc *memdesc = &phys_entry->memdesc;
+
+ if (!IS_ALIGNED(offset | size, kgsl_memdesc_get_pagesize(memdesc)))
+ return false;
+
+ if (!(flags & KGSL_SPARSE_BIND_MULTIPLE_TO_PHYS) &&
+ offset + size > memdesc->size)
+ return false;
+
+ return true;
+}
+
+static int _sparse_bind(struct kgsl_process_private *process,
+ struct kgsl_mem_entry *virt_entry, uint64_t v_offset,
+ struct kgsl_mem_entry *phys_entry, uint64_t p_offset,
+ uint64_t size, uint64_t flags)
+{
+ int ret;
+ struct kgsl_pagetable *pagetable;
+ struct kgsl_memdesc *memdesc = &phys_entry->memdesc;
+
+ /* map the memory after unlocking if gpuaddr has been assigned */
+ if (memdesc->gpuaddr)
+ return -EINVAL;
+
+ if (memdesc->useraddr != 0)
+ return -EINVAL;
+
+ pagetable = memdesc->pagetable;
+
+ /* Clear out any mappings */
+ ret = kgsl_mmu_unmap_offset(pagetable, &virt_entry->memdesc,
+ virt_entry->memdesc.gpuaddr, v_offset, size);
+ if (ret)
+ return ret;
+
+ ret = kgsl_mmu_map_offset(pagetable, virt_entry->memdesc.gpuaddr,
+ v_offset, memdesc, p_offset, size, flags);
+ if (ret) {
+ /* Try to clean up, but not the end of the world */
+ kgsl_mmu_sparse_dummy_map(pagetable, &virt_entry->memdesc,
+ v_offset, size);
+ return ret;
+ }
+
+ ret = _sparse_add_to_bind_tree(virt_entry, v_offset, memdesc,
+ p_offset, size, flags);
+ if (ret == 0)
+ memdesc->cur_bindings += size / PAGE_SIZE;
+
+ return ret;
+}
+
+static long sparse_bind_range(struct kgsl_process_private *private,
+ struct kgsl_sparse_binding_object *obj,
+ struct kgsl_mem_entry *virt_entry)
+{
+ struct kgsl_mem_entry *phys_entry;
+ int ret;
+
+ phys_entry = kgsl_sharedmem_find_id_flags(private, obj->id,
+ KGSL_MEMFLAGS_SPARSE_PHYS);
+ if (phys_entry == NULL)
+ return -EINVAL;
+
+ if (!_is_phys_bindable(phys_entry, obj->physoffset, obj->size,
+ obj->flags)) {
+ kgsl_mem_entry_put(phys_entry);
+ return -EINVAL;
+ }
+
+ if (kgsl_memdesc_get_align(&virt_entry->memdesc) !=
+ kgsl_memdesc_get_align(&phys_entry->memdesc)) {
+ kgsl_mem_entry_put(phys_entry);
+ return -EINVAL;
+ }
+
+ ret = sparse_unbind_range(obj, virt_entry);
+ if (ret) {
+ kgsl_mem_entry_put(phys_entry);
+ return -EINVAL;
+ }
+
+ ret = _sparse_bind(private, virt_entry, obj->virtoffset,
+ phys_entry, obj->physoffset, obj->size,
+ obj->flags & KGSL_SPARSE_BIND_MULTIPLE_TO_PHYS);
+ if (ret == 0) {
+ KGSL_STATS_ADD(obj->size, &kgsl_driver.stats.mapped,
+ &kgsl_driver.stats.mapped_max);
+
+ trace_sparse_bind(virt_entry->id, obj->virtoffset,
+ phys_entry->id, obj->physoffset,
+ obj->size, obj->flags);
+ }
+
+ kgsl_mem_entry_put(phys_entry);
+
+ return ret;
+}
+
+long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data)
+{
+ struct kgsl_process_private *private = dev_priv->process_priv;
+ struct kgsl_sparse_bind *param = data;
+ struct kgsl_sparse_binding_object obj;
+ struct kgsl_mem_entry *virt_entry;
+ int pg_sz;
+ void __user *ptr;
+ int ret = 0;
+ int i = 0;
+
+ ptr = (void __user *) (uintptr_t) param->list;
+
+ if (param->size > sizeof(struct kgsl_sparse_binding_object) ||
+ param->count == 0 || ptr == NULL)
+ return -EINVAL;
+
+ virt_entry = kgsl_sharedmem_find_id_flags(private, param->id,
+ KGSL_MEMFLAGS_SPARSE_VIRT);
+ if (virt_entry == NULL)
+ return -EINVAL;
+
+ pg_sz = kgsl_memdesc_get_pagesize(&virt_entry->memdesc);
+
+ for (i = 0; i < param->count; i++) {
+ memset(&obj, 0, sizeof(obj));
+ ret = _copy_from_user(&obj, ptr, sizeof(obj), param->size);
+ if (ret)
+ break;
+
+ /* Sanity check initial range */
+ if (obj.size == 0 ||
+ obj.virtoffset + obj.size > virt_entry->memdesc.size ||
+ !(IS_ALIGNED(obj.virtoffset | obj.size, pg_sz))) {
+ ret = -EINVAL;
+ break;
+ }
+
+ if (obj.flags & KGSL_SPARSE_BIND)
+ ret = sparse_bind_range(private, &obj, virt_entry);
+ else if (obj.flags & KGSL_SPARSE_UNBIND)
+ ret = sparse_unbind_range(&obj, virt_entry);
+ else
+ ret = -EINVAL;
+ if (ret)
+ break;
+
+ ptr += sizeof(obj);
+ }
+
+ kgsl_mem_entry_put(virt_entry);
+
+ return ret;
+}
+
long kgsl_ioctl_gpuobj_info(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data)
{
@@ -3356,6 +3915,13 @@ get_mmap_entry(struct kgsl_process_private *private,
goto err_put;
}
+ if (entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_PHYS) {
+ if (len != entry->memdesc.size) {
+ ret = -EINVAL;
+ goto err_put;
+ }
+ }
+
if (entry->memdesc.useraddr != 0) {
ret = -EBUSY;
goto err_put;
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index ee7149e1fd41..25f5de6ce645 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -184,6 +184,7 @@ struct kgsl_memdesc_ops {
* @attrs: dma attributes for this memory
* @pages: An array of pointers to allocated pages
* @page_count: Total number of pages allocated
+ * @cur_bindings: Number of sparse pages actively bound
*/
struct kgsl_memdesc {
struct kgsl_pagetable *pagetable;
@@ -202,6 +203,7 @@ struct kgsl_memdesc {
struct dma_attrs attrs;
struct page **pages;
unsigned int page_count;
+ unsigned int cur_bindings;
};
/*
@@ -235,6 +237,8 @@ struct kgsl_memdesc {
* @dev_priv: back pointer to the device file that created this entry.
* @metadata: String containing user specified metadata for the entry
* @work: Work struct used to schedule a kgsl_mem_entry_put in atomic contexts
+ * @bind_lock: Lock for sparse memory bindings
+ * @bind_tree: RB Tree for sparse memory bindings
*/
struct kgsl_mem_entry {
struct kref refcount;
@@ -246,6 +250,8 @@ struct kgsl_mem_entry {
int pending_free;
char metadata[KGSL_GPUOBJ_ALLOC_METADATA_MAX + 1];
struct work_struct work;
+ spinlock_t bind_lock;
+ struct rb_root bind_tree;
};
struct kgsl_device_private;
@@ -315,6 +321,24 @@ struct kgsl_protected_registers {
int range;
};
+/**
+ * struct sparse_bind_object - Bind metadata
+ * @node: Node for the rb tree
+ * @p_memdesc: Physical memdesc bound to
+ * @v_off: Offset of bind in the virtual entry
+ * @p_off: Offset of bind in the physical memdesc
+ * @size: Size of the bind
+ * @flags: Flags for the bind
+ */
+struct sparse_bind_object {
+ struct rb_node node;
+ struct kgsl_memdesc *p_memdesc;
+ uint64_t v_off;
+ uint64_t p_off;
+ uint64_t size;
+ uint64_t flags;
+};
+
long kgsl_ioctl_device_getproperty(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data);
long kgsl_ioctl_device_setproperty(struct kgsl_device_private *dev_priv,
@@ -377,6 +401,19 @@ long kgsl_ioctl_gpu_command(struct kgsl_device_private *dev_priv,
long kgsl_ioctl_gpuobj_set_info(struct kgsl_device_private *dev_priv,
unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_phys_alloc(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_phys_free(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_virt_alloc(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_virt_free(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_bind(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+long kgsl_ioctl_sparse_unbind(struct kgsl_device_private *dev_priv,
+ unsigned int cmd, void *data);
+
void kgsl_mem_entry_destroy(struct kref *kref);
struct kgsl_mem_entry * __must_check
diff --git a/drivers/gpu/msm/kgsl_compat.c b/drivers/gpu/msm/kgsl_compat.c
index 248c78b7e5c4..028a9566fa14 100644
--- a/drivers/gpu/msm/kgsl_compat.c
+++ b/drivers/gpu/msm/kgsl_compat.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2016, 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
@@ -372,6 +372,16 @@ static const struct kgsl_ioctl kgsl_compat_ioctl_funcs[] = {
kgsl_ioctl_gpu_command),
KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_SET_INFO,
kgsl_ioctl_gpuobj_set_info),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_ALLOC,
+ kgsl_ioctl_sparse_phys_alloc),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_FREE,
+ kgsl_ioctl_sparse_phys_free),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_ALLOC,
+ kgsl_ioctl_sparse_virt_alloc),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_FREE,
+ kgsl_ioctl_sparse_virt_free),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_BIND,
+ kgsl_ioctl_sparse_bind),
};
long kgsl_compat_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 93ac790f3a55..df9eb9ebd779 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -129,10 +129,13 @@ static int print_mem_entry(int id, void *ptr, void *data)
{
struct seq_file *s = data;
struct kgsl_mem_entry *entry = ptr;
- char flags[9];
+ char flags[10];
char usage[16];
struct kgsl_memdesc *m = &entry->memdesc;
+ if (m->flags & KGSL_MEMFLAGS_SPARSE_VIRT)
+ return 0;
+
flags[0] = kgsl_memdesc_is_global(m) ? 'g' : '-';
flags[1] = '-';
flags[2] = !(m->flags & KGSL_MEMFLAGS_GPUREADONLY) ? 'w' : '-';
@@ -141,7 +144,8 @@ static int print_mem_entry(int id, void *ptr, void *data)
flags[5] = kgsl_memdesc_use_cpu_map(m) ? 'p' : '-';
flags[6] = (m->useraddr) ? 'Y' : 'N';
flags[7] = kgsl_memdesc_is_secured(m) ? 's' : '-';
- flags[8] = '\0';
+ flags[8] = m->flags & KGSL_MEMFLAGS_SPARSE_PHYS ? 'P' : '-';
+ flags[9] = '\0';
kgsl_get_memory_usage(usage, sizeof(usage), m->flags);
@@ -211,6 +215,70 @@ static const struct file_operations process_mem_fops = {
.release = process_mem_release,
};
+static int print_sparse_mem_entry(int id, void *ptr, void *data)
+{
+ struct seq_file *s = data;
+ struct kgsl_mem_entry *entry = ptr;
+ struct kgsl_memdesc *m = &entry->memdesc;
+ struct rb_node *node;
+
+ if (!(m->flags & KGSL_MEMFLAGS_SPARSE_VIRT))
+ return 0;
+
+ node = rb_first(&entry->bind_tree);
+
+ while (node != NULL) {
+ struct sparse_bind_object *obj = rb_entry(node,
+ struct sparse_bind_object, node);
+ seq_printf(s, "%5d %16llx %16llx %16llx %16llx\n",
+ entry->id, entry->memdesc.gpuaddr,
+ obj->v_off, obj->size, obj->p_off);
+ node = rb_next(node);
+ }
+
+ seq_putc(s, '\n');
+
+ return 0;
+}
+
+static int process_sparse_mem_print(struct seq_file *s, void *unused)
+{
+ struct kgsl_process_private *private = s->private;
+
+ seq_printf(s, "%5s %16s %16s %16s %16s\n",
+ "v_id", "gpuaddr", "v_offset", "v_size", "p_offset");
+
+ spin_lock(&private->mem_lock);
+ idr_for_each(&private->mem_idr, print_sparse_mem_entry, s);
+ spin_unlock(&private->mem_lock);
+
+ return 0;
+}
+
+static int process_sparse_mem_open(struct inode *inode, struct file *file)
+{
+ int ret;
+ pid_t pid = (pid_t) (unsigned long) inode->i_private;
+ struct kgsl_process_private *private = NULL;
+
+ private = kgsl_process_private_find(pid);
+
+ if (!private)
+ return -ENODEV;
+
+ ret = single_open(file, process_sparse_mem_print, private);
+ if (ret)
+ kgsl_process_private_put(private);
+
+ return ret;
+}
+
+static const struct file_operations process_sparse_mem_fops = {
+ .open = process_sparse_mem_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = process_mem_release,
+};
/**
* kgsl_process_init_debugfs() - Initialize debugfs for a process
@@ -251,6 +319,15 @@ void kgsl_process_init_debugfs(struct kgsl_process_private *private)
if (IS_ERR_OR_NULL(dentry))
WARN((dentry == NULL),
"Unable to create 'mem' file for %s\n", name);
+
+ dentry = debugfs_create_file("sparse_mem", 0444, private->debug_root,
+ (void *) ((unsigned long) private->pid),
+ &process_sparse_mem_fops);
+
+ if (IS_ERR_OR_NULL(dentry))
+ WARN((dentry == NULL),
+ "Unable to create 'sparse_mem' file for %s\n", name);
+
}
void kgsl_core_debugfs_init(void)
diff --git a/drivers/gpu/msm/kgsl_ioctl.c b/drivers/gpu/msm/kgsl_ioctl.c
index 0802e94f56ad..894e6a4a146b 100644
--- a/drivers/gpu/msm/kgsl_ioctl.c
+++ b/drivers/gpu/msm/kgsl_ioctl.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2016, 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
@@ -90,6 +90,16 @@ static const struct kgsl_ioctl kgsl_ioctl_funcs[] = {
kgsl_ioctl_gpu_command),
KGSL_IOCTL_FUNC(IOCTL_KGSL_GPUOBJ_SET_INFO,
kgsl_ioctl_gpuobj_set_info),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_ALLOC,
+ kgsl_ioctl_sparse_phys_alloc),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_PHYS_FREE,
+ kgsl_ioctl_sparse_phys_free),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_ALLOC,
+ kgsl_ioctl_sparse_virt_alloc),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_VIRT_FREE,
+ kgsl_ioctl_sparse_virt_free),
+ KGSL_IOCTL_FUNC(IOCTL_KGSL_SPARSE_BIND,
+ kgsl_ioctl_sparse_bind),
};
long kgsl_ioctl_copy_in(unsigned int kernel_cmd, unsigned int user_cmd,
diff --git a/drivers/gpu/msm/kgsl_iommu.c b/drivers/gpu/msm/kgsl_iommu.c
index b467ef81d257..166bb68e64a1 100644
--- a/drivers/gpu/msm/kgsl_iommu.c
+++ b/drivers/gpu/msm/kgsl_iommu.c
@@ -323,8 +323,8 @@ static int _iommu_map_sync_pc(struct kgsl_pagetable *pt,
_unlock_if_secure_mmu(memdesc, pt->mmu);
if (ret) {
- KGSL_CORE_ERR("map err: %p, 0x%016llX, 0x%llx, 0x%x, %d\n",
- iommu_pt->domain, gpuaddr, size, flags, ret);
+ KGSL_CORE_ERR("map err: 0x%016llX, 0x%llx, 0x%x, %d\n",
+ gpuaddr, size, flags, ret);
return -ENODEV;
}
@@ -351,8 +351,8 @@ static int _iommu_unmap_sync_pc(struct kgsl_pagetable *pt,
_unlock_if_secure_mmu(memdesc, pt->mmu);
if (unmapped != size) {
- KGSL_CORE_ERR("unmap err: %p, 0x%016llx, 0x%llx, %zd\n",
- iommu_pt->domain, addr, size, unmapped);
+ KGSL_CORE_ERR("unmap err: 0x%016llx, 0x%llx, %zd\n",
+ addr, size, unmapped);
return -ENODEV;
}
@@ -421,8 +421,9 @@ static int _iommu_map_sg_offset_sync_pc(struct kgsl_pagetable *pt,
if (size != 0) {
/* Cleanup on error */
_iommu_unmap_sync_pc(pt, memdesc, addr, mapped);
- KGSL_CORE_ERR("map err: %p, 0x%016llX, %d, %x, %zd\n",
- iommu_pt->domain, addr, nents, flags, mapped);
+ KGSL_CORE_ERR(
+ "map sg offset err: 0x%016llX, %d, %x, %zd\n",
+ addr, nents, flags, mapped);
return -ENODEV;
}
@@ -451,8 +452,8 @@ static int _iommu_map_sg_sync_pc(struct kgsl_pagetable *pt,
_unlock_if_secure_mmu(memdesc, pt->mmu);
if (mapped == 0) {
- KGSL_CORE_ERR("map err: %p, 0x%016llX, %d, %x, %zd\n",
- iommu_pt->domain, addr, nents, flags, mapped);
+ KGSL_CORE_ERR("map sg err: 0x%016llX, %d, %x, %zd\n",
+ addr, nents, flags, mapped);
return -ENODEV;
}
@@ -467,6 +468,13 @@ static int _iommu_map_sg_sync_pc(struct kgsl_pagetable *pt,
static struct page *kgsl_guard_page;
static struct kgsl_memdesc kgsl_secure_guard_page_memdesc;
+/*
+ * The dummy page is a placeholder/extra page to be used for sparse mappings.
+ * This page will be mapped to all virtual sparse bindings that are not
+ * physically backed.
+ */
+static struct page *kgsl_dummy_page;
+
/* These functions help find the nearest allocated memory entries on either side
* of a faulting address. If we know the nearby allocations memory we can
* get a better determination of what we think should have been located in the
@@ -1309,6 +1317,11 @@ static void kgsl_iommu_close(struct kgsl_mmu *mmu)
kgsl_guard_page = NULL;
}
+ if (kgsl_dummy_page != NULL) {
+ __free_page(kgsl_dummy_page);
+ kgsl_dummy_page = NULL;
+ }
+
kgsl_iommu_remove_global(mmu, &iommu->setstate);
kgsl_sharedmem_free(&iommu->setstate);
kgsl_cleanup_qdss_desc(mmu);
@@ -1523,6 +1536,8 @@ kgsl_iommu_unmap_offset(struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc, uint64_t addr,
uint64_t offset, uint64_t size)
{
+ if (size == 0 || (size + offset) > kgsl_memdesc_footprint(memdesc))
+ return -EINVAL;
/*
* All GPU addresses as assigned are page aligned, but some
* functions perturb the gpuaddr with an offset, so apply the
@@ -1530,9 +1545,8 @@ kgsl_iommu_unmap_offset(struct kgsl_pagetable *pt,
*/
addr = PAGE_ALIGN(addr);
-
- if (size == 0 || addr == 0)
- return 0;
+ if (addr == 0)
+ return -EINVAL;
return _iommu_unmap_sync_pc(pt, memdesc, addr + offset, size);
}
@@ -1540,13 +1554,11 @@ kgsl_iommu_unmap_offset(struct kgsl_pagetable *pt,
static int
kgsl_iommu_unmap(struct kgsl_pagetable *pt, struct kgsl_memdesc *memdesc)
{
- uint64_t size = memdesc->size;
-
- if (kgsl_memdesc_has_guard_page(memdesc))
- size += kgsl_memdesc_guard_page_size(pt->mmu, memdesc);
+ if (memdesc->size == 0 || memdesc->gpuaddr == 0)
+ return -EINVAL;
return kgsl_iommu_unmap_offset(pt, memdesc, memdesc->gpuaddr, 0,
- size);
+ kgsl_memdesc_footprint(memdesc));
}
/**
@@ -1593,7 +1605,7 @@ static int _iommu_map_guard_page(struct kgsl_pagetable *pt,
} else {
if (kgsl_guard_page == NULL) {
kgsl_guard_page = alloc_page(GFP_KERNEL | __GFP_ZERO |
- __GFP_HIGHMEM);
+ __GFP_NORETRY | __GFP_HIGHMEM);
if (kgsl_guard_page == NULL)
return -ENOMEM;
}
@@ -1602,7 +1614,7 @@ static int _iommu_map_guard_page(struct kgsl_pagetable *pt,
}
return _iommu_map_sync_pc(pt, memdesc, gpuaddr, physaddr,
- kgsl_memdesc_guard_page_size(pt->mmu, memdesc),
+ kgsl_memdesc_guard_page_size(memdesc),
protflags & ~IOMMU_WRITE);
}
@@ -1658,6 +1670,100 @@ done:
return ret;
}
+static int kgsl_iommu_sparse_dummy_map(struct kgsl_pagetable *pt,
+ struct kgsl_memdesc *memdesc, uint64_t offset, uint64_t size)
+{
+ int ret = 0, i;
+ struct page **pages = NULL;
+ struct sg_table sgt;
+ int count = size >> PAGE_SHIFT;
+
+ /* verify the offset is within our range */
+ if (size + offset > memdesc->size)
+ return -EINVAL;
+
+ if (kgsl_dummy_page == NULL) {
+ kgsl_dummy_page = alloc_page(GFP_KERNEL | __GFP_ZERO |
+ __GFP_HIGHMEM);
+ if (kgsl_dummy_page == NULL)
+ return -ENOMEM;
+ }
+
+ pages = kcalloc(count, sizeof(struct page *), GFP_KERNEL);
+ if (pages == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++)
+ pages[i] = kgsl_dummy_page;
+
+ ret = sg_alloc_table_from_pages(&sgt, pages, count,
+ 0, size, GFP_KERNEL);
+ if (ret == 0) {
+ ret = _iommu_map_sg_sync_pc(pt, memdesc->gpuaddr + offset,
+ memdesc, sgt.sgl, sgt.nents,
+ IOMMU_READ | IOMMU_NOEXEC);
+ sg_free_table(&sgt);
+ }
+
+ kfree(pages);
+
+ return ret;
+}
+
+static int _map_to_one_page(struct kgsl_pagetable *pt, uint64_t addr,
+ struct kgsl_memdesc *memdesc, uint64_t physoffset,
+ uint64_t size, unsigned int map_flags)
+{
+ int ret = 0, i;
+ int pg_sz = kgsl_memdesc_get_pagesize(memdesc);
+ int count = size >> PAGE_SHIFT;
+ struct page *page = NULL;
+ struct page **pages = NULL;
+ struct sg_page_iter sg_iter;
+ struct sg_table sgt;
+
+ /* Find our physaddr offset addr */
+ if (memdesc->pages != NULL)
+ page = memdesc->pages[physoffset >> PAGE_SHIFT];
+ else {
+ for_each_sg_page(memdesc->sgt->sgl, &sg_iter,
+ memdesc->sgt->nents, physoffset >> PAGE_SHIFT) {
+ page = sg_page_iter_page(&sg_iter);
+ break;
+ }
+ }
+
+ if (page == NULL)
+ return -EINVAL;
+
+ pages = kcalloc(count, sizeof(struct page *), GFP_KERNEL);
+ if (pages == NULL)
+ return -ENOMEM;
+
+ for (i = 0; i < count; i++) {
+ if (pg_sz != PAGE_SIZE) {
+ struct page *tmp_page = page;
+ int j;
+
+ for (j = 0; j < 16; j++, tmp_page += PAGE_SIZE)
+ pages[i++] = tmp_page;
+ } else
+ pages[i] = page;
+ }
+
+ ret = sg_alloc_table_from_pages(&sgt, pages, count,
+ 0, size, GFP_KERNEL);
+ if (ret == 0) {
+ ret = _iommu_map_sg_sync_pc(pt, addr, memdesc, sgt.sgl,
+ sgt.nents, map_flags);
+ sg_free_table(&sgt);
+ }
+
+ kfree(pages);
+
+ return ret;
+}
+
static int kgsl_iommu_map_offset(struct kgsl_pagetable *pt,
uint64_t virtaddr, uint64_t virtoffset,
struct kgsl_memdesc *memdesc, uint64_t physoffset,
@@ -1668,13 +1774,17 @@ static int kgsl_iommu_map_offset(struct kgsl_pagetable *pt,
int ret;
struct sg_table *sgt = NULL;
- pg_sz = (1 << kgsl_memdesc_get_align(memdesc));
+ pg_sz = kgsl_memdesc_get_pagesize(memdesc);
if (!IS_ALIGNED(virtaddr | virtoffset | physoffset | size, pg_sz))
return -EINVAL;
if (size == 0)
return -EINVAL;
+ if (!(feature_flag & KGSL_SPARSE_BIND_MULTIPLE_TO_PHYS) &&
+ size + physoffset > kgsl_memdesc_footprint(memdesc))
+ return -EINVAL;
+
/*
* For paged memory allocated through kgsl, memdesc->pages is not NULL.
* Allocate sgt here just for its map operation. Contiguous memory
@@ -1688,9 +1798,13 @@ static int kgsl_iommu_map_offset(struct kgsl_pagetable *pt,
if (IS_ERR(sgt))
return PTR_ERR(sgt);
- ret = _iommu_map_sg_offset_sync_pc(pt, virtaddr + virtoffset,
- memdesc, sgt->sgl, sgt->nents,
- physoffset, size, protflags);
+ if (feature_flag & KGSL_SPARSE_BIND_MULTIPLE_TO_PHYS)
+ ret = _map_to_one_page(pt, virtaddr + virtoffset,
+ memdesc, physoffset, size, protflags);
+ else
+ ret = _iommu_map_sg_offset_sync_pc(pt, virtaddr + virtoffset,
+ memdesc, sgt->sgl, sgt->nents,
+ physoffset, size, protflags);
if (memdesc->pages != NULL)
kgsl_free_sgt(sgt);
@@ -2152,8 +2266,7 @@ static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable,
{
struct kgsl_iommu_pt *pt = pagetable->priv;
int ret = 0;
- uint64_t addr, start, end;
- uint64_t size = memdesc->size;
+ uint64_t addr, start, end, size;
unsigned int align;
BUG_ON(kgsl_memdesc_use_cpu_map(memdesc));
@@ -2162,8 +2275,7 @@ static int kgsl_iommu_get_gpuaddr(struct kgsl_pagetable *pagetable,
pagetable->name != KGSL_MMU_SECURE_PT)
return -EINVAL;
- if (kgsl_memdesc_has_guard_page(memdesc))
- size += kgsl_memdesc_guard_page_size(pagetable->mmu, memdesc);
+ size = kgsl_memdesc_footprint(memdesc);
align = 1 << kgsl_memdesc_get_align(memdesc);
@@ -2445,4 +2557,5 @@ static struct kgsl_mmu_pt_ops iommu_pt_ops = {
.addr_in_range = kgsl_iommu_addr_in_range,
.mmu_map_offset = kgsl_iommu_map_offset,
.mmu_unmap_offset = kgsl_iommu_unmap_offset,
+ .mmu_sparse_dummy_map = kgsl_iommu_sparse_dummy_map,
};
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index 8b0d93fda32c..10f6b8049d36 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -386,29 +386,24 @@ int
kgsl_mmu_map(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc)
{
- int ret = 0;
int size;
if (!memdesc->gpuaddr)
return -EINVAL;
- /* Only global mappings should be mapped multiple times */
- if (!kgsl_memdesc_is_global(memdesc) &&
- (KGSL_MEMDESC_MAPPED & memdesc->priv))
- return -EINVAL;
size = kgsl_memdesc_footprint(memdesc);
- if (PT_OP_VALID(pagetable, mmu_map))
- ret = pagetable->pt_ops->mmu_map(pagetable, memdesc);
-
- if (ret)
- return ret;
+ if (PT_OP_VALID(pagetable, mmu_map)) {
+ int ret;
- atomic_inc(&pagetable->stats.entries);
- KGSL_STATS_ADD(size, &pagetable->stats.mapped,
- &pagetable->stats.max_mapped);
+ ret = pagetable->pt_ops->mmu_map(pagetable, memdesc);
+ if (ret)
+ return ret;
- memdesc->priv |= KGSL_MEMDESC_MAPPED;
+ atomic_inc(&pagetable->stats.entries);
+ KGSL_STATS_ADD(size, &pagetable->stats.mapped,
+ &pagetable->stats.max_mapped);
+ }
return 0;
}
@@ -455,22 +450,22 @@ int
kgsl_mmu_unmap(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc)
{
- uint64_t size;
-
- if (memdesc->size == 0 || memdesc->gpuaddr == 0 ||
- !(KGSL_MEMDESC_MAPPED & memdesc->priv))
+ if (memdesc->size == 0)
return -EINVAL;
- size = kgsl_memdesc_footprint(memdesc);
+ if (PT_OP_VALID(pagetable, mmu_unmap)) {
+ int ret;
+ uint64_t size;
- if (PT_OP_VALID(pagetable, mmu_unmap))
- pagetable->pt_ops->mmu_unmap(pagetable, memdesc);
+ size = kgsl_memdesc_footprint(memdesc);
- atomic_dec(&pagetable->stats.entries);
- atomic_long_sub(size, &pagetable->stats.mapped);
+ ret = pagetable->pt_ops->mmu_unmap(pagetable, memdesc);
+ if (ret)
+ return ret;
- if (!kgsl_memdesc_is_global(memdesc))
- memdesc->priv &= ~KGSL_MEMDESC_MAPPED;
+ atomic_dec(&pagetable->stats.entries);
+ atomic_long_sub(size, &pagetable->stats.mapped);
+ }
return 0;
}
@@ -481,11 +476,20 @@ int kgsl_mmu_map_offset(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc, uint64_t physoffset,
uint64_t size, uint64_t flags)
{
- if (PT_OP_VALID(pagetable, mmu_map_offset))
- return pagetable->pt_ops->mmu_map_offset(pagetable, virtaddr,
+ if (PT_OP_VALID(pagetable, mmu_map_offset)) {
+ int ret;
+
+ ret = pagetable->pt_ops->mmu_map_offset(pagetable, virtaddr,
virtoffset, memdesc, physoffset, size, flags);
+ if (ret)
+ return ret;
+
+ atomic_inc(&pagetable->stats.entries);
+ KGSL_STATS_ADD(size, &pagetable->stats.mapped,
+ &pagetable->stats.max_mapped);
+ }
- return -EINVAL;
+ return 0;
}
EXPORT_SYMBOL(kgsl_mmu_map_offset);
@@ -493,14 +497,41 @@ int kgsl_mmu_unmap_offset(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *memdesc, uint64_t addr, uint64_t offset,
uint64_t size)
{
- if (PT_OP_VALID(pagetable, mmu_unmap_offset))
- return pagetable->pt_ops->mmu_unmap_offset(pagetable, memdesc,
+ if (PT_OP_VALID(pagetable, mmu_unmap_offset)) {
+ int ret;
+
+ ret = pagetable->pt_ops->mmu_unmap_offset(pagetable, memdesc,
addr, offset, size);
+ if (ret)
+ return ret;
+
+ atomic_dec(&pagetable->stats.entries);
+ atomic_long_sub(size, &pagetable->stats.mapped);
+ }
- return -EINVAL;
+ return 0;
}
EXPORT_SYMBOL(kgsl_mmu_unmap_offset);
+int kgsl_mmu_sparse_dummy_map(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc, uint64_t offset, uint64_t size)
+{
+ if (PT_OP_VALID(pagetable, mmu_sparse_dummy_map)) {
+ int ret;
+
+ ret = pagetable->pt_ops->mmu_sparse_dummy_map(pagetable,
+ memdesc, offset, size);
+ if (ret)
+ return ret;
+
+ atomic_dec(&pagetable->stats.entries);
+ atomic_long_sub(size, &pagetable->stats.mapped);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(kgsl_mmu_sparse_dummy_map);
+
void kgsl_mmu_remove_global(struct kgsl_device *device,
struct kgsl_memdesc *memdesc)
{
diff --git a/drivers/gpu/msm/kgsl_mmu.h b/drivers/gpu/msm/kgsl_mmu.h
index 588777af353f..53645cc1741c 100644
--- a/drivers/gpu/msm/kgsl_mmu.h
+++ b/drivers/gpu/msm/kgsl_mmu.h
@@ -106,6 +106,9 @@ struct kgsl_mmu_pt_ops {
int (*mmu_unmap_offset)(struct kgsl_pagetable *pt,
struct kgsl_memdesc *memdesc, uint64_t addr,
uint64_t offset, uint64_t size);
+ int (*mmu_sparse_dummy_map)(struct kgsl_pagetable *pt,
+ struct kgsl_memdesc *memdesc, uint64_t offset,
+ uint64_t size);
};
/*
@@ -230,6 +233,9 @@ int kgsl_mmu_unmap_offset(struct kgsl_pagetable *pagetable,
struct kgsl_memdesc *kgsl_mmu_get_qdss_global_entry(struct kgsl_device *device);
+int kgsl_mmu_sparse_dummy_map(struct kgsl_pagetable *pagetable,
+ struct kgsl_memdesc *memdesc, uint64_t offset, uint64_t size);
+
/*
* Static inline functions of MMU that simply call the SMMU specific
* function using a function pointer. These functions can be thought
diff --git a/drivers/gpu/msm/kgsl_sharedmem.h b/drivers/gpu/msm/kgsl_sharedmem.h
index c05aaecb5284..565ae4c39fdd 100644
--- a/drivers/gpu/msm/kgsl_sharedmem.h
+++ b/drivers/gpu/msm/kgsl_sharedmem.h
@@ -92,6 +92,18 @@ kgsl_memdesc_get_align(const struct kgsl_memdesc *memdesc)
}
/*
+ * kgsl_memdesc_get_pagesize - Get pagesize based on alignment
+ * @memdesc - the memdesc
+ *
+ * Returns the pagesize based on memdesc alignment
+ */
+static inline int
+kgsl_memdesc_get_pagesize(const struct kgsl_memdesc *memdesc)
+{
+ return (1 << kgsl_memdesc_get_align(memdesc));
+}
+
+/*
* kgsl_memdesc_get_cachemode - Get cache mode of a memdesc
* @memdesc: the memdesc
*
@@ -211,12 +223,19 @@ kgsl_memdesc_has_guard_page(const struct kgsl_memdesc *memdesc)
*
* Returns guard page size
*/
-static inline int
-kgsl_memdesc_guard_page_size(const struct kgsl_mmu *mmu,
- const struct kgsl_memdesc *memdesc)
+static inline uint64_t
+kgsl_memdesc_guard_page_size(const struct kgsl_memdesc *memdesc)
{
- return kgsl_memdesc_is_secured(memdesc) ? mmu->secure_align_mask + 1 :
- PAGE_SIZE;
+ if (!kgsl_memdesc_has_guard_page(memdesc))
+ return 0;
+
+ if (kgsl_memdesc_is_secured(memdesc)) {
+ if (memdesc->pagetable != NULL &&
+ memdesc->pagetable->mmu != NULL)
+ return memdesc->pagetable->mmu->secure_align_mask + 1;
+ }
+
+ return PAGE_SIZE;
}
/*
@@ -241,10 +260,7 @@ kgsl_memdesc_use_cpu_map(const struct kgsl_memdesc *memdesc)
static inline uint64_t
kgsl_memdesc_footprint(const struct kgsl_memdesc *memdesc)
{
- uint64_t size = memdesc->size;
- if (kgsl_memdesc_has_guard_page(memdesc))
- size += SZ_4K;
- return size;
+ return memdesc->size + kgsl_memdesc_guard_page_size(memdesc);
}
/*
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 69ae2e3fd2d7..f9d3ede718ab 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -313,6 +313,13 @@ int kgsl_snapshot_get_object(struct kgsl_snapshot *snapshot,
goto err_put;
}
+ /* Do not save sparse memory */
+ if (entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_VIRT ||
+ entry->memdesc.flags & KGSL_MEMFLAGS_SPARSE_PHYS) {
+ ret = 0;
+ goto err_put;
+ }
+
/*
* size indicates the number of bytes in the region to save. This might
* not always be the entire size of the region because some buffers are
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 8988dc12839f..bac09175cf12 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -1102,6 +1102,100 @@ TRACE_EVENT(kgsl_msg,
)
);
+DECLARE_EVENT_CLASS(sparse_alloc_template,
+ TP_PROTO(unsigned int id, uint64_t size, unsigned int pagesize),
+ TP_ARGS(id, size, pagesize),
+ TP_STRUCT__entry(
+ __field(unsigned int, id)
+ __field(uint64_t, size)
+ __field(unsigned int, pagesize)
+ ),
+ TP_fast_assign(
+ __entry->id = id;
+ __entry->size = size;
+ __entry->pagesize = pagesize;
+ ),
+ TP_printk("id=%d size=0x%llX pagesize=0x%X",
+ __entry->id, __entry->size, __entry->pagesize)
+);
+
+DEFINE_EVENT(sparse_alloc_template, sparse_phys_alloc,
+ TP_PROTO(unsigned int id, uint64_t size, unsigned int pagesize),
+ TP_ARGS(id, size, pagesize)
+);
+
+DEFINE_EVENT(sparse_alloc_template, sparse_virt_alloc,
+ TP_PROTO(unsigned int id, uint64_t size, unsigned int pagesize),
+ TP_ARGS(id, size, pagesize)
+);
+
+DECLARE_EVENT_CLASS(sparse_free_template,
+ TP_PROTO(unsigned int id),
+ TP_ARGS(id),
+ TP_STRUCT__entry(
+ __field(unsigned int, id)
+ ),
+ TP_fast_assign(
+ __entry->id = id;
+ ),
+ TP_printk("id=%d", __entry->id)
+);
+
+DEFINE_EVENT(sparse_free_template, sparse_phys_free,
+ TP_PROTO(unsigned int id),
+ TP_ARGS(id)
+);
+
+DEFINE_EVENT(sparse_free_template, sparse_virt_free,
+ TP_PROTO(unsigned int id),
+ TP_ARGS(id)
+);
+
+TRACE_EVENT(sparse_bind,
+ TP_PROTO(unsigned int v_id, uint64_t v_off,
+ unsigned int p_id, uint64_t p_off,
+ uint64_t size, uint64_t flags),
+ TP_ARGS(v_id, v_off, p_id, p_off, size, flags),
+ TP_STRUCT__entry(
+ __field(unsigned int, v_id)
+ __field(uint64_t, v_off)
+ __field(unsigned int, p_id)
+ __field(uint64_t, p_off)
+ __field(uint64_t, size)
+ __field(uint64_t, flags)
+ ),
+ TP_fast_assign(
+ __entry->v_id = v_id;
+ __entry->v_off = v_off;
+ __entry->p_id = p_id;
+ __entry->p_off = p_off;
+ __entry->size = size;
+ __entry->flags = flags;
+ ),
+ TP_printk(
+ "v_id=%d v_off=0x%llX p_id=%d p_off=0x%llX size=0x%llX flags=0x%llX",
+ __entry->v_id, __entry->v_off,
+ __entry->p_id, __entry->p_off,
+ __entry->size, __entry->flags)
+);
+
+TRACE_EVENT(sparse_unbind,
+ TP_PROTO(unsigned int v_id, uint64_t v_off, uint64_t size),
+ TP_ARGS(v_id, v_off, size),
+ TP_STRUCT__entry(
+ __field(unsigned int, v_id)
+ __field(uint64_t, v_off)
+ __field(uint64_t, size)
+ ),
+ TP_fast_assign(
+ __entry->v_id = v_id;
+ __entry->v_off = v_off;
+ __entry->size = size;
+ ),
+ TP_printk("v_id=%d v_off=0x%llX size=0x%llX",
+ __entry->v_id, __entry->v_off, __entry->size)
+);
+
#endif /* _KGSL_TRACE_H */
diff --git a/drivers/iommu/dma-mapping-fast.c b/drivers/iommu/dma-mapping-fast.c
index c28b8df4194e..ea8db1a431d0 100644
--- a/drivers/iommu/dma-mapping-fast.c
+++ b/drivers/iommu/dma-mapping-fast.c
@@ -14,6 +14,7 @@
#include <linux/dma-mapping.h>
#include <linux/dma-mapping-fast.h>
#include <linux/io-pgtable-fast.h>
+#include <linux/vmalloc.h>
#include <asm/cacheflush.h>
#include <asm/dma-iommu.h>
@@ -512,6 +513,33 @@ static void fast_smmu_free(struct device *dev, size_t size,
__fast_smmu_free_pages(pages, count);
}
+static int fast_smmu_mmap_attrs(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t dma_addr,
+ size_t size, struct dma_attrs *attrs)
+{
+ struct vm_struct *area;
+ unsigned long uaddr = vma->vm_start;
+ struct page **pages;
+ int i, nr_pages, ret = 0;
+
+ vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
+
+ area = find_vm_area(cpu_addr);
+ if (!area)
+ return -EINVAL;
+
+ pages = area->pages;
+ nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
+ for (i = vma->vm_pgoff; i < nr_pages && uaddr < vma->vm_end; i++) {
+ ret = vm_insert_page(vma, uaddr, pages[i]);
+ if (ret)
+ break;
+ uaddr += PAGE_SIZE;
+ }
+
+ return ret;
+}
+
static int fast_smmu_dma_supported(struct device *dev, u64 mask)
{
return mask <= 0xffffffff;
@@ -559,6 +587,7 @@ static int fast_smmu_notify(struct notifier_block *self,
static const struct dma_map_ops fast_smmu_dma_ops = {
.alloc = fast_smmu_alloc,
.free = fast_smmu_free,
+ .mmap = fast_smmu_mmap_attrs,
.map_page = fast_smmu_map_page,
.unmap_page = fast_smmu_unmap_page,
.map_sg = fast_smmu_map_sg,
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index 8721fc18eaa8..ac2d508269a4 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -184,6 +184,7 @@ int msm_isp_validate_axi_request(struct msm_vfe_axi_shared_data *axi_data,
case V4L2_PIX_FMT_P16RGGB10:
case V4L2_PIX_FMT_JPEG:
case V4L2_PIX_FMT_META:
+ case V4L2_PIX_FMT_META10:
case V4L2_PIX_FMT_GREY:
stream_info->num_planes = 1;
stream_info->format_factor = ISP_Q2;
@@ -288,6 +289,7 @@ static uint32_t msm_isp_axi_get_plane_size(
case V4L2_PIX_FMT_QGBRG10:
case V4L2_PIX_FMT_QGRBG10:
case V4L2_PIX_FMT_QRGGB10:
+ case V4L2_PIX_FMT_META10:
/* TODO: fix me */
size = plane_cfg[plane_idx].output_height *
plane_cfg[plane_idx].output_width;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 5e24b146619d..e47a8de30aa9 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -1396,6 +1396,7 @@ int msm_isp_cal_word_per_line(uint32_t output_format,
case V4L2_PIX_FMT_SGBRG10DPCM8:
case V4L2_PIX_FMT_SGRBG10DPCM8:
case V4L2_PIX_FMT_SRGGB10DPCM8:
+ case V4L2_PIX_FMT_META10:
val = CAL_WORD(pixel_per_line, 5, 32);
break;
case V4L2_PIX_FMT_SBGGR12:
@@ -1581,6 +1582,8 @@ int msm_isp_get_bit_per_pixel(uint32_t output_format)
case V4L2_PIX_FMT_P16GBRG10:
case V4L2_PIX_FMT_P16GRBG10:
case V4L2_PIX_FMT_P16RGGB10:
+ case V4L2_PIX_FMT_META10:
+ case MSM_V4L2_PIX_FMT_META10:
return 10;
case V4L2_PIX_FMT_SBGGR12:
case V4L2_PIX_FMT_SGBRG12:
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
index 1fc51d900cf8..d0ce1de1162a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
@@ -920,6 +920,14 @@ static int32_t msm_flash_get_dt_data(struct device_node *of_node,
fctrl->flash_driver_type = FLASH_DRIVER_I2C;
}
+ /* Read the flash and torch source info from device tree node */
+ rc = msm_flash_get_pmic_source_info(of_node, fctrl);
+ if (rc < 0) {
+ pr_err("%s:%d msm_flash_get_pmic_source_info failed rc %d\n",
+ __func__, __LINE__, rc);
+ return rc;
+ }
+
/* Read the gpio information from device tree */
rc = msm_sensor_driver_get_gpio_data(
&(fctrl->power_info.gpio_conf), of_node);
@@ -934,13 +942,6 @@ static int32_t msm_flash_get_dt_data(struct device_node *of_node,
CDBG("%s:%d fctrl->flash_driver_type = %d", __func__, __LINE__,
fctrl->flash_driver_type);
- /* Read the flash and torch source info from device tree node */
- rc = msm_flash_get_pmic_source_info(of_node, fctrl);
- if (rc < 0) {
- pr_err("%s:%d msm_flash_get_pmic_source_info failed rc %d\n",
- __func__, __LINE__, rc);
- return rc;
- }
return rc;
}
diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c
index 96fefea39241..ee3df23115a5 100644
--- a/drivers/media/platform/msm/vidc/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc/msm_vdec.c
@@ -601,10 +601,6 @@ static struct msm_vidc_ctrl msm_vdec_ctrls[] = {
#define NUM_CTRLS ARRAY_SIZE(msm_vdec_ctrls)
-static int set_buffer_size(struct msm_vidc_inst *inst,
- u32 buffer_size, enum hal_buffer buffer_type);
-static int update_output_buffer_size(struct msm_vidc_inst *inst,
- struct v4l2_format *f, int num_planes);
static int vdec_hal_to_v4l2(int id, int value);
static u32 get_frame_size_nv12(int plane,
@@ -1181,13 +1177,6 @@ int msm_vdec_g_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
for (i = 0; i < fmt->num_planes; ++i)
inst->bufq[CAPTURE_PORT].vb2_bufq.plane_sizes[i] =
f->fmt.pix_mp.plane_fmt[i].sizeimage;
- rc = update_output_buffer_size(inst, f, fmt->num_planes);
- if (rc) {
- dprintk(VIDC_ERR,
- "%s - failed to update buffer size: %d\n",
- __func__, rc);
- goto exit;
- }
}
if (stride && scanlines) {
@@ -1220,95 +1209,6 @@ exit:
return rc;
}
-static int set_buffer_size(struct msm_vidc_inst *inst,
- u32 buffer_size, enum hal_buffer buffer_type)
-{
- int rc = 0;
- struct hfi_device *hdev;
- struct hal_buffer_size_minimum b;
-
- if (!inst || !inst->core || !inst->core->device) {
- dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
- return -EINVAL;
- }
-
- hdev = inst->core->device;
-
- dprintk(VIDC_DBG,
- "Set minimum buffer size = %d for buffer type %d to fw\n",
- buffer_size, buffer_type);
-
- b.buffer_type = buffer_type;
- b.buffer_size = buffer_size;
- rc = call_hfi_op(hdev, session_set_property,
- inst->session, HAL_PARAM_BUFFER_SIZE_MINIMUM,
- &b);
- if (rc)
- dprintk(VIDC_ERR,
- "%s - failed to set actual buffer size %u on firmware\n",
- __func__, buffer_size);
- return rc;
-}
-
-static int update_output_buffer_size(struct msm_vidc_inst *inst,
- struct v4l2_format *f, int num_planes)
-{
- int rc = 0, i = 0;
- struct hal_buffer_requirements *bufreq;
-
- if (!inst || !f)
- return -EINVAL;
-
- /*
- * Firmware expects driver to always set the minimum buffer
- * size negotiated with the v4l2 client. Firmware will use this
- * size to check for buffer sufficiency in dynamic buffer mode.
- */
- for (i = 0; i < num_planes; ++i) {
- enum hal_buffer type = msm_comm_get_hal_output_buffer(inst);
-
- if (EXTRADATA_IDX(num_planes) &&
- i == EXTRADATA_IDX(num_planes))
- continue;
-
- bufreq = get_buff_req_buffer(inst, type);
- if (!bufreq)
- goto exit;
-
- if (f->fmt.pix_mp.plane_fmt[i].sizeimage >=
- bufreq->buffer_size) {
- rc = set_buffer_size(inst,
- f->fmt.pix_mp.plane_fmt[i].sizeimage, type);
- if (rc)
- goto exit;
- }
- }
-
- /*
- * Set min buffer size for DPB buffers as well.
- * Firmware mandates setting of minimum buffer size
- * and actual buffer count for both OUTPUT and OUTPUT2.
- * Hence we are setting back the same buffer size
- * information back to firmware.
- */
- if (msm_comm_get_stream_output_mode(inst) ==
- HAL_VIDEO_DECODER_SECONDARY) {
- bufreq = get_buff_req_buffer(inst, HAL_BUFFER_OUTPUT);
- if (!bufreq) {
- rc = -EINVAL;
- goto exit;
- }
-
- rc = set_buffer_size(inst, bufreq->buffer_size,
- HAL_BUFFER_OUTPUT);
- if (rc)
- goto exit;
- }
-
-exit:
- return rc;
-}
-
static int set_default_properties(struct msm_vidc_inst *inst)
{
struct hfi_device *hdev;
@@ -1370,13 +1270,9 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
inst->prop.width[CAPTURE_PORT] = f->fmt.pix_mp.width;
inst->prop.height[CAPTURE_PORT] = f->fmt.pix_mp.height;
- if (msm_comm_get_stream_output_mode(inst) ==
- HAL_VIDEO_DECODER_PRIMARY) {
- inst->prop.width[OUTPUT_PORT] = f->fmt.pix_mp.width;
- inst->prop.height[OUTPUT_PORT] = f->fmt.pix_mp.height;
- msm_comm_set_color_format(inst, HAL_BUFFER_OUTPUT,
+ msm_comm_set_color_format(inst,
+ msm_comm_get_hal_output_buffer(inst),
f->fmt.pix_mp.pixelformat);
- }
inst->fmts[fmt->type] = fmt;
if (msm_comm_get_stream_output_mode(inst) ==
@@ -1384,8 +1280,6 @@ int msm_vdec_s_fmt(struct msm_vidc_inst *inst, struct v4l2_format *f)
frame_sz.buffer_type = HAL_BUFFER_OUTPUT2;
frame_sz.width = inst->prop.width[CAPTURE_PORT];
frame_sz.height = inst->prop.height[CAPTURE_PORT];
- msm_comm_set_color_format(inst, HAL_BUFFER_OUTPUT2,
- f->fmt.pix_mp.pixelformat);
dprintk(VIDC_DBG,
"buffer type = %d width = %d, height = %d\n",
frame_sz.buffer_type, frame_sz.width,
@@ -1793,12 +1687,28 @@ static inline int start_streaming(struct msm_vidc_inst *inst)
int rc = 0;
struct hfi_device *hdev;
bool slave_side_cp = inst->core->resources.slave_side_cp;
+ struct hal_buffer_size_minimum b;
+ unsigned int buffer_size;
+ struct msm_vidc_format *fmt = NULL;
+ fmt = inst->fmts[CAPTURE_PORT];
+ buffer_size = fmt->get_frame_size(0,
+ inst->prop.height[CAPTURE_PORT],
+ inst->prop.width[CAPTURE_PORT]);
hdev = inst->core->device;
if (msm_comm_get_stream_output_mode(inst) ==
- HAL_VIDEO_DECODER_SECONDARY)
+ HAL_VIDEO_DECODER_SECONDARY) {
rc = msm_vidc_check_scaling_supported(inst);
+ b.buffer_type = HAL_BUFFER_OUTPUT2;
+ } else {
+ b.buffer_type = HAL_BUFFER_OUTPUT;
+ }
+
+ b.buffer_size = buffer_size;
+ rc = call_hfi_op(hdev, session_set_property,
+ inst->session, HAL_PARAM_BUFFER_SIZE_MINIMUM,
+ &b);
if (rc) {
dprintk(VIDC_ERR, "H/w scaling is not in valid range\n");
return -EINVAL;
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index c08084a54e86..55ee7e02973c 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -2702,7 +2702,7 @@ static int try_set_ctrl(struct msm_vidc_inst *inst, struct v4l2_ctrl *ctrl)
(inst->fmts[CAPTURE_PORT]->fourcc == V4L2_PIX_FMT_HEVC);
if (is_cont_intra_supported) {
- if (air_mbs || air_ref || cir_mbs)
+ if (ctrl->val != HAL_INTRA_REFRESH_NONE)
enable.enable = true;
else
enable.enable = false;
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_common.c b/drivers/media/platform/msm/vidc/msm_vidc_common.c
index 1f071ba36ec1..587aa930cf9c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_common.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_common.c
@@ -3010,6 +3010,7 @@ static int set_output_buffers(struct msm_vidc_inst *inst,
struct hal_buffer_requirements *output_buf, *extradata_buf;
int i;
struct hfi_device *hdev;
+ struct hal_buffer_size_minimum b;
hdev = inst->core->device;
@@ -3026,6 +3027,11 @@ static int set_output_buffers(struct msm_vidc_inst *inst,
output_buf->buffer_size);
buffer_size = output_buf->buffer_size;
+ b.buffer_type = buffer_type;
+ b.buffer_size = buffer_size;
+ rc = call_hfi_op(hdev, session_set_property,
+ inst->session, HAL_PARAM_BUFFER_SIZE_MINIMUM,
+ &b);
extradata_buf = get_buff_req_buffer(inst, HAL_BUFFER_EXTRADATA_OUTPUT);
if (extradata_buf) {
diff --git a/drivers/mfd/wcd9xxx-irq.c b/drivers/mfd/wcd9xxx-irq.c
index 1b93c83ae98e..0c5754341991 100644
--- a/drivers/mfd/wcd9xxx-irq.c
+++ b/drivers/mfd/wcd9xxx-irq.c
@@ -741,6 +741,7 @@ static int wcd9xxx_irq_remove(struct platform_device *pdev)
wmb();
irq_domain_remove(data->domain);
kfree(data);
+ domain->host_data = NULL;
return 0;
}
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 84932513f008..0acebc87ec20 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -796,14 +796,13 @@ static inline void early_init_dt_check_for_initrd(unsigned long node)
#endif /* CONFIG_BLK_DEV_INITRD */
#ifdef CONFIG_SERIAL_EARLYCON
-extern struct of_device_id __earlycon_of_table[];
static int __init early_init_dt_scan_chosen_serial(void)
{
int offset;
const char *p;
int l;
- const struct of_device_id *match = __earlycon_of_table;
+ const struct earlycon_id *match;
const void *fdt = initial_boot_params;
offset = fdt_path_offset(fdt, "/chosen");
@@ -826,19 +825,20 @@ static int __init early_init_dt_scan_chosen_serial(void)
if (offset < 0)
return -ENODEV;
- while (match->compatible[0]) {
+ for (match = __earlycon_table; match < __earlycon_table_end; match++) {
u64 addr;
- if (fdt_node_check_compatible(fdt, offset, match->compatible)) {
- match++;
+ if (!match->compatible[0])
+ continue;
+
+ if (fdt_node_check_compatible(fdt, offset, match->compatible))
continue;
- }
addr = fdt_translate_address(fdt, offset);
if (addr == OF_BAD_ADDR)
return -ENXIO;
- of_setup_earlycon(addr, match->data);
+ of_setup_earlycon(addr, match->setup);
return 0;
}
return -ENODEV;
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 53e3af9052a9..71154ec99d3c 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -550,6 +550,7 @@ static void armpmu_init(struct arm_pmu *armpmu)
.stop = armpmu_stop,
.read = armpmu_read,
.filter_match = armpmu_filter_match,
+ .events_across_hotplug = 1,
};
}
@@ -686,31 +687,12 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
return 0;
}
-/*
- * PMU hardware loses all context when a CPU goes offline.
- * When a CPU is hotplugged back in, since some hardware registers are
- * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
- * junk values out of them.
- */
-static int cpu_pmu_notify(struct notifier_block *b, unsigned long action,
- void *hcpu)
-{
- int cpu = (unsigned long)hcpu;
- struct arm_pmu *pmu = container_of(b, struct arm_pmu, hotplug_nb);
-
- if ((action & ~CPU_TASKS_FROZEN) != CPU_STARTING)
- return NOTIFY_DONE;
-
- if (!cpumask_test_cpu(cpu, &pmu->supported_cpus))
- return NOTIFY_DONE;
-
- if (pmu->reset)
- pmu->reset(pmu);
- else
- return NOTIFY_DONE;
-
- return NOTIFY_OK;
-}
+struct cpu_pm_pmu_args {
+ struct arm_pmu *armpmu;
+ unsigned long cmd;
+ int cpu;
+ int ret;
+};
#ifdef CONFIG_CPU_PM
static void cpu_pm_pmu_setup(struct arm_pmu *armpmu, unsigned long cmd)
@@ -758,15 +740,19 @@ static void cpu_pm_pmu_setup(struct arm_pmu *armpmu, unsigned long cmd)
}
}
-static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
- void *v)
+static void cpu_pm_pmu_common(void *info)
{
- struct arm_pmu *armpmu = container_of(b, struct arm_pmu, cpu_pm_nb);
+ struct cpu_pm_pmu_args *data = info;
+ struct arm_pmu *armpmu = data->armpmu;
+ unsigned long cmd = data->cmd;
+ int cpu = data->cpu;
struct pmu_hw_events *hw_events = this_cpu_ptr(armpmu->hw_events);
int enabled = bitmap_weight(hw_events->used_mask, armpmu->num_events);
- if (!cpumask_test_cpu(smp_processor_id(), &armpmu->supported_cpus))
- return NOTIFY_DONE;
+ if (!cpumask_test_cpu(cpu, &armpmu->supported_cpus)) {
+ data->ret = NOTIFY_DONE;
+ return;
+ }
/*
* Always reset the PMU registers on power-up even if
@@ -775,8 +761,12 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
if (cmd == CPU_PM_EXIT && armpmu->reset)
armpmu->reset(armpmu);
- if (!enabled)
- return NOTIFY_OK;
+ if (!enabled) {
+ data->ret = NOTIFY_OK;
+ return;
+ }
+
+ data->ret = NOTIFY_OK;
switch (cmd) {
case CPU_PM_ENTER:
@@ -784,15 +774,29 @@ static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
cpu_pm_pmu_setup(armpmu, cmd);
break;
case CPU_PM_EXIT:
- cpu_pm_pmu_setup(armpmu, cmd);
case CPU_PM_ENTER_FAILED:
+ cpu_pm_pmu_setup(armpmu, cmd);
armpmu->start(armpmu);
break;
default:
- return NOTIFY_DONE;
+ data->ret = NOTIFY_DONE;
+ break;
}
- return NOTIFY_OK;
+ return;
+}
+
+static int cpu_pm_pmu_notify(struct notifier_block *b, unsigned long cmd,
+ void *v)
+{
+ struct cpu_pm_pmu_args data = {
+ .armpmu = container_of(b, struct arm_pmu, cpu_pm_nb),
+ .cmd = cmd,
+ .cpu = smp_processor_id(),
+ };
+
+ cpu_pm_pmu_common(&data);
+ return data.ret;
}
static int cpu_pm_pmu_register(struct arm_pmu *cpu_pmu)
@@ -808,8 +812,62 @@ static void cpu_pm_pmu_unregister(struct arm_pmu *cpu_pmu)
#else
static inline int cpu_pm_pmu_register(struct arm_pmu *cpu_pmu) { return 0; }
static inline void cpu_pm_pmu_unregister(struct arm_pmu *cpu_pmu) { }
+static inline void cpu_pm_pmu_common(void *info) { }
#endif
+/*
+ * PMU hardware loses all context when a CPU goes offline.
+ * When a CPU is hotplugged back in, since some hardware registers are
+ * UNKNOWN at reset, the PMU must be explicitly reset to avoid reading
+ * junk values out of them.
+ */
+static int cpu_pmu_notify(struct notifier_block *b, unsigned long action,
+ void *hcpu)
+{
+ unsigned long masked_action = (action & ~CPU_TASKS_FROZEN);
+ struct cpu_pm_pmu_args data = {
+ .armpmu = container_of(b, struct arm_pmu, hotplug_nb),
+ .cpu = (unsigned long)hcpu,
+ };
+
+ if (!cpumask_test_cpu(data.cpu, &data.armpmu->supported_cpus))
+ return NOTIFY_DONE;
+
+ switch (masked_action) {
+ case CPU_STARTING:
+ data.cmd = CPU_PM_EXIT;
+ break;
+ case CPU_DYING:
+ data.cmd = CPU_PM_ENTER;
+ break;
+ case CPU_DOWN_FAILED:
+ data.cmd = CPU_PM_ENTER_FAILED;
+ break;
+ case CPU_ONLINE:
+ if (data.armpmu->plat_device) {
+ struct platform_device *pmu_device =
+ data.armpmu->plat_device;
+ int irq = platform_get_irq(pmu_device, 0);
+
+ if (irq >= 0 && irq_is_percpu(irq)) {
+ smp_call_function_single(data.cpu,
+ cpu_pmu_enable_percpu_irq, &irq, 1);
+ }
+ }
+ return NOTIFY_DONE;
+ default:
+ return NOTIFY_DONE;
+ }
+
+ if (smp_processor_id() == data.cpu)
+ cpu_pm_pmu_common(&data);
+ else
+ smp_call_function_single(data.cpu,
+ cpu_pm_pmu_common, &data, 1);
+
+ return data.ret;
+}
+
static int cpu_pmu_init(struct arm_pmu *cpu_pmu)
{
int err;
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index c45cbfa8a786..56555af4c2c6 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -669,7 +669,7 @@ config MSM_EVENT_TIMER
config MSM_AVTIMER
tristate "Avtimer Driver"
- depends on MSM_QDSP6_APRV2 || MSM_QDSP6_APRV3
+ depends on MSM_QDSP6_APRV2 || MSM_QDSP6_APRV3 || MSM_QDSP6_APRV2_GLINK
help
This driver gets the Q6 out of power collapsed state and
exposes ioctl control to read avtimer tick.
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index 16ca3eaee61b..bfe2072ee554 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -33,6 +33,7 @@
#include <linux/dma-mapping.h>
#include <linux/qmi_encdec.h>
#include <linux/ipc_logging.h>
+#include <linux/msm-bus.h>
#include <soc/qcom/memory_dump.h>
#include <soc/qcom/icnss.h>
#include <soc/qcom/msm_qmi_interface.h>
@@ -43,7 +44,6 @@
#define ICNSS_PANIC 1
#define WLFW_TIMEOUT_MS 3000
#define WLFW_SERVICE_INS_ID_V01 0
-#define SMMU_CLOCK_NAME "smmu_aggre2_noc_clk"
#define MAX_PROP_SIZE 32
#define MAX_VOLTAGE_LEVEL 2
#define VREG_ON 1
@@ -203,7 +203,8 @@ static struct icnss_data {
size_t smmu_iova_len;
dma_addr_t smmu_iova_ipa_start;
size_t smmu_iova_ipa_len;
- struct clk *smmu_clk;
+ struct msm_bus_scale_pdata *bus_scale_table;
+ uint32_t bus_client;
struct qmi_handle *wlfw_clnt;
struct list_head event_list;
spinlock_t event_lock;
@@ -1789,44 +1790,60 @@ int icnss_smmu_map(struct device *dev,
}
EXPORT_SYMBOL(icnss_smmu_map);
-static struct clk *icnss_clock_init(struct device *dev, const char *cname)
+static int icnss_bw_vote(struct icnss_data *priv, int index)
{
- struct clk *c;
- long rate;
-
- if (of_property_match_string(dev->of_node, "clock-names", cname) < 0) {
- icnss_pr_err("Clock %s not found!", cname);
- return NULL;
- }
-
- c = devm_clk_get(dev, cname);
- if (IS_ERR(c)) {
- icnss_pr_err("Couldn't get clock %s!", cname);
- return NULL;
- }
+ int ret = 0;
- if (clk_get_rate(c) == 0) {
- rate = clk_round_rate(c, 1000);
- clk_set_rate(c, rate);
- }
+ icnss_pr_dbg("Vote %d for msm_bus, state 0x%lx\n",
+ index, priv->state);
+ ret = msm_bus_scale_client_update_request(priv->bus_client, index);
+ if (ret)
+ icnss_pr_err("Fail to vote %d: ret %d, state 0x%lx!\n",
+ index, ret, priv->state);
- return c;
+ return ret;
}
-static int icnss_clock_enable(struct clk *c)
+static int icnss_bw_init(struct icnss_data *priv)
{
int ret = 0;
- ret = clk_prepare_enable(c);
+ priv->bus_scale_table = msm_bus_cl_get_pdata(priv->pdev);
+ if (!priv->bus_scale_table) {
+ icnss_pr_err("Missing entry for msm_bus scale table\n");
+ return -EINVAL;
+ }
- if (ret < 0)
- icnss_pr_err("Couldn't enable clock: %d!\n", ret);
+ priv->bus_client = msm_bus_scale_register_client(priv->bus_scale_table);
+ if (!priv->bus_client) {
+ icnss_pr_err("Fail to register with bus_scale client\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ ret = icnss_bw_vote(priv, 1);
+ if (ret)
+ goto out;
+
+ return 0;
+
+out:
+ msm_bus_cl_clear_pdata(priv->bus_scale_table);
return ret;
}
-static void icnss_clock_disable(struct clk *c)
+static void icnss_bw_deinit(struct icnss_data *priv)
{
- clk_disable_unprepare(c);
+ if (!priv)
+ return;
+
+ if (priv->bus_client) {
+ icnss_bw_vote(priv, 0);
+ msm_bus_scale_unregister_client(priv->bus_client);
+ }
+
+ if (priv->bus_scale_table)
+ msm_bus_cl_clear_pdata(priv->bus_scale_table);
}
static int icnss_smmu_init(struct device *dev)
@@ -2460,12 +2477,9 @@ static int icnss_probe(struct platform_device *pdev)
goto err_smmu_init;
}
- penv->smmu_clk = icnss_clock_init(&pdev->dev, SMMU_CLOCK_NAME);
- if (penv->smmu_clk) {
- ret = icnss_clock_enable(penv->smmu_clk);
- if (ret < 0)
- goto err_smmu_clock_enable;
- }
+ ret = icnss_bw_init(penv);
+ if (ret)
+ goto err_bw_init;
}
penv->skip_qmi = of_property_read_bool(dev->of_node,
@@ -2478,7 +2492,7 @@ static int icnss_probe(struct platform_device *pdev)
if (!penv->event_wq) {
icnss_pr_err("Workqueue creation failed\n");
ret = -EFAULT;
- goto err_smmu_clock_enable;
+ goto err_alloc_workqueue;
}
INIT_WORK(&penv->event_work, icnss_driver_event_work);
@@ -2503,7 +2517,9 @@ static int icnss_probe(struct platform_device *pdev)
err_qmi:
if (penv->event_wq)
destroy_workqueue(penv->event_wq);
-err_smmu_clock_enable:
+err_alloc_workqueue:
+ icnss_bw_deinit(penv);
+err_bw_init:
if (penv->smmu_mapping)
icnss_smmu_remove(&pdev->dev);
err_smmu_init:
@@ -2538,11 +2554,7 @@ static int icnss_remove(struct platform_device *pdev)
if (penv->event_wq)
destroy_workqueue(penv->event_wq);
- if (penv->smmu_mapping) {
- if (penv->smmu_clk)
- icnss_clock_disable(penv->smmu_clk);
- icnss_smmu_remove(&pdev->dev);
- }
+ icnss_bw_deinit(penv);
if (penv->msa_va)
dma_free_coherent(&pdev->dev, penv->msa_mem_size,
diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c
index 9426e0751c4a..24018c544b06 100644
--- a/drivers/soc/qcom/service-locator.c
+++ b/drivers/soc/qcom/service-locator.c
@@ -208,8 +208,8 @@ static int servreg_loc_send_msg(struct msg_desc *req_desc,
static int service_locator_send_msg(struct pd_qmi_client_data *pd)
{
struct msg_desc req_desc, resp_desc;
- struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp;
- struct qmi_servreg_loc_get_domain_list_req_msg_v01 *req;
+ struct qmi_servreg_loc_get_domain_list_resp_msg_v01 *resp = NULL;
+ struct qmi_servreg_loc_get_domain_list_req_msg_v01 *req = NULL;
int rc;
int db_rev_count = 0, domains_read = 0;
diff --git a/drivers/soundwire/swr-wcd-ctrl.c b/drivers/soundwire/swr-wcd-ctrl.c
index 2cb60c11e212..266091486bf1 100644
--- a/drivers/soundwire/swr-wcd-ctrl.c
+++ b/drivers/soundwire/swr-wcd-ctrl.c
@@ -325,6 +325,7 @@ static int swrm_set_ch_map(struct swr_mstr_ctrl *swrm, void *data)
GFP_KERNEL);
if (!swrm->mstr_port->port) {
kfree(swrm->mstr_port);
+ swrm->mstr_port = NULL;
return -ENOMEM;
}
memcpy(swrm->mstr_port->port, pinfo->port, pinfo->num_port);
@@ -476,7 +477,7 @@ static int swrm_read(struct swr_master *master, u8 dev_num, u16 reg_addr,
{
struct swr_mstr_ctrl *swrm = swr_get_ctrl_data(master);
int ret = 0;
- int val = 0;
+ int val;
u8 *reg_val = (u8 *)buf;
if (!swrm) {
@@ -1474,7 +1475,9 @@ static int swrm_remove(struct platform_device *pdev)
swrm, SWR_IRQ_FREE);
if (swrm->mstr_port) {
kfree(swrm->mstr_port->port);
+ swrm->mstr_port->port = NULL;
kfree(swrm->mstr_port);
+ swrm->mstr_port = NULL;
}
pm_runtime_disable(&pdev->dev);
pm_runtime_set_suspended(&pdev->dev);
diff --git a/drivers/staging/android/ion/ion_page_pool.c b/drivers/staging/android/ion/ion_page_pool.c
index d549d6271d89..513d015a5ace 100644
--- a/drivers/staging/android/ion/ion_page_pool.c
+++ b/drivers/staging/android/ion/ion_page_pool.c
@@ -54,8 +54,7 @@ static void ion_page_pool_free_pages(struct ion_page_pool *pool,
__free_pages(page, pool->order);
}
-static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page,
- bool prefetch)
+static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page)
{
mutex_lock(&pool->mutex);
if (PageHighMem(page)) {
@@ -65,15 +64,11 @@ static int ion_page_pool_add(struct ion_page_pool *pool, struct page *page,
list_add_tail(&page->lru, &pool->low_items);
pool->low_count++;
}
- if (!prefetch)
- pool->nr_unreserved++;
-
mutex_unlock(&pool->mutex);
return 0;
}
-static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high,
- bool prefetch)
+static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high)
{
struct page *page;
@@ -87,13 +82,6 @@ static struct page *ion_page_pool_remove(struct ion_page_pool *pool, bool high,
pool->low_count--;
}
- if (prefetch) {
- BUG_ON(!pool->nr_unreserved);
- pool->nr_unreserved--;
- }
- pool->nr_unreserved = min_t(int, pool->high_count + pool->low_count,
- pool->nr_unreserved);
-
list_del(&page->lru);
return page;
}
@@ -108,9 +96,9 @@ void *ion_page_pool_alloc(struct ion_page_pool *pool, bool *from_pool)
if (mutex_trylock(&pool->mutex)) {
if (pool->high_count)
- page = ion_page_pool_remove(pool, true, false);
+ page = ion_page_pool_remove(pool, true);
else if (pool->low_count)
- page = ion_page_pool_remove(pool, false, false);
+ page = ion_page_pool_remove(pool, false);
mutex_unlock(&pool->mutex);
}
if (!page) {
@@ -120,27 +108,6 @@ void *ion_page_pool_alloc(struct ion_page_pool *pool, bool *from_pool)
return page;
}
-void *ion_page_pool_prefetch(struct ion_page_pool *pool, bool *from_pool)
-{
- struct page *page = NULL;
-
- BUG_ON(!pool);
-
- *from_pool = true;
-
- if (mutex_trylock(&pool->mutex)) {
- if (pool->high_count && pool->nr_unreserved > 0)
- page = ion_page_pool_remove(pool, true, true);
- else if (pool->low_count && pool->nr_unreserved > 0)
- page = ion_page_pool_remove(pool, false, true);
- mutex_unlock(&pool->mutex);
- }
- if (!page) {
- page = ion_page_pool_alloc_pages(pool);
- *from_pool = false;
- }
- return page;
-}
/*
* Tries to allocate from only the specified Pool and returns NULL otherwise
*/
@@ -152,24 +119,20 @@ void *ion_page_pool_alloc_pool_only(struct ion_page_pool *pool)
if (mutex_trylock(&pool->mutex)) {
if (pool->high_count)
- page = ion_page_pool_remove(pool, true, false);
+ page = ion_page_pool_remove(pool, true);
else if (pool->low_count)
- page = ion_page_pool_remove(pool, false, false);
+ page = ion_page_pool_remove(pool, false);
mutex_unlock(&pool->mutex);
}
return page;
}
-void ion_page_pool_free(struct ion_page_pool *pool, struct page *page,
- bool prefetch)
+void ion_page_pool_free(struct ion_page_pool *pool, struct page *page)
{
int ret;
- BUG_ON(pool->order != compound_order(page));
-
- ret = ion_page_pool_add(pool, page, prefetch);
- /* FIXME? For a secure page, not hyp unassigned in this err path */
+ ret = ion_page_pool_add(pool, page);
if (ret)
ion_page_pool_free_pages(pool, page);
}
@@ -208,9 +171,9 @@ int ion_page_pool_shrink(struct ion_page_pool *pool, gfp_t gfp_mask,
mutex_lock(&pool->mutex);
if (pool->low_count) {
- page = ion_page_pool_remove(pool, false, false);
+ page = ion_page_pool_remove(pool, false);
} else if (high && pool->high_count) {
- page = ion_page_pool_remove(pool, true, false);
+ page = ion_page_pool_remove(pool, true);
} else {
mutex_unlock(&pool->mutex);
break;
@@ -233,10 +196,9 @@ struct ion_page_pool *ion_page_pool_create(struct device *dev, gfp_t gfp_mask,
pool->dev = dev;
pool->high_count = 0;
pool->low_count = 0;
- pool->nr_unreserved = 0;
INIT_LIST_HEAD(&pool->low_items);
INIT_LIST_HEAD(&pool->high_items);
- pool->gfp_mask = gfp_mask | __GFP_COMP;
+ pool->gfp_mask = gfp_mask;
pool->order = order;
mutex_init(&pool->mutex);
plist_node_init(&pool->list, order);
diff --git a/drivers/staging/android/ion/ion_priv.h b/drivers/staging/android/ion/ion_priv.h
index 4f383661258a..69da287c064f 100644
--- a/drivers/staging/android/ion/ion_priv.h
+++ b/drivers/staging/android/ion/ion_priv.h
@@ -415,8 +415,6 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
* struct ion_page_pool - pagepool struct
* @high_count: number of highmem items in the pool
* @low_count: number of lowmem items in the pool
- * @nr_unreserved: number of items in the pool which have not been reserved
- * by a prefetch allocation
* @high_items: list of highmem items
* @low_items: list of lowmem items
* @mutex: lock protecting this struct and especially the count
@@ -433,7 +431,6 @@ void ion_carveout_free(struct ion_heap *heap, ion_phys_addr_t addr,
struct ion_page_pool {
int high_count;
int low_count;
- int nr_unreserved;
struct list_head high_items;
struct list_head low_items;
struct mutex mutex;
@@ -448,10 +445,9 @@ struct ion_page_pool *ion_page_pool_create(struct device *dev, gfp_t gfp_mask,
void ion_page_pool_destroy(struct ion_page_pool *);
void *ion_page_pool_alloc(struct ion_page_pool *, bool *from_pool);
void *ion_page_pool_alloc_pool_only(struct ion_page_pool *);
-void ion_page_pool_free(struct ion_page_pool *, struct page *, bool prefetch);
+void ion_page_pool_free(struct ion_page_pool *, struct page *);
void ion_page_pool_free_immediate(struct ion_page_pool *, struct page *);
int ion_page_pool_total(struct ion_page_pool *pool, bool high);
-void *ion_page_pool_prefetch(struct ion_page_pool *pool, bool *from_pool);
#ifdef CONFIG_ION_POOL_CACHE_POLICY
static inline void ion_page_pool_alloc_set_cache_policy
diff --git a/drivers/staging/android/ion/ion_system_heap.c b/drivers/staging/android/ion/ion_system_heap.c
index ff75e1690f59..981cb2f622cb 100644
--- a/drivers/staging/android/ion/ion_system_heap.c
+++ b/drivers/staging/android/ion/ion_system_heap.c
@@ -63,6 +63,8 @@ struct ion_system_heap {
struct ion_page_pool **uncached_pools;
struct ion_page_pool **cached_pools;
struct ion_page_pool **secure_pools[VMID_LAST];
+ /* Prevents unnecessary page splitting */
+ struct mutex split_page_mutex;
};
struct page_info {
@@ -78,7 +80,6 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap,
bool *from_pool)
{
bool cached = ion_buffer_cached(buffer);
- bool prefetch = buffer->flags & ION_FLAG_POOL_PREFETCH;
struct page *page;
struct ion_page_pool *pool;
int vmid = get_secure_vmid(buffer->flags);
@@ -92,10 +93,7 @@ static struct page *alloc_buffer_page(struct ion_system_heap *heap,
else
pool = heap->cached_pools[order_to_index(order)];
- if (prefetch)
- page = ion_page_pool_prefetch(pool, from_pool);
- else
- page = ion_page_pool_alloc(pool, from_pool);
+ page = ion_page_pool_alloc(pool, from_pool);
} else {
gfp_t gfp_mask = low_order_gfp_flags;
if (order)
@@ -119,7 +117,6 @@ static void free_buffer_page(struct ion_system_heap *heap,
unsigned int order)
{
bool cached = ion_buffer_cached(buffer);
- bool prefetch = buffer->flags & ION_FLAG_POOL_PREFETCH;
int vmid = get_secure_vmid(buffer->flags);
if (!(buffer->flags & ION_FLAG_POOL_FORCE_ALLOC)) {
@@ -134,12 +131,65 @@ static void free_buffer_page(struct ion_system_heap *heap,
if (buffer->private_flags & ION_PRIV_FLAG_SHRINKER_FREE)
ion_page_pool_free_immediate(pool, page);
else
- ion_page_pool_free(pool, page, prefetch);
+ ion_page_pool_free(pool, page);
} else {
__free_pages(page, order);
}
}
+static struct page *alloc_from_secure_pool_order(struct ion_system_heap *heap,
+ struct ion_buffer *buffer,
+ unsigned long order)
+{
+ int vmid = get_secure_vmid(buffer->flags);
+ struct ion_page_pool *pool;
+
+ if (!is_secure_vmid_valid(vmid))
+ return NULL;
+
+ pool = heap->secure_pools[vmid][order_to_index(order)];
+ return ion_page_pool_alloc_pool_only(pool);
+}
+
+static struct page *split_page_from_secure_pool(struct ion_system_heap *heap,
+ struct ion_buffer *buffer)
+{
+ int i, j;
+ struct page *page;
+ unsigned int order;
+
+ mutex_lock(&heap->split_page_mutex);
+
+ /*
+ * Someone may have just split a page and returned the unused portion
+ * back to the pool, so try allocating from the pool one more time
+ * before splitting. We want to maintain large pages sizes when
+ * possible.
+ */
+ page = alloc_from_secure_pool_order(heap, buffer, 0);
+ if (page)
+ goto got_page;
+
+ for (i = num_orders - 2; i >= 0; i--) {
+ order = orders[i];
+ page = alloc_from_secure_pool_order(heap, buffer, order);
+ if (!page)
+ continue;
+
+ split_page(page, order);
+ break;
+ }
+ /* Return the remaining order-0 pages to the pool */
+ if (page)
+ for (j = 1; j < (1 << order); j++)
+ free_buffer_page(heap, buffer, page + j, 0);
+
+got_page:
+ mutex_unlock(&heap->split_page_mutex);
+
+ return page;
+}
+
static struct page_info *alloc_largest_available(struct ion_system_heap *heap,
struct ion_buffer *buffer,
unsigned long size,
@@ -174,6 +224,49 @@ static struct page_info *alloc_largest_available(struct ion_system_heap *heap,
return NULL;
}
+
+static struct page_info *alloc_from_pool_preferred(
+ struct ion_system_heap *heap, struct ion_buffer *buffer,
+ unsigned long size, unsigned int max_order)
+{
+ struct page *page;
+ struct page_info *info;
+ int i;
+
+ info = kmalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return NULL;
+
+ for (i = 0; i < num_orders; i++) {
+ if (size < order_to_size(orders[i]))
+ continue;
+ if (max_order < orders[i])
+ continue;
+
+ page = alloc_from_secure_pool_order(heap, buffer, orders[i]);
+ if (!page)
+ continue;
+
+ info->page = page;
+ info->order = orders[i];
+ info->from_pool = true;
+ INIT_LIST_HEAD(&info->list);
+ return info;
+ }
+
+ page = split_page_from_secure_pool(heap, buffer);
+ if (page) {
+ info->page = page;
+ info->order = 0;
+ info->from_pool = true;
+ INIT_LIST_HEAD(&info->list);
+ return info;
+ }
+
+ kfree(info);
+ return alloc_largest_available(heap, buffer, size, max_order);
+}
+
static unsigned int process_info(struct page_info *info,
struct scatterlist *sg,
struct scatterlist *sg_sync,
@@ -236,9 +329,17 @@ static int ion_system_heap_allocate(struct ion_heap *heap,
data.size = 0;
INIT_LIST_HEAD(&pages);
INIT_LIST_HEAD(&pages_from_pool);
+
while (size_remaining > 0) {
- info = alloc_largest_available(sys_heap, buffer, size_remaining,
- max_order);
+ if (is_secure_vmid_valid(vmid))
+ info = alloc_from_pool_preferred(
+ sys_heap, buffer, size_remaining,
+ max_order);
+ else
+ info = alloc_largest_available(
+ sys_heap, buffer, size_remaining,
+ max_order);
+
if (!info)
goto err;
@@ -452,7 +553,7 @@ out1:
/* Restore pages to secure pool */
list_for_each_entry_safe(page, tmp, &pages, lru) {
list_del(&page->lru);
- ion_page_pool_free(pool, page, false);
+ ion_page_pool_free(pool, page);
}
return 0;
out2:
@@ -692,6 +793,8 @@ struct ion_heap *ion_system_heap_create(struct ion_platform_heap *data)
if (ion_system_heap_create_pools(dev, heap->cached_pools))
goto err_create_cached_pools;
+ mutex_init(&heap->split_page_mutex);
+
heap->heap.debug_show = ion_system_heap_debug_show;
return &heap->heap;
diff --git a/drivers/staging/android/ion/ion_system_secure_heap.c b/drivers/staging/android/ion/ion_system_secure_heap.c
index 5c0225cd4e24..9570ab520ca2 100644
--- a/drivers/staging/android/ion/ion_system_secure_heap.c
+++ b/drivers/staging/android/ion/ion_system_secure_heap.c
@@ -151,8 +151,7 @@ static void ion_system_secure_heap_prefetch_work(struct work_struct *work)
/* buffer->heap used by free() */
buffer->heap = &secure_heap->heap;
- buffer->flags = ION_FLAG_POOL_PREFETCH;
- buffer->flags |= vmid_flags;
+ buffer->flags = vmid_flags;
ret = sys_heap->ops->allocate(sys_heap, buffer, size,
PAGE_SIZE, 0);
if (ret) {
diff --git a/drivers/staging/android/uapi/msm_ion.h b/drivers/staging/android/uapi/msm_ion.h
index 73b4d1edcaad..b3c29826834e 100644
--- a/drivers/staging/android/uapi/msm_ion.h
+++ b/drivers/staging/android/uapi/msm_ion.h
@@ -110,8 +110,6 @@ enum cp_mem_usage {
*/
#define ION_FLAG_POOL_FORCE_ALLOC (1 << 16)
-#define ION_FLAG_POOL_PREFETCH (1 << 27)
-
/**
* Deprecated! Please use the corresponding ION_FLAG_*
*/
@@ -176,7 +174,6 @@ struct ion_prefetch_regions {
struct ion_prefetch_data {
int heap_id;
unsigned long len;
- /* Is unsigned long bad? 32bit compiler vs 64 bit compiler*/
struct ion_prefetch_regions __user *regions;
unsigned int nr_regions;
};
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 899a77187bde..2a2975c352f4 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -2227,7 +2227,6 @@ static int __init pl011_early_console_setup(struct earlycon_device *device,
device->con->write = pl011_early_write;
return 0;
}
-EARLYCON_DECLARE(pl011, pl011_early_console_setup);
OF_EARLYCON_DECLARE(pl011, "arm,pl011", pl011_early_console_setup);
#else
diff --git a/drivers/tty/serial/arc_uart.c b/drivers/tty/serial/arc_uart.c
index 03ebe401fff7..3a1de5c87cb4 100644
--- a/drivers/tty/serial/arc_uart.c
+++ b/drivers/tty/serial/arc_uart.c
@@ -576,7 +576,6 @@ static int __init arc_early_console_setup(struct earlycon_device *dev,
dev->con->write = arc_early_serial_write;
return 0;
}
-EARLYCON_DECLARE(arc_uart, arc_early_console_setup);
OF_EARLYCON_DECLARE(arc_uart, "snps,arc-uart", arc_early_console_setup);
#endif /* CONFIG_SERIAL_ARC_CONSOLE */
diff --git a/drivers/tty/serial/earlycon.c b/drivers/tty/serial/earlycon.c
index b5b2f2be6be7..4d2e3e7a40bb 100644
--- a/drivers/tty/serial/earlycon.c
+++ b/drivers/tty/serial/earlycon.c
@@ -19,7 +19,6 @@
#include <linux/io.h>
#include <linux/serial_core.h>
#include <linux/sizes.h>
-#include <linux/mod_devicetable.h>
#ifdef CONFIG_FIX_EARLYCON_MEM
#include <asm/fixmap.h>
@@ -37,13 +36,6 @@ static struct earlycon_device early_console_dev = {
.con = &early_con,
};
-extern struct earlycon_id __earlycon_table[];
-static const struct earlycon_id __earlycon_table_sentinel
- __used __section(__earlycon_table_end);
-
-static const struct of_device_id __earlycon_of_table_sentinel
- __used __section(__earlycon_of_table_end);
-
static void __iomem * __init earlycon_map(unsigned long paddr, size_t size)
{
void __iomem *base;
@@ -159,7 +151,7 @@ int __init setup_earlycon(char *buf)
if (early_con.flags & CON_ENABLED)
return -EALREADY;
- for (match = __earlycon_table; match->name[0]; match++) {
+ for (match = __earlycon_table; match < __earlycon_table_end; match++) {
size_t len = strlen(match->name);
if (strncmp(buf, match->name, len))
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index edd66bb7bd4c..670eda466438 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -19,33 +19,147 @@
# define SUPPORT_SYSRQ
#endif
+#include <linux/kernel.h>
#include <linux/atomic.h>
#include <linux/dma-mapping.h>
#include <linux/dmaengine.h>
-#include <linux/hrtimer.h>
#include <linux/module.h>
#include <linux/io.h>
#include <linux/ioport.h>
-#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/tty.h>
#include <linux/tty_flip.h>
#include <linux/serial_core.h>
-#include <linux/serial.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/of.h>
#include <linux/of_device.h>
-
-#include "msm_serial.h"
-
-#define UARTDM_BURST_SIZE 16 /* in bytes */
-#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */
-#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */
-#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4)
+#include <linux/wait.h>
+
+#define UART_MR1 0x0000
+
+#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
+#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
+#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00
+#define UART_MR1_RX_RDY_CTL BIT(7)
+#define UART_MR1_CTS_CTL BIT(6)
+
+#define UART_MR2 0x0004
+#define UART_MR2_ERROR_MODE BIT(6)
+#define UART_MR2_BITS_PER_CHAR 0x30
+#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
+#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
+#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4)
+#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4)
+#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2)
+#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2)
+#define UART_MR2_PARITY_MODE_NONE 0x0
+#define UART_MR2_PARITY_MODE_ODD 0x1
+#define UART_MR2_PARITY_MODE_EVEN 0x2
+#define UART_MR2_PARITY_MODE_SPACE 0x3
+#define UART_MR2_PARITY_MODE 0x3
+
+#define UART_CSR 0x0008
+
+#define UART_TF 0x000C
+#define UARTDM_TF 0x0070
+
+#define UART_CR 0x0010
+#define UART_CR_CMD_NULL (0 << 4)
+#define UART_CR_CMD_RESET_RX (1 << 4)
+#define UART_CR_CMD_RESET_TX (2 << 4)
+#define UART_CR_CMD_RESET_ERR (3 << 4)
+#define UART_CR_CMD_RESET_BREAK_INT (4 << 4)
+#define UART_CR_CMD_START_BREAK (5 << 4)
+#define UART_CR_CMD_STOP_BREAK (6 << 4)
+#define UART_CR_CMD_RESET_CTS (7 << 4)
+#define UART_CR_CMD_RESET_STALE_INT (8 << 4)
+#define UART_CR_CMD_PACKET_MODE (9 << 4)
+#define UART_CR_CMD_MODE_RESET (12 << 4)
+#define UART_CR_CMD_SET_RFR (13 << 4)
+#define UART_CR_CMD_RESET_RFR (14 << 4)
+#define UART_CR_CMD_PROTECTION_EN (16 << 4)
+#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8)
+#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
+#define UART_CR_CMD_FORCE_STALE (4 << 8)
+#define UART_CR_CMD_RESET_TX_READY (3 << 8)
+#define UART_CR_TX_DISABLE BIT(3)
+#define UART_CR_TX_ENABLE BIT(2)
+#define UART_CR_RX_DISABLE BIT(1)
+#define UART_CR_RX_ENABLE BIT(0)
+#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4))
+
+#define UART_IMR 0x0014
+#define UART_IMR_TXLEV BIT(0)
+#define UART_IMR_RXSTALE BIT(3)
+#define UART_IMR_RXLEV BIT(4)
+#define UART_IMR_DELTA_CTS BIT(5)
+#define UART_IMR_CURRENT_CTS BIT(6)
+#define UART_IMR_RXBREAK_START BIT(10)
+
+#define UART_IPR_RXSTALE_LAST 0x20
+#define UART_IPR_STALE_LSB 0x1F
+#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
+#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80
+
+#define UART_IPR 0x0018
+#define UART_TFWR 0x001C
+#define UART_RFWR 0x0020
+#define UART_HCR 0x0024
+
+#define UART_MREG 0x0028
+#define UART_NREG 0x002C
+#define UART_DREG 0x0030
+#define UART_MNDREG 0x0034
+#define UART_IRDA 0x0038
+#define UART_MISR_MODE 0x0040
+#define UART_MISR_RESET 0x0044
+#define UART_MISR_EXPORT 0x0048
+#define UART_MISR_VAL 0x004C
+#define UART_TEST_CTRL 0x0050
+
+#define UART_SR 0x0008
+#define UART_SR_HUNT_CHAR BIT(7)
+#define UART_SR_RX_BREAK BIT(6)
+#define UART_SR_PAR_FRAME_ERR BIT(5)
+#define UART_SR_OVERRUN BIT(4)
+#define UART_SR_TX_EMPTY BIT(3)
+#define UART_SR_TX_READY BIT(2)
+#define UART_SR_RX_FULL BIT(1)
+#define UART_SR_RX_READY BIT(0)
+
+#define UART_RF 0x000C
+#define UARTDM_RF 0x0070
+#define UART_MISR 0x0010
+#define UART_ISR 0x0014
+#define UART_ISR_TX_READY BIT(7)
+
+#define UARTDM_RXFS 0x50
+#define UARTDM_RXFS_BUF_SHIFT 0x7
+#define UARTDM_RXFS_BUF_MASK 0x7
+
+#define UARTDM_DMEN 0x3C
+#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
+#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
+
+#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */
+#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */
+
+#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */
+#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */
+
+#define UARTDM_DMRX 0x34
+#define UARTDM_NCF_TX 0x40
+#define UARTDM_RX_TOTAL_SNAP 0x38
+
+#define UARTDM_BURST_SIZE 16 /* in bytes */
+#define UARTDM_TX_AIGN(x) ((x) & ~0x3) /* valid for > 1p3 */
+#define UARTDM_TX_MAX 256 /* in bytes, valid for <= 1p3 */
+#define UARTDM_RX_SIZE (UART_XMIT_SIZE / 4)
enum {
UARTDM_1P1 = 1,
@@ -78,10 +192,65 @@ struct msm_port {
struct msm_dma rx_dma;
};
+#define UART_TO_MSM(uart_port) container_of(uart_port, struct msm_port, uart)
+
+static
+void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
+{
+ writel_relaxed(val, port->membase + off);
+}
+
+static
+unsigned int msm_read(struct uart_port *port, unsigned int off)
+{
+ return readl_relaxed(port->membase + off);
+}
+
+/*
+ * Setup the MND registers to use the TCXO clock.
+ */
+static void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
+{
+ msm_write(port, 0x06, UART_MREG);
+ msm_write(port, 0xF1, UART_NREG);
+ msm_write(port, 0x0F, UART_DREG);
+ msm_write(port, 0x1A, UART_MNDREG);
+ port->uartclk = 1843200;
+}
+
+/*
+ * Setup the MND registers to use the TCXO clock divided by 4.
+ */
+static void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
+{
+ msm_write(port, 0x18, UART_MREG);
+ msm_write(port, 0xF6, UART_NREG);
+ msm_write(port, 0x0F, UART_DREG);
+ msm_write(port, 0x0A, UART_MNDREG);
+ port->uartclk = 1843200;
+}
+
+static void msm_serial_set_mnd_regs(struct uart_port *port)
+{
+ struct msm_port *msm_port = UART_TO_MSM(port);
+
+ /*
+ * These registers don't exist so we change the clk input rate
+ * on uartdm hardware instead
+ */
+ if (msm_port->is_uartdm)
+ return;
+
+ if (port->uartclk == 19200000)
+ msm_serial_set_mnd_regs_tcxo(port);
+ else if (port->uartclk == 4800000)
+ msm_serial_set_mnd_regs_tcxoby4(port);
+}
+
static void msm_handle_tx(struct uart_port *port);
static void msm_start_rx_dma(struct msm_port *msm_port);
-void msm_stop_dma(struct uart_port *port, struct msm_dma *dma)
+static void msm_stop_dma(struct uart_port *port, struct msm_dma *dma)
{
struct device *dev = port->dev;
unsigned int mapped;
@@ -388,10 +557,6 @@ static void msm_complete_rx_dma(void *args)
val &= ~dma->enable_bit;
msm_write(port, val, UARTDM_DMEN);
- /* Restore interrupts */
- msm_port->imr |= UART_IMR_RXLEV | UART_IMR_RXSTALE;
- msm_write(port, msm_port->imr, UART_IMR);
-
if (msm_read(port, UART_SR) & UART_SR_OVERRUN) {
port->icount.overrun++;
tty_insert_flip_char(tport, 0, TTY_OVERRUN);
@@ -726,7 +891,7 @@ static void msm_handle_tx(struct uart_port *port)
return;
}
- pio_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE);
+ pio_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
dma_count = CIRC_CNT_TO_END(xmit->head, xmit->tail, UART_XMIT_SIZE);
dma_min = 1; /* Always DMA */
@@ -861,37 +1026,72 @@ struct msm_baud_map {
};
static const struct msm_baud_map *
-msm_find_best_baud(struct uart_port *port, unsigned int baud)
+msm_find_best_baud(struct uart_port *port, unsigned int baud,
+ unsigned long *rate)
{
- unsigned int i, divisor;
- const struct msm_baud_map *entry;
+ struct msm_port *msm_port = UART_TO_MSM(port);
+ unsigned int divisor, result;
+ unsigned long target, old, best_rate = 0, diff, best_diff = ULONG_MAX;
+ const struct msm_baud_map *entry, *end, *best;
static const struct msm_baud_map table[] = {
- { 1536, 0x00, 1 },
- { 768, 0x11, 1 },
- { 384, 0x22, 1 },
- { 192, 0x33, 1 },
- { 96, 0x44, 1 },
- { 48, 0x55, 1 },
- { 32, 0x66, 1 },
- { 24, 0x77, 1 },
- { 16, 0x88, 1 },
- { 12, 0x99, 6 },
- { 8, 0xaa, 6 },
- { 6, 0xbb, 6 },
- { 4, 0xcc, 6 },
- { 3, 0xdd, 8 },
- { 2, 0xee, 16 },
{ 1, 0xff, 31 },
- { 0, 0xff, 31 },
+ { 2, 0xee, 16 },
+ { 3, 0xdd, 8 },
+ { 4, 0xcc, 6 },
+ { 6, 0xbb, 6 },
+ { 8, 0xaa, 6 },
+ { 12, 0x99, 6 },
+ { 16, 0x88, 1 },
+ { 24, 0x77, 1 },
+ { 32, 0x66, 1 },
+ { 48, 0x55, 1 },
+ { 96, 0x44, 1 },
+ { 192, 0x33, 1 },
+ { 384, 0x22, 1 },
+ { 768, 0x11, 1 },
+ { 1536, 0x00, 1 },
};
- divisor = uart_get_divisor(port, baud);
+ best = table; /* Default to smallest divider */
+ target = clk_round_rate(msm_port->clk, 16 * baud);
+ divisor = DIV_ROUND_CLOSEST(target, 16 * baud);
+
+ end = table + ARRAY_SIZE(table);
+ entry = table;
+ while (entry < end) {
+ if (entry->divisor <= divisor) {
+ result = target / entry->divisor / 16;
+ diff = abs(result - baud);
+
+ /* Keep track of best entry */
+ if (diff < best_diff) {
+ best_diff = diff;
+ best = entry;
+ best_rate = target;
+ }
- for (i = 0, entry = table; i < ARRAY_SIZE(table); i++, entry++)
- if (entry->divisor <= divisor)
- break;
+ if (result == baud)
+ break;
+ } else if (entry->divisor > divisor) {
+ old = target;
+ target = clk_round_rate(msm_port->clk, old + 1);
+ /*
+ * The rate didn't get any faster so we can't do
+ * better at dividing it down
+ */
+ if (target == old)
+ break;
- return entry; /* Default to smallest divider */
+ /* Start the divisor search over at this new rate */
+ entry = table;
+ divisor = DIV_ROUND_CLOSEST(target, 16 * baud);
+ continue;
+ }
+ entry++;
+ }
+
+ *rate = best_rate;
+ return best;
}
static int msm_set_baud_rate(struct uart_port *port, unsigned int baud,
@@ -900,22 +1100,20 @@ static int msm_set_baud_rate(struct uart_port *port, unsigned int baud,
unsigned int rxstale, watermark, mask;
struct msm_port *msm_port = UART_TO_MSM(port);
const struct msm_baud_map *entry;
- unsigned long flags;
-
- entry = msm_find_best_baud(port, baud);
-
- msm_write(port, entry->code, UART_CSR);
-
- if (baud > 460800)
- port->uartclk = baud * 16;
+ unsigned long flags, rate;
flags = *saved_flags;
spin_unlock_irqrestore(&port->lock, flags);
- clk_set_rate(msm_port->clk, port->uartclk);
+ entry = msm_find_best_baud(port, baud, &rate);
+ clk_set_rate(msm_port->clk, rate);
+ baud = rate / 16 / entry->divisor;
spin_lock_irqsave(&port->lock, flags);
*saved_flags = flags;
+ port->uartclk = rate;
+
+ msm_write(port, entry->code, UART_CSR);
/* RX stale watermark */
rxstale = entry->rxstale;
@@ -1480,7 +1678,6 @@ msm_serial_early_console_setup(struct earlycon_device *device, const char *opt)
device->con->write = msm_serial_early_write;
return 0;
}
-EARLYCON_DECLARE(msm_serial, msm_serial_early_console_setup);
OF_EARLYCON_DECLARE(msm_serial, "qcom,msm-uart",
msm_serial_early_console_setup);
@@ -1502,7 +1699,6 @@ msm_serial_early_console_setup_dm(struct earlycon_device *device,
device->con->write = msm_serial_early_write_dm;
return 0;
}
-EARLYCON_DECLARE(msm_serial_dm, msm_serial_early_console_setup_dm);
OF_EARLYCON_DECLARE(msm_serial_dm, "qcom,msm-uartdm",
msm_serial_early_console_setup_dm);
@@ -1581,8 +1777,6 @@ static int msm_serial_probe(struct platform_device *pdev)
msm_port->pclk = devm_clk_get(&pdev->dev, "iface");
if (IS_ERR(msm_port->pclk))
return PTR_ERR(msm_port->pclk);
-
- clk_set_rate(msm_port->clk, 1843200);
}
port->uartclk = clk_get_rate(msm_port->clk);
diff --git a/drivers/tty/serial/msm_serial.h b/drivers/tty/serial/msm_serial.h
deleted file mode 100644
index dfdf73707e9d..000000000000
--- a/drivers/tty/serial/msm_serial.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * Copyright (C) 2007 Google, Inc.
- * Author: Robert Love <rlove@google.com>
- * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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 __DRIVERS_SERIAL_MSM_SERIAL_H
-#define __DRIVERS_SERIAL_MSM_SERIAL_H
-
-#define UART_MR1 0x0000
-
-#define UART_MR1_AUTO_RFR_LEVEL0 0x3F
-#define UART_MR1_AUTO_RFR_LEVEL1 0x3FF00
-#define UART_DM_MR1_AUTO_RFR_LEVEL1 0xFFFFFF00
-#define UART_MR1_RX_RDY_CTL BIT(7)
-#define UART_MR1_CTS_CTL BIT(6)
-
-#define UART_MR2 0x0004
-#define UART_MR2_ERROR_MODE BIT(6)
-#define UART_MR2_BITS_PER_CHAR 0x30
-#define UART_MR2_BITS_PER_CHAR_5 (0x0 << 4)
-#define UART_MR2_BITS_PER_CHAR_6 (0x1 << 4)
-#define UART_MR2_BITS_PER_CHAR_7 (0x2 << 4)
-#define UART_MR2_BITS_PER_CHAR_8 (0x3 << 4)
-#define UART_MR2_STOP_BIT_LEN_ONE (0x1 << 2)
-#define UART_MR2_STOP_BIT_LEN_TWO (0x3 << 2)
-#define UART_MR2_PARITY_MODE_NONE 0x0
-#define UART_MR2_PARITY_MODE_ODD 0x1
-#define UART_MR2_PARITY_MODE_EVEN 0x2
-#define UART_MR2_PARITY_MODE_SPACE 0x3
-#define UART_MR2_PARITY_MODE 0x3
-
-#define UART_CSR 0x0008
-
-#define UART_TF 0x000C
-#define UARTDM_TF 0x0070
-
-#define UART_CR 0x0010
-#define UART_CR_CMD_NULL (0 << 4)
-#define UART_CR_CMD_RESET_RX (1 << 4)
-#define UART_CR_CMD_RESET_TX (2 << 4)
-#define UART_CR_CMD_RESET_ERR (3 << 4)
-#define UART_CR_CMD_RESET_BREAK_INT (4 << 4)
-#define UART_CR_CMD_START_BREAK (5 << 4)
-#define UART_CR_CMD_STOP_BREAK (6 << 4)
-#define UART_CR_CMD_RESET_CTS (7 << 4)
-#define UART_CR_CMD_RESET_STALE_INT (8 << 4)
-#define UART_CR_CMD_PACKET_MODE (9 << 4)
-#define UART_CR_CMD_MODE_RESET (12 << 4)
-#define UART_CR_CMD_SET_RFR (13 << 4)
-#define UART_CR_CMD_RESET_RFR (14 << 4)
-#define UART_CR_CMD_PROTECTION_EN (16 << 4)
-#define UART_CR_CMD_STALE_EVENT_DISABLE (6 << 8)
-#define UART_CR_CMD_STALE_EVENT_ENABLE (80 << 4)
-#define UART_CR_CMD_FORCE_STALE (4 << 8)
-#define UART_CR_CMD_RESET_TX_READY (3 << 8)
-#define UART_CR_TX_DISABLE BIT(3)
-#define UART_CR_TX_ENABLE BIT(2)
-#define UART_CR_RX_DISABLE BIT(1)
-#define UART_CR_RX_ENABLE BIT(0)
-#define UART_CR_CMD_RESET_RXBREAK_START ((1 << 11) | (2 << 4))
-
-#define UART_IMR 0x0014
-#define UART_IMR_TXLEV BIT(0)
-#define UART_IMR_RXSTALE BIT(3)
-#define UART_IMR_RXLEV BIT(4)
-#define UART_IMR_DELTA_CTS BIT(5)
-#define UART_IMR_CURRENT_CTS BIT(6)
-#define UART_IMR_RXBREAK_START BIT(10)
-
-#define UART_IPR_RXSTALE_LAST 0x20
-#define UART_IPR_STALE_LSB 0x1F
-#define UART_IPR_STALE_TIMEOUT_MSB 0x3FF80
-#define UART_DM_IPR_STALE_TIMEOUT_MSB 0xFFFFFF80
-
-#define UART_IPR 0x0018
-#define UART_TFWR 0x001C
-#define UART_RFWR 0x0020
-#define UART_HCR 0x0024
-
-#define UART_MREG 0x0028
-#define UART_NREG 0x002C
-#define UART_DREG 0x0030
-#define UART_MNDREG 0x0034
-#define UART_IRDA 0x0038
-#define UART_MISR_MODE 0x0040
-#define UART_MISR_RESET 0x0044
-#define UART_MISR_EXPORT 0x0048
-#define UART_MISR_VAL 0x004C
-#define UART_TEST_CTRL 0x0050
-
-#define UART_SR 0x0008
-#define UART_SR_HUNT_CHAR BIT(7)
-#define UART_SR_RX_BREAK BIT(6)
-#define UART_SR_PAR_FRAME_ERR BIT(5)
-#define UART_SR_OVERRUN BIT(4)
-#define UART_SR_TX_EMPTY BIT(3)
-#define UART_SR_TX_READY BIT(2)
-#define UART_SR_RX_FULL BIT(1)
-#define UART_SR_RX_READY BIT(0)
-
-#define UART_RF 0x000C
-#define UARTDM_RF 0x0070
-#define UART_MISR 0x0010
-#define UART_ISR 0x0014
-#define UART_ISR_TX_READY BIT(7)
-
-#define UARTDM_RXFS 0x50
-#define UARTDM_RXFS_BUF_SHIFT 0x7
-#define UARTDM_RXFS_BUF_MASK 0x7
-
-#define UARTDM_DMEN 0x3C
-#define UARTDM_DMEN_RX_SC_ENABLE BIT(5)
-#define UARTDM_DMEN_TX_SC_ENABLE BIT(4)
-
-#define UARTDM_DMEN_TX_BAM_ENABLE BIT(2) /* UARTDM_1P4 */
-#define UARTDM_DMEN_TX_DM_ENABLE BIT(0) /* < UARTDM_1P4 */
-
-#define UARTDM_DMEN_RX_BAM_ENABLE BIT(3) /* UARTDM_1P4 */
-#define UARTDM_DMEN_RX_DM_ENABLE BIT(1) /* < UARTDM_1P4 */
-
-#define UARTDM_DMRX 0x34
-#define UARTDM_NCF_TX 0x40
-#define UARTDM_RX_TOTAL_SNAP 0x38
-
-#define UART_TO_MSM(uart_port) ((struct msm_port *) uart_port)
-
-static inline
-void msm_write(struct uart_port *port, unsigned int val, unsigned int off)
-{
- writel_relaxed_no_log(val, port->membase + off);
-}
-
-static inline
-unsigned int msm_read(struct uart_port *port, unsigned int off)
-{
- return readl_relaxed_no_log(port->membase + off);
-}
-
-/*
- * Setup the MND registers to use the TCXO clock.
- */
-static inline void msm_serial_set_mnd_regs_tcxo(struct uart_port *port)
-{
- msm_write(port, 0x06, UART_MREG);
- msm_write(port, 0xF1, UART_NREG);
- msm_write(port, 0x0F, UART_DREG);
- msm_write(port, 0x1A, UART_MNDREG);
- port->uartclk = 1843200;
-}
-
-/*
- * Setup the MND registers to use the TCXO clock divided by 4.
- */
-static inline void msm_serial_set_mnd_regs_tcxoby4(struct uart_port *port)
-{
- msm_write(port, 0x18, UART_MREG);
- msm_write(port, 0xF6, UART_NREG);
- msm_write(port, 0x0F, UART_DREG);
- msm_write(port, 0x0A, UART_MNDREG);
- port->uartclk = 1843200;
-}
-
-static inline
-void msm_serial_set_mnd_regs_from_uartclk(struct uart_port *port)
-{
- if (port->uartclk == 19200000)
- msm_serial_set_mnd_regs_tcxo(port);
- else if (port->uartclk == 4800000)
- msm_serial_set_mnd_regs_tcxoby4(port);
-}
-
-#define msm_serial_set_mnd_regs msm_serial_set_mnd_regs_from_uartclk
-
-#endif /* __DRIVERS_SERIAL_MSM_SERIAL_H */
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index d72cd736bdc6..fd9c47f2f29f 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -2451,7 +2451,6 @@ static int __init s3c2410_early_console_setup(struct earlycon_device *device,
}
OF_EARLYCON_DECLARE(s3c2410, "samsung,s3c2410-uart",
s3c2410_early_console_setup);
-EARLYCON_DECLARE(s3c2410, s3c2410_early_console_setup);
/* S3C2412, S3C2440, S3C64xx */
static struct samsung_early_console_data s3c2440_early_console_data = {
@@ -2470,9 +2469,6 @@ OF_EARLYCON_DECLARE(s3c2440, "samsung,s3c2440-uart",
s3c2440_early_console_setup);
OF_EARLYCON_DECLARE(s3c6400, "samsung,s3c6400-uart",
s3c2440_early_console_setup);
-EARLYCON_DECLARE(s3c2412, s3c2440_early_console_setup);
-EARLYCON_DECLARE(s3c2440, s3c2440_early_console_setup);
-EARLYCON_DECLARE(s3c6400, s3c2440_early_console_setup);
/* S5PV210, EXYNOS */
static struct samsung_early_console_data s5pv210_early_console_data = {
@@ -2489,8 +2485,6 @@ OF_EARLYCON_DECLARE(s5pv210, "samsung,s5pv210-uart",
s5pv210_early_console_setup);
OF_EARLYCON_DECLARE(exynos4210, "samsung,exynos4210-uart",
s5pv210_early_console_setup);
-EARLYCON_DECLARE(s5pv210, s5pv210_early_console_setup);
-EARLYCON_DECLARE(exynos4210, s5pv210_early_console_setup);
#endif
MODULE_ALIAS("platform:samsung-uart");
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index 9dbae01d41ce..9ae182a54784 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -624,8 +624,6 @@ static int __init sprd_early_console_setup(
device->con->write = sprd_early_write;
return 0;
}
-
-EARLYCON_DECLARE(sprd_serial, sprd_early_console_setup);
OF_EARLYCON_DECLARE(sprd_serial, "sprd,sc9836-uart",
sprd_early_console_setup);
diff --git a/drivers/usb/pd/policy_engine.c b/drivers/usb/pd/policy_engine.c
index 7bc6b5340dd7..42ebc60089ba 100644
--- a/drivers/usb/pd/policy_engine.c
+++ b/drivers/usb/pd/policy_engine.c
@@ -240,9 +240,6 @@ static void *usbpd_ipc_log;
static int min_sink_current = 900;
module_param(min_sink_current, int, S_IRUSR | S_IWUSR);
-static int max_sink_current = 3000;
-module_param(max_sink_current, int, S_IRUSR | S_IWUSR);
-
static const u32 default_src_caps[] = { 0x36019096 }; /* VSafe5V @ 1.5A */
static const u32 default_snk_caps[] = { 0x2601905A, /* 5V @ 900mA */
@@ -406,8 +403,8 @@ static int pd_send_msg(struct usbpd *pd, u8 hdr_type, const u32 *data,
static int pd_select_pdo(struct usbpd *pd, int pdo_pos)
{
- int curr = min_sink_current;
- int max_current = max_sink_current;
+ int curr;
+ int max_current;
bool mismatch = false;
u32 pdo = pd->received_pdos[pdo_pos - 1];
@@ -417,18 +414,19 @@ static int pd_select_pdo(struct usbpd *pd, int pdo_pos)
return -ENOTSUPP;
}
+ curr = max_current = PD_SRC_PDO_FIXED_MAX_CURR(pdo) * 10;
+
/*
* Check if the PDO has enough current, otherwise set the
* Capability Mismatch flag
*/
- if ((PD_SRC_PDO_FIXED_MAX_CURR(pdo) * 10) < curr) {
+ if (curr < min_sink_current) {
mismatch = true;
- max_current = curr;
- curr = PD_SRC_PDO_FIXED_MAX_CURR(pdo) * 10;
+ max_current = min_sink_current;
}
pd->requested_voltage = PD_SRC_PDO_FIXED_VOLTAGE(pdo) * 50 * 1000;
- pd->requested_current = max_current;
+ pd->requested_current = curr;
pd->requested_pdo = pdo_pos;
pd->rdo = PD_RDO_FIXED(pdo_pos, 0, mismatch, 1, 1, curr / 10,
max_current / 10);
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 61e99f47f02f..4724f4378e23 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -277,6 +277,8 @@ struct mdss_data_type {
struct regulator *fs;
struct regulator *venus;
struct regulator *vdd_cx;
+ u32 vdd_cx_min_uv;
+ u32 vdd_cx_max_uv;
bool batfet_required;
struct regulator *batfet;
bool en_svs_high;
diff --git a/drivers/video/fbdev/msm/mdss_dp.c b/drivers/video/fbdev/msm/mdss_dp.c
index 0ac5ef4f750c..e0dd3f5d5635 100644
--- a/drivers/video/fbdev/msm/mdss_dp.c
+++ b/drivers/video/fbdev/msm/mdss_dp.c
@@ -42,43 +42,6 @@
#define VDDA_UA_ON_LOAD 100000 /* uA units */
#define VDDA_UA_OFF_LOAD 100 /* uA units */
-static char edid_buf1[] = {
- 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
- 0x22, 0xf0, 0x52, 0x29, 0x01, 0x01, 0x01, 0x01,
- 0x16, 0x16, 0x01, 0x03, 0x80, 0x30, 0x1b, 0x78,
- 0x2e, 0xee, 0x95, 0xa3, 0x54, 0x4c, 0x99, 0x26,
- 0x0f, 0x50, 0x54, 0xa1, 0x08, 0x00, 0xd1, 0xc0,
- 0x81, 0xc0, 0xa9, 0xc0, 0xb3, 0x00, 0x95, 0x00,
- 0x81, 0x40, 0x81, 0x80, 0x01, 0x01, 0x02, 0x3a,
- 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
- 0x45, 0x00, 0xdb, 0x0b, 0x11, 0x00, 0x00, 0x1e,
- 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32, 0x4c, 0x18,
- 0x5e, 0x11, 0x00, 0x0a, 0x20, 0x20, 0x20, 0x20,
- 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x48,
- 0x50, 0x20, 0x5a, 0x52, 0x32, 0x32, 0x34, 0x30,
- 0x77, 0x0a, 0x20, 0x20, 0x00, 0x00, 0x00, 0xff,
- 0x00, 0x43, 0x4e, 0x34, 0x32, 0x32, 0x32, 0x30,
- 0x30, 0x33, 0x46, 0x0a, 0x20, 0x20, 0x01, 0xb1,
-
- 0x02, 0x03, 0x17, 0xb1, 0x4c, 0x90, 0x1f, 0x05,
- 0x14, 0x04, 0x13, 0x03, 0x02, 0x07, 0x06, 0x12,
- 0x01, 0x65, 0x03, 0x0c, 0x00, 0x10, 0x00, 0x02,
- 0x3a, 0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58,
- 0x2c, 0x45, 0x00, 0xdb, 0x0b, 0x11, 0x00, 0x00,
- 0x1e, 0x02, 0x3a, 0x80, 0xd0, 0x72, 0x38, 0x2d,
- 0x40, 0x10, 0x2c, 0x45, 0x80, 0xdb, 0x0b, 0x11,
- 0x00, 0x00, 0x1e, 0x01, 0x1d, 0x00, 0x72, 0x51,
- 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00, 0xdb,
- 0x0b, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d, 0x00,
- 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28, 0x55,
- 0x40, 0xdb, 0x0b, 0x11, 0x00, 0x00, 0x1e, 0x8c,
- 0x0a, 0xd0, 0x8a, 0x20, 0xe0, 0x2d, 0x10, 0x10,
- 0x3e, 0x96, 0x00, 0xdb, 0x0b, 0x11, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b
-};
-
-
static void mdss_dp_put_dt_clk_data(struct device *dev,
struct dss_module_power *module_power)
{
@@ -945,9 +908,6 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
pr_err("Unabled to start core clocks\n");
return ret;
}
- mdss_dp_phy_reset(&dp_drv->ctrl_io);
- mdss_dp_aux_reset(&dp_drv->ctrl_io);
- mdss_dp_aux_ctrl(&dp_drv->ctrl_io, true);
mdss_dp_hpd_configure(&dp_drv->ctrl_io, true);
orientation = usbpd_get_plug_orientation(dp_drv->pd);
@@ -971,11 +931,6 @@ int mdss_dp_on(struct mdss_panel_data *pdata)
if (dp_drv->new_vic && (dp_drv->new_vic != dp_drv->vic))
dp_init_panel_info(dp_drv, dp_drv->new_vic);
- mdss_dp_phy_aux_setup(&dp_drv->phy_io);
-
- mdss_dp_irq_enable(dp_drv);
- pr_debug("irq enabled\n");
- mdss_dp_dpcd_cap_read(dp_drv);
dp_drv->link_rate =
mdss_dp_gen_link_clk(&dp_drv->panel_data.panel_info,
dp_drv->dpcd.max_lane_count);
@@ -1143,9 +1098,10 @@ static int mdss_dp_edid_init(struct mdss_panel_data *pdata)
return -ENODEV;
}
- /* Use the existing EDID buffer for 1080p */
- memcpy(edid_init_data.buf, edid_buf1, sizeof(edid_buf1));
dp_drv->panel_data.panel_info.edid_data = edid_data;
+ /* initialize EDID buffer pointers */
+ dp_drv->edid_buf = edid_init_data.buf;
+ dp_drv->edid_buf_size = edid_init_data.buf_size;
return 0;
}
@@ -1189,17 +1145,30 @@ static int mdss_dp_host_init(struct mdss_panel_data *pdata)
mdss_dp_get_ctrl_hw_version(&dp_drv->ctrl_io),
mdss_dp_get_phy_hw_version(&dp_drv->phy_io));
+ mdss_dp_phy_aux_setup(&dp_drv->phy_io);
+
+ mdss_dp_irq_enable(dp_drv);
+ pr_debug("irq enabled\n");
+ mdss_dp_dpcd_cap_read(dp_drv);
+
+ ret = mdss_dp_edid_read(dp_drv);
+ if (ret)
+ goto edid_error;
+
+ pr_debug("edid_read success. buf_size=%d\n",
+ dp_drv->edid_buf_size);
+
ret = hdmi_edid_parser(dp_drv->panel_data.panel_info.edid_data);
if (ret) {
DEV_ERR("%s: edid parse failed\n", __func__);
- goto edid_parser_error;
+ goto edid_error;
}
mdss_dp_send_cable_notification(dp_drv, true);
return ret;
-edid_parser_error:
+edid_error:
mdss_dp_clk_ctrl(dp_drv, DP_CORE_PM, false);
clk_error:
mdss_dp_regulator_ctrl(dp_drv, false);
@@ -1422,7 +1391,7 @@ static void mdss_dp_event_work(struct work_struct *work)
switch (todo) {
case EV_EDID_READ:
- mdss_dp_edid_read(dp, 0);
+ mdss_dp_edid_read(dp);
break;
case EV_DPCD_CAP_READ:
mdss_dp_dpcd_cap_read(dp);
diff --git a/drivers/video/fbdev/msm/mdss_dp.h b/drivers/video/fbdev/msm/mdss_dp.h
index 03646cd7cc65..4a80c25dd157 100644
--- a/drivers/video/fbdev/msm/mdss_dp.h
+++ b/drivers/video/fbdev/msm/mdss_dp.h
@@ -106,15 +106,6 @@
#define EDP_INTR_MASK2 (EDP_INTR_STATUS2 << 2)
-struct edp_cmd {
- char read; /* 1 == read, 0 == write */
- char i2c; /* 1 == i2c cmd, 0 == native cmd */
- u32 addr; /* 20 bits */
- char *datap;
- int len; /* len to be tx OR len to be rx for read */
- char next; /* next command */
-};
-
struct edp_buf {
char *start; /* buffer start addr */
char *end; /* buffer end addr */
@@ -378,6 +369,8 @@ struct mdss_dp_drv_pdata {
char train_link_rate; /* X 27000000 for real rate */
char train_lane_cnt;
+ u8 *edid_buf;
+ u32 edid_buf_size;
struct edp_edid edid;
struct dpcd_cap dpcd;
@@ -464,7 +457,7 @@ void mdss_dp_phy_initialize(struct mdss_dp_drv_pdata *dp);
void mdss_dp_dpcd_cap_read(struct mdss_dp_drv_pdata *dp);
int mdss_dp_dpcd_status_read(struct mdss_dp_drv_pdata *dp);
-void mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp, int block);
+int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp);
int mdss_dp_link_train(struct mdss_dp_drv_pdata *dp);
void dp_aux_i2c_handler(struct mdss_dp_drv_pdata *dp, u32 isr);
void dp_aux_native_handler(struct mdss_dp_drv_pdata *dp, u32 isr);
diff --git a/drivers/video/fbdev/msm/mdss_dp_aux.c b/drivers/video/fbdev/msm/mdss_dp_aux.c
index 7b14a7efb9dc..7e9510cf08c7 100644
--- a/drivers/video/fbdev/msm/mdss_dp_aux.c
+++ b/drivers/video/fbdev/msm/mdss_dp_aux.c
@@ -228,6 +228,11 @@ static int dp_aux_write_cmds(struct mdss_dp_drv_pdata *ep,
return ret;
}
+int dp_aux_write(void *ep, struct edp_cmd *cmd)
+{
+ return dp_aux_write_cmds(ep, cmd);
+}
+
static int dp_aux_read_cmds(struct mdss_dp_drv_pdata *ep,
struct edp_cmd *cmds)
{
@@ -275,12 +280,20 @@ static int dp_aux_read_cmds(struct mdss_dp_drv_pdata *ep,
else
ret = ep->aux_error_num;
+ if (cmds->out_buf)
+ memcpy(cmds->out_buf, rp->data, cmds->len);
+
ep->aux_cmd_busy = 0;
mutex_unlock(&ep->aux_mutex);
return ret;
}
+int dp_aux_read(void *ep, struct edp_cmd *cmds)
+{
+ return dp_aux_read_cmds(ep, cmds);
+}
+
void dp_aux_native_handler(struct mdss_dp_drv_pdata *ep, u32 isr)
{
@@ -665,7 +678,7 @@ static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep)
char data = 0;
for (cnt = 5; cnt; cnt--) {
- ret = dp_aux_write_buf(ep, 0x50, &data, 1, 1);
+ ret = dp_aux_write_buf(ep, EDID_START_ADDRESS, &data, 1, 1);
pr_debug("ret=%d\n", ret);
if (ret >= 0)
break;
@@ -680,43 +693,85 @@ static int dp_aux_chan_ready(struct mdss_dp_drv_pdata *ep)
return 0;
}
-static int dp_sink_edid_read(struct mdss_dp_drv_pdata *ep, int block)
+int mdss_dp_edid_read(struct mdss_dp_drv_pdata *dp)
{
struct edp_buf *rp;
int cnt, rlen;
int ret = 0;
+ int blk_num = 0;
- ret = dp_aux_chan_ready(ep);
+ ret = dp_aux_chan_ready(dp);
if (ret) {
pr_err("aux chan NOT ready\n");
return ret;
}
for (cnt = 5; cnt; cnt--) {
- rlen = dp_aux_read_buf(ep, 0x50, 128, 1);
+ rlen = dp_aux_read_buf
+ (dp, EDID_START_ADDRESS, EDID_BLOCK_SIZE, 1);
if (rlen > 0) {
- pr_debug("rlen=%d\n", rlen);
+ pr_debug("cnt=%d, block=%d, rlen=%d\n",
+ cnt, blk_num, rlen);
- rp = &ep->rxp;
+ rp = &dp->rxp;
if (!dp_edid_buf_error(rp->data, rp->len))
break;
}
}
- if (cnt <= 0) {
- pr_err("Failed\n");
+ if ((cnt <= 0) && (rlen != EDID_BLOCK_SIZE)) {
+ pr_err("Read failed. rlen=%d\n", rlen);
return -EINVAL;
}
- dp_extract_edid_manufacturer(&ep->edid, rp->data);
- dp_extract_edid_product(&ep->edid, rp->data);
- dp_extract_edid_version(&ep->edid, rp->data);
- dp_extract_edid_ext_block_cnt(&ep->edid, rp->data);
- dp_extract_edid_video_support(&ep->edid, rp->data);
- dp_extract_edid_feature(&ep->edid, rp->data);
- dp_extract_edid_detailed_timing_description(&ep->edid, rp->data);
+ rp = &dp->rxp;
+
+ dp_extract_edid_manufacturer(&dp->edid, rp->data);
+ dp_extract_edid_product(&dp->edid, rp->data);
+ dp_extract_edid_version(&dp->edid, rp->data);
+ dp_extract_edid_ext_block_cnt(&dp->edid, rp->data);
+ dp_extract_edid_video_support(&dp->edid, rp->data);
+ dp_extract_edid_feature(&dp->edid, rp->data);
+ dp_extract_edid_detailed_timing_description(&dp->edid, rp->data);
+ /* for the first block initialize the edid buffer size */
+ dp->edid_buf_size = 0;
+
+ pr_debug("edid extension = %d\n",
+ dp->edid.ext_block_cnt);
+
+ memcpy(dp->edid_buf, rp->data, EDID_BLOCK_SIZE);
+ dp->edid_buf_size += EDID_BLOCK_SIZE;
- return 128;
+ if (!dp->edid.ext_block_cnt)
+ return 0;
+
+ for (blk_num = 1; blk_num <= dp->edid.ext_block_cnt;
+ blk_num++) {
+ for (cnt = 5; cnt; cnt--) {
+ rlen = dp_aux_read_buf
+ (dp, EDID_START_ADDRESS +
+ (blk_num * EDID_BLOCK_SIZE),
+ EDID_BLOCK_SIZE, 1);
+ if (rlen > 0) {
+ pr_debug("cnt=%d, blk_num=%d, rlen=%d\n",
+ cnt, blk_num, rlen);
+ rp = &dp->rxp;
+ if (!dp_edid_buf_error(rp->data, rp->len))
+ break;
+ }
+ }
+
+ if ((cnt <= 0) && (rlen != EDID_BLOCK_SIZE)) {
+ pr_err("Read failed. rlen=%d\n", rlen);
+ return -EINVAL;
+ }
+
+ memcpy(dp->edid_buf + (blk_num * EDID_BLOCK_SIZE),
+ rp->data, EDID_BLOCK_SIZE);
+ dp->edid_buf_size += EDID_BLOCK_SIZE;
+ }
+
+ return 0;
}
static void dp_sink_capability_read(struct mdss_dp_drv_pdata *ep,
@@ -1357,11 +1412,6 @@ void mdss_dp_fill_link_cfg(struct mdss_dp_drv_pdata *ep)
}
-void mdss_dp_edid_read(struct mdss_dp_drv_pdata *ep, int block)
-{
- dp_sink_edid_read(ep, block);
-}
-
int mdss_dp_link_train(struct mdss_dp_drv_pdata *ep)
{
int ret;
diff --git a/drivers/video/fbdev/msm/mdss_dp_util.h b/drivers/video/fbdev/msm/mdss_dp_util.h
index 8ef00dd7248e..a2649b8c1611 100644
--- a/drivers/video/fbdev/msm/mdss_dp_util.h
+++ b/drivers/video/fbdev/msm/mdss_dp_util.h
@@ -86,6 +86,33 @@
#define TXn_TX_DRV_LVL 0x001C
#define TCSR_USB3_DP_PHYMODE 0x48
+#define EDID_START_ADDRESS 0x50
+
+/* DP HDCP 1.3 registers */
+#define DP_HDCP_CTRL (0x0A0)
+#define DP_HDCP_STATUS (0x0A4)
+#define DP_HDCP_SW_UPPER_AKSV (0x298)
+#define DP_HDCP_SW_LOWER_AKSV (0x29C)
+#define DP_HDCP_ENTROPY_CTRL0 (0x750)
+#define DP_HDCP_ENTROPY_CTRL1 (0x75C)
+#define DP_HDCP_SHA_STATUS (0x0C8)
+#define DP_HDCP_RCVPORT_DATA2_0 (0x0B0)
+#define DP_HDCP_RCVPORT_DATA3 (0x2A4)
+#define DP_HDCP_RCVPORT_DATA4 (0x2A8)
+#define DP_HDCP_RCVPORT_DATA5 (0x0C0)
+#define DP_HDCP_RCVPORT_DATA6 (0x0C4)
+
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_CTRL (0x024)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA0 (0x004)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA1 (0x008)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA7 (0x00C)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA8 (0x010)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA9 (0x014)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA10 (0x018)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11 (0x01C)
+#define HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12 (0x020)
+
+#define DP_INTERRUPT_STATUS_2 (0x024)
struct lane_mapping {
char lane0;
@@ -94,6 +121,18 @@ struct lane_mapping {
char lane3;
};
+struct edp_cmd {
+ char read; /* 1 == read, 0 == write */
+ char i2c; /* 1 == i2c cmd, 0 == native cmd */
+ u32 addr; /* 20 bits */
+ char *datap;
+ char *out_buf;
+ int len; /* len to be tx OR len to be rx for read */
+ char next; /* next command */
+};
+
+int dp_aux_read(void *ep, struct edp_cmd *cmds);
+int dp_aux_write(void *ep, struct edp_cmd *cmd);
void mdss_dp_state_ctrl(struct dss_io_data *ctrl_io, u32 data);
u32 mdss_dp_get_ctrl_hw_version(struct dss_io_data *ctrl_io);
u32 mdss_dp_get_phy_hw_version(struct dss_io_data *phy_io);
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c
index 6256c9a99877..dad089e74934 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.c
@@ -15,9 +15,11 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/stat.h>
+#include <linux/iopoll.h>
#include <soc/qcom/scm.h>
#include <linux/hdcp_qseecom.h>
#include "mdss_hdmi_hdcp.h"
+#include "mdss_dp_util.h"
#include "video/msm_hdmi_hdcp_mgr.h"
#define HDCP_STATE_NAME (hdcp_state_name(hdcp_ctrl->hdcp_state))
@@ -36,15 +38,188 @@
#define HDCP_REG_ENABLE 0x01
#define HDCP_REG_DISABLE 0x00
-#define HDCP_INT_CLR (BIT(1) | BIT(5) | BIT(7) | BIT(9) | BIT(13))
+#define HDCP_INT_CLR (isr->auth_success_ack | isr->auth_fail_ack | \
+ isr->auth_fail_info_ack | isr->tx_req_ack | \
+ isr->encryption_ready_ack | \
+ isr->encryption_not_ready | isr->tx_req_done_ack)
+
+#define HDCP_INT_EN (isr->auth_success_mask | isr->auth_fail_mask | \
+ isr->encryption_ready_mask | \
+ isr->encryption_not_ready_mask)
+
+#define HDCP_POLL_SLEEP_US (20 * 1000)
+#define HDCP_POLL_TIMEOUT_US (HDCP_POLL_SLEEP_US * 1000)
+
+#define reg_set_data(x) \
+ (hdcp_ctrl->init_data.sec_access ? reg_set->sec_data##x : \
+ reg_set->data##x)
+
+struct hdcp_sink_addr {
+ char *name;
+ u32 addr;
+ u32 len;
+};
struct hdmi_hdcp_reg_data {
u32 reg_id;
- u32 off;
- char *name;
- u32 reg_val;
+ struct hdcp_sink_addr *sink;
+};
+
+struct hdcp_sink_addr_map {
+ /* addresses to read from sink */
+ struct hdcp_sink_addr bcaps;
+ struct hdcp_sink_addr bksv;
+ struct hdcp_sink_addr r0;
+ struct hdcp_sink_addr bstatus;
+ struct hdcp_sink_addr ksv_fifo;
+ struct hdcp_sink_addr v_h0;
+ struct hdcp_sink_addr v_h1;
+ struct hdcp_sink_addr v_h2;
+ struct hdcp_sink_addr v_h3;
+ struct hdcp_sink_addr v_h4;
+
+ /* addresses to write to sink */
+ struct hdcp_sink_addr an;
+ struct hdcp_sink_addr aksv;
+ struct hdcp_sink_addr rep;
+};
+
+struct hdcp_int_set {
+ /* interrupt register */
+ u32 int_reg;
+
+ /* interrupt enable/disable masks */
+ u32 auth_success_mask;
+ u32 auth_fail_mask;
+ u32 encryption_ready_mask;
+ u32 encryption_not_ready_mask;
+ u32 tx_req_mask;
+ u32 tx_req_done_mask;
+
+ /* interrupt acknowledgment */
+ u32 auth_success_ack;
+ u32 auth_fail_ack;
+ u32 auth_fail_info_ack;
+ u32 encryption_ready_ack;
+ u32 encryption_not_ready_ack;
+ u32 tx_req_ack;
+ u32 tx_req_done_ack;
+
+ /* interrupt status */
+ u32 auth_success_int;
+ u32 auth_fail_int;
+ u32 encryption_ready;
+ u32 encryption_not_ready;
+ u32 tx_req_int;
+ u32 tx_req_done_int;
+};
+
+struct hdcp_reg_set {
+ u32 status;
+ u32 keys_offset;
+ u32 r0_offset;
+ u32 v_offset;
+ u32 ctrl;
+ u32 aksv_lsb;
+ u32 aksv_msb;
+ u32 entropy_ctrl0;
+ u32 entropy_ctrl1;
+ u32 sha_ctrl;
+ u32 sec_sha_ctrl;
+ u32 sha_status;
+
+ u32 data0;
+ u32 data1;
+ u32 data2_0;
+ u32 data3;
+ u32 data4;
+ u32 data5;
+ u32 data6;
+ u32 data7;
+ u32 data8;
+ u32 data9;
+ u32 data10;
+ u32 data11;
+ u32 data12;
+
+ u32 sec_data0;
+ u32 sec_data1;
+ u32 sec_data7;
+ u32 sec_data8;
+ u32 sec_data9;
+ u32 sec_data10;
+ u32 sec_data11;
+ u32 sec_data12;
+
+ u32 reset;
};
+#define HDCP_REG_SET_CLIENT_HDMI \
+ {HDMI_HDCP_LINK0_STATUS, 28, 24, 20, HDMI_HDCP_CTRL, \
+ HDMI_HDCP_SW_LOWER_AKSV, HDMI_HDCP_SW_UPPER_AKSV, \
+ HDMI_HDCP_ENTROPY_CTRL0, HDMI_HDCP_ENTROPY_CTRL1, \
+ HDMI_HDCP_SHA_CTRL, HDCP_SEC_TZ_HV_HLOS_HDCP_SHA_CTRL, \
+ HDMI_HDCP_SHA_STATUS, HDMI_HDCP_RCVPORT_DATA0, \
+ HDMI_HDCP_RCVPORT_DATA1, HDMI_HDCP_RCVPORT_DATA2_0, \
+ HDMI_HDCP_RCVPORT_DATA3, HDMI_HDCP_RCVPORT_DATA4, \
+ HDMI_HDCP_RCVPORT_DATA5, HDMI_HDCP_RCVPORT_DATA6, \
+ HDMI_HDCP_RCVPORT_DATA7, HDMI_HDCP_RCVPORT_DATA8, \
+ HDMI_HDCP_RCVPORT_DATA9, HDMI_HDCP_RCVPORT_DATA10, \
+ HDMI_HDCP_RCVPORT_DATA11, HDMI_HDCP_RCVPORT_DATA12, \
+ HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA0, \
+ HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA1, \
+ HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA7, \
+ HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA8, \
+ HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA9, \
+ HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA10, \
+ HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA11, \
+ HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA12, \
+ HDMI_HDCP_RESET}
+
+#define HDCP_REG_SET_CLIENT_DP \
+ {DP_HDCP_STATUS, 16, 14, 13, DP_HDCP_CTRL, \
+ DP_HDCP_SW_LOWER_AKSV, DP_HDCP_SW_UPPER_AKSV, \
+ DP_HDCP_ENTROPY_CTRL0, DP_HDCP_ENTROPY_CTRL1, \
+ 0, HDCP_SEC_DP_TZ_HV_HLOS_HDCP_SHA_CTRL, \
+ DP_HDCP_SHA_STATUS, 0, 0, DP_HDCP_RCVPORT_DATA2_0, \
+ DP_HDCP_RCVPORT_DATA3, DP_HDCP_RCVPORT_DATA4, \
+ DP_HDCP_RCVPORT_DATA5, DP_HDCP_RCVPORT_DATA6, \
+ 0, 0, 0, 0, 0, 0, \
+ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA0, \
+ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA1, \
+ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA7, \
+ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA8, \
+ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA9, \
+ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA10, \
+ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA11, \
+ HDCP_SEC_DP_TZ_HV_HLOS_HDCP_RCVPORT_DATA12, 0}
+
+#define HDCP_HDMI_SINK_ADDR_MAP \
+ {{"bcaps", 0x40, 1}, {"bksv", 0x00, 5}, {"r0'", 0x08, 2}, \
+ {"bstatus", 0x41, 2}, {"ksv-fifo", 0x43, 0}, {"v_h0", 0x20, 4}, \
+ {"v_h1", 0x24, 4}, {"v_h2", 0x28, 4}, {"v_h3", 0x2c, 4}, \
+ {"v_h4", 0x30, 4}, {"an", 0x16, 8}, {"aksv", 0x10, 5}, \
+ {"repater", 0x00, 0} }
+
+#define HDCP_DP_SINK_ADDR_MAP \
+ {{"bcaps", 0x68028, 1}, {"bksv", 0x68000, 5}, {"r0'", 0x68005, 2}, \
+ {"bstatus", 0x6802A, 2}, {"ksv-fifo", 0x6802A, 0}, \
+ {"v_h0", 0x68014, 4}, {"v_h1", 0x68018, 4}, {"v_h2", 0x6801C, 4}, \
+ {"v_h3", 0x68020, 4}, {"v_h4", 0x68024, 4}, {"an", 0x6800C, 8}, \
+ {"aksv", 0x68007, 5}, {"repater", 0x68028, 1} }
+
+#define HDCP_HDMI_INT_SET \
+ {HDMI_HDCP_INT_CTRL, \
+ BIT(2), BIT(6), 0, 0, 0, 0, \
+ BIT(1), BIT(5), BIT(7), 0, 0, 0, 0, \
+ BIT(0), BIT(4), 0, 0, 0, 0}
+
+#define HDCP_DP_INT_SET \
+ {DP_INTERRUPT_STATUS_2, \
+ BIT(17), BIT(20), BIT(24), BIT(27), 0, 0, \
+ BIT(16), BIT(19), BIT(21), BIT(23), BIT(26), 0, 0, \
+ BIT(15), BIT(18), BIT(22), BIT(25), 0, 0}
+
struct hdmi_hdcp_ctrl {
u32 auth_retries;
u32 tp_msgid;
@@ -57,7 +232,9 @@ struct hdmi_hdcp_ctrl {
struct completion r0_checked;
struct hdmi_hdcp_init_data init_data;
struct hdmi_hdcp_ops *ops;
- bool hdmi_tx_ver_4;
+ struct hdcp_reg_set reg_set;
+ struct hdcp_int_set int_set;
+ struct hdcp_sink_addr_map sink_addr;
};
const char *hdcp_state_name(enum hdmi_hdcp_state hdcp_state)
@@ -256,6 +433,7 @@ static int hdmi_hdcp_load_keys(void *input)
struct dss_io_data *io;
struct dss_io_data *qfprom_io;
struct hdmi_hdcp_ctrl *hdcp_ctrl = input;
+ struct hdcp_reg_set *reg_set;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io ||
!hdcp_ctrl->init_data.qfprom_io) {
@@ -274,6 +452,7 @@ static int hdmi_hdcp_load_keys(void *input)
io = hdcp_ctrl->init_data.core_io;
qfprom_io = hdcp_ctrl->init_data.qfprom_io;
+ reg_set = &hdcp_ctrl->reg_set;
/* On compatible hardware, use SW keys */
reg_val = DSS_REG_R(qfprom_io, SEC_CTRL_HW_VERSION);
@@ -297,7 +476,7 @@ static int hdmi_hdcp_load_keys(void *input)
ksv_lsb_addr = HDCP_KSV_LSB;
ksv_msb_addr = HDCP_KSV_MSB;
- if (hdcp_ctrl->hdmi_tx_ver_4) {
+ if (hdcp_ctrl->init_data.sec_access) {
ksv_lsb_addr += HDCP_KSV_VERSION_4_OFFSET;
ksv_msb_addr += HDCP_KSV_VERSION_4_OFFSET;
}
@@ -322,27 +501,121 @@ static int hdmi_hdcp_load_keys(void *input)
goto end;
}
- DSS_REG_W(io, HDMI_HDCP_SW_LOWER_AKSV, aksv_lsb);
- DSS_REG_W(io, HDMI_HDCP_SW_UPPER_AKSV, aksv_msb);
+ DSS_REG_W(io, reg_set->aksv_lsb, aksv_lsb);
+ DSS_REG_W(io, reg_set->aksv_msb, aksv_msb);
/* Setup seed values for random number An */
- DSS_REG_W(io, HDMI_HDCP_ENTROPY_CTRL0, 0xB1FFB0FF);
- DSS_REG_W(io, HDMI_HDCP_ENTROPY_CTRL1, 0xF00DFACE);
-
- /* Disable the RngCipher state */
- DSS_REG_W(io, HDMI_HDCP_DEBUG_CTRL,
- DSS_REG_R(io, HDMI_HDCP_DEBUG_CTRL) & ~(BIT(2)));
+ DSS_REG_W(io, reg_set->entropy_ctrl0, 0xB1FFB0FF);
+ DSS_REG_W(io, reg_set->entropy_ctrl1, 0xF00DFACE);
/* make sure hw is programmed */
wmb();
- DSS_REG_W(io, HDMI_HDCP_CTRL, BIT(0));
+ /* enable hdcp engine */
+ DSS_REG_W(io, reg_set->ctrl, 0x1);
hdcp_ctrl->hdcp_state = HDCP_STATE_AUTHENTICATING;
end:
return rc;
}
+static int hdmi_hdcp_read(struct hdmi_hdcp_ctrl *hdcp_ctrl,
+ struct hdcp_sink_addr *sink,
+ u8 *buf, bool realign)
+{
+ u32 rc = 0;
+ struct hdmi_tx_ddc_data ddc_data;
+
+ if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_HDMI) {
+ reset_hdcp_ddc_failures(hdcp_ctrl);
+
+ memset(&ddc_data, 0, sizeof(ddc_data));
+ ddc_data.dev_addr = 0x74;
+ ddc_data.offset = sink->addr;
+ ddc_data.data_buf = buf;
+ ddc_data.data_len = sink->len;
+ ddc_data.request_len = sink->len;
+ ddc_data.retry = 5;
+ ddc_data.what = sink->name;
+ ddc_data.retry_align = realign;
+
+ hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
+
+ rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
+ if (rc)
+ DEV_ERR("%s: %s: %s read failed\n", __func__,
+ HDCP_STATE_NAME, sink->name);
+ } else if (IS_ENABLED(CONFIG_FB_MSM_MDSS_DP_PANEL) &&
+ hdcp_ctrl->init_data.client_id == HDCP_CLIENT_DP) {
+ struct edp_cmd cmd = {0};
+
+ cmd.read = 1;
+ cmd.addr = sink->addr;
+ cmd.out_buf = buf;
+ cmd.len = sink->len;
+
+ rc = dp_aux_read(hdcp_ctrl->init_data.dp_data, &cmd);
+ if (rc)
+ DEV_ERR("%s: %s: %s read failed\n", __func__,
+ HDCP_STATE_NAME, sink->name);
+ }
+
+ return rc;
+}
+
+static int hdmi_hdcp_write(struct hdmi_hdcp_ctrl *hdcp_ctrl,
+ u32 offset, u32 len, u8 *buf, char *name)
+{
+ int rc = 0;
+ struct hdmi_tx_ddc_data ddc_data;
+
+ if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_HDMI) {
+ memset(&ddc_data, 0, sizeof(ddc_data));
+
+ ddc_data.dev_addr = 0x74;
+ ddc_data.offset = offset;
+ ddc_data.data_buf = buf;
+ ddc_data.data_len = len;
+ ddc_data.what = name;
+ hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
+
+ rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl);
+ if (rc)
+ DEV_ERR("%s: %s: %s write failed\n", __func__,
+ HDCP_STATE_NAME, name);
+ } else if (IS_ENABLED(CONFIG_FB_MSM_MDSS_DP_PANEL) &&
+ hdcp_ctrl->init_data.client_id == HDCP_CLIENT_DP) {
+ struct edp_cmd cmd = {0};
+
+ cmd.addr = offset;
+ cmd.len = len;
+ cmd.datap = buf;
+
+ rc = dp_aux_write(hdcp_ctrl->init_data.dp_data, &cmd);
+ if (rc)
+ DEV_ERR("%s: %s: %s read failed\n", __func__,
+ HDCP_STATE_NAME, name);
+ }
+
+ return rc;
+}
+
+static void hdmi_hdcp_enable_interrupts(struct hdmi_hdcp_ctrl *hdcp_ctrl)
+{
+ u32 intr_reg;
+ struct dss_io_data *io;
+ struct hdcp_int_set *isr;
+
+ io = hdcp_ctrl->init_data.core_io;
+ isr = &hdcp_ctrl->int_set;
+
+ intr_reg = DSS_REG_R(io, isr->int_reg);
+
+ intr_reg |= HDCP_INT_CLR | HDCP_INT_EN;
+
+ DSS_REG_W(io, isr->int_reg, intr_reg);
+}
+
static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
{
int rc;
@@ -353,13 +626,12 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
bool is_match;
struct dss_io_data *io;
struct dss_io_data *hdcp_io;
+ struct hdcp_reg_set *reg_set;
u8 aksv[5], *bksv = NULL;
u8 an[8];
u8 bcaps;
- struct hdmi_tx_ddc_data ddc_data;
- u32 link0_status, an_ready, keys_state;
+ u32 link0_status;
u8 buf[0xFF];
-
struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG];
u32 phy_addr;
u32 ret = 0;
@@ -376,6 +648,7 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
bksv = hdcp_ctrl->current_tp.bksv;
io = hdcp_ctrl->init_data.core_io;
hdcp_io = hdcp_ctrl->init_data.hdcp_io;
+ reg_set = &hdcp_ctrl->reg_set;
if (HDCP_STATE_AUTHENTICATING != hdcp_ctrl->hdcp_state) {
DEV_ERR("%s: %s: invalid state. returning\n", __func__,
@@ -384,32 +657,14 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
goto error;
}
- /* Clear any DDC failures from previous tries */
- reset_hdcp_ddc_failures(hdcp_ctrl);
-
- /*
- * Read BCAPS
- * We need to first try to read an HDCP register on the sink to see if
- * the sink is ready for HDCP authentication
- */
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0x74;
- ddc_data.offset = 0x40;
- ddc_data.data_buf = &bcaps;
- ddc_data.data_len = 1;
- ddc_data.request_len = 1;
- ddc_data.retry = 5;
- ddc_data.what = "Bcaps";
-
- hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
-
- rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
- if (rc) {
- DEV_ERR("%s: %s: BCAPS read failed\n", __func__,
- HDCP_STATE_NAME);
+ rc = hdmi_hdcp_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.bcaps,
+ &bcaps, false);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: error reading bcaps\n", __func__);
goto error;
}
- DEV_DBG("%s: %s: BCAPS=%02x\n", __func__, HDCP_STATE_NAME, bcaps);
+
+ hdmi_hdcp_enable_interrupts(hdcp_ctrl);
/* receiver (0), repeater (1) */
hdcp_ctrl->current_tp.ds_type =
@@ -419,7 +674,7 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
if (hdcp_ctrl->tz_hdcp) {
memset(scm_buf, 0x00, sizeof(scm_buf));
- scm_buf[0].addr = phy_addr + HDMI_HDCP_RCVPORT_DATA12;
+ scm_buf[0].addr = phy_addr + reg_set->data12;
scm_buf[0].val = bcaps;
ret = hdcp_scm_call(scm_buf, &resp);
@@ -429,30 +684,19 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
rc = -EINVAL;
goto error;
}
- } else if (hdcp_ctrl->hdmi_tx_ver_4) {
- DSS_REG_W(hdcp_io, HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA12,
- bcaps);
+ } else if (hdcp_ctrl->init_data.sec_access) {
+ DSS_REG_W(hdcp_io, reg_set->sec_data12, bcaps);
} else {
- DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA12, bcaps);
+ DSS_REG_W(io, reg_set->data12, bcaps);
}
/* Wait for HDCP keys to be checked and validated */
- timeout_count = 100;
- keys_state = (link0_status >> 28) & 0x7;
- while ((keys_state != HDCP_KEYS_STATE_VALID) &&
- --timeout_count) {
- link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
- keys_state = (link0_status >> 28) & 0x7;
- DEV_DBG("%s: %s: Keys not ready(%d). s=%d\n, l0=%0x08x",
- __func__, HDCP_STATE_NAME, timeout_count,
- keys_state, link0_status);
- msleep(20);
- }
-
- if (!timeout_count) {
- DEV_ERR("%s: %s: Invalid Keys State: %d\n", __func__,
- HDCP_STATE_NAME, keys_state);
- rc = -EINVAL;
+ rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
+ ((link0_status >> reg_set->keys_offset) & 0x7)
+ == HDCP_KEYS_STATE_VALID,
+ HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: key not ready\n", __func__);
goto error;
}
@@ -460,39 +704,39 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
* 1.1_Features turned off by default.
* No need to write AInfo since 1.1_Features is disabled.
*/
- DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA4, 0);
+ DSS_REG_W(io, reg_set->data4, 0);
/* Wait for An0 and An1 bit to be ready */
- timeout_count = 100;
- do {
- link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
- an_ready = (link0_status & BIT(8)) && (link0_status & BIT(9));
- if (!an_ready) {
- DEV_DBG("%s: %s: An not ready(%d). l0_status=0x%08x\n",
- __func__, HDCP_STATE_NAME, timeout_count,
- link0_status);
- msleep(20);
- }
- } while (!an_ready && --timeout_count);
-
- if (!timeout_count) {
- rc = -ETIMEDOUT;
- DEV_ERR("%s: %s: timedout, An0=%ld, An1=%ld\n", __func__,
- HDCP_STATE_NAME, (link0_status & BIT(8)) >> 8,
- (link0_status & BIT(9)) >> 9);
+ rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
+ (link0_status & (BIT(8) | BIT(9))),
+ HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: An not ready\n", __func__);
goto error;
}
/* As per hardware recommendations, wait before reading An */
msleep(20);
- /* Read An0 and An1 */
- link0_an_0 = DSS_REG_R(io, HDMI_HDCP_RCVPORT_DATA5);
- link0_an_1 = DSS_REG_R(io, HDMI_HDCP_RCVPORT_DATA6);
+ /*
+ * As per hardware recommendation, for DP, read AN0 and AN1 again
+ * with a delay of 1 micro second each.
+ */
+ link0_an_0 = DSS_REG_R(io, reg_set->data5);
+ if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_DP) {
+ udelay(1);
+ link0_an_0 = DSS_REG_R(io, reg_set->data5);
+ }
+
+ link0_an_1 = DSS_REG_R(io, reg_set->data6);
+ if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_DP) {
+ udelay(1);
+ link0_an_0 = DSS_REG_R(io, reg_set->data6);
+ }
/* Read AKSV */
- link0_aksv_0 = DSS_REG_R(io, HDMI_HDCP_RCVPORT_DATA3);
- link0_aksv_1 = DSS_REG_R(io, HDMI_HDCP_RCVPORT_DATA4);
+ link0_aksv_0 = DSS_REG_R(io, reg_set->data3);
+ link0_aksv_1 = DSS_REG_R(io, reg_set->data4);
/* Copy An and AKSV to byte arrays for transmission */
aksv[0] = link0_aksv_0 & 0xFF;
@@ -510,55 +754,21 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
an[6] = (link0_an_1 >> 16) & 0xFF;
an[7] = (link0_an_1 >> 24) & 0xFF;
- /* Write An to offset 0x18 */
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0x74;
- ddc_data.offset = 0x18;
- ddc_data.data_buf = an;
- ddc_data.data_len = 8;
- ddc_data.what = "An";
- hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
-
- rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl);
- if (rc) {
- DEV_ERR("%s: %s: An write failed\n", __func__, HDCP_STATE_NAME);
+ rc = hdmi_hdcp_write(hdcp_ctrl, 0x18, 8, an, "an");
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: error writing an to sink\n", __func__);
goto error;
}
- /* Write AKSV to offset 0x10 */
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0x74;
- ddc_data.offset = 0x10;
- ddc_data.data_buf = aksv;
- ddc_data.data_len = 5;
- ddc_data.what = "Aksv";
- hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
-
- rc = hdmi_ddc_write(hdcp_ctrl->init_data.ddc_ctrl);
- if (rc) {
- DEV_ERR("%s: %s: AKSV write failed\n", __func__,
- HDCP_STATE_NAME);
+ rc = hdmi_hdcp_write(hdcp_ctrl, 0x10, 5, aksv, "aksv");
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: error writing aksv to sink\n", __func__);
goto error;
}
- DEV_DBG("%s: %s: Link0-AKSV=%02x%08x\n", __func__,
- HDCP_STATE_NAME, link0_aksv_1 & 0xFF, link0_aksv_0);
-
- /* Read BKSV at offset 0x00 */
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0x74;
- ddc_data.offset = 0x00;
- ddc_data.data_buf = bksv;
- ddc_data.data_len = 5;
- ddc_data.request_len = 5;
- ddc_data.retry = 5;
- ddc_data.what = "Bksv";
-
- hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
- rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
- if (rc) {
- DEV_ERR("%s: %s: BKSV read failed\n", __func__,
- HDCP_STATE_NAME);
+ rc = hdmi_hdcp_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.bksv, bksv, false);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: error reading bksv from sink\n", __func__);
goto error;
}
@@ -584,9 +794,9 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
if (hdcp_ctrl->tz_hdcp) {
memset(scm_buf, 0x00, sizeof(scm_buf));
- scm_buf[0].addr = phy_addr + HDMI_HDCP_RCVPORT_DATA0;
+ scm_buf[0].addr = phy_addr + reg_set->data0;
scm_buf[0].val = link0_bksv_0;
- scm_buf[1].addr = phy_addr + HDMI_HDCP_RCVPORT_DATA1;
+ scm_buf[1].addr = phy_addr + reg_set->data1;
scm_buf[1].val = link0_bksv_1;
ret = hdcp_scm_call(scm_buf, &resp);
@@ -597,52 +807,45 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
rc = -EINVAL;
goto error;
}
- } else if (hdcp_ctrl->hdmi_tx_ver_4) {
- DSS_REG_W(hdcp_io, HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA0,
- link0_bksv_0);
- DSS_REG_W(hdcp_io, HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA1,
- link0_bksv_1);
+ } else if (hdcp_ctrl->init_data.sec_access) {
+ DSS_REG_W(hdcp_io, reg_set->sec_data0, link0_bksv_0);
+ DSS_REG_W(hdcp_io, reg_set->sec_data1, link0_bksv_1);
} else {
- DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA0, link0_bksv_0);
- DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA1, link0_bksv_1);
+ DSS_REG_W(io, reg_set->data0, link0_bksv_0);
+ DSS_REG_W(io, reg_set->data1, link0_bksv_1);
}
- /* Enable HDCP interrupts and ack/clear any stale interrupts */
- DSS_REG_W(io, HDMI_HDCP_INT_CTRL, 0xE6);
-
/*
* HDCP Compliace Test case 1A-01:
* Wait here at least 100ms before reading R0'
*/
msleep(125);
- /* Read R0' at offset 0x08 */
+ /* Wait for HDCP R0 computation to be completed */
+ rc = readl_poll_timeout(io->base + reg_set->status, link0_status,
+ link0_status & BIT(reg_set->r0_offset),
+ HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: R0 not ready\n", __func__);
+ goto error;
+ }
+
memset(buf, 0, sizeof(buf));
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0x74;
- ddc_data.offset = 0x08;
- ddc_data.data_buf = buf;
- ddc_data.data_len = 2;
- ddc_data.request_len = 2;
- ddc_data.retry = 5;
- ddc_data.what = "R0'";
-
- hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
-
- rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
- if (rc) {
- DEV_ERR("%s: %s: R0' read failed\n", __func__, HDCP_STATE_NAME);
+ rc = hdmi_hdcp_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.r0, buf, false);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: error reading R0' from sink\n", __func__);
goto error;
}
+
DEV_DBG("%s: %s: R0'=%02x%02x\n", __func__, HDCP_STATE_NAME,
buf[1], buf[0]);
/* Write R0' to HDCP registers and check to see if it is a match */
reinit_completion(&hdcp_ctrl->r0_checked);
- DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA2_0, (((u32)buf[1]) << 8) | buf[0]);
+ DSS_REG_W(io, reg_set->data2_0, (((u32)buf[1]) << 8) | buf[0]);
timeout_count = wait_for_completion_timeout(
&hdcp_ctrl->r0_checked, HZ*2);
- link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
+ link0_status = DSS_REG_R(io, reg_set->status);
is_match = link0_status & BIT(12);
if (!is_match) {
DEV_DBG("%s: %s: Link0_Status=0x%08x\n", __func__,
@@ -663,166 +866,108 @@ static int hdmi_hdcp_authentication_part1(struct hdmi_hdcp_ctrl *hdcp_ctrl)
}
error:
- if (rc) {
+ if (rc)
DEV_ERR("%s: %s: Authentication Part I failed\n", __func__,
hdcp_ctrl ? HDCP_STATE_NAME : "???");
- } else {
- /* Enable HDCP Encryption */
- DSS_REG_W(io, HDMI_HDCP_CTRL, BIT(0) | BIT(8));
+ else
DEV_INFO("%s: %s: Authentication Part I successful\n",
__func__, HDCP_STATE_NAME);
- }
return rc;
} /* hdmi_hdcp_authentication_part1 */
-#define READ_WRITE_V_H(io, off, name, reg, wr) \
-do { \
- ddc_data.offset = (off); \
- memset(what, 0, sizeof(what)); \
- snprintf(what, sizeof(what), (name)); \
- hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data; \
- rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl); \
- if (rc) { \
- DEV_ERR("%s: %s: Read %s failed\n", __func__, HDCP_STATE_NAME, \
- what); \
- goto error; \
- } \
- DEV_DBG("%s: %s: %s: buf[0]=%x, buf[1]=%x, buf[2]=%x, buf[3]=%x\n", \
- __func__, HDCP_STATE_NAME, what, buf[0], buf[1], \
- buf[2], buf[3]); \
- if (wr) { \
- DSS_REG_W((io), (reg), \
- (buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0])); \
- } \
-} while (0);
+static int hdmi_hdcp_set_v_h(struct hdmi_hdcp_ctrl *hdcp_ctrl,
+ struct hdmi_hdcp_reg_data *rd, u8 *buf)
+{
+ int rc;
+ struct dss_io_data *io;
+
+ if (!hdcp_ctrl->tz_hdcp && hdcp_ctrl->init_data.sec_access)
+ io = hdcp_ctrl->init_data.hdcp_io;
+ else
+ io = hdcp_ctrl->init_data.core_io;
+
+ rc = hdmi_hdcp_read(hdcp_ctrl, rd->sink, buf, false);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: error reading %s\n", __func__, rd->sink->name);
+ goto end;
+ }
+
+ DEV_DBG("%s: %s: %s: buf[0]=%x, buf[1]=%x, buf[2]=%x, buf[3]=%x\n",
+ __func__, HDCP_STATE_NAME, rd->sink->name, buf[0], buf[1],
+ buf[2], buf[3]);
+
+ if (!hdcp_ctrl->tz_hdcp)
+ DSS_REG_W(io, rd->reg_id,
+ (buf[3] << 24 | buf[2] << 16 | buf[1] << 8 | buf[0]));
+end:
+ return rc;
+}
static int hdmi_hdcp_transfer_v_h(struct hdmi_hdcp_ctrl *hdcp_ctrl)
{
- char what[20];
int rc = 0;
u8 buf[4];
- struct hdmi_tx_ddc_data ddc_data;
- struct dss_io_data *io;
-
struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG];
u32 phy_addr;
-
+ struct hdcp_reg_set *reg_set = &hdcp_ctrl->reg_set;
struct hdmi_hdcp_reg_data reg_data[] = {
- {HDMI_HDCP_RCVPORT_DATA7, 0x20, "V' H0"},
- {HDMI_HDCP_RCVPORT_DATA8, 0x24, "V' H1"},
- {HDMI_HDCP_RCVPORT_DATA9, 0x28, "V' H2"},
- {HDMI_HDCP_RCVPORT_DATA10, 0x2C, "V' H3"},
- {HDMI_HDCP_RCVPORT_DATA11, 0x30, "V' H4"},
+ {reg_set_data(7), &hdcp_ctrl->sink_addr.v_h0},
+ {reg_set_data(8), &hdcp_ctrl->sink_addr.v_h1},
+ {reg_set_data(9), &hdcp_ctrl->sink_addr.v_h2},
+ {reg_set_data(10), &hdcp_ctrl->sink_addr.v_h3},
+ {reg_set_data(11), &hdcp_ctrl->sink_addr.v_h4},
};
- u32 size = sizeof(reg_data)/sizeof(reg_data[0]);
- u32 iter = 0;
- u32 ret = 0;
- u32 resp = 0;
-
- if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
- DEV_ERR("%s: invalid input\n", __func__);
- return -EINVAL;
- }
+ u32 size = ARRAY_SIZE(reg_data);
+ u32 iter = 0, ret = 0, resp = 0;
phy_addr = hdcp_ctrl->init_data.phy_addr;
- io = hdcp_ctrl->init_data.core_io;
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0x74;
- ddc_data.data_buf = buf;
- ddc_data.data_len = 4;
- ddc_data.request_len = 4;
- ddc_data.retry = 5;
- ddc_data.what = what;
-
- if (hdcp_ctrl->tz_hdcp) {
- memset(scm_buf, 0x00, sizeof(scm_buf));
+ memset(scm_buf, 0x00, sizeof(scm_buf));
- for (iter = 0; iter < size && iter < SCM_HDCP_MAX_REG; iter++) {
- struct hdmi_hdcp_reg_data *rd = reg_data + iter;
+ for (iter = 0; iter < size; iter++) {
+ struct hdmi_hdcp_reg_data *rd = reg_data + iter;
- READ_WRITE_V_H(io, rd->off, rd->name, 0, false);
+ memset(buf, 0, sizeof(buf));
+ hdmi_hdcp_set_v_h(hdcp_ctrl, rd, buf);
- rd->reg_val = buf[3] << 24 | buf[2] << 16 |
+ if (hdcp_ctrl->tz_hdcp) {
+ u32 reg_val = buf[3] << 24 | buf[2] << 16 |
buf[1] << 8 | buf[0];
scm_buf[iter].addr = phy_addr + reg_data[iter].reg_id;
- scm_buf[iter].val = reg_data[iter].reg_val;
- }
+ scm_buf[iter].val = reg_val;
- ret = hdcp_scm_call(scm_buf, &resp);
- if (ret || resp) {
- DEV_ERR("%s: error: scm_call ret = %d, resp = %d\n",
- __func__, ret, resp);
- rc = -EINVAL;
- goto error;
+ ret = hdcp_scm_call(scm_buf, &resp);
+ if (ret || resp) {
+ DEV_ERR("%s: scm err: ret=%d, resp=%d\n",
+ __func__, ret, resp);
+ rc = -EINVAL;
+ goto error;
+ }
}
- } else if (hdcp_ctrl->hdmi_tx_ver_4) {
- struct dss_io_data *hdcp_io = hdcp_ctrl->init_data.hdcp_io;
-
- /* Read V'.HO 4 Byte at offset 0x20 */
- READ_WRITE_V_H(hdcp_io, 0x20, "V' H0",
- HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA7, true);
-
- /* Read V'.H1 4 Byte at offset 0x24 */
- READ_WRITE_V_H(hdcp_io, 0x24, "V' H1",
- HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA8, true);
-
- /* Read V'.H2 4 Byte at offset 0x28 */
- READ_WRITE_V_H(hdcp_io, 0x28, "V' H2",
- HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA9, true);
-
- /* Read V'.H3 4 Byte at offset 0x2C */
- READ_WRITE_V_H(hdcp_io, 0x2C, "V' H3",
- HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA10, true);
-
- /* Read V'.H4 4 Byte at offset 0x30 */
- READ_WRITE_V_H(hdcp_io, 0x30, "V' H4",
- HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA11, true);
- } else {
- /* Read V'.HO 4 Byte at offset 0x20 */
- READ_WRITE_V_H(io, 0x20, "V' H0", HDMI_HDCP_RCVPORT_DATA7,
- true);
-
- /* Read V'.H1 4 Byte at offset 0x24 */
- READ_WRITE_V_H(io, 0x24, "V' H1", HDMI_HDCP_RCVPORT_DATA8,
- true);
-
- /* Read V'.H2 4 Byte at offset 0x28 */
- READ_WRITE_V_H(io, 0x28, "V' H2", HDMI_HDCP_RCVPORT_DATA9,
- true);
-
- /* Read V'.H3 4 Byte at offset 0x2C */
- READ_WRITE_V_H(io, 0x2C, "V' H3", HDMI_HDCP_RCVPORT_DATA10,
- true);
-
- /* Read V'.H4 4 Byte at offset 0x30 */
- READ_WRITE_V_H(io, 0x30, "V' H4", HDMI_HDCP_RCVPORT_DATA11,
- true);
}
-
error:
return rc;
}
static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
{
- int rc, cnt, i;
- struct hdmi_tx_ddc_data ddc_data;
+ int rc, i;
u32 timeout_count, down_stream_devices = 0;
u32 repeater_cascade_depth = 0;
u8 buf[0xFF];
u8 *ksv_fifo = NULL;
- u8 bcaps;
- u16 bstatus, max_devs_exceeded = 0, max_cascade_exceeded = 0;
- u32 link0_status;
+ u8 bcaps = 0;
+ u16 bstatus = 0, max_devs_exceeded = 0, max_cascade_exceeded = 0;
+ u32 status = 0, sha_status = 0;
u32 ksv_bytes;
struct dss_io_data *io;
-
+ struct hdcp_reg_set *reg_set;
struct scm_hdcp_req scm_buf[SCM_HDCP_MAX_REG];
u32 phy_addr;
u32 ret = 0;
u32 resp = 0;
+ u32 ksv_read_retry = 20;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -831,6 +976,7 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
}
phy_addr = hdcp_ctrl->init_data.phy_addr;
+ reg_set = &hdcp_ctrl->reg_set;
if (HDCP_STATE_AUTHENTICATING != hdcp_ctrl->hdcp_state) {
DEV_DBG("%s: %s: invalid state. returning\n", __func__,
@@ -844,8 +990,7 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
io = hdcp_ctrl->init_data.core_io;
memset(buf, 0, sizeof(buf));
- memset(ksv_fifo, 0,
- sizeof(hdcp_ctrl->current_tp.ksv_list));
+ memset(ksv_fifo, 0, sizeof(hdcp_ctrl->current_tp.ksv_list));
/*
* Wait until READY bit is set in BCAPS, as per HDCP specifications
@@ -853,48 +998,22 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
*/
timeout_count = 50;
do {
- timeout_count--;
- /* Read BCAPS at offset 0x40 */
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0x74;
- ddc_data.offset = 0x40;
- ddc_data.data_buf = &bcaps;
- ddc_data.data_len = 1;
- ddc_data.request_len = 1;
- ddc_data.retry = 5;
- ddc_data.what = "Bcaps";
- ddc_data.retry_align = true;
-
- hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
-
- rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
- if (rc) {
- DEV_ERR("%s: %s: BCAPS read failed\n", __func__,
- HDCP_STATE_NAME);
+ rc = hdmi_hdcp_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.bcaps,
+ &bcaps, true);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: error reading bcaps\n", __func__);
goto error;
}
msleep(100);
- } while (!(bcaps & BIT(5)) && timeout_count);
-
- /* Read BSTATUS at offset 0x41 */
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0x74;
- ddc_data.offset = 0x41;
- ddc_data.data_buf = buf;
- ddc_data.data_len = 2;
- ddc_data.request_len = 2;
- ddc_data.retry = 5;
- ddc_data.what = "Bstatuss";
- ddc_data.retry_align = true;
-
- hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
-
- rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
- if (rc) {
- DEV_ERR("%s: %s: BSTATUS read failed\n", __func__,
- HDCP_STATE_NAME);
+ } while (!(bcaps & BIT(5)) && --timeout_count);
+
+ rc = hdmi_hdcp_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.bstatus,
+ buf, true);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: error reading bstatus\n", __func__);
goto error;
}
+
bstatus = buf[1];
bstatus = (bstatus << 8) | buf[0];
@@ -902,7 +1021,7 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
memset(scm_buf, 0x00, sizeof(scm_buf));
/* Write BSTATUS and BCAPS to HDCP registers */
- scm_buf[0].addr = phy_addr + HDMI_HDCP_RCVPORT_DATA12;
+ scm_buf[0].addr = phy_addr + reg_set->data12;
scm_buf[0].val = bcaps | (bstatus << 8);
ret = hdcp_scm_call(scm_buf, &resp);
@@ -912,12 +1031,12 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
rc = -EINVAL;
goto error;
}
- } else if (hdcp_ctrl->hdmi_tx_ver_4) {
+ } else if (hdcp_ctrl->init_data.sec_access) {
DSS_REG_W(hdcp_ctrl->init_data.hdcp_io,
- HDCP_SEC_TZ_HV_HLOS_HDCP_RCVPORT_DATA12,
- bcaps | (bstatus << 8));
+ reg_set->sec_data12,
+ bcaps | (bstatus << 8));
} else {
- DSS_REG_W(io, HDMI_HDCP_RCVPORT_DATA12, bcaps | (bstatus << 8));
+ DSS_REG_W(io, reg_set->data12, bcaps | (bstatus << 8));
}
down_stream_devices = bstatus & 0x7F;
@@ -972,37 +1091,28 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
* HDCP Repeaters (REPEATER == 0).
*/
ksv_bytes = 5 * down_stream_devices;
- memset(&ddc_data, 0, sizeof(ddc_data));
- ddc_data.dev_addr = 0x74;
- ddc_data.offset = 0x43;
- ddc_data.data_buf = ksv_fifo;
- ddc_data.data_len = ksv_bytes;
- ddc_data.request_len = ksv_bytes;
- ddc_data.retry = 5;
- ddc_data.what = "KSV FIFO";
-
- hdcp_ctrl->init_data.ddc_ctrl->ddc_data = ddc_data;
-
- cnt = 0;
+ hdcp_ctrl->sink_addr.ksv_fifo.len = ksv_bytes;
+
do {
- rc = hdmi_ddc_read(hdcp_ctrl->init_data.ddc_ctrl);
- if (rc) {
- DEV_ERR("%s: %s: KSV FIFO read failed\n", __func__,
- HDCP_STATE_NAME);
+ rc = hdmi_hdcp_read(hdcp_ctrl, &hdcp_ctrl->sink_addr.ksv_fifo,
+ ksv_fifo, false);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_DBG("%s: could not read ksv fifo (%d)\n",
+ __func__, ksv_read_retry);
/*
* HDCP Compliace Test case 1B-01:
* Wait here until all the ksv bytes have been
* read from the KSV FIFO register.
*/
msleep(25);
- } else {
- break;
+
}
- cnt++;
- } while (cnt != 20);
+ } while (rc && --ksv_read_retry);
- if (cnt == 20)
+ if (rc) {
+ DEV_ERR("%s: error reading ksv_fifo\n", __func__);
goto error;
+ }
rc = hdmi_hdcp_transfer_v_h(hdcp_ctrl);
if (rc)
@@ -1019,9 +1129,9 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
if (hdcp_ctrl->tz_hdcp) {
memset(scm_buf, 0x00, sizeof(scm_buf));
- scm_buf[0].addr = phy_addr + HDMI_HDCP_SHA_CTRL;
+ scm_buf[0].addr = phy_addr + reg_set->sha_ctrl;
scm_buf[0].val = HDCP_REG_ENABLE;
- scm_buf[1].addr = phy_addr + HDMI_HDCP_SHA_CTRL;
+ scm_buf[1].addr = phy_addr + reg_set->sha_ctrl;
scm_buf[1].val = HDCP_REG_DISABLE;
ret = hdcp_scm_call(scm_buf, &resp);
@@ -1031,16 +1141,16 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
rc = -EINVAL;
goto error;
}
- } else if (hdcp_ctrl->hdmi_tx_ver_4) {
+ } else if (hdcp_ctrl->init_data.sec_access) {
DSS_REG_W(hdcp_ctrl->init_data.hdcp_io,
- HDCP_SEC_TZ_HV_HLOS_HDCP_SHA_CTRL,
+ reg_set->sec_sha_ctrl,
HDCP_REG_ENABLE);
DSS_REG_W(hdcp_ctrl->init_data.hdcp_io,
- HDCP_SEC_TZ_HV_HLOS_HDCP_SHA_CTRL,
+ reg_set->sec_sha_ctrl,
HDCP_REG_DISABLE);
} else {
- DSS_REG_W(io, HDMI_HDCP_SHA_CTRL, HDCP_REG_ENABLE);
- DSS_REG_W(io, HDMI_HDCP_SHA_CTRL, HDCP_REG_DISABLE);
+ DSS_REG_W(io, reg_set->sha_ctrl, HDCP_REG_ENABLE);
+ DSS_REG_W(io, reg_set->sha_ctrl, HDCP_REG_DISABLE);
}
for (i = 0; i < ksv_bytes - 1; i++) {
@@ -1048,7 +1158,7 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
if (hdcp_ctrl->tz_hdcp) {
memset(scm_buf, 0x00, sizeof(scm_buf));
- scm_buf[0].addr = phy_addr + HDMI_HDCP_SHA_DATA;
+ scm_buf[0].addr = phy_addr + reg_set->sha_ctrl;
scm_buf[0].val = ksv_fifo[i] << 16;
ret = hdcp_scm_call(scm_buf, &resp);
@@ -1058,12 +1168,12 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
rc = -EINVAL;
goto error;
}
- } else if (hdcp_ctrl->hdmi_tx_ver_4) {
+ } else if (hdcp_ctrl->init_data.sec_access) {
DSS_REG_W_ND(hdcp_ctrl->init_data.hdcp_io,
- HDCP_SEC_TZ_HV_HLOS_HDCP_SHA_DATA,
+ reg_set->sec_sha_ctrl,
ksv_fifo[i] << 16);
} else {
- DSS_REG_W_ND(io, HDMI_HDCP_SHA_DATA, ksv_fifo[i] << 16);
+ DSS_REG_W_ND(io, reg_set->sha_ctrl, ksv_fifo[i] << 16);
}
/*
@@ -1071,31 +1181,22 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
* HDCP_SHA_BLOCK_DONE before writing any further
*/
if (i && !((i + 1) % 64)) {
- timeout_count = 100;
- while (!(DSS_REG_R(io, HDMI_HDCP_SHA_STATUS) & BIT(0))
- && (--timeout_count)) {
- DEV_DBG("%s: %s: Wrote 64 bytes KSV FIFO\n",
- __func__, HDCP_STATE_NAME);
- DEV_DBG("%s: %s: HDCP_SHA_STATUS=%08x\n",
- __func__, HDCP_STATE_NAME,
- DSS_REG_R(io, HDMI_HDCP_SHA_STATUS));
- msleep(20);
- }
- if (!timeout_count) {
- rc = -ETIMEDOUT;
- DEV_ERR("%s: %s: Write KSV FIFO timedout",
- __func__, HDCP_STATE_NAME);
+ rc = readl_poll_timeout(io->base + reg_set->sha_status,
+ sha_status, sha_status & BIT(0),
+ HDCP_POLL_SLEEP_US,
+ HDCP_POLL_TIMEOUT_US);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: block not done\n", __func__);
goto error;
}
}
-
}
/* Write l to DONE bit[0] */
if (hdcp_ctrl->tz_hdcp) {
memset(scm_buf, 0x00, sizeof(scm_buf));
- scm_buf[0].addr = phy_addr + HDMI_HDCP_SHA_DATA;
+ scm_buf[0].addr = phy_addr + reg_set->sha_ctrl;
scm_buf[0].val = (ksv_fifo[ksv_bytes - 1] << 16) | 0x1;
ret = hdcp_scm_call(scm_buf, &resp);
@@ -1105,43 +1206,32 @@ static int hdmi_hdcp_authentication_part2(struct hdmi_hdcp_ctrl *hdcp_ctrl)
rc = -EINVAL;
goto error;
}
- } else if (hdcp_ctrl->hdmi_tx_ver_4) {
+ } else if (hdcp_ctrl->init_data.sec_access) {
DSS_REG_W_ND(hdcp_ctrl->init_data.hdcp_io,
- HDCP_SEC_TZ_HV_HLOS_HDCP_SHA_DATA,
+ reg_set->sec_sha_ctrl,
(ksv_fifo[ksv_bytes - 1] << 16) | 0x1);
} else {
- DSS_REG_W_ND(io, HDMI_HDCP_SHA_DATA,
+ DSS_REG_W_ND(io, reg_set->sha_ctrl,
(ksv_fifo[ksv_bytes - 1] << 16) | 0x1);
}
/* Now wait for HDCP_SHA_COMP_DONE */
- timeout_count = 100;
- while ((0x10 != (DSS_REG_R(io, HDMI_HDCP_SHA_STATUS)
- & 0xFFFFFF10)) && --timeout_count)
- msleep(20);
- if (!timeout_count) {
- rc = -ETIMEDOUT;
- DEV_ERR("%s: %s: SHA computation timedout", __func__,
- HDCP_STATE_NAME);
+ rc = readl_poll_timeout(io->base + reg_set->sha_status, sha_status,
+ sha_status & BIT(4),
+ HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: comp not done\n", __func__);
goto error;
}
/* Wait for V_MATCHES */
- timeout_count = 100;
- link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
- while (((link0_status & BIT(20)) != BIT(20)) && --timeout_count) {
- DEV_DBG("%s: %s: Waiting for V_MATCHES(%d). l0_status=0x%08x\n",
- __func__, HDCP_STATE_NAME, timeout_count, link0_status);
- msleep(20);
- link0_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
- }
- if (!timeout_count) {
- rc = -ETIMEDOUT;
- DEV_ERR("%s: %s: HDCP V Match timedout", __func__,
- HDCP_STATE_NAME);
+ rc = readl_poll_timeout(io->base + reg_set->status, status,
+ status & BIT(reg_set->v_offset),
+ HDCP_POLL_SLEEP_US, HDCP_POLL_TIMEOUT_US);
+ if (IS_ERR_VALUE(rc)) {
+ DEV_ERR("%s: V not ready\n", __func__);
goto error;
}
-
error:
if (rc)
DEV_ERR("%s: %s: Authentication Part II failed\n", __func__,
@@ -1236,7 +1326,8 @@ static void hdmi_hdcp_auth_work(struct work_struct *work)
io = hdcp_ctrl->init_data.core_io;
/* Enabling Software DDC */
- DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION , DSS_REG_R(io,
+ if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_HDMI)
+ DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION, DSS_REG_R(io,
HDMI_DDC_ARBITRATION) & ~(BIT(4)));
rc = hdmi_hdcp_authentication_part1(hdcp_ctrl);
@@ -1258,7 +1349,8 @@ static void hdmi_hdcp_auth_work(struct work_struct *work)
}
/* Disabling software DDC before going into part3 to make sure
* there is no Arbitration between software and hardware for DDC */
- DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION , DSS_REG_R(io,
+ if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_HDMI)
+ DSS_REG_W_ND(io, HDMI_DDC_ARBITRATION, DSS_REG_R(io,
HDMI_DDC_ARBITRATION) | (BIT(4)));
error:
@@ -1314,12 +1406,17 @@ int hdmi_hdcp_authenticate(void *input)
DEV_DBG("%s: %s: Queuing work to start HDCP authentication", __func__,
HDCP_STATE_NAME);
- if (!hdmi_hdcp_load_keys(input))
+ if (!hdmi_hdcp_load_keys(input)) {
+ flush_delayed_work(&hdcp_ctrl->hdcp_auth_work);
+
queue_delayed_work(hdcp_ctrl->init_data.workq,
&hdcp_ctrl->hdcp_auth_work, HZ/2);
- else
+ } else {
+ flush_work(&hdcp_ctrl->hdcp_int_work);
+
queue_work(hdcp_ctrl->init_data.workq,
&hdcp_ctrl->hdcp_int_work);
+ }
return 0;
} /* hdmi_hdcp_authenticate */
@@ -1328,6 +1425,8 @@ int hdmi_hdcp_reauthenticate(void *input)
{
struct hdmi_hdcp_ctrl *hdcp_ctrl = (struct hdmi_hdcp_ctrl *)input;
struct dss_io_data *io;
+ struct hdcp_reg_set *reg_set;
+ struct hdcp_int_set *isr;
u32 hdmi_hw_version;
u32 ret = 0;
@@ -1337,6 +1436,8 @@ int hdmi_hdcp_reauthenticate(void *input)
}
io = hdcp_ctrl->init_data.core_io;
+ reg_set = &hdcp_ctrl->reg_set;
+ isr = &hdcp_ctrl->int_set;
if (HDCP_STATE_AUTH_FAIL != hdcp_ctrl->hdcp_state) {
DEV_DBG("%s: %s: invalid state. returning\n", __func__,
@@ -1344,22 +1445,25 @@ int hdmi_hdcp_reauthenticate(void *input)
return 0;
}
- hdmi_hw_version = DSS_REG_R(io, HDMI_VERSION);
- if (hdmi_hw_version >= 0x30030000) {
- DSS_REG_W(io, HDMI_CTRL_SW_RESET, BIT(1));
- DSS_REG_W(io, HDMI_CTRL_SW_RESET, 0);
+ if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_HDMI) {
+ hdmi_hw_version = DSS_REG_R(io, HDMI_VERSION);
+ if (hdmi_hw_version >= 0x30030000) {
+ DSS_REG_W(io, HDMI_CTRL_SW_RESET, BIT(1));
+ DSS_REG_W(io, HDMI_CTRL_SW_RESET, 0);
+ }
+
+ /* Wait to be clean on DDC HW engine */
+ hdmi_hdcp_hw_ddc_clean(hdcp_ctrl);
}
/* Disable HDCP interrupts */
- DSS_REG_W(io, HDMI_HDCP_INT_CTRL, 0);
-
- DSS_REG_W(io, HDMI_HDCP_RESET, BIT(0));
+ DSS_REG_W(io, isr->int_reg, DSS_REG_R(io, isr->int_reg) & ~HDCP_INT_EN);
- /* Wait to be clean on DDC HW engine */
- hdmi_hdcp_hw_ddc_clean(hdcp_ctrl);
+ if (reg_set->reset)
+ DSS_REG_W(io, reg_set->reset, BIT(0));
/* Disable encryption and disable the HDCP block */
- DSS_REG_W(io, HDMI_HDCP_CTRL, 0);
+ DSS_REG_W(io, reg_set->ctrl, 0);
if (!hdmi_hdcp_load_keys(input))
queue_delayed_work(hdcp_ctrl->init_data.workq,
@@ -1375,6 +1479,8 @@ void hdmi_hdcp_off(void *input)
{
struct hdmi_hdcp_ctrl *hdcp_ctrl = (struct hdmi_hdcp_ctrl *)input;
struct dss_io_data *io;
+ struct hdcp_reg_set *reg_set;
+ struct hdcp_int_set *isr;
int rc = 0;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
@@ -1383,6 +1489,8 @@ void hdmi_hdcp_off(void *input)
}
io = hdcp_ctrl->init_data.core_io;
+ reg_set = &hdcp_ctrl->reg_set;
+ isr = &hdcp_ctrl->int_set;
if (HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) {
DEV_DBG("%s: %s: inactive. returning\n", __func__,
@@ -1396,7 +1504,8 @@ void hdmi_hdcp_off(void *input)
* reauth works will know that the HDCP session has been turned off.
*/
mutex_lock(hdcp_ctrl->init_data.mutex);
- DSS_REG_W(io, HDMI_HDCP_INT_CTRL, 0);
+ DSS_REG_W(io, isr->int_reg,
+ DSS_REG_R(io, isr->int_reg) & ~HDCP_INT_EN);
hdcp_ctrl->hdcp_state = HDCP_STATE_INACTIVE;
mutex_unlock(hdcp_ctrl->init_data.mutex);
@@ -1415,10 +1524,11 @@ void hdmi_hdcp_off(void *input)
DEV_DBG("%s: %s: Deleted hdcp int work\n", __func__,
HDCP_STATE_NAME);
- DSS_REG_W(io, HDMI_HDCP_RESET, BIT(0));
+ if (reg_set->reset)
+ DSS_REG_W(io, reg_set->reset, BIT(0));
/* Disable encryption and disable the HDCP block */
- DSS_REG_W(io, HDMI_HDCP_CTRL, 0);
+ DSS_REG_W(io, reg_set->ctrl, 0);
DEV_DBG("%s: %s: HDCP: Off\n", __func__, HDCP_STATE_NAME);
} /* hdmi_hdcp_off */
@@ -1429,6 +1539,8 @@ int hdmi_hdcp_isr(void *input)
int rc = 0;
struct dss_io_data *io;
u32 hdcp_int_val;
+ struct hdcp_reg_set *reg_set;
+ struct hdcp_int_set *isr;
if (!hdcp_ctrl || !hdcp_ctrl->init_data.core_io) {
DEV_ERR("%s: invalid input\n", __func__);
@@ -1437,28 +1549,33 @@ int hdmi_hdcp_isr(void *input)
}
io = hdcp_ctrl->init_data.core_io;
+ reg_set = &hdcp_ctrl->reg_set;
+ isr = &hdcp_ctrl->int_set;
- hdcp_int_val = DSS_REG_R(io, HDMI_HDCP_INT_CTRL);
+ hdcp_int_val = DSS_REG_R(io, isr->int_reg);
/* Ignore HDCP interrupts if HDCP is disabled */
if (HDCP_STATE_INACTIVE == hdcp_ctrl->hdcp_state) {
- DSS_REG_W(io, HDMI_HDCP_INT_CTRL, HDCP_INT_CLR);
+ DSS_REG_W(io, isr->int_reg, hdcp_int_val | HDCP_INT_CLR);
return 0;
}
- if (hdcp_int_val & BIT(0)) {
+ if (hdcp_int_val & isr->auth_success_int) {
/* AUTH_SUCCESS_INT */
- DSS_REG_W(io, HDMI_HDCP_INT_CTRL, (hdcp_int_val | BIT(1)));
+ DSS_REG_W(io, isr->int_reg,
+ (hdcp_int_val | isr->auth_success_ack));
DEV_INFO("%s: %s: AUTH_SUCCESS_INT received\n", __func__,
HDCP_STATE_NAME);
if (HDCP_STATE_AUTHENTICATING == hdcp_ctrl->hdcp_state)
complete_all(&hdcp_ctrl->r0_checked);
}
- if (hdcp_int_val & BIT(4)) {
+ if (hdcp_int_val & isr->auth_fail_int) {
/* AUTH_FAIL_INT */
- u32 link_status = DSS_REG_R(io, HDMI_HDCP_LINK0_STATUS);
- DSS_REG_W(io, HDMI_HDCP_INT_CTRL, (hdcp_int_val | BIT(5)));
+ u32 link_status = DSS_REG_R(io, reg_set->status);
+
+ DSS_REG_W(io, isr->int_reg,
+ (hdcp_int_val | isr->auth_fail_ack));
DEV_INFO("%s: %s: AUTH_FAIL_INT rcvd, LINK0_STATUS=0x%08x\n",
__func__, HDCP_STATE_NAME, link_status);
if (HDCP_STATE_AUTHENTICATED == hdcp_ctrl->hdcp_state) {
@@ -1471,23 +1588,42 @@ int hdmi_hdcp_isr(void *input)
}
/* Clear AUTH_FAIL_INFO as well */
- DSS_REG_W(io, HDMI_HDCP_INT_CTRL, (hdcp_int_val | BIT(7)));
+ DSS_REG_W(io, isr->int_reg,
+ (hdcp_int_val | isr->auth_fail_info_ack));
}
- if (hdcp_int_val & BIT(8)) {
+ if (hdcp_int_val & isr->tx_req_int) {
/* DDC_XFER_REQ_INT */
- DSS_REG_W(io, HDMI_HDCP_INT_CTRL, (hdcp_int_val | BIT(9)));
+ DSS_REG_W(io, isr->int_reg,
+ (hdcp_int_val | isr->tx_req_ack));
DEV_INFO("%s: %s: DDC_XFER_REQ_INT received\n", __func__,
HDCP_STATE_NAME);
}
- if (hdcp_int_val & BIT(12)) {
+ if (hdcp_int_val & isr->tx_req_done_int) {
/* DDC_XFER_DONE_INT */
- DSS_REG_W(io, HDMI_HDCP_INT_CTRL, (hdcp_int_val | BIT(13)));
+ DSS_REG_W(io, isr->int_reg,
+ (hdcp_int_val | isr->tx_req_done_ack));
DEV_INFO("%s: %s: DDC_XFER_DONE received\n", __func__,
HDCP_STATE_NAME);
}
+ if (hdcp_int_val & isr->encryption_ready) {
+ /* Encryption enabled */
+ DSS_REG_W(io, isr->int_reg,
+ (hdcp_int_val | isr->encryption_ready_ack));
+ DEV_INFO("%s: %s: encryption ready received\n", __func__,
+ HDCP_STATE_NAME);
+ }
+
+ if (hdcp_int_val & isr->encryption_not_ready) {
+ /* Encryption enabled */
+ DSS_REG_W(io, isr->int_reg,
+ (hdcp_int_val | isr->encryption_not_ready_ack));
+ DEV_INFO("%s: %s: encryption not ready received\n", __func__,
+ HDCP_STATE_NAME);
+ }
+
error:
return rc;
} /* hdmi_hdcp_isr */
@@ -1605,6 +1741,27 @@ void hdmi_hdcp_deinit(void *input)
kfree(hdcp_ctrl);
} /* hdmi_hdcp_deinit */
+static void hdmi_hdcp_update_client_reg_set(struct hdmi_hdcp_ctrl *hdcp_ctrl)
+{
+ if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_HDMI) {
+ struct hdcp_reg_set reg_set = HDCP_REG_SET_CLIENT_HDMI;
+ struct hdcp_sink_addr_map sink_addr = HDCP_HDMI_SINK_ADDR_MAP;
+ struct hdcp_int_set isr = HDCP_HDMI_INT_SET;
+
+ hdcp_ctrl->reg_set = reg_set;
+ hdcp_ctrl->sink_addr = sink_addr;
+ hdcp_ctrl->int_set = isr;
+ } else if (hdcp_ctrl->init_data.client_id == HDCP_CLIENT_DP) {
+ struct hdcp_reg_set reg_set = HDCP_REG_SET_CLIENT_DP;
+ struct hdcp_sink_addr_map sink_addr = HDCP_DP_SINK_ADDR_MAP;
+ struct hdcp_int_set isr = HDCP_DP_INT_SET;
+
+ hdcp_ctrl->reg_set = reg_set;
+ hdcp_ctrl->sink_addr = sink_addr;
+ hdcp_ctrl->int_set = isr;
+ }
+}
+
void *hdmi_hdcp_init(struct hdmi_hdcp_init_data *init_data)
{
struct hdmi_hdcp_ctrl *hdcp_ctrl = NULL;
@@ -1624,9 +1781,8 @@ void *hdmi_hdcp_init(struct hdmi_hdcp_init_data *init_data)
goto error;
}
- if (init_data->hdmi_tx_ver >= HDMI_TX_VERSION_4
- && !init_data->hdcp_io) {
- DEV_ERR("%s: hdcp_io required for HDMI Tx Ver 4\n", __func__);
+ if (init_data->sec_access && !init_data->hdcp_io) {
+ DEV_ERR("%s: hdcp_io required\n", __func__);
goto error;
}
@@ -1638,8 +1794,8 @@ void *hdmi_hdcp_init(struct hdmi_hdcp_init_data *init_data)
hdcp_ctrl->init_data = *init_data;
hdcp_ctrl->ops = &ops;
- hdcp_ctrl->hdmi_tx_ver_4 =
- (init_data->hdmi_tx_ver >= HDMI_TX_VERSION_4);
+
+ hdmi_hdcp_update_client_reg_set(hdcp_ctrl);
if (sysfs_create_group(init_data->sysfs_kobj,
&hdmi_hdcp_fs_attr_group)) {
@@ -1653,7 +1809,7 @@ void *hdmi_hdcp_init(struct hdmi_hdcp_init_data *init_data)
hdcp_ctrl->hdcp_state = HDCP_STATE_INACTIVE;
init_completion(&hdcp_ctrl->r0_checked);
- if (!hdcp_ctrl->hdmi_tx_ver_4) {
+ if (!hdcp_ctrl->init_data.sec_access) {
ret = scm_is_call_available(SCM_SVC_HDCP, SCM_CMD_HDCP);
if (ret <= 0) {
DEV_ERR("%s: secure hdcp service unavailable, ret = %d",
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h
index 7dda3ff5c67d..4f2bdc4bfd3d 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h
+++ b/drivers/video/fbdev/msm/mdss_hdmi_hdcp.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, 2014-2015 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012, 2014-2016, 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
@@ -17,6 +17,11 @@
#include <video/msm_hdmi_modes.h>
#include <soc/qcom/scm.h>
+enum hdcp_client_id {
+ HDCP_CLIENT_HDMI,
+ HDCP_CLIENT_DP,
+};
+
enum hdmi_hdcp_state {
HDCP_STATE_INACTIVE,
HDCP_STATE_AUTHENTICATING,
@@ -37,10 +42,13 @@ struct hdmi_hdcp_init_data {
void *cb_data;
void (*notify_status)(void *cb_data, enum hdmi_hdcp_state status);
struct hdmi_tx_ddc_ctrl *ddc_ctrl;
+ void *dp_data;
u32 phy_addr;
u32 hdmi_tx_ver;
struct msm_hdmi_mode_timing_info *timing;
bool tethered;
+ bool sec_access;
+ enum hdcp_client_id client_id;
};
struct hdmi_hdcp_ops {
diff --git a/drivers/video/fbdev/msm/mdss_hdmi_tx.c b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
index cd3017219005..050c4a4cecdf 100644
--- a/drivers/video/fbdev/msm/mdss_hdmi_tx.c
+++ b/drivers/video/fbdev/msm/mdss_hdmi_tx.c
@@ -1801,6 +1801,7 @@ static int hdmi_tx_init_hdcp(struct hdmi_tx_ctrl *hdmi_ctrl)
hdcp_init_data.notify_status = hdmi_tx_hdcp_cb;
hdcp_init_data.cb_data = (void *)hdmi_ctrl;
hdcp_init_data.hdmi_tx_ver = hdmi_ctrl->hdmi_tx_major_version;
+ hdcp_init_data.sec_access = true;
hdcp_init_data.timing = &hdmi_ctrl->timing;
if (hdmi_ctrl->hdcp14_present) {
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index 518b84fbad51..a9571a4b8d15 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -1703,6 +1703,24 @@ static int mdss_mdp_irq_clk_setup(struct mdss_data_type *mdata)
pr_debug("unable to get CX reg. rc=%d\n",
PTR_RET(mdata->vdd_cx));
mdata->vdd_cx = NULL;
+ } else {
+ /* Parse CX voltage settings */
+ ret = of_property_read_u32(mdata->pdev->dev.of_node,
+ "vdd-cx-min-uV", &mdata->vdd_cx_min_uv);
+ if (ret) {
+ pr_err("min uV for vdd-cx not specified. rc=%d\n", ret);
+ return ret;
+ }
+
+ ret = of_property_read_u32(mdata->pdev->dev.of_node,
+ "vdd-cx-max-uV", &mdata->vdd_cx_max_uv);
+ if (ret) {
+ pr_err("max uV for vdd-cx not specified. rc=%d\n", ret);
+ return ret;
+ }
+
+ pr_debug("vdd_cx [min_uV, max_uV] = [%d %d]\n",
+ mdata->vdd_cx_min_uv, mdata->vdd_cx_max_uv);
}
mdata->reg_bus_clt = mdss_reg_bus_vote_client_create("mdp\0");
@@ -1947,7 +1965,6 @@ static void mdss_mdp_hw_rev_caps_init(struct mdss_data_type *mdata)
mdss_mdp_init_default_prefill_factors(mdata);
mdss_set_quirk(mdata, MDSS_QUIRK_DSC_RIGHT_ONLY_PU);
mdss_set_quirk(mdata, MDSS_QUIRK_DSC_2SLICE_PU_THRPUT);
- mdss_set_quirk(mdata, MDSS_QUIRK_SRC_SPLIT_ALWAYS);
mdata->has_wb_ubwc = true;
set_bit(MDSS_CAPS_10_BIT_SUPPORTED, mdata->mdss_caps_map);
set_bit(MDSS_CAPS_AVR_SUPPORTED, mdata->mdss_caps_map);
@@ -4744,8 +4761,8 @@ static int mdss_mdp_cx_ctrl(struct mdss_data_type *mdata, int enable)
if (enable) {
rc = regulator_set_voltage(
mdata->vdd_cx,
- RPM_REGULATOR_CORNER_SVS_SOC,
- RPM_REGULATOR_CORNER_SUPER_TURBO);
+ mdata->vdd_cx_min_uv,
+ mdata->vdd_cx_max_uv);
if (rc < 0)
goto vreg_set_voltage_fail;
@@ -4764,8 +4781,8 @@ static int mdss_mdp_cx_ctrl(struct mdss_data_type *mdata, int enable)
}
rc = regulator_set_voltage(
mdata->vdd_cx,
- RPM_REGULATOR_CORNER_NONE,
- RPM_REGULATOR_CORNER_SUPER_TURBO);
+ 0,
+ mdata->vdd_cx_max_uv);
if (rc < 0)
goto vreg_set_voltage_fail;
}
diff --git a/drivers/video/fbdev/msm/mdss_mdp_layer.c b/drivers/video/fbdev/msm/mdss_mdp_layer.c
index 3a39d4fdc895..600701041309 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_layer.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_layer.c
@@ -347,10 +347,7 @@ static void __update_avr_info(struct mdss_mdp_ctl *ctl,
*/
static bool __layer_needs_src_split(struct mdp_input_layer *layer)
{
- struct mdss_data_type *mdata = mdss_mdp_get_mdata();
-
- return (layer->flags & MDP_LAYER_ASYNC) ||
- mdss_has_quirk(mdata, MDSS_QUIRK_SRC_SPLIT_ALWAYS);
+ return (layer->flags & MDP_LAYER_ASYNC);
}
static int __async_update_position_check(struct msm_fb_data_type *mfd,
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pipe.c b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
index bcb4867b4ffd..8cfb8e46777c 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pipe.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pipe.c
@@ -2690,6 +2690,16 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
if (pipe->scaler.enable)
mdss_mdp_pipe_program_pixel_extn(pipe);
+
+ ret = mdss_mdp_pipe_pp_setup(pipe, &opmode);
+ if (ret) {
+ pr_err("pipe pp setup error for pnum=%d\n", pipe->num);
+
+ MDSS_XLOG(pipe->num, pipe->mixer_left->num,
+ pipe->play_cnt, 0xbad);
+
+ goto done;
+ }
}
if ((!(pipe->flags & MDP_VPU_PIPE) && (src_data == NULL)) ||
@@ -2708,12 +2718,6 @@ int mdss_mdp_pipe_queue_data(struct mdss_mdp_pipe *pipe,
if (params_changed) {
pipe->params_changed = 0;
- ret = mdss_mdp_pipe_pp_setup(pipe, &opmode);
- if (ret) {
- pr_err("pipe pp setup error for pnum=%d\n", pipe->num);
- goto done;
- }
-
ret = mdss_mdp_image_setup(pipe, src_data);
if (ret) {
pr_err("image setup error for pnum=%d\n", pipe->num);
diff --git a/drivers/video/fbdev/msm/msm_ext_display.c b/drivers/video/fbdev/msm/msm_ext_display.c
index 5474df66eefb..a21242870a35 100644
--- a/drivers/video/fbdev/msm/msm_ext_display.c
+++ b/drivers/video/fbdev/msm/msm_ext_display.c
@@ -360,10 +360,13 @@ static int msm_ext_disp_hpd(struct platform_device *pdev,
ext_disp->current_disp = data->type;
} else if ((state == EXT_DISPLAY_CABLE_DISCONNECT) &&
!ext_disp->ack_enabled) {
- ext_disp->ops->audio_info_setup = NULL;
- ext_disp->ops->get_audio_edid_blk = NULL;
- ext_disp->ops->cable_status = NULL;
- ext_disp->ops->get_intf_id = NULL;
+ if (ext_disp->ops) {
+ ext_disp->ops->audio_info_setup = NULL;
+ ext_disp->ops->get_audio_edid_blk = NULL;
+ ext_disp->ops->cable_status = NULL;
+ ext_disp->ops->get_intf_id = NULL;
+ }
+
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
}
@@ -451,7 +454,7 @@ static int msm_ext_disp_notify(struct platform_device *pdev,
if (ret)
goto end;
- if (new_state == EXT_DISPLAY_CABLE_CONNECT) {
+ if (new_state == EXT_DISPLAY_CABLE_CONNECT && ext_disp->ops) {
ext_disp->ops->audio_info_setup =
data->codec_ops.audio_info_setup;
ext_disp->ops->get_audio_edid_blk =
@@ -524,10 +527,13 @@ static int msm_ext_disp_audio_ack(struct platform_device *pdev, u32 ack)
* empty.
*/
if (!ack_hpd) {
- ext_disp->ops->audio_info_setup = NULL;
- ext_disp->ops->get_audio_edid_blk = NULL;
- ext_disp->ops->cable_status = NULL;
- ext_disp->ops->get_intf_id = NULL;
+ if (ext_disp->ops) {
+ ext_disp->ops->audio_info_setup = NULL;
+ ext_disp->ops->get_audio_edid_blk = NULL;
+ ext_disp->ops->cable_status = NULL;
+ ext_disp->ops->get_intf_id = NULL;
+ }
+
ext_disp->current_disp = EXT_DISPLAY_TYPE_MAX;
}
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 772c784ba763..8f5a12ab2f2b 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -157,7 +157,7 @@
#define EARLYCON_TABLE() STRUCT_ALIGN(); \
VMLINUX_SYMBOL(__earlycon_table) = .; \
*(__earlycon_table) \
- *(__earlycon_table_end)
+ VMLINUX_SYMBOL(__earlycon_table_end) = .;
#else
#define EARLYCON_TABLE()
#endif
@@ -179,7 +179,6 @@
#define RESERVEDMEM_OF_TABLES() OF_TABLE(CONFIG_OF_RESERVED_MEM, reservedmem)
#define CPU_METHOD_OF_TABLES() OF_TABLE(CONFIG_SMP, cpu_method)
#define CPUIDLE_METHOD_OF_TABLES() OF_TABLE(CONFIG_CPU_IDLE, cpuidle_method)
-#define EARLYCON_OF_TABLES() OF_TABLE(CONFIG_SERIAL_EARLYCON, earlycon)
#ifdef CONFIG_ACPI
#define ACPI_PROBE_TABLE(name) \
@@ -527,8 +526,7 @@
IRQCHIP_OF_MATCH_TABLE() \
ACPI_PROBE_TABLE(irqchip) \
ACPI_PROBE_TABLE(clksrc) \
- EARLYCON_TABLE() \
- EARLYCON_OF_TABLES()
+ EARLYCON_TABLE()
#define INIT_TEXT \
*(.init.text) \
diff --git a/include/dt-bindings/clock/msm-clocks-cobalt.h b/include/dt-bindings/clock/msm-clocks-cobalt.h
index 28efd55ea8f6..85e28a9edc03 100644
--- a/include/dt-bindings/clock/msm-clocks-cobalt.h
+++ b/include/dt-bindings/clock/msm-clocks-cobalt.h
@@ -484,10 +484,6 @@
#define clk_gpu_pll0_pll_out_even 0xb0ed5009
#define clk_gpu_pll0_pll_out_odd 0x08c5a8a5
#define clk_gpu_pll0_postdiv_clk 0x76c19f3c
-#define clk_gpu_pll1_pll 0x09ac81ef
-#define clk_gpu_pll1_pll_out_even 0xa503de04
-#define clk_gpu_pll1_pll_out_odd 0x1c205dfb
-#define clk_gpu_pll1_postdiv_clk 0xdf546700
#define clk_gpucc_mx_clk 0x1edbb879
#define clk_gpucc_gcc_dbg_clk 0x9ae8cd3c
#define clk_gfxcc_dbg_clk 0x3ed47625
diff --git a/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h b/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h
index 7ef57256d8f0..6f0e35511cc9 100644
--- a/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h
+++ b/include/dt-bindings/clock/msm-clocks-hwio-cobalt.h
@@ -235,8 +235,6 @@
#define GPUCC_GPU_PLL0_PLL_MODE 0x00000
#define GPUCC_GPU_PLL0_USER_CTL_MODE 0x0000C
-#define GPUCC_GPU_PLL1_PLL_MODE 0x00040
-#define GPUCC_GPU_PLL1_USER_CTL_MODE 0x0004C
#define GPUCC_GFX3D_CMD_RCGR 0x01070
#define GPUCC_RBBMTIMER_CMD_RCGR 0x010B0
#define GPUCC_GFX3D_ISENSE_CMD_RCGR 0x01100
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 9f9e60736eba..ea0009064bbc 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -522,10 +522,6 @@ struct mm_struct {
#ifdef CONFIG_HUGETLB_PAGE
atomic_long_t hugetlb_usage;
#endif
-#ifdef CONFIG_MSM_APP_SETTINGS
- int app_setting;
-#endif
-
};
static inline void mm_init_cpumask(struct mm_struct *mm)
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 0afc11f8f300..b2c1ea2a4739 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -342,22 +342,26 @@ struct earlycon_device {
struct earlycon_id {
char name[16];
+ char compatible[128];
int (*setup)(struct earlycon_device *, const char *options);
} __aligned(32);
+extern const struct earlycon_id __earlycon_table[];
+extern const struct earlycon_id __earlycon_table_end[];
+
+#define OF_EARLYCON_DECLARE(_name, compat, fn) \
+ static const struct earlycon_id __UNIQUE_ID(__earlycon_##_name) \
+ __used __section(__earlycon_table) \
+ = { .name = __stringify(_name), \
+ .compatible = compat, \
+ .setup = fn }
+
+#define EARLYCON_DECLARE(_name, fn) OF_EARLYCON_DECLARE(_name, "", fn)
+
extern int setup_earlycon(char *buf);
extern int of_setup_earlycon(unsigned long addr,
int (*setup)(struct earlycon_device *, const char *));
-#define EARLYCON_DECLARE(_name, func) \
- static const struct earlycon_id __earlycon_##_name \
- __used __section(__earlycon_table) \
- = { .name = __stringify(_name), \
- .setup = func }
-
-#define OF_EARLYCON_DECLARE(name, compat, fn) \
- _OF_DECLARE(earlycon, name, compat, fn, void *)
-
struct uart_port *uart_get_console(struct uart_port *ports, int nr,
struct console *c);
int uart_parse_earlycon(char *p, unsigned char *iotype, unsigned long *addr,
diff --git a/include/soc/qcom/service-locator.h b/include/soc/qcom/service-locator.h
index 6bf8ac0be15f..7fa25b90fc12 100644
--- a/include/soc/qcom/service-locator.h
+++ b/include/soc/qcom/service-locator.h
@@ -80,7 +80,7 @@ int find_subsys(const char *pd_path, char *subsys);
#else
static inline int get_service_location(char *client_name,
- char *service_name, struct notifier_block *locator_nb);
+ char *service_name, struct notifier_block *locator_nb)
{
return -ENODEV;
}
diff --git a/include/soc/qcom/service-notifier.h b/include/soc/qcom/service-notifier.h
index be3f134eebe3..90fceba091b9 100644
--- a/include/soc/qcom/service-notifier.h
+++ b/include/soc/qcom/service-notifier.h
@@ -53,7 +53,7 @@ static void *service_notif_register_notifier(const char *service_path,
int instance_id, struct notifier_block *nb,
int *curr_state)
{
- return -ENODEV;
+ return PTR_ERR(-ENODEV);
}
static int service_notif_unregister_notifier(void *service_notif_handle,
diff --git a/include/uapi/linux/msm_kgsl.h b/include/uapi/linux/msm_kgsl.h
index a80278954a77..aac11dbe5984 100644
--- a/include/uapi/linux/msm_kgsl.h
+++ b/include/uapi/linux/msm_kgsl.h
@@ -121,6 +121,11 @@
#define KGSL_MEMFLAGS_GPUWRITEONLY 0x02000000U
#define KGSL_MEMFLAGS_FORCE_32BIT 0x100000000ULL
+/* Flag for binding all the virt range to single phys data */
+#define KGSL_SPARSE_BIND_MULTIPLE_TO_PHYS 0x400000000ULL
+#define KGSL_SPARSE_BIND 0x1ULL
+#define KGSL_SPARSE_UNBIND 0x2ULL
+
/* Memory caching hints */
#define KGSL_CACHEMODE_MASK 0x0C000000U
#define KGSL_CACHEMODE_SHIFT 26
@@ -131,6 +136,8 @@
#define KGSL_CACHEMODE_WRITEBACK 3
#define KGSL_MEMFLAGS_USE_CPU_MAP 0x10000000ULL
+#define KGSL_MEMFLAGS_SPARSE_PHYS 0x20000000ULL
+#define KGSL_MEMFLAGS_SPARSE_VIRT 0x40000000ULL
/* Memory types for which allocations are made */
#define KGSL_MEMTYPE_MASK 0x0000FF00
@@ -1457,4 +1464,96 @@ struct kgsl_gpuobj_set_info {
#define IOCTL_KGSL_GPUOBJ_SET_INFO \
_IOW(KGSL_IOC_TYPE, 0x4C, struct kgsl_gpuobj_set_info)
+/**
+ * struct kgsl_sparse_phys_alloc - Argument for IOCTL_KGSL_SPARSE_PHYS_ALLOC
+ * @size: Size in bytes to back
+ * @pagesize: Pagesize alignment required
+ * @flags: Flags for this allocation
+ * @id: Returned ID for this allocation
+ */
+struct kgsl_sparse_phys_alloc {
+ uint64_t size;
+ uint64_t pagesize;
+ uint64_t flags;
+ unsigned int id;
+};
+
+#define IOCTL_KGSL_SPARSE_PHYS_ALLOC \
+ _IOWR(KGSL_IOC_TYPE, 0x50, struct kgsl_sparse_phys_alloc)
+
+/**
+ * struct kgsl_sparse_phys_free - Argument for IOCTL_KGSL_SPARSE_PHYS_FREE
+ * @id: ID to free
+ */
+struct kgsl_sparse_phys_free {
+ unsigned int id;
+};
+
+#define IOCTL_KGSL_SPARSE_PHYS_FREE \
+ _IOW(KGSL_IOC_TYPE, 0x51, struct kgsl_sparse_phys_free)
+
+/**
+ * struct kgsl_sparse_virt_alloc - Argument for IOCTL_KGSL_SPARSE_VIRT_ALLOC
+ * @size: Size in bytes to reserve
+ * @pagesize: Pagesize alignment required
+ * @flags: Flags for this allocation
+ * @id: Returned ID for this allocation
+ * @gpuaddr: Returned GPU address for this allocation
+ */
+struct kgsl_sparse_virt_alloc {
+ uint64_t size;
+ uint64_t pagesize;
+ uint64_t flags;
+ uint64_t gpuaddr;
+ unsigned int id;
+};
+
+#define IOCTL_KGSL_SPARSE_VIRT_ALLOC \
+ _IOWR(KGSL_IOC_TYPE, 0x52, struct kgsl_sparse_virt_alloc)
+
+/**
+ * struct kgsl_sparse_virt_free - Argument for IOCTL_KGSL_SPARSE_VIRT_FREE
+ * @id: ID to free
+ */
+struct kgsl_sparse_virt_free {
+ unsigned int id;
+};
+
+#define IOCTL_KGSL_SPARSE_VIRT_FREE \
+ _IOW(KGSL_IOC_TYPE, 0x53, struct kgsl_sparse_virt_free)
+
+/**
+ * struct kgsl_sparse_binding_object - Argument for kgsl_sparse_bind
+ * @virtoffset: Offset into the virtual ID
+ * @physoffset: Offset into the physical ID (bind only)
+ * @size: Size in bytes to reserve
+ * @flags: Flags for this kgsl_sparse_binding_object
+ * @id: Physical ID to bind (bind only)
+ */
+struct kgsl_sparse_binding_object {
+ uint64_t virtoffset;
+ uint64_t physoffset;
+ uint64_t size;
+ uint64_t flags;
+ unsigned int id;
+};
+
+/**
+ * struct kgsl_sparse_bind - Argument for IOCTL_KGSL_SPARSE_BIND
+ * @list: List of kgsl_sparse_bind_objects to bind/unbind
+ * @id: Virtual ID to bind/unbind
+ * @size: Size of kgsl_sparse_bind_object
+ * @count: Number of elements in list
+ *
+ */
+struct kgsl_sparse_bind {
+ uint64_t __user list;
+ unsigned int id;
+ unsigned int size;
+ unsigned int count;
+};
+
+#define IOCTL_KGSL_SPARSE_BIND \
+ _IOW(KGSL_IOC_TYPE, 0x54, struct kgsl_sparse_bind)
+
#endif /* _UAPI_MSM_KGSL_H */
diff --git a/include/uapi/media/msm_cam_sensor.h b/include/uapi/media/msm_cam_sensor.h
index 5d340b9a2523..540a96c57e5b 100644
--- a/include/uapi/media/msm_cam_sensor.h
+++ b/include/uapi/media/msm_cam_sensor.h
@@ -35,6 +35,7 @@
#define MAX_REGULATOR 5
#define MSM_V4L2_PIX_FMT_META v4l2_fourcc('M', 'E', 'T', 'A') /* META */
+#define MSM_V4L2_PIX_FMT_META10 v4l2_fourcc('M', 'E', '1', '0') /* META10 */
#define MSM_V4L2_PIX_FMT_SBGGR14 v4l2_fourcc('B', 'G', '1', '4')
/* 14 BGBG.. GRGR.. */
#define MSM_V4L2_PIX_FMT_SGBRG14 v4l2_fourcc('G', 'B', '1', '4')
diff --git a/include/uapi/media/msmb_isp.h b/include/uapi/media/msmb_isp.h
index 93613855228e..9f933dc7e84f 100644
--- a/include/uapi/media/msmb_isp.h
+++ b/include/uapi/media/msmb_isp.h
@@ -802,6 +802,7 @@ struct msm_isp_ahb_clk_cfg {
#define V4L2_PIX_FMT_NV14 v4l2_fourcc('N', 'V', '1', '4')
#define V4L2_PIX_FMT_NV41 v4l2_fourcc('N', 'V', '4', '1')
#define V4L2_PIX_FMT_META v4l2_fourcc('Q', 'M', 'E', 'T')
+#define V4L2_PIX_FMT_META10 v4l2_fourcc('Q', 'M', '1', '0')
#define V4L2_PIX_FMT_SBGGR14 v4l2_fourcc('B', 'G', '1', '4') /* 14 BGBG.GRGR.*/
#define V4L2_PIX_FMT_SGBRG14 v4l2_fourcc('G', 'B', '1', '4') /* 14 GBGB.RGRG.*/
#define V4L2_PIX_FMT_SGRBG14 v4l2_fourcc('B', 'A', '1', '4') /* 14 GRGR.BGBG.*/
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 96100cc046c5..32e2617d654f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -158,6 +158,7 @@ enum event_type_t {
struct static_key_deferred perf_sched_events __read_mostly;
static DEFINE_PER_CPU(atomic_t, perf_cgroup_events);
static DEFINE_PER_CPU(int, perf_sched_cb_usages);
+static DEFINE_PER_CPU(bool, is_idle);
static atomic_t nr_mmap_events __read_mostly;
static atomic_t nr_comm_events __read_mostly;
@@ -3388,9 +3389,12 @@ static int perf_event_read(struct perf_event *event, bool group)
.group = group,
.ret = 0,
};
- smp_call_function_single(event->oncpu,
- __perf_event_read, &data, 1);
- ret = data.ret;
+ if (!event->attr.exclude_idle ||
+ !per_cpu(is_idle, event->oncpu)) {
+ smp_call_function_single(event->oncpu,
+ __perf_event_read, &data, 1);
+ ret = data.ret;
+ }
} else if (event->state == PERF_EVENT_STATE_INACTIVE) {
struct perf_event_context *ctx = event->ctx;
unsigned long flags;
@@ -9479,6 +9483,25 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu)
return NOTIFY_OK;
}
+static int event_idle_notif(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ switch (action) {
+ case IDLE_START:
+ __this_cpu_write(is_idle, true);
+ break;
+ case IDLE_END:
+ __this_cpu_write(is_idle, false);
+ break;
+ }
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block perf_event_idle_nb = {
+ .notifier_call = event_idle_notif,
+};
+
void __init perf_event_init(void)
{
int ret;
@@ -9492,6 +9515,7 @@ void __init perf_event_init(void)
perf_pmu_register(&perf_task_clock, NULL, -1);
perf_tp_register();
perf_cpu_notifier(perf_cpu_notify);
+ idle_notifier_register(&perf_event_idle_nb);
register_reboot_notifier(&perf_reboot_notifier);
ret = init_hw_breakpoint();
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 58303b3dc356..db0472b37feb 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -85,9 +85,6 @@
#ifdef CONFIG_PARAVIRT
#include <asm/paravirt.h>
#endif
-#ifdef CONFIG_MSM_APP_SETTINGS
-#include <asm/app_api.h>
-#endif
#include "sched.h"
#include "../workqueue_internal.h"
@@ -5895,11 +5892,6 @@ prepare_task_switch(struct rq *rq, struct task_struct *prev,
fire_sched_out_preempt_notifiers(prev, next);
prepare_lock_switch(rq, next);
prepare_arch_switch(next);
-
-#ifdef CONFIG_MSM_APP_SETTINGS
- if (use_app_setting)
- switch_app_setting_bit(prev, next);
-#endif
}
/**
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index 958d79e1933c..584cd048c24b 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -4096,7 +4096,8 @@ static inline int migration_needed(struct task_struct *p, int cpu)
int nice;
struct related_thread_group *grp;
- if (!sched_enable_hmp || p->state != TASK_RUNNING)
+ if (!sched_enable_hmp || p->state != TASK_RUNNING ||
+ p->nr_cpus_allowed == 1)
return 0;
/* No need to migrate task that is about to be throttled */
diff --git a/mm/mmap.c b/mm/mmap.c
index 8b0a0ed2c466..6c561acdca92 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -48,10 +48,6 @@
#include <asm/tlb.h>
#include <asm/mmu_context.h>
-#ifdef CONFIG_MSM_APP_SETTINGS
-#include <asm/app_api.h>
-#endif
-
#include "internal.h"
#ifndef arch_mmap_check
@@ -1301,11 +1297,6 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
if (!len)
return -EINVAL;
-#ifdef CONFIG_MSM_APP_SETTINGS
- if (use_app_setting)
- apply_app_setting_bit(file);
-#endif
-
/*
* Does the application expect PROT_READ to imply PROT_EXEC?
*
diff --git a/sound/soc/codecs/wcd9330.c b/sound/soc/codecs/wcd9330.c
index 16a23aa9770c..a8d6e0fa4732 100644
--- a/sound/soc/codecs/wcd9330.c
+++ b/sound/soc/codecs/wcd9330.c
@@ -8956,8 +8956,11 @@ static int tomtom_codec_probe(struct snd_soc_codec *codec)
err_pdata:
kfree(ptr);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
err_hwdep:
kfree(tomtom->fw_data);
+ tomtom->fw_data = NULL;
err_nomem_slimch:
devm_kfree(codec->dev, tomtom);
return ret;
@@ -8965,12 +8968,17 @@ err_nomem_slimch:
static int tomtom_codec_remove(struct snd_soc_codec *codec)
{
struct tomtom_priv *tomtom = snd_soc_codec_get_drvdata(codec);
+ struct wcd9xxx *control;
WCD9XXX_BG_CLK_LOCK(&tomtom->resmgr);
atomic_set(&kp_tomtom_priv, 0);
WCD9XXX_BG_CLK_UNLOCK(&tomtom->resmgr);
+ control = dev_get_drvdata(codec->dev->parent);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
+
if (tomtom->wcd_ext_clk)
clk_put(tomtom->wcd_ext_clk);
tomtom_cleanup_irqs(tomtom);
diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c
index e922a5a0e262..5a52b25764a4 100644
--- a/sound/soc/codecs/wcd9335.c
+++ b/sound/soc/codecs/wcd9335.c
@@ -13357,8 +13357,11 @@ static int tasha_codec_probe(struct snd_soc_codec *codec)
err_pdata:
devm_kfree(codec->dev, ptr);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
err_hwdep:
devm_kfree(codec->dev, tasha->fw_data);
+ tasha->fw_data = NULL;
err:
return ret;
}
@@ -13366,6 +13369,11 @@ err:
static int tasha_codec_remove(struct snd_soc_codec *codec)
{
struct tasha_priv *tasha = snd_soc_codec_get_drvdata(codec);
+ struct wcd9xxx *control;
+
+ control = dev_get_drvdata(codec->dev->parent);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
tasha_cleanup_irqs(tasha);
/* Cleanup MBHC */
diff --git a/sound/soc/codecs/wcd934x/wcd934x.c b/sound/soc/codecs/wcd934x/wcd934x.c
index af3bbafeefe7..8c2387dc194b 100644
--- a/sound/soc/codecs/wcd934x/wcd934x.c
+++ b/sound/soc/codecs/wcd934x/wcd934x.c
@@ -5556,6 +5556,8 @@ static int tavil_soc_codec_probe(struct snd_soc_codec *codec)
err_pdata:
devm_kfree(codec->dev, ptr);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
err:
return ret;
}
@@ -5567,6 +5569,8 @@ static int tavil_soc_codec_remove(struct snd_soc_codec *codec)
control = dev_get_drvdata(codec->dev->parent);
devm_kfree(codec->dev, control->rx_chs);
+ control->rx_chs = NULL;
+ control->tx_chs = NULL;
tavil_cleanup_irqs(tavil);
return 0;
diff --git a/sound/soc/msm/msm-audio-pinctrl.c b/sound/soc/msm/msm-audio-pinctrl.c
index d30b0c40f993..2b30271500eb 100644
--- a/sound/soc/msm/msm-audio-pinctrl.c
+++ b/sound/soc/msm/msm-audio-pinctrl.c
@@ -1,4 +1,4 @@
- /* Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ /* Copyright (c) 2015-2016, 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
@@ -200,28 +200,40 @@ int msm_gpioset_initialize(enum pinctrl_client client,
err:
/* Free up memory allocated for gpio set combinations */
for (i = 0; i < gpioset_info[client].gpiosets_max; i++) {
- if (NULL != gpioset_info[client].gpiosets[i])
+ if (gpioset_info[client].gpiosets[i] != NULL) {
devm_kfree(dev, gpioset_info[client].gpiosets[i]);
+ gpioset_info[client].gpiosets[i] = NULL;
+ }
}
- if (NULL != gpioset_info[client].gpiosets)
+ if (gpioset_info[client].gpiosets != NULL) {
devm_kfree(dev, gpioset_info[client].gpiosets);
+ gpioset_info[client].gpiosets = NULL;
+ }
/* Free up memory allocated for gpio set combinations */
for (i = 0; i < gpioset_info[client].gpiosets_comb_max; i++) {
- if (NULL != gpioset_info[client].gpiosets_comb_names[i])
+ if (gpioset_info[client].gpiosets_comb_names[i] != NULL) {
devm_kfree(dev,
gpioset_info[client].gpiosets_comb_names[i]);
+ gpioset_info[client].gpiosets_comb_names[i] = NULL;
+ }
}
- if (NULL != gpioset_info[client].gpiosets_comb_names)
+ if (gpioset_info[client].gpiosets_comb_names != NULL) {
devm_kfree(dev, gpioset_info[client].gpiosets_comb_names);
+ gpioset_info[client].gpiosets_comb_names = NULL;
+ }
/* Free up memory allocated for handles to pinctrl states */
- if (NULL != pinctrl_info[client].cdc_lines)
+ if (pinctrl_info[client].cdc_lines != NULL) {
devm_kfree(dev, pinctrl_info[client].cdc_lines);
+ pinctrl_info[client].cdc_lines = NULL;
+ }
/* Free up memory allocated for counter of gpio sets */
- if (NULL != gpioset_info[client].gpioset_state)
+ if (gpioset_info[client].gpioset_state != NULL) {
devm_kfree(dev, gpioset_info[client].gpioset_state);
+ gpioset_info[client].gpioset_state = NULL;
+ }
success:
return ret;
diff --git a/sound/soc/msm/msmcobalt.c b/sound/soc/msm/msmcobalt.c
index 8ee14eff2d98..4d2347aabb25 100644
--- a/sound/soc/msm/msmcobalt.c
+++ b/sound/soc/msm/msmcobalt.c
@@ -2042,32 +2042,6 @@ static struct snd_soc_ops msm_wcn_ops = {
.hw_params = msm_wcn_hw_params,
};
-static int msm_get_ll_qos_val(struct snd_pcm_runtime *runtime)
-{
- int usecs;
-
- /* take 10% of period time as the deadline */
- usecs = (100000 / runtime->rate) * runtime->period_size;
- usecs += ((100000 % runtime->rate) * runtime->period_size) /
- runtime->rate;
-
- return usecs;
-}
-
-static int msm_mm5_prepare(struct snd_pcm_substream *substream)
-{
- if (pm_qos_request_active(&substream->latency_pm_qos_req))
- pm_qos_remove_request(&substream->latency_pm_qos_req);
- pm_qos_add_request(&substream->latency_pm_qos_req,
- PM_QOS_CPU_DMA_LATENCY,
- msm_get_ll_qos_val(substream->runtime));
- return 0;
-}
-
-static struct snd_soc_ops msm_mm5_ops = {
- .prepare = msm_mm5_prepare,
-};
-
/* Digital audio interface glue - connects codec <---> CPU */
static struct snd_soc_dai_link msm_common_dai_links[] = {
/* FrontEnd DAI Links */
@@ -2300,7 +2274,6 @@ static struct snd_soc_dai_link msm_common_dai_links[] = {
/* this dainlink has playback support */
.ignore_pmdown_time = 1,
.be_id = MSM_FRONTEND_DAI_MULTIMEDIA5,
- .ops = &msm_mm5_ops,
},
{
.name = "Listen 1 Audio Service",