Merge "msm: acpuclock-8930{aa}: Lower VDD_DIG voltage vote for L2 at 384MHz"
diff --git a/Documentation/devicetree/bindings/arm/msm/ipc-spinlock.txt b/Documentation/devicetree/bindings/arm/msm/ipc-spinlock.txt
new file mode 100644
index 0000000..c71b190
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/ipc-spinlock.txt
@@ -0,0 +1,14 @@
+Qualcomm Interprocessor Communication Spinlock
+
+Required properties:
+- compatible : should be "qcom,ipc-spinlock"
+- reg : the location and size of the spinlock hardware
+- qcom,num-locks : the number of locks supported
+
+Example:
+
+ qcom,ipc-spinlock@fd484000 {
+ compatible = "qcom,ipc-spinlock";
+ reg = <0xfd484000 0x1000>;
+ qcom,num-locks = <32>;
+ };
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_iommu_domains.txt b/Documentation/devicetree/bindings/arm/msm/msm_iommu_domains.txt
new file mode 100644
index 0000000..7d69749
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/msm_iommu_domains.txt
@@ -0,0 +1,50 @@
+IOMMU Domains
+
+An IOMMU domain is a collection of IOMMU context banks and an optional
+virtual address space that is to be used with the domain. Domains that are
+defined will be created at bootup and associated with an iommu group. Clients
+can then refer to the iommu group and perform operations on the iommu group
+instead of individual devices/contexts.
+
+Required properties
+
+- compatible: "qcom,iommu-domains"
+
+- At least one child that defines a domain is required with the
+ following properties:
+
+ - label: Name of the domain
+ - qcom,iommu-contexts: List of phandles to context that belongs to
+ this domain.
+
+ Optional properties
+
+ - qcom,virtual-addr-pool: List of <start_address size> pairs
+ that define the virtual address space for this domain.
+ - qcom,secure-domain: boolean indicating that this is a secure
+ domain that is to be programmed by Trustzone.
+ - qcom,l2-redirect: boolean indicating that page tables should
+ be cached in L2 cache.
+Example:
+ qcom,iommu-domains {
+ compatible = "qcom,iommu-domains";
+
+ qcom,iommu-domain1 {
+ label = "lpass_secure";
+ qcom,iommu-contexts = <&lpass_q6_fw>;
+ qcom,virtual-addr-pool = <0x00000000 0x0FFFFFFF
+ 0xF0000000 0x0FFFFFFF>;
+ };
+
+ qcom,iommu-domain2 {
+ label = "lpass_audio";
+ qcom,iommu-contexts = <&lpass_audio_shared>;
+ qcom,virtual-addr-pool = <0x10000000 0x0FFFFFFF>;
+ };
+
+ qcom,iommu-domain3 {
+ label = "lpass_video";
+ qcom,iommu-contexts = <&lpass_video_shared>;
+ qcom,virtual-addr-pool = <0x20000000 0x0FFFFFFF>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/gpio/gpio-msm.txt b/Documentation/devicetree/bindings/gpio/gpio-msm.txt
index a5d50fd..1f88037 100644
--- a/Documentation/devicetree/bindings/gpio/gpio-msm.txt
+++ b/Documentation/devicetree/bindings/gpio/gpio-msm.txt
@@ -10,6 +10,9 @@
- #interrupt-cells : Should be 2.
- interrupt-controller: Mark the device node as an interrupt controller
- interrupts : Specify the TLMM summary interrupt number
+- ngpio : Specify the number of MSM GPIOs
+- qcom,direct-connect-irqs : Specifies the number of GPIOs that can be used as
+ direct connect interrupts
Example:
@@ -21,6 +24,8 @@
#interrupt-cells = <2>;
reg = <0xfd510000 0x4000>;
interrupts = <0 208 0>;
+ ngpio = <150>;
+ qcom,direct-connect-irqs = <8>;
};
To specify gpios for a device:
diff --git a/Documentation/devicetree/bindings/usb/msm-ssusb.txt b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
index d686523..5d10940 100644
--- a/Documentation/devicetree/bindings/usb/msm-ssusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-ssusb.txt
@@ -40,6 +40,8 @@
otherwise depend on PHY.
- qcom,charging-disabled: If present then battery charging using USB
is disabled.
+- qcom,dwc-hsphy-init: This property if present represents phy init
+ value to be used for overriding HSPHY parameters.
Example MSM USB3.0 controller device node :
usb@f9200000 {
@@ -56,6 +58,7 @@
vbus_dwc3-supply = <&pm8941_mvs1>;
qcom,dwc-usb3-msm-dbm-eps = <4>
qcom,vdd-voltage-level = <1 5 7>;
+ qcom,dwc-hsphy-init = <0x00D195A4>;
qcom,msm_bus,name = "usb3";
qcom,msm_bus,num_cases = <2>;
diff --git a/arch/arm/boot/dts/mpq8092.dtsi b/arch/arm/boot/dts/mpq8092.dtsi
index 0ab0a0c..339faa9 100644
--- a/arch/arm/boot/dts/mpq8092.dtsi
+++ b/arch/arm/boot/dts/mpq8092.dtsi
@@ -35,7 +35,9 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0xfd510000 0x4000>;
+ ngpio = <146>;
interrupts = <0 208 0>;
+ qcom,direct-connect-irqs = <8>;
};
timer {
diff --git a/arch/arm/boot/dts/msm-iommu-v1.dtsi b/arch/arm/boot/dts/msm-iommu-v1.dtsi
index 5a08f51..ea4fa75 100644
--- a/arch/arm/boot/dts/msm-iommu-v1.dtsi
+++ b/arch/arm/boot/dts/msm-iommu-v1.dtsi
@@ -21,28 +21,28 @@
label = "lpass_iommu";
status = "disabled";
- qcom,iommu-ctx@fd000000 {
+ lpass_q6_fw: qcom,iommu-ctx@fd000000 {
reg = <0xfd000000 0x1000>;
interrupts = <0 250 0>;
qcom,iommu-ctx-mids = <0 15>;
label = "q6_fw";
};
- qcom,iommu-ctx@fd001000 {
+ lpass_audio_shared: qcom,iommu-ctx@fd001000 {
reg = <0xfd001000 0x1000>;
interrupts = <0 250 0>;
qcom,iommu-ctx-mids = <1>;
label = "audio_shared";
};
- qcom,iommu-ctx@fd002000 {
+ lpass_video_shared: qcom,iommu-ctx@fd002000 {
reg = <0xfd002000 0x1000>;
interrupts = <0 250 0>;
qcom,iommu-ctx-mids = <2>;
label = "video_shared";
};
- qcom,iommu-ctx@fd003000 {
+ lpass_q6_spare: qcom,iommu-ctx@fd003000 {
reg = <0xfd003000 0x1000>;
interrupts = <0 250 0>;
qcom,iommu-ctx-mids = <3 4 5 6 7 8 9 10 11 12 13 14>;
diff --git a/arch/arm/boot/dts/msm8226.dtsi b/arch/arm/boot/dts/msm8226.dtsi
index 3c8ea84..bba15a3 100644
--- a/arch/arm/boot/dts/msm8226.dtsi
+++ b/arch/arm/boot/dts/msm8226.dtsi
@@ -34,7 +34,9 @@
reg = <0xfd510000 0x4000>;
gpio-controller;
#gpio-cells = <2>;
+ ngpio = <117>;
interrupts = <0 208 0>;
+ qcom,direct-connect-irqs = <8>;
};
timer {
diff --git a/arch/arm/boot/dts/msm8910-iommu-domains.dtsi b/arch/arm/boot/dts/msm8910-iommu-domains.dtsi
new file mode 100644
index 0000000..dbdbd5f
--- /dev/null
+++ b/arch/arm/boot/dts/msm8910-iommu-domains.dtsi
@@ -0,0 +1,36 @@
+/* Copyright (c) 2012, 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.
+ */
+
+/ {
+ qcom,iommu-domains {
+ compatible = "qcom,iommu-domains";
+
+ qcom,iommu-domain1 {
+ label = "lpass_secure";
+ qcom,iommu-contexts = <&lpass_q6_fw>;
+ qcom,virtual-addr-pool = <0x00000000 0x0FFFFFFF
+ 0xF0000000 0x0FFFFFFF>;
+ };
+
+ qcom,iommu-domain2 {
+ label = "lpass_audio";
+ qcom,iommu-contexts = <&lpass_audio_shared>;
+ qcom,virtual-addr-pool = <0x10000000 0x0FFFFFFF>;
+ };
+
+ qcom,iommu-domain3 {
+ label = "lpass_video";
+ qcom,iommu-contexts = <&lpass_video_shared>;
+ qcom,virtual-addr-pool = <0x20000000 0x0FFFFFFF>;
+ };
+ };
+};
diff --git a/arch/arm/boot/dts/msm8910.dtsi b/arch/arm/boot/dts/msm8910.dtsi
index 61f1dcd..a08c165 100644
--- a/arch/arm/boot/dts/msm8910.dtsi
+++ b/arch/arm/boot/dts/msm8910.dtsi
@@ -35,7 +35,9 @@
reg = <0xfd510000 0x4000>;
gpio-controller;
#gpio-cells = <2>;
+ ngpio = <102>;
interrupts = <0 208 0>;
+ qcom,direct-connect-irqs = <8>;
};
timer {
@@ -340,5 +342,7 @@
status = "ok";
};
+/include/ "msm8910-iommu-domains.dtsi"
+
/include/ "msm8910-regulator.dtsi"
/include/ "msm-pm8110.dtsi"
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index bd0711c..6a9a071 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -40,7 +40,9 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0xfd510000 0x4000>;
+ ngpio = <146>;
interrupts = <0 208 0>;
+ qcom,direct-connect-irqs = <8>;
};
wcd9xxx_intc: wcd9xxx-irq {
diff --git a/arch/arm/boot/dts/msm9625.dtsi b/arch/arm/boot/dts/msm9625.dtsi
index bf66de6..75a0ae5 100644
--- a/arch/arm/boot/dts/msm9625.dtsi
+++ b/arch/arm/boot/dts/msm9625.dtsi
@@ -42,7 +42,9 @@
interrupt-controller;
#interrupt-cells = <2>;
reg = <0xfd510000 0x4000>;
+ ngpio = <76>;
interrupts = <0 208 0>;
+ qcom,direct-connect-irqs = <8>;
};
timer: msm-qtimer@f9021000 {
diff --git a/arch/arm/configs/msm8910_defconfig b/arch/arm/configs/msm8910_defconfig
index 67fabd4..bf163e0 100644
--- a/arch/arm/configs/msm8910_defconfig
+++ b/arch/arm/configs/msm8910_defconfig
@@ -157,7 +157,6 @@
CONFIG_DEBUG_FS=y
CONFIG_SCHEDSTATS=y
CONFIG_TIMER_STATS=y
-# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_INFO=y
CONFIG_DEBUG_MEMORY_INIT=y
CONFIG_DYNAMIC_DEBUG=y
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 1aaf7ea..b78acc1 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -246,7 +246,6 @@
CONFIG_RFKILL=y
CONFIG_GENLOCK=y
CONFIG_GENLOCK_MISCDEVICE=y
-CONFIG_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_TSPP=m
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 94d12e0..c88539b 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -251,7 +251,6 @@
CONFIG_RFKILL=y
CONFIG_GENLOCK=y
CONFIG_GENLOCK_MISCDEVICE=y
-CONFIG_CMA=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_BLK_DEV_RAM=y
CONFIG_TSPP=m
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 8debb93..17fe60a 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -388,7 +388,6 @@
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_MSM_SSBI=y
CONFIG_SPS=y
CONFIG_USB_BAM=y
CONFIG_SPS_SUPPORT_BAMDMA=y
@@ -429,3 +428,5 @@
CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 0f8c469..6bafdad 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -389,7 +389,6 @@
CONFIG_ANDROID_RAM_CONSOLE=y
CONFIG_ANDROID_TIMED_GPIO=y
CONFIG_ANDROID_LOW_MEMORY_KILLER=y
-CONFIG_MSM_SSBI=y
CONFIG_SPS=y
CONFIG_USB_BAM=y
CONFIG_SPS_SUPPORT_BAMDMA=y
@@ -419,7 +418,6 @@
CONFIG_TIMER_STATS=y
CONFIG_DEBUG_KMEMLEAK=y
CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
-# CONFIG_DEBUG_PREEMPT is not set
CONFIG_DEBUG_SPINLOCK=y
CONFIG_DEBUG_MUTEXES=y
CONFIG_DEBUG_ATOMIC_SLEEP=y
@@ -444,3 +442,5 @@
CONFIG_CRYPTO_DEV_QCE=m
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
+CONFIG_SYNC=y
+CONFIG_SW_SYNC=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index cbdcc5b..0b003fd 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -88,7 +88,13 @@
CONFIG_NF_CONNTRACK=y
CONFIG_NF_CONNTRACK_EVENTS=y
CONFIG_NF_CONNTRACK_TIMESTAMP=y
+CONFIG_NF_CT_PROTO_UDPLITE=y
+CONFIG_NF_CONNTRACK_AMANDA=y
CONFIG_NF_CONNTRACK_FTP=y
+CONFIG_NF_CONNTRACK_H323=y
+CONFIG_NF_CONNTRACK_IRC=y
+CONFIG_NF_CONNTRACK_NETBIOS_NS=y
+CONFIG_NF_CONNTRACK_SNMP=y
CONFIG_NF_CONNTRACK_PPTP=y
CONFIG_NF_CONNTRACK_SIP=y
CONFIG_NF_CONNTRACK_TFTP=y
@@ -97,6 +103,8 @@
CONFIG_NETFILTER_XT_MATCH_ADDRTYPE=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNTRACK=y
+CONFIG_NETFILTER_XT_MATCH_DSCP=y
+CONFIG_NETFILTER_XT_MATCH_ESP=y
CONFIG_NETFILTER_XT_MATCH_IPRANGE=y
CONFIG_NETFILTER_XT_MATCH_MULTIPORT=y
CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
@@ -262,3 +270,32 @@
CONFIG_CRYPTO_DEV_QCEDEV=m
CONFIG_CRC_CCITT=y
CONFIG_LIBCRC32C=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+CONFIG_USB_SUSPEND=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_EHSET=y
+CONFIG_USB_EHCI_MSM=y
+CONFIG_USB_STORAGE=y
+CONFIG_USB_STORAGE_DEBUG=y
+CONFIG_USB_STORAGE_DATAFAB=y
+CONFIG_USB_STORAGE_FREECOM=y
+CONFIG_USB_STORAGE_ISD200=y
+CONFIG_USB_STORAGE_USBAT=y
+CONFIG_USB_STORAGE_SDDR09=y
+CONFIG_USB_STORAGE_SDDR55=y
+CONFIG_USB_STORAGE_JUMPSHOT=y
+CONFIG_USB_STORAGE_ALAUDA=y
+CONFIG_USB_STORAGE_ONETOUCH=y
+CONFIG_USB_STORAGE_KARMA=y
+CONFIG_USB_STORAGE_CYPRESS_ATACB=y
+CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_SCSI=y
+CONFIG_SCSI_TGT=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_CHR_DEV_SCH=y
+CONFIG_SCSI_MULTI_LUN=y
+CONFIG_SCSI_CONSTANTS=y
+CONFIG_SCSI_LOGGING=y
+CONFIG_SCSI_SCAN_ASYNC=y
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index d5fa3a7..f782dfe 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -298,7 +298,6 @@
.reusable = FMEM_ENABLED,
.mem_is_fmem = FMEM_ENABLED,
.fixed_position = FIXED_MIDDLE,
- .is_cma = 1,
.no_nonsecure_alloc = 1,
};
diff --git a/arch/arm/mach-msm/board-8092-gpiomux.c b/arch/arm/mach-msm/board-8092-gpiomux.c
index 823ef70..7cefe8a 100644
--- a/arch/arm/mach-msm/board-8092-gpiomux.c
+++ b/arch/arm/mach-msm/board-8092-gpiomux.c
@@ -43,9 +43,9 @@
{
int rc;
- rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ rc = msm_gpiomux_init_dt();
if (rc) {
- pr_err(KERN_ERR "mpq8092_init_gpiomux failed %d\n", rc);
+ pr_err("%s failed %d\n", __func__, rc);
return;
}
diff --git a/arch/arm/mach-msm/board-8226-gpiomux.c b/arch/arm/mach-msm/board-8226-gpiomux.c
index eb88ef4..2b5399f 100644
--- a/arch/arm/mach-msm/board-8226-gpiomux.c
+++ b/arch/arm/mach-msm/board-8226-gpiomux.c
@@ -21,9 +21,9 @@
{
int rc;
- rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ rc = msm_gpiomux_init_dt();
if (rc) {
- pr_err(KERN_ERR "msm_8226_init_gpiomux failed %d\n", rc);
+ pr_err("%s failed %d\n", __func__, rc);
return;
}
}
diff --git a/arch/arm/mach-msm/board-8910-gpiomux.c b/arch/arm/mach-msm/board-8910-gpiomux.c
index a67f916..a295a17 100644
--- a/arch/arm/mach-msm/board-8910-gpiomux.c
+++ b/arch/arm/mach-msm/board-8910-gpiomux.c
@@ -21,9 +21,9 @@
{
int rc;
- rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ rc = msm_gpiomux_init_dt();
if (rc) {
- pr_err(KERN_ERR "msm_8910_init_gpiomux failed %d\n", rc);
+ pr_err("%s failed %d\n", __func__, rc);
return;
}
}
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 1a953da..3785fb2 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -343,7 +343,6 @@
.reusable = FMEM_ENABLED,
.mem_is_fmem = FMEM_ENABLED,
.fixed_position = FIXED_MIDDLE,
- .is_cma = 1,
.no_nonsecure_alloc = 1,
};
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 9b19810..f64bf18 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -366,7 +366,6 @@
.fixed_position = FIXED_MIDDLE,
.iommu_map_all = 1,
.iommu_2x_map_domain = VIDEO_DOMAIN,
- .is_cma = 1,
.no_nonsecure_alloc = 1,
};
@@ -3002,6 +3001,9 @@
kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
/* 8960PRO nominal clock rate is 320Mhz */
kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 320000000;
+#ifdef CONFIG_MSM_BUS_SCALING
+ kgsl_3d0_pdata->bus_scale_table = &grp3d_bus_scale_pdata_ab;
+#endif
/*
* If this an A320 GPU device (MSM8960AB), then
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 4bd100d..fdad2e5 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -862,9 +862,9 @@
{
int rc;
- rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ rc = msm_gpiomux_init_dt();
if (rc) {
- pr_err(KERN_ERR "msm_8974_init_gpiomux failed %d\n", rc);
+ pr_err("%s failed %d\n", __func__, rc);
return;
}
diff --git a/arch/arm/mach-msm/board-9625-gpiomux.c b/arch/arm/mach-msm/board-9625-gpiomux.c
index 686bb41..4465440 100644
--- a/arch/arm/mach-msm/board-9625-gpiomux.c
+++ b/arch/arm/mach-msm/board-9625-gpiomux.c
@@ -280,9 +280,9 @@
{
int rc;
- rc = msm_gpiomux_init(NR_GPIO_IRQS);
+ rc = msm_gpiomux_init_dt();
if (rc) {
- pr_err(KERN_ERR "msm9625_init_gpiomux failed %d\n", rc);
+ pr_err("%s failed %d\n", __func__, rc);
return;
}
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
index ccf6755..3b1df2e 100644
--- a/arch/arm/mach-msm/clock-9625.c
+++ b/arch/arm/mach-msm/clock-9625.c
@@ -2171,6 +2171,7 @@
CLK_LOOKUP("core_clk", qdss_clk.c, "fc319000.funnel"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc31a000.funnel"),
CLK_LOOKUP("core_clk", qdss_clk.c, "fc321000.stm"),
+ CLK_LOOKUP("core_clk", qdss_clk.c, "fc332000.etm"),
CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc322000.tmc"),
CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc318000.tpiu"),
@@ -2180,6 +2181,7 @@
CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc319000.funnel"),
CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc31a000.funnel"),
CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc321000.stm"),
+ CLK_LOOKUP("core_a_clk", qdss_clk.c, "fc332000.etm"),
};
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 4780c57..446f3f2 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -19,6 +19,7 @@
#include <linux/gpio.h>
#include <linux/coresight.h>
#include <asm/clkdev.h>
+#include <mach/gpio.h>
#include <mach/kgsl.h>
#include <linux/android_pmem.h>
#include <mach/irqs-8960.h>
@@ -3131,6 +3132,81 @@
},
};
+struct msm_bus_vectors grp3d_init_vectors_1[] = {
+ {
+ .src = MSM_BUS_MASTER_GRAPHICS_3D,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+ {
+ .src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = 0,
+ },
+};
+
+struct msm_bus_vectors grp3d_low_vectors_1[] = {
+ {
+ .src = MSM_BUS_MASTER_GRAPHICS_3D,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = KGSL_CONVERT_TO_MBPS(1000),
+ },
+ {
+ .src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = KGSL_CONVERT_TO_MBPS(1000),
+ },
+};
+
+struct msm_bus_vectors grp3d_nominal_low_vectors_1[] = {
+ {
+ .src = MSM_BUS_MASTER_GRAPHICS_3D,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = KGSL_CONVERT_TO_MBPS(2048),
+ },
+ {
+ .src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = KGSL_CONVERT_TO_MBPS(2048),
+ },
+};
+
+struct msm_bus_vectors grp3d_nominal_high_vectors_1[] = {
+ {
+ .src = MSM_BUS_MASTER_GRAPHICS_3D,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = KGSL_CONVERT_TO_MBPS(2656),
+ },
+ {
+ .src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = KGSL_CONVERT_TO_MBPS(2656),
+ },
+};
+
+struct msm_bus_vectors grp3d_max_vectors_1[] = {
+ {
+ .src = MSM_BUS_MASTER_GRAPHICS_3D,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = KGSL_CONVERT_TO_MBPS(3968),
+ },
+ {
+ .src = MSM_BUS_MASTER_GRAPHICS_3D_PORT1,
+ .dst = MSM_BUS_SLAVE_EBI_CH0,
+ .ab = 0,
+ .ib = KGSL_CONVERT_TO_MBPS(3968),
+ },
+};
+
static struct msm_bus_paths grp3d_bus_scale_usecases[] = {
{
ARRAY_SIZE(grp3d_init_vectors),
@@ -3154,12 +3230,41 @@
},
};
+struct msm_bus_paths grp3d_bus_scale_usecases_1[] = {
+ {
+ ARRAY_SIZE(grp3d_init_vectors_1),
+ grp3d_init_vectors_1,
+ },
+ {
+ ARRAY_SIZE(grp3d_low_vectors_1),
+ grp3d_low_vectors_1,
+ },
+ {
+ ARRAY_SIZE(grp3d_nominal_low_vectors_1),
+ grp3d_nominal_low_vectors_1,
+ },
+ {
+ ARRAY_SIZE(grp3d_nominal_high_vectors_1),
+ grp3d_nominal_high_vectors_1,
+ },
+ {
+ ARRAY_SIZE(grp3d_max_vectors_1),
+ grp3d_max_vectors_1,
+ },
+};
+
static struct msm_bus_scale_pdata grp3d_bus_scale_pdata = {
grp3d_bus_scale_usecases,
ARRAY_SIZE(grp3d_bus_scale_usecases),
.name = "grp3d",
};
+struct msm_bus_scale_pdata grp3d_bus_scale_pdata_ab = {
+ grp3d_bus_scale_usecases_1,
+ ARRAY_SIZE(grp3d_bus_scale_usecases_1),
+ .name = "grp3d",
+};
+
static struct msm_bus_vectors grp2d0_init_vectors[] = {
{
.src = MSM_BUS_MASTER_GRAPHICS_2D_CORE0,
@@ -4438,11 +4543,17 @@
},
};
+static struct msm_gpio_pdata msm8960_gpio_pdata = {
+ .ngpio = 152,
+ .direct_connect_irqs = 8,
+};
+
struct platform_device msm_gpio_device = {
- .name = "msmgpio",
- .id = -1,
- .num_resources = ARRAY_SIZE(msm_gpio_resources),
- .resource = msm_gpio_resources,
+ .name = "msmgpio",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(msm_gpio_resources),
+ .resource = msm_gpio_resources,
+ .dev.platform_data = &msm8960_gpio_pdata,
};
struct platform_device mdm_sglte_device = {
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index fc65cb7..cec57fd 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -34,6 +34,7 @@
#include <mach/dma.h>
#include "pm.h"
#include "devices.h"
+#include <mach/gpio.h>
#include <mach/mpm.h>
#include "spm.h"
#include "rpm_resources.h"
@@ -1514,11 +1515,17 @@
},
};
+static struct msm_gpio_pdata msm9615_gpio_pdata = {
+ .ngpio = 88,
+ .direct_connect_irqs = 8,
+};
+
struct platform_device msm_gpio_device = {
- .name = "msmgpio",
- .id = -1,
- .num_resources = ARRAY_SIZE(msm_gpio_resources),
- .resource = msm_gpio_resources,
+ .name = "msmgpio",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(msm_gpio_resources),
+ .resource = msm_gpio_resources,
+ .dev.platform_data = &msm9615_gpio_pdata,
};
void __init msm9615_device_init(void)
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 0a080b1..5a517df 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -108,11 +108,17 @@
},
};
+static struct msm_gpio_pdata msm8660_gpio_pdata = {
+ .ngpio = 173,
+ .direct_connect_irqs = 10,
+};
+
struct platform_device msm_gpio_device = {
- .name = "msmgpio",
- .id = -1,
- .num_resources = ARRAY_SIZE(msm_gpio_resources),
- .resource = msm_gpio_resources,
+ .name = "msmgpio",
+ .id = -1,
+ .num_resources = ARRAY_SIZE(msm_gpio_resources),
+ .resource = msm_gpio_resources,
+ .dev.platform_data = &msm8660_gpio_pdata,
};
static void charm_ap2mdm_kpdpwr_on(void)
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index b676518..2339706 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -330,6 +330,9 @@
extern struct resource kgsl_3d0_resources_8960ab[];
extern int kgsl_num_resources_8960ab;
+#ifdef CONFIG_MSM_BUS_SCALING
+extern struct msm_bus_scale_pdata grp3d_bus_scale_pdata_ab;
+#endif
extern struct platform_device msm_mipi_dsi1_device;
extern struct platform_device mipi_dsi_device;
diff --git a/arch/arm/mach-msm/gpiomux.c b/arch/arm/mach-msm/gpiomux.c
index 85936ba..0af83e8 100644
--- a/arch/arm/mach-msm/gpiomux.c
+++ b/arch/arm/mach-msm/gpiomux.c
@@ -10,6 +10,7 @@
* GNU General Public License for more details.
*/
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <mach/gpiomux.h>
@@ -148,3 +149,26 @@
}
}
EXPORT_SYMBOL(msm_gpiomux_install);
+
+int msm_gpiomux_init_dt(void)
+{
+ int rc;
+ unsigned int ngpio;
+ struct device_node *of_gpio_node;
+
+ of_gpio_node = of_find_compatible_node(NULL, NULL, "qcom,msm-gpio");
+ if (!of_gpio_node) {
+ pr_err("%s: Failed to find qcom,msm-gpio node\n", __func__);
+ return -ENODEV;
+ }
+
+ rc = of_property_read_u32(of_gpio_node, "ngpio", &ngpio);
+ if (rc) {
+ pr_err("%s: Failed to find ngpio property in msm-gpio device node %d\n"
+ , __func__, rc);
+ return rc;
+ }
+
+ return msm_gpiomux_init(ngpio);
+}
+EXPORT_SYMBOL(msm_gpiomux_init_dt);
diff --git a/arch/arm/mach-msm/include/mach/gpio.h b/arch/arm/mach-msm/include/mach/gpio.h
index a0bcd2b..137d243 100644
--- a/arch/arm/mach-msm/include/mach/gpio.h
+++ b/arch/arm/mach-msm/include/mach/gpio.h
@@ -40,6 +40,11 @@
const char *label;
};
+struct msm_gpio_pdata {
+ int ngpio;
+ int direct_connect_irqs;
+};
+
/**
* msm_gpios_request_enable() - request and enable set of GPIOs
*
diff --git a/arch/arm/mach-msm/include/mach/gpiomux.h b/arch/arm/mach-msm/include/mach/gpiomux.h
index f75b0e0..f16caed 100644
--- a/arch/arm/mach-msm/include/mach/gpiomux.h
+++ b/arch/arm/mach-msm/include/mach/gpiomux.h
@@ -117,6 +117,11 @@
*/
int msm_gpiomux_init(size_t ngpio);
+/* DT Variant of msm_gpiomux_init. This will look up the number of gpios from
+ * device tree rather than relying on NR_GPIO_IRQS
+ */
+int msm_gpiomux_init_dt(void);
+
/* Install a block of gpiomux configurations in gpiomux. This is functionally
* identical to calling msm_gpiomux_write many times.
*/
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index 8ebd0cf..8b39e34 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -130,6 +130,7 @@
* @secure_context true if this is a secure context programmed by
the secure environment, false otherwise
* @asid ASID used with this context.
+ * @attach_count Number of time this context has been attached.
*
* A msm_iommu_ctx_drvdata holds the driver data for a single context bank
* within each IOMMU hardware instance
@@ -144,6 +145,7 @@
unsigned int nsid;
unsigned int secure_context;
int asid;
+ int attach_count;
};
/*
diff --git a/arch/arm/mach-msm/include/mach/iommu_domains.h b/arch/arm/mach-msm/include/mach/iommu_domains.h
index 01bc479..07f82ec 100644
--- a/arch/arm/mach-msm/include/mach/iommu_domains.h
+++ b/arch/arm/mach-msm/include/mach/iommu_domains.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2011-2012, 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
@@ -77,6 +77,7 @@
#if defined(CONFIG_MSM_IOMMU)
extern struct iommu_domain *msm_get_iommu_domain(int domain_num);
+extern int msm_find_domain_no(const struct iommu_domain *domain);
extern int msm_allocate_iova_address(unsigned int iommu_domain,
unsigned int partition_no,
@@ -123,6 +124,10 @@
*msm_get_iommu_domain(int subsys_id) { return NULL; }
+static inline int msm_find_domain_no(const struct iommu_domain *domain)
+{
+ return -EINVAL;
+}
static inline int msm_allocate_iova_address(unsigned int iommu_domain,
unsigned int partition_no,
diff --git a/arch/arm/mach-msm/include/mach/irqs-8x60.h b/arch/arm/mach-msm/include/mach/irqs-8x60.h
index d08f645..1e2c606 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8x60.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8x60.h
@@ -242,7 +242,6 @@
#define SMPSS_SPARE_6 (GIC_SPI_START + 222)
#define SMPSS_SPARE_7 (GIC_SPI_START + 223)
-#define NR_TLMM_MSM_DIR_CONN_IRQ 10
#define NR_GPIO_IRQS 173
#define NR_MSM_GPIOS NR_GPIO_IRQS
#define NR_MSM_IRQS 256
diff --git a/arch/arm/mach-msm/include/mach/irqs-9615.h b/arch/arm/mach-msm/include/mach/irqs-9615.h
index b9c66c3..35b5848 100644
--- a/arch/arm/mach-msm/include/mach/irqs-9615.h
+++ b/arch/arm/mach-msm/include/mach/irqs-9615.h
@@ -181,7 +181,6 @@
#define NR_WCD9XXX_IRQS 49
#define NR_TABLA_IRQS NR_WCD9XXX_IRQS
#define NR_BOARD_IRQS (NR_PM8018_IRQS + NR_WCD9XXX_IRQS)
-#define NR_TLMM_MSM_DIR_CONN_IRQ 8 /*Need to Verify this Count*/
#define NR_MSM_GPIOS NR_GPIO_IRQS
/* Backwards compatible IRQ macros. */
diff --git a/arch/arm/mach-msm/include/mach/irqs-9625.h b/arch/arm/mach-msm/include/mach/irqs-9625.h
index 9ba77af..278c6a5 100644
--- a/arch/arm/mach-msm/include/mach/irqs-9625.h
+++ b/arch/arm/mach-msm/include/mach/irqs-9625.h
@@ -20,10 +20,6 @@
#define APCC_QGICL2PERFMONIRPTREQ (GIC_SPI_START + 1)
#define SC_SICL2PERFMONIRPTREQ APCC_QGICL2PERFMONIRPTREQ
-#define NR_MSM_IRQS 288
-#define NR_GPIO_IRQS 76
-#define NR_BOARD_IRQS 0
#define NR_TLMM_MSM_DIR_CONN_IRQ 8 /*Need to Verify this Count*/
-#define NR_MSM_GPIOS NR_GPIO_IRQS
#endif
diff --git a/arch/arm/mach-msm/include/mach/irqs.h b/arch/arm/mach-msm/include/mach/irqs.h
index 8c6b959..6955c80 100644
--- a/arch/arm/mach-msm/include/mach/irqs.h
+++ b/arch/arm/mach-msm/include/mach/irqs.h
@@ -37,22 +37,6 @@
#include "irqs-8092.h"
#endif
-#define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
-#define NR_GPIO_IRQS 146
-#define NR_QPNP_IRQS 32768
-#define NR_BOARD_IRQS NR_QPNP_IRQS
-#define NR_TLMM_MSM_DIR_CONN_IRQ 8
-#define NR_MSM_GPIOS NR_GPIO_IRQS
-
-#elif defined(CONFIG_ARCH_MSM8910) || defined(CONFIG_ARCH_MSM8226)
-
-#define NR_MSM_IRQS 256
-#define NR_GPIO_IRQS 117
-#define NR_QPNP_IRQS 32768
-#define NR_BOARD_IRQS NR_QPNP_IRQS
-#define NR_TLMM_MSM_DIR_CONN_IRQ 8
-#define NR_MSM_GPIOS NR_GPIO_IRQS
-
#elif defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064) || \
defined(CONFIG_ARCH_MSM8930)
@@ -85,7 +69,6 @@
#define NR_BOARD_IRQS (NR_PM8921_IRQS + NR_PM8821_IRQS + \
NR_WCD9XXX_IRQS + NR_GPIO_EXPANDER_IRQS)
#endif
-#define NR_TLMM_MSM_DIR_CONN_IRQ 8 /*Need to Verify this Count*/
#define NR_MSM_GPIOS NR_GPIO_IRQS
#else
@@ -113,17 +96,36 @@
#elif defined(CONFIG_ARCH_FSM9XXX)
#include "irqs-fsm9xxx.h"
#include "sirc.h"
-#else
-#error "Unknown architecture specification"
#endif
#endif
#if !defined(CONFIG_SPARSE_IRQ)
+
+#if defined(CONFIG_ARCH_MSM8974) || defined(CONFIG_ARCH_MPQ8092)
+#define NR_MSM_IRQS 1020 /* Should be 256 - but higher due to bug in sim */
+#define NR_GPIO_IRQS 146
+#define NR_QPNP_IRQS 32768
+#define NR_BOARD_IRQS NR_QPNP_IRQS
+
+#elif defined(CONFIG_ARCH_MSM8910) || defined(CONFIG_ARCH_MSM8226)
+#define NR_MSM_IRQS 256
+#define NR_GPIO_IRQS 117
+#define NR_QPNP_IRQS 32768
+#define NR_BOARD_IRQS NR_QPNP_IRQS
+
+#elif defined(CONFIG_ARCH_MSM9625)
+#define NR_MSM_IRQS 288
+#define NR_GPIO_IRQS 76
+#define NR_BOARD_IRQS 0
+
+#endif
+
#define NR_IRQS (NR_MSM_IRQS + NR_GPIO_IRQS + NR_BOARD_IRQS)
#define MSM_GPIO_TO_INT(n) (NR_MSM_IRQS + (n))
#define FIRST_GPIO_IRQ MSM_GPIO_TO_INT(0)
#define MSM_INT_TO_REG(base, irq) (base + irq / 32)
+
#endif
#if defined(CONFIG_PCI_MSI) && defined(CONFIG_MSM_PCIE)
diff --git a/arch/arm/mach-msm/iommu_domains.c b/arch/arm/mach-msm/iommu_domains.c
index 75e56fe..dc67403 100644
--- a/arch/arm/mach-msm/iommu_domains.c
+++ b/arch/arm/mach-msm/iommu_domains.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2012, 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
@@ -25,6 +25,9 @@
#include <mach/iommu_domains.h>
#include <mach/socinfo.h>
#include <mach/msm_subsystem_map.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
/* dummy 64K for overmapping */
char iommu_dummy[2*SZ_64K-4];
@@ -269,6 +272,27 @@
}
EXPORT_SYMBOL(msm_get_iommu_domain);
+int msm_find_domain_no(const struct iommu_domain *domain)
+{
+ struct rb_root *root = &domain_root;
+ struct rb_node *n;
+ struct msm_iova_data *node;
+ int domain_num = -EINVAL;
+
+ mutex_lock(&domain_mutex);
+
+ for (n = rb_first(root); n; n = rb_next(n)) {
+ node = rb_entry(n, struct msm_iova_data, node);
+ if (node->domain == domain) {
+ domain_num = node->domain_num;
+ break;
+ }
+ }
+ mutex_unlock(&domain_mutex);
+ return domain_num;
+}
+EXPORT_SYMBOL(msm_find_domain_no);
+
int msm_allocate_iova_address(unsigned int iommu_domain,
unsigned int partition_no,
unsigned long size,
@@ -411,7 +435,170 @@
}
EXPORT_SYMBOL(msm_register_domain);
-static int __init iommu_domain_probe(struct platform_device *pdev)
+static int find_and_add_contexts(struct iommu_group *group,
+ const struct device_node *node,
+ unsigned int num_contexts)
+{
+ unsigned int i;
+ struct device *ctx;
+ const char *name;
+ struct device_node *ctx_node;
+ int ret_val = 0;
+
+ for (i = 0; i < num_contexts; ++i) {
+ ctx_node = of_parse_phandle((struct device_node *) node,
+ "qcom,iommu-contexts", i);
+ if (!ctx_node) {
+ pr_err("Unable to parse phandle #%u\n", i);
+ ret_val = -EINVAL;
+ goto out;
+ }
+ if (of_property_read_string(ctx_node, "label", &name)) {
+ pr_err("Could not find label property\n");
+ ret_val = -EINVAL;
+ goto out;
+ }
+ ctx = msm_iommu_get_ctx(name);
+ if (!ctx) {
+ pr_err("Unable to find context %s\n", name);
+ ret_val = -EINVAL;
+ goto out;
+ }
+ iommu_group_add_device(group, ctx);
+ }
+out:
+ return ret_val;
+}
+
+static int create_and_add_domain(struct iommu_group *group,
+ const struct device_node *node)
+{
+ unsigned int ret_val = 0;
+ unsigned int i;
+ struct msm_iova_layout l;
+ struct msm_iova_partition *part = 0;
+ struct iommu_domain *domain = 0;
+ unsigned int *addr_array;
+ unsigned int array_size;
+ int domain_no;
+ int secure_domain;
+ int l2_redirect;
+
+ if (of_get_property(node, "qcom,virtual-addr-pool", &array_size)) {
+ l.npartitions = array_size / sizeof(unsigned int) / 2;
+ part = kmalloc(
+ sizeof(struct msm_iova_partition) * l.npartitions,
+ GFP_KERNEL);
+ if (!part) {
+ pr_err("%s: could not allocate space for partition",
+ __func__);
+ ret_val = -ENOMEM;
+ goto out;
+ }
+ addr_array = kmalloc(array_size, GFP_KERNEL);
+ if (!addr_array) {
+ pr_err("%s: could not allocate space for partition",
+ __func__);
+ ret_val = -ENOMEM;
+ goto free_mem;
+ }
+
+ ret_val = of_property_read_u32_array(node,
+ "qcom,virtual-addr-pool",
+ addr_array,
+ array_size/sizeof(unsigned int));
+ if (ret_val) {
+ ret_val = -EINVAL;
+ goto free_mem;
+ }
+
+ for (i = 0; i < l.npartitions * 2; i += 2) {
+ part[i].start = addr_array[i];
+ part[i].size = addr_array[i+1];
+ }
+ } else {
+ l.npartitions = 1;
+ part = kmalloc(
+ sizeof(struct msm_iova_partition) * l.npartitions,
+ GFP_KERNEL);
+ if (!part) {
+ pr_err("%s: could not allocate space for partition",
+ __func__);
+ ret_val = -ENOMEM;
+ goto out;
+ }
+ part[0].start = 0x0;
+ part[0].size = 0xFFFFFFFF;
+ }
+
+ l.partitions = part;
+
+ secure_domain = of_property_read_bool(node, "qcom,secure-domain");
+ l.is_secure = (secure_domain) ? MSM_IOMMU_DOMAIN_SECURE : 0;
+
+ l2_redirect = of_property_read_bool(node, "qcom,l2-redirect");
+ l.domain_flags = (l2_redirect) ? MSM_IOMMU_DOMAIN_PT_CACHEABLE : 0;
+
+ domain_no = msm_register_domain(&l);
+ if (domain_no >= 0)
+ domain = msm_get_iommu_domain(domain_no);
+ else
+ ret_val = domain_no;
+
+ iommu_group_set_iommudata(group, domain, NULL);
+
+free_mem:
+ kfree(part);
+out:
+ return ret_val;
+}
+
+static int iommu_domain_parse_dt(const struct device_node *dt_node)
+{
+ struct device_node *node;
+ int sz;
+ unsigned int num_contexts;
+ int ret_val = 0;
+ struct iommu_group *group = 0;
+ const char *name;
+
+ for_each_child_of_node(dt_node, node) {
+ group = iommu_group_alloc();
+ if (IS_ERR(group)) {
+ ret_val = PTR_ERR(group);
+ goto out;
+ }
+ if (of_property_read_string(node, "label", &name)) {
+ ret_val = -EINVAL;
+ goto free_group;
+ }
+ iommu_group_set_name(group, name);
+
+ if (!of_get_property(node, "qcom,iommu-contexts", &sz)) {
+ pr_err("Could not find qcom,iommu-contexts property\n");
+ ret_val = -EINVAL;
+ goto free_group;
+ }
+ num_contexts = sz / sizeof(unsigned int);
+
+ ret_val = find_and_add_contexts(group, node, num_contexts);
+ if (ret_val) {
+ ret_val = -EINVAL;
+ goto free_group;
+ }
+ ret_val = create_and_add_domain(group, node);
+ if (ret_val) {
+ ret_val = -EINVAL;
+ goto free_group;
+ }
+ }
+free_group:
+ /* No iommu_group_free() function */
+out:
+ return ret_val;
+}
+
+static int iommu_domain_probe(struct platform_device *pdev)
{
struct iommu_domains_pdata *p = pdev->dev.platform_data;
int i, j;
@@ -419,7 +606,9 @@
if (!msm_use_iommu())
return -ENODEV;
- if (!p)
+ if (pdev->dev.of_node)
+ return iommu_domain_parse_dt(pdev->dev.of_node);
+ else if (!p)
return -ENODEV;
for (i = 0; i < p->ndomains; i++) {
@@ -465,26 +654,48 @@
continue;
if (iommu_attach_device(domain, ctx)) {
- WARN(1, "%s: could not attach domain %p to context %s."
- " iommu programming will not occur.\n",
- __func__, domain,
- p->domain_names[i].name);
+ WARN(1, "%s: could not attach domain %p to context %s. iommu programming will not occur.\n",
+ __func__, domain, p->domain_names[i].name);
continue;
}
}
-
return 0;
}
+static int __devexit iommu_domain_exit(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static struct of_device_id msm_iommu_domain_match_table[] = {
+ { .name = "qcom,iommu-domains", },
+ {}
+};
+
static struct platform_driver iommu_domain_driver = {
.driver = {
.name = "iommu_domains",
+ .of_match_table = msm_iommu_domain_match_table,
.owner = THIS_MODULE
},
+ .probe = iommu_domain_probe,
+ .remove = __devexit_p(iommu_domain_exit),
};
static int __init msm_subsystem_iommu_init(void)
{
- return platform_driver_probe(&iommu_domain_driver, iommu_domain_probe);
+ int ret;
+ ret = platform_driver_register(&iommu_domain_driver);
+ if (ret != 0)
+ pr_err("Failed to register IOMMU domain driver\n");
+ return ret;
}
+
+static void __exit msm_subsystem_iommu_exit(void)
+{
+ platform_driver_unregister(&iommu_domain_driver);
+}
+
device_initcall(msm_subsystem_iommu_init);
+module_exit(msm_subsystem_iommu_exit);
+
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index ab88749..de3a544 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -118,7 +118,7 @@
val &= ~(Q6SS_L2DATA_SLP_NRET_N | Q6SS_SLP_RET_N |
Q6SS_L2TAG_SLP_NRET_N | Q6SS_ETB_SLP_NRET_N |
Q6SS_L2DATA_STBY_N);
- writel_relaxed(Q6SS_CLAMP_IO, drv->reg_base + QDSP6SS_PWR_CTL);
+ writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
/* Assert Q6 resets */
val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
diff --git a/arch/arm/mach-msm/remote_spinlock.c b/arch/arm/mach-msm/remote_spinlock.c
index 2480433..98a3278 100644
--- a/arch/arm/mach-msm/remote_spinlock.c
+++ b/arch/arm/mach-msm/remote_spinlock.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, 2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2009, 2011-2012 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
@@ -15,6 +15,10 @@
#include <linux/kernel.h>
#include <linux/string.h>
#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
#include <asm/system.h>
@@ -22,7 +26,6 @@
#include <mach/remote_spinlock.h>
#include <mach/dal.h>
#include "smd_private.h"
-#include <linux/module.h>
static void remote_spin_release_all_locks(uint32_t pid, int count);
@@ -30,31 +33,85 @@
#define SFPB_SPINLOCK_COUNT 8
#define MSM_SFPB_MUTEX_REG_BASE 0x01200600
#define MSM_SFPB_MUTEX_REG_SIZE (33 * 4)
+#define SFPB_SPINLOCK_OFFSET 4
+#define SFPB_SPINLOCK_SIZE 4
+
+static uint32_t lock_count;
+static phys_addr_t reg_base;
+static uint32_t reg_size;
+static uint32_t lock_offset; /* offset into the hardware block before lock 0 */
+static uint32_t lock_size;
static void *hw_mutex_reg_base;
static DEFINE_MUTEX(hw_map_init_lock);
+static char *compatible_string = "qcom,ipc-spinlock";
+
+static int init_hw_mutex(struct device_node *node)
+{
+ struct resource r;
+ int rc;
+
+ rc = of_address_to_resource(node, 0, &r);
+ if (rc)
+ BUG();
+
+ rc = of_property_read_u32(node, "qcom,num-locks", &lock_count);
+ if (rc)
+ BUG();
+
+ reg_base = r.start;
+ reg_size = (uint32_t)(resource_size(&r));
+ lock_offset = 0;
+ lock_size = reg_size / lock_count;
+
+ return 0;
+}
+
+static void find_and_init_hw_mutex(void)
+{
+ struct device_node *node;
+
+ node = of_find_compatible_node(NULL, NULL, compatible_string);
+ if (node) {
+ init_hw_mutex(node);
+ } else {
+ lock_count = SFPB_SPINLOCK_COUNT;
+ reg_base = MSM_SFPB_MUTEX_REG_BASE;
+ reg_size = MSM_SFPB_MUTEX_REG_SIZE;
+ lock_offset = SFPB_SPINLOCK_OFFSET;
+ lock_size = SFPB_SPINLOCK_SIZE;
+ }
+ hw_mutex_reg_base = ioremap(reg_base, reg_size);
+ BUG_ON(hw_mutex_reg_base == NULL);
+}
+
static int remote_spinlock_init_address(int id, _remote_spinlock_t *lock)
{
- if (id >= SFPB_SPINLOCK_COUNT)
- return -EINVAL;
-
+ /*
+ * Optimistic locking. Init only needs to be done once by the first
+ * caller. After that, serializing inits between different callers
+ * is unnecessary. The second check after the lock ensures init
+ * wasn't previously completed by someone else before the lock could
+ * be grabbed.
+ */
if (!hw_mutex_reg_base) {
mutex_lock(&hw_map_init_lock);
if (!hw_mutex_reg_base)
- hw_mutex_reg_base = ioremap(MSM_SFPB_MUTEX_REG_BASE,
- MSM_SFPB_MUTEX_REG_SIZE);
+ find_and_init_hw_mutex();
mutex_unlock(&hw_map_init_lock);
- BUG_ON(hw_mutex_reg_base == NULL);
}
- *lock = hw_mutex_reg_base + 0x4 + id * 4;
+ if (id >= lock_count)
+ return -EINVAL;
+
+ *lock = hw_mutex_reg_base + lock_offset + id * lock_size;
return 0;
}
void _remote_spin_release_all(uint32_t pid)
{
- remote_spin_release_all_locks(pid, SFPB_SPINLOCK_COUNT);
+ remote_spin_release_all_locks(pid, lock_count);
}
#else
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 7966177..58d445e 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -266,6 +266,9 @@
{
int rc;
+ if (use_restart_v2())
+ return 0;
+
if (pmic_reset_irq != 0) {
rc = request_any_context_irq(pmic_reset_irq,
resout_irq_handler, IRQF_TRIGGER_HIGH,
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index ad42505..c607202 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -657,8 +657,8 @@
};
struct smd_channel {
- volatile void *send; /* some variant of smd_half_channel */
- volatile void *recv; /* some variant of smd_half_channel */
+ volatile void __iomem *send; /* some variant of smd_half_channel */
+ volatile void __iomem *recv; /* some variant of smd_half_channel */
unsigned char *send_data;
unsigned char *recv_data;
unsigned fifo_size;
diff --git a/arch/arm/mach-msm/smd_private.c b/arch/arm/mach-msm/smd_private.c
index 5a78b6f..4cde8eb 100644
--- a/arch/arm/mach-msm/smd_private.c
+++ b/arch/arm/mach-msm/smd_private.c
@@ -12,227 +12,256 @@
#include "smd_private.h"
-void set_state(volatile void *half_channel, unsigned data)
+void set_state(volatile void __iomem *half_channel, unsigned data)
{
- ((struct smd_half_channel *)(half_channel))->state = data;
+ ((struct smd_half_channel __force *)(half_channel))->state = data;
}
-unsigned get_state(volatile void *half_channel)
+unsigned get_state(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->state;
+ return ((struct smd_half_channel __force *)(half_channel))->state;
}
-void set_fDSR(volatile void *half_channel, unsigned char data)
+void set_fDSR(volatile void __iomem *half_channel, unsigned char data)
{
- ((struct smd_half_channel *)(half_channel))->fDSR = data;
+ ((struct smd_half_channel __force *)(half_channel))->fDSR = data;
}
-unsigned get_fDSR(volatile void *half_channel)
+unsigned get_fDSR(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->fDSR;
+ return ((struct smd_half_channel __force *)(half_channel))->fDSR;
}
-void set_fCTS(volatile void *half_channel, unsigned char data)
+void set_fCTS(volatile void __iomem *half_channel, unsigned char data)
{
- ((struct smd_half_channel *)(half_channel))->fCTS = data;
+ ((struct smd_half_channel __force *)(half_channel))->fCTS = data;
}
-unsigned get_fCTS(volatile void *half_channel)
+unsigned get_fCTS(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->fCTS;
+ return ((struct smd_half_channel __force *)(half_channel))->fCTS;
}
-void set_fCD(volatile void *half_channel, unsigned char data)
+void set_fCD(volatile void __iomem *half_channel, unsigned char data)
{
- ((struct smd_half_channel *)(half_channel))->fCD = data;
+ ((struct smd_half_channel __force *)(half_channel))->fCD = data;
}
-unsigned get_fCD(volatile void *half_channel)
+unsigned get_fCD(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->fCD;
+ return ((struct smd_half_channel __force *)(half_channel))->fCD;
}
-void set_fRI(volatile void *half_channel, unsigned char data)
+void set_fRI(volatile void __iomem *half_channel, unsigned char data)
{
- ((struct smd_half_channel *)(half_channel))->fRI = data;
+ ((struct smd_half_channel __force *)(half_channel))->fRI = data;
}
-unsigned get_fRI(volatile void *half_channel)
+unsigned get_fRI(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->fRI;
+ return ((struct smd_half_channel __force *)(half_channel))->fRI;
}
-void set_fHEAD(volatile void *half_channel, unsigned char data)
+void set_fHEAD(volatile void __iomem *half_channel, unsigned char data)
{
- ((struct smd_half_channel *)(half_channel))->fHEAD = data;
+ ((struct smd_half_channel __force *)(half_channel))->fHEAD = data;
}
-unsigned get_fHEAD(volatile void *half_channel)
+unsigned get_fHEAD(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->fHEAD;
+ return ((struct smd_half_channel __force *)(half_channel))->fHEAD;
}
-void set_fTAIL(volatile void *half_channel, unsigned char data)
+void set_fTAIL(volatile void __iomem *half_channel, unsigned char data)
{
- ((struct smd_half_channel *)(half_channel))->fTAIL = data;
+ ((struct smd_half_channel __force *)(half_channel))->fTAIL = data;
}
-unsigned get_fTAIL(volatile void *half_channel)
+unsigned get_fTAIL(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->fTAIL;
+ return ((struct smd_half_channel __force *)(half_channel))->fTAIL;
}
-void set_fSTATE(volatile void *half_channel, unsigned char data)
+void set_fSTATE(volatile void __iomem *half_channel, unsigned char data)
{
- ((struct smd_half_channel *)(half_channel))->fSTATE = data;
+ ((struct smd_half_channel __force *)(half_channel))->fSTATE = data;
}
-unsigned get_fSTATE(volatile void *half_channel)
+unsigned get_fSTATE(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->fSTATE;
+ return ((struct smd_half_channel __force *)(half_channel))->fSTATE;
}
-void set_fBLOCKREADINTR(volatile void *half_channel, unsigned char data)
+void set_fBLOCKREADINTR(volatile void __iomem *half_channel, unsigned char data)
{
- ((struct smd_half_channel *)(half_channel))->fBLOCKREADINTR = data;
+ ((struct smd_half_channel __force *)
+ (half_channel))->fBLOCKREADINTR = data;
}
-unsigned get_fBLOCKREADINTR(volatile void *half_channel)
+unsigned get_fBLOCKREADINTR(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->fBLOCKREADINTR;
+ return ((struct smd_half_channel __force *)
+ (half_channel))->fBLOCKREADINTR;
}
-void set_tail(volatile void *half_channel, unsigned data)
+void set_tail(volatile void __iomem *half_channel, unsigned data)
{
- ((struct smd_half_channel *)(half_channel))->tail = data;
+ ((struct smd_half_channel __force *)(half_channel))->tail = data;
}
-unsigned get_tail(volatile void *half_channel)
+unsigned get_tail(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->tail;
+ return ((struct smd_half_channel __force *)(half_channel))->tail;
}
-void set_head(volatile void *half_channel, unsigned data)
+void set_head(volatile void __iomem *half_channel, unsigned data)
{
- ((struct smd_half_channel *)(half_channel))->head = data;
+ ((struct smd_half_channel __force *)(half_channel))->head = data;
}
-unsigned get_head(volatile void *half_channel)
+unsigned get_head(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel *)(half_channel))->head;
+ return ((struct smd_half_channel __force *)(half_channel))->head;
}
-void set_state_word_access(volatile void *half_channel, unsigned data)
+void set_state_word_access(volatile void __iomem *half_channel, unsigned data)
{
- ((struct smd_half_channel_word_access *)(half_channel))->state = data;
+ ((struct smd_half_channel_word_access __force *)
+ (half_channel))->state = data;
}
-unsigned get_state_word_access(volatile void *half_channel)
+unsigned get_state_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)(half_channel))->state;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->state;
}
-void set_fDSR_word_access(volatile void *half_channel, unsigned char data)
+void set_fDSR_word_access(volatile void __iomem *half_channel,
+ unsigned char data)
{
- ((struct smd_half_channel_word_access *)(half_channel))->fDSR = data;
+ ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fDSR = data;
}
-unsigned get_fDSR_word_access(volatile void *half_channel)
+unsigned get_fDSR_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)(half_channel))->fDSR;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fDSR;
}
-void set_fCTS_word_access(volatile void *half_channel, unsigned char data)
+void set_fCTS_word_access(volatile void __iomem *half_channel,
+ unsigned char data)
{
- ((struct smd_half_channel_word_access *)(half_channel))->fCTS = data;
+ ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fCTS = data;
}
-unsigned get_fCTS_word_access(volatile void *half_channel)
+unsigned get_fCTS_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)(half_channel))->fCTS;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fCTS;
}
-void set_fCD_word_access(volatile void *half_channel, unsigned char data)
+void set_fCD_word_access(volatile void __iomem *half_channel,
+ unsigned char data)
{
- ((struct smd_half_channel_word_access *)(half_channel))->fCD = data;
+ ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fCD = data;
}
-unsigned get_fCD_word_access(volatile void *half_channel)
+unsigned get_fCD_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)(half_channel))->fCD;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fCD;
}
-void set_fRI_word_access(volatile void *half_channel, unsigned char data)
+void set_fRI_word_access(volatile void __iomem *half_channel,
+ unsigned char data)
{
- ((struct smd_half_channel_word_access *)(half_channel))->fRI = data;
+ ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fRI = data;
}
-unsigned get_fRI_word_access(volatile void *half_channel)
+unsigned get_fRI_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)(half_channel))->fRI;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fRI;
}
-void set_fHEAD_word_access(volatile void *half_channel, unsigned char data)
+void set_fHEAD_word_access(volatile void __iomem *half_channel,
+ unsigned char data)
{
- ((struct smd_half_channel_word_access *)(half_channel))->fHEAD = data;
+ ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fHEAD = data;
}
-unsigned get_fHEAD_word_access(volatile void *half_channel)
+unsigned get_fHEAD_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)(half_channel))->fHEAD;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fHEAD;
}
-void set_fTAIL_word_access(volatile void *half_channel, unsigned char data)
+void set_fTAIL_word_access(volatile void __iomem *half_channel,
+ unsigned char data)
{
- ((struct smd_half_channel_word_access *)(half_channel))->fTAIL = data;
+ ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fTAIL = data;
}
-unsigned get_fTAIL_word_access(volatile void *half_channel)
+unsigned get_fTAIL_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)(half_channel))->fTAIL;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fTAIL;
}
-void set_fSTATE_word_access(volatile void *half_channel, unsigned char data)
+void set_fSTATE_word_access(volatile void __iomem *half_channel,
+ unsigned char data)
{
- ((struct smd_half_channel_word_access *)(half_channel))->fSTATE = data;
+ ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fSTATE = data;
}
-unsigned get_fSTATE_word_access(volatile void *half_channel)
+unsigned get_fSTATE_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)(half_channel))->fSTATE;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fSTATE;
}
-void set_fBLOCKREADINTR_word_access(volatile void *half_channel,
+void set_fBLOCKREADINTR_word_access(volatile void __iomem *half_channel,
unsigned char data)
{
- ((struct smd_half_channel_word_access *)
+ ((struct smd_half_channel_word_access __force *)
(half_channel))->fBLOCKREADINTR = data;
}
-unsigned get_fBLOCKREADINTR_word_access(volatile void *half_channel)
+unsigned get_fBLOCKREADINTR_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)
- (half_channel))->fBLOCKREADINTR;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->fBLOCKREADINTR;
}
-void set_tail_word_access(volatile void *half_channel, unsigned data)
+void set_tail_word_access(volatile void __iomem *half_channel, unsigned data)
{
- ((struct smd_half_channel_word_access *)(half_channel))->tail = data;
+ ((struct smd_half_channel_word_access __force *)
+ (half_channel))->tail = data;
}
-unsigned get_tail_word_access(volatile void *half_channel)
+unsigned get_tail_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)(half_channel))->tail;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->tail;
}
-void set_head_word_access(volatile void *half_channel, unsigned data)
+void set_head_word_access(volatile void __iomem *half_channel, unsigned data)
{
- ((struct smd_half_channel_word_access *)(half_channel))->head = data;
+ ((struct smd_half_channel_word_access __force *)
+ (half_channel))->head = data;
}
-unsigned get_head_word_access(volatile void *half_channel)
+unsigned get_head_word_access(volatile void __iomem *half_channel)
{
- return ((struct smd_half_channel_word_access *)(half_channel))->head;
+ return ((struct smd_half_channel_word_access __force *)
+ (half_channel))->head;
}
int is_word_access_ch(unsigned ch_type)
diff --git a/arch/arm/mach-msm/smd_private.h b/arch/arm/mach-msm/smd_private.h
index 7f39a24..2033fbe 100644
--- a/arch/arm/mach-msm/smd_private.h
+++ b/arch/arm/mach-msm/smd_private.h
@@ -147,29 +147,36 @@
};
struct smd_half_channel_access {
- void (*set_state)(volatile void *half_channel, unsigned data);
- unsigned (*get_state)(volatile void *half_channel);
- void (*set_fDSR)(volatile void *half_channel, unsigned char data);
- unsigned (*get_fDSR)(volatile void *half_channel);
- void (*set_fCTS)(volatile void *half_channel, unsigned char data);
- unsigned (*get_fCTS)(volatile void *half_channel);
- void (*set_fCD)(volatile void *half_channel, unsigned char data);
- unsigned (*get_fCD)(volatile void *half_channel);
- void (*set_fRI)(volatile void *half_channel, unsigned char data);
- unsigned (*get_fRI)(volatile void *half_channel);
- void (*set_fHEAD)(volatile void *half_channel, unsigned char data);
- unsigned (*get_fHEAD)(volatile void *half_channel);
- void (*set_fTAIL)(volatile void *half_channel, unsigned char data);
- unsigned (*get_fTAIL)(volatile void *half_channel);
- void (*set_fSTATE)(volatile void *half_channel, unsigned char data);
- unsigned (*get_fSTATE)(volatile void *half_channel);
- void (*set_fBLOCKREADINTR)(volatile void *half_channel,
+ void (*set_state)(volatile void __iomem *half_channel, unsigned data);
+ unsigned (*get_state)(volatile void __iomem *half_channel);
+ void (*set_fDSR)(volatile void __iomem *half_channel,
unsigned char data);
- unsigned (*get_fBLOCKREADINTR)(volatile void *half_channel);
- void (*set_tail)(volatile void *half_channel, unsigned data);
- unsigned (*get_tail)(volatile void *half_channel);
- void (*set_head)(volatile void *half_channel, unsigned data);
- unsigned (*get_head)(volatile void *half_channel);
+ unsigned (*get_fDSR)(volatile void __iomem *half_channel);
+ void (*set_fCTS)(volatile void __iomem *half_channel,
+ unsigned char data);
+ unsigned (*get_fCTS)(volatile void __iomem *half_channel);
+ void (*set_fCD)(volatile void __iomem *half_channel,
+ unsigned char data);
+ unsigned (*get_fCD)(volatile void __iomem *half_channel);
+ void (*set_fRI)(volatile void __iomem *half_channel,
+ unsigned char data);
+ unsigned (*get_fRI)(volatile void __iomem *half_channel);
+ void (*set_fHEAD)(volatile void __iomem *half_channel,
+ unsigned char data);
+ unsigned (*get_fHEAD)(volatile void __iomem *half_channel);
+ void (*set_fTAIL)(volatile void __iomem *half_channel,
+ unsigned char data);
+ unsigned (*get_fTAIL)(volatile void __iomem *half_channel);
+ void (*set_fSTATE)(volatile void __iomem *half_channel,
+ unsigned char data);
+ unsigned (*get_fSTATE)(volatile void __iomem *half_channel);
+ void (*set_fBLOCKREADINTR)(volatile void __iomem *half_channel,
+ unsigned char data);
+ unsigned (*get_fBLOCKREADINTR)(volatile void __iomem *half_channel);
+ void (*set_tail)(volatile void __iomem *half_channel, unsigned data);
+ unsigned (*get_tail)(volatile void __iomem *half_channel);
+ void (*set_head)(volatile void __iomem *half_channel, unsigned data);
+ unsigned (*get_head)(volatile void __iomem *half_channel);
};
int is_word_access_ch(unsigned ch_type);
diff --git a/drivers/gpio/gpio-msm-common.c b/drivers/gpio/gpio-msm-common.c
index 150c434..3332fc5 100644
--- a/drivers/gpio/gpio-msm-common.c
+++ b/drivers/gpio/gpio-msm-common.c
@@ -24,6 +24,7 @@
#include <linux/of.h>
#include <linux/err.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include <asm/mach/irq.h>
@@ -48,7 +49,7 @@
};
#endif
-static int tlmm_msm_summary_irq;
+static int tlmm_msm_summary_irq, nr_direct_connect_irqs;
struct tlmm_field_cfg {
enum msm_tlmm_register reg;
@@ -117,9 +118,9 @@
*/
struct msm_gpio_dev {
struct gpio_chip gpio_chip;
- DECLARE_BITMAP(enabled_irqs, NR_MSM_GPIOS);
- DECLARE_BITMAP(wake_irqs, NR_MSM_GPIOS);
- DECLARE_BITMAP(dual_edge_irqs, NR_MSM_GPIOS);
+ unsigned long *enabled_irqs;
+ unsigned long *wake_irqs;
+ unsigned long *dual_edge_irqs;
struct irq_domain *domain;
};
@@ -207,7 +208,6 @@
.gpio_chip = {
.label = "msmgpio",
.base = 0,
- .ngpio = NR_MSM_GPIOS,
.direction_input = msm_gpio_direction_input,
.direction_output = msm_gpio_direction_output,
.get = msm_gpio_get,
@@ -362,12 +362,13 @@
unsigned long i;
struct irq_desc *desc = irq_to_desc(irq);
struct irq_chip *chip = irq_desc_get_chip(desc);
+ int ngpio = msm_gpio.gpio_chip.ngpio;
chained_irq_enter(chip, desc);
- for (i = find_first_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
- i < NR_MSM_GPIOS;
- i = find_next_bit(msm_gpio.enabled_irqs, NR_MSM_GPIOS, i + 1)) {
+ for (i = find_first_bit(msm_gpio.enabled_irqs, ngpio);
+ i < ngpio;
+ i = find_next_bit(msm_gpio.enabled_irqs, ngpio, i + 1)) {
if (__msm_gpio_get_intr_status(i))
generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
i));
@@ -380,14 +381,15 @@
static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
{
int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
+ int ngpio = msm_gpio.gpio_chip.ngpio;
if (on) {
- if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
+ if (bitmap_empty(msm_gpio.wake_irqs, ngpio))
irq_set_irq_wake(tlmm_msm_summary_irq, 1);
set_bit(gpio, msm_gpio.wake_irqs);
} else {
clear_bit(gpio, msm_gpio.wake_irqs);
- if (bitmap_empty(msm_gpio.wake_irqs, NR_MSM_GPIOS))
+ if (bitmap_empty(msm_gpio.wake_irqs, ngpio))
irq_set_irq_wake(tlmm_msm_summary_irq, 0);
}
@@ -412,12 +414,13 @@
{
unsigned long irq_flags;
unsigned long i;
+ int ngpio = msm_gpio.gpio_chip.ngpio;
spin_lock_irqsave(&tlmm_lock, irq_flags);
- for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
+ for_each_set_bit(i, msm_gpio.enabled_irqs, ngpio)
__msm_gpio_set_intr_cfg_enable(i, 0);
- for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
+ for_each_set_bit(i, msm_gpio.wake_irqs, ngpio)
__msm_gpio_set_intr_cfg_enable(i, 1);
mb();
spin_unlock_irqrestore(&tlmm_lock, irq_flags);
@@ -428,12 +431,13 @@
{
unsigned long irq_flags;
int i, irq, intstat;
+ int ngpio = msm_gpio.gpio_chip.ngpio;
if (!msm_show_resume_irq_mask)
return;
spin_lock_irqsave(&tlmm_lock, irq_flags);
- for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS) {
+ for_each_set_bit(i, msm_gpio.wake_irqs, ngpio) {
intstat = __msm_gpio_get_intr_status(i);
if (intstat) {
irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
@@ -448,14 +452,15 @@
{
unsigned long irq_flags;
unsigned long i;
+ int ngpio = msm_gpio.gpio_chip.ngpio;
msm_gpio_show_resume_irq();
spin_lock_irqsave(&tlmm_lock, irq_flags);
- for_each_set_bit(i, msm_gpio.wake_irqs, NR_MSM_GPIOS)
+ for_each_set_bit(i, msm_gpio.wake_irqs, ngpio)
__msm_gpio_set_intr_cfg_enable(i, 0);
- for_each_set_bit(i, msm_gpio.enabled_irqs, NR_MSM_GPIOS)
+ for_each_set_bit(i, msm_gpio.enabled_irqs, ngpio)
__msm_gpio_set_intr_cfg_enable(i, 1);
mb();
spin_unlock_irqrestore(&tlmm_lock, irq_flags);
@@ -502,8 +507,9 @@
int gpio_tlmm_config(unsigned config, unsigned disable)
{
unsigned gpio = GPIO_PIN(config);
+ int ngpio = msm_gpio.gpio_chip.ngpio;
- if (gpio > NR_MSM_GPIOS)
+ if (gpio > ngpio)
return -EINVAL;
__gpio_tlmm_config(config);
@@ -517,8 +523,9 @@
unsigned int input_polarity)
{
unsigned long irq_flags;
+ int ngpio = msm_gpio.gpio_chip.ngpio;
- if (gpio >= NR_MSM_GPIOS || irq >= NR_TLMM_MSM_DIR_CONN_IRQ)
+ if (gpio >= ngpio || irq >= nr_direct_connect_irqs)
return -EINVAL;
spin_lock_irqsave(&tlmm_lock, irq_flags);
@@ -536,37 +543,89 @@
*/
static struct lock_class_key msm_gpio_lock_class;
+static inline void msm_gpio_set_irq_handler(struct device *dev)
+{
+ int irq, i;
+
+ if (!dev->of_node) {
+ for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
+ irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
+ irq_set_lockdep_class(irq, &msm_gpio_lock_class);
+ irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
+ handle_level_irq);
+ set_irq_flags(irq, IRQF_VALID);
+ }
+ }
+}
+
static int __devinit msm_gpio_probe(struct platform_device *pdev)
{
- int ret;
-#ifndef CONFIG_OF
- int irq, i;
-#endif
+ int ret, ngpio = 0;
+ struct msm_gpio_pdata *pdata = pdev->dev.platform_data;
+
+ if (pdev->dev.of_node) {
+ ret = of_property_read_u32(pdev->dev.of_node, "ngpio", &ngpio);
+ if (ret) {
+ pr_err("%s: Failed to find ngpio property\n", __func__);
+ return ret;
+ }
+ ret = of_property_read_u32(pdev->dev.of_node,
+ "qcom,direct-connect-irqs",
+ &nr_direct_connect_irqs);
+ if (ret) {
+ pr_err("%s: Failed to find qcom,direct-connect-irqs property\n"
+ , __func__);
+ return ret;
+ }
+ } else {
+ ngpio = pdata->ngpio;
+ nr_direct_connect_irqs = pdata->direct_connect_irqs;
+ }
+
tlmm_msm_summary_irq = platform_get_irq(pdev, 0);
if (tlmm_msm_summary_irq < 0) {
pr_err("%s: No interrupt defined for msmgpio\n", __func__);
return -ENXIO;
}
+
msm_gpio.gpio_chip.dev = &pdev->dev;
+ msm_gpio.gpio_chip.ngpio = ngpio;
spin_lock_init(&tlmm_lock);
- bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
- bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
- bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
+ msm_gpio.enabled_irqs = devm_kzalloc(&pdev->dev, sizeof(unsigned long)
+ * BITS_TO_LONGS(ngpio), GFP_KERNEL);
+ if (!msm_gpio.enabled_irqs) {
+ dev_err(&pdev->dev, "%s failed to allocated enabled_irqs bitmap\n"
+ , __func__);
+ return -ENOMEM;
+ }
+
+ msm_gpio.wake_irqs = devm_kzalloc(&pdev->dev, sizeof(unsigned long) *
+ BITS_TO_LONGS(ngpio), GFP_KERNEL);
+ if (!msm_gpio.wake_irqs) {
+ dev_err(&pdev->dev, "%s failed to allocated wake_irqs bitmap\n"
+ , __func__);
+ return -ENOMEM;
+ }
+ msm_gpio.dual_edge_irqs = devm_kzalloc(&pdev->dev, sizeof(unsigned long)
+ * BITS_TO_LONGS(ngpio), GFP_KERNEL);
+ if (!msm_gpio.dual_edge_irqs) {
+ dev_err(&pdev->dev, "%s failed to allocated dual_edge_irqs bitmap\n"
+ , __func__);
+ return -ENOMEM;
+ }
+
+ bitmap_zero(msm_gpio.enabled_irqs, ngpio);
+ bitmap_zero(msm_gpio.wake_irqs, ngpio);
+ bitmap_zero(msm_gpio.dual_edge_irqs, ngpio);
ret = gpiochip_add(&msm_gpio.gpio_chip);
if (ret < 0)
return ret;
-#ifndef CONFIG_OF
- for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
- irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
- irq_set_lockdep_class(irq, &msm_gpio_lock_class);
- irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
- handle_level_irq);
- set_irq_flags(irq, IRQF_VALID);
- }
-#endif
- ret = request_irq(tlmm_msm_summary_irq, msm_summary_irq_handler,
- IRQF_TRIGGER_HIGH, "msmgpio", NULL);
+ msm_gpio_set_irq_handler(&pdev->dev);
+
+ ret = devm_request_irq(&pdev->dev, tlmm_msm_summary_irq,
+ msm_summary_irq_handler, IRQF_TRIGGER_HIGH,
+ "msmgpio", NULL);
if (ret) {
pr_err("Request_irq failed for tlmm_msm_summary_irq - %d\n",
ret);
@@ -658,7 +717,14 @@
int __init msm_gpio_of_init(struct device_node *node,
struct device_node *parent)
{
- msm_gpio.domain = irq_domain_add_linear(node, NR_MSM_GPIOS,
+ int ngpio, ret;
+
+ ret = of_property_read_u32(node, "ngpio", &ngpio);
+ if (ret) {
+ WARN(1, "Cannot get numgpios from device tree\n");
+ return ret;
+ }
+ msm_gpio.domain = irq_domain_add_linear(node, ngpio,
&msm_gpio_irq_domain_ops, &msm_gpio);
if (!msm_gpio.domain) {
WARN(1, "Cannot allocate irq_domain\n");
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 8071687e..0290335 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -171,6 +171,51 @@
return 0;
}
+static void trigger_iadc_completion(struct work_struct *work)
+{
+ struct qpnp_iadc_drv *iadc = qpnp_iadc;
+
+ if (!iadc || !iadc->iadc_initialized)
+ return;
+
+ complete(&iadc->adc->adc_rslt_completion);
+
+ return;
+}
+DECLARE_WORK(trigger_iadc_completion_work, trigger_iadc_completion);
+
+static irqreturn_t qpnp_iadc_isr(int irq, void *dev_id)
+{
+ schedule_work(&trigger_iadc_completion_work);
+
+ return IRQ_HANDLED;
+}
+
+static int32_t qpnp_iadc_enable(bool state)
+{
+ int rc = 0;
+ u8 data = 0;
+
+ data = QPNP_IADC_ADC_EN;
+ if (state) {
+ rc = qpnp_iadc_write_reg(QPNP_IADC_EN_CTL1,
+ data);
+ if (rc < 0) {
+ pr_err("IADC enable failed\n");
+ return rc;
+ }
+ } else {
+ rc = qpnp_iadc_write_reg(QPNP_IADC_EN_CTL1,
+ (~data & QPNP_IADC_ADC_EN));
+ if (rc < 0) {
+ pr_err("IADC disable failed\n");
+ return rc;
+ }
+ }
+
+ return 0;
+}
+
static int32_t qpnp_iadc_status_debug(void)
{
int rc = 0;
@@ -209,46 +254,10 @@
pr_err("EOC not set with status:%x, dig:%x, ch:%x, mode:%x, en:%x\n",
status1, dig, chan, mode, en);
- return 0;
-}
-
-static void trigger_iadc_completion(struct work_struct *work)
-{
- struct qpnp_iadc_drv *iadc = qpnp_iadc;
-
- complete(&iadc->adc->adc_rslt_completion);
-
- return;
-}
-DECLARE_WORK(trigger_iadc_completion_work, trigger_iadc_completion);
-
-static irqreturn_t qpnp_iadc_isr(int irq, void *dev_id)
-{
- schedule_work(&trigger_iadc_completion_work);
-
- return IRQ_HANDLED;
-}
-
-static int32_t qpnp_iadc_enable(bool state)
-{
- int rc = 0;
- u8 data = 0;
-
- data = QPNP_IADC_ADC_EN;
- if (state) {
- rc = qpnp_iadc_write_reg(QPNP_IADC_EN_CTL1,
- data);
- if (rc < 0) {
- pr_err("IADC enable failed\n");
- return rc;
- }
- } else {
- rc = qpnp_iadc_write_reg(QPNP_IADC_EN_CTL1,
- (~data & QPNP_IADC_ADC_EN));
- if (rc < 0) {
- pr_err("IADC disable failed\n");
- return rc;
- }
+ rc = qpnp_iadc_enable(false);
+ if (rc < 0) {
+ pr_err("IADC disable failed with %d\n", rc);
+ return rc;
}
return 0;
@@ -721,7 +730,8 @@
GFP_KERNEL);
if (!adc_qpnp) {
dev_err(&spmi->dev, "Unable to allocate memory\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto fail;
}
iadc->adc = adc_qpnp;
@@ -729,14 +739,14 @@
rc = qpnp_adc_get_devicetree_data(spmi, iadc->adc);
if (rc) {
dev_err(&spmi->dev, "failed to read device tree\n");
- return rc;
+ goto fail;
}
rc = of_property_read_u32(node, "qcom,rsense",
&iadc->rsense);
if (rc) {
pr_err("Invalid rsens reference property\n");
- return -EINVAL;
+ goto fail;
}
rc = devm_request_irq(&spmi->dev, iadc->adc->adc_irq_eoc,
@@ -744,7 +754,7 @@
IRQF_TRIGGER_RISING, "qpnp_iadc_interrupt", iadc);
if (rc) {
dev_err(&spmi->dev, "failed to request adc irq\n");
- return rc;
+ goto fail;
} else
enable_irq_wake(iadc->adc->adc_irq_eoc);
@@ -755,20 +765,20 @@
rc = qpnp_iadc_init_hwmon(spmi);
if (rc) {
dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
- return rc;
+ goto fail;
}
iadc->iadc_hwmon = hwmon_device_register(&iadc->adc->spmi->dev);
rc = qpnp_iadc_version_check();
if (rc) {
dev_err(&spmi->dev, "IADC version not supported\n");
- return rc;
+ goto fail;
}
rc = qpnp_iadc_calibrate_for_trim();
if (rc) {
dev_err(&spmi->dev, "failed to calibrate for USR trim\n");
- return rc;
+ goto fail;
}
iadc->iadc_init_calib = true;
INIT_DELAYED_WORK(&iadc->iadc_work, qpnp_iadc_work);
@@ -778,6 +788,9 @@
iadc->iadc_initialized = true;
return 0;
+fail:
+ adc_qpnp = NULL;
+ return rc;
}
static int __devexit qpnp_iadc_remove(struct spmi_device *spmi)
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index d8d5b53..3df19d7 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -170,6 +170,58 @@
return 0;
}
+static int32_t qpnp_vadc_status_debug(void)
+{
+ int rc = 0;
+ u8 mode = 0, status1 = 0, chan = 0, dig = 0, en = 0, status2 = 0;
+
+ rc = qpnp_vadc_read_reg(QPNP_VADC_MODE_CTL, &mode);
+ if (rc < 0) {
+ pr_err("mode ctl register read failed with %d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_DIG_PARAM, &dig);
+ if (rc < 0) {
+ pr_err("digital param read failed with %d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_CH_SEL_CTL, &chan);
+ if (rc < 0) {
+ pr_err("channel read failed with %d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
+ if (rc < 0) {
+ pr_err("status1 read failed with %d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS2, &status2);
+ if (rc < 0) {
+ pr_err("status2 read failed with %d\n", rc);
+ return rc;
+ }
+
+ rc = qpnp_vadc_read_reg(QPNP_VADC_EN_CTL1, &en);
+ if (rc < 0) {
+ pr_err("en read failed with %d\n", rc);
+ return rc;
+ }
+
+ pr_err("EOC not set - status1/2:%x/%x, dig:%x, ch:%x, mode:%x, en:%x\n",
+ status1, status2, dig, chan, mode, en);
+
+ rc = qpnp_vadc_enable(false);
+ if (rc < 0) {
+ pr_err("VADC disable failed with %d\n", rc);
+ return rc;
+ }
+
+ return 0;
+}
static int32_t qpnp_vadc_configure(
struct qpnp_adc_amux_properties *chan_prop)
{
@@ -339,6 +391,9 @@
{
struct qpnp_vadc_drv *vadc = qpnp_vadc;
+ if (!vadc || !vadc->vadc_initialized)
+ return;
+
complete(&vadc->adc->adc_rslt_completion);
return;
@@ -563,20 +618,21 @@
if (!vadc || !vadc->vadc_initialized)
return -EPROBE_DEFER;
+ mutex_lock(&vadc->adc->adc_lock);
+
if (!vadc->vadc_init_calib) {
rc = qpnp_vadc_version_check();
if (rc)
- return rc;
+ goto fail_unlock;
+
rc = qpnp_vadc_calib_device();
if (rc) {
pr_err("Calibration failed\n");
- return rc;
+ goto fail_unlock;
} else
vadc->vadc_init_calib = true;
}
- mutex_lock(&vadc->adc->adc_lock);
-
vadc->adc->amux_prop->amux_channel = channel;
while ((vadc->adc->adc_channels[dt_index].channel_num
@@ -626,7 +682,9 @@
if (status1 == QPNP_VADC_STATUS1_EOC)
pr_debug("End of conversion status set\n");
else {
- pr_err("EOC interrupt not received\n");
+ rc = qpnp_vadc_status_debug();
+ if (rc < 0)
+ pr_err("VADC disable failed\n");
rc = -EINVAL;
goto fail_unlock;
}
@@ -765,7 +823,8 @@
GFP_KERNEL);
if (!adc_qpnp) {
dev_err(&spmi->dev, "Unable to allocate memory\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto fail;
}
vadc->adc = adc_qpnp;
@@ -773,7 +832,7 @@
rc = qpnp_adc_get_devicetree_data(spmi, vadc->adc);
if (rc) {
dev_err(&spmi->dev, "failed to read device tree\n");
- return rc;
+ goto fail;
}
rc = devm_request_irq(&spmi->dev, vadc->adc->adc_irq_eoc,
@@ -782,7 +841,7 @@
if (rc) {
dev_err(&spmi->dev,
"failed to request adc irq with error %d\n", rc);
- return rc;
+ goto fail;
} else {
enable_irq_wake(vadc->adc->adc_irq_eoc);
}
@@ -792,7 +851,7 @@
rc = qpnp_vadc_init_hwmon(spmi);
if (rc) {
dev_err(&spmi->dev, "failed to initialize qpnp hwmon adc\n");
- return rc;
+ goto fail;
}
vadc->vadc_hwmon = hwmon_device_register(&vadc->adc->spmi->dev);
vadc->vadc_init_calib = false;
@@ -800,6 +859,9 @@
vadc->vadc_initialized = true;
return 0;
+fail:
+ qpnp_vadc = NULL;
+ return rc;
}
static int __devexit qpnp_vadc_remove(struct spmi_device *spmi)
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 1ce1cf8..38e6fb7 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -428,7 +428,7 @@
if (!priv || !dev) {
ret = -EINVAL;
- goto fail;
+ goto unlock;
}
iommu_drvdata = dev_get_drvdata(dev->parent);
@@ -436,23 +436,28 @@
if (!iommu_drvdata || !ctx_drvdata) {
ret = -EINVAL;
- goto fail;
+ goto unlock;
}
+ ++ctx_drvdata->attach_count;
+
+ if (ctx_drvdata->attach_count > 1)
+ goto unlock;
+
if (!list_empty(&ctx_drvdata->attached_elm)) {
ret = -EBUSY;
- goto fail;
+ goto unlock;
}
list_for_each_entry(tmp_drvdata, &priv->list_attached, attached_elm)
if (tmp_drvdata == ctx_drvdata) {
ret = -EBUSY;
- goto fail;
+ goto unlock;
}
ret = __enable_clocks(iommu_drvdata);
if (ret)
- goto fail;
+ goto unlock;
__program_context(iommu_drvdata->base, iommu_drvdata->glb_base,
ctx_drvdata->num, iommu_drvdata->ncb,
@@ -463,7 +468,7 @@
list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
ctx_drvdata->attached_domain = domain;
-fail:
+unlock:
mutex_unlock(&msm_iommu_lock);
return ret;
}
@@ -472,7 +477,6 @@
struct device *dev)
{
struct msm_priv *priv;
- struct msm_iommu_ctx_dev *ctx_dev;
struct msm_iommu_drvdata *iommu_drvdata;
struct msm_iommu_ctx_drvdata *ctx_drvdata;
int ret;
@@ -481,33 +485,38 @@
priv = domain->priv;
if (!priv || !dev)
- goto fail;
+ goto unlock;
iommu_drvdata = dev_get_drvdata(dev->parent);
ctx_drvdata = dev_get_drvdata(dev);
- ctx_dev = dev->platform_data;
- if (!iommu_drvdata || !ctx_drvdata || !ctx_dev)
- goto fail;
+ if (!iommu_drvdata || !ctx_drvdata)
+ goto unlock;
+
+ --ctx_drvdata->attach_count;
+ BUG_ON(ctx_drvdata->attach_count < 0);
+
+ if (ctx_drvdata->attach_count > 0)
+ goto unlock;
ret = __enable_clocks(iommu_drvdata);
if (ret)
- goto fail;
+ goto unlock;
msm_iommu_remote_spin_lock();
- SET_TLBIASID(iommu_drvdata->base, ctx_dev->num,
- GET_CONTEXTIDR_ASID(iommu_drvdata->base, ctx_dev->num));
+ SET_TLBIASID(iommu_drvdata->base, ctx_drvdata->num,
+ GET_CONTEXTIDR_ASID(iommu_drvdata->base, ctx_drvdata->num));
__reset_context(iommu_drvdata->base, iommu_drvdata->glb_base,
- ctx_dev->num);
+ ctx_drvdata->num);
msm_iommu_remote_spin_unlock();
__disable_clocks(iommu_drvdata);
list_del_init(&ctx_drvdata->attached_elm);
ctx_drvdata->attached_domain = NULL;
-fail:
+unlock:
mutex_unlock(&msm_iommu_lock);
}
diff --git a/drivers/iommu/msm_iommu_dev.c b/drivers/iommu/msm_iommu_dev.c
index 44fe454..470d8ce 100644
--- a/drivers/iommu/msm_iommu_dev.c
+++ b/drivers/iommu/msm_iommu_dev.c
@@ -489,6 +489,7 @@
ctx_drvdata->pdev = pdev;
INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
platform_set_drvdata(pdev, ctx_drvdata);
+ ctx_drvdata->attach_count = 0;
if (pdev->dev.of_node) {
ret = msm_iommu_ctx_parse_dt(pdev, ctx_drvdata);
diff --git a/drivers/media/video/msm_vidc/Makefile b/drivers/media/video/msm_vidc/Makefile
index 2a1f40f..c8e7076 100644
--- a/drivers/media/video/msm_vidc/Makefile
+++ b/drivers/media/video/msm_vidc/Makefile
@@ -5,5 +5,6 @@
msm_venc.o \
msm_smem.o \
msm_vidc_debug.o \
- vidc_hal.o \
- vidc_hal_interrupt_handler.o \
+ venus_hfi.o \
+ hfi_response_handler.o \
+ hfi_packetization.o \
diff --git a/drivers/media/video/msm_vidc/hfi_packetization.c b/drivers/media/video/msm_vidc/hfi_packetization.c
new file mode 100644
index 0000000..509b013
--- /dev/null
+++ b/drivers/media/video/msm_vidc/hfi_packetization.c
@@ -0,0 +1,1101 @@
+/* Copyright (c) 2012, 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 "hfi_packetization.h"
+#include "msm_vidc_debug.h"
+#include <linux/errno.h>
+#include <mach/ocmem.h>
+
+int create_pkt_cmd_sys_init(struct hfi_cmd_sys_init_packet *pkt,
+ u32 arch_type)
+{
+ int rc = 0;
+ if (!pkt)
+ return -EINVAL;
+
+ pkt->packet_type = HFI_CMD_SYS_INIT;
+ pkt->size = sizeof(struct hfi_cmd_sys_init_packet);
+ pkt->arch_type = arch_type;
+ return rc;
+}
+
+int create_pkt_cmd_sys_pc_prep(struct hfi_cmd_sys_pc_prep_packet *pkt)
+{
+ int rc = 0;
+ if (!pkt)
+ return -EINVAL;
+
+ pkt->packet_type = HFI_CMD_SYS_PC_PREP;
+ pkt->size = sizeof(struct hfi_cmd_sys_pc_prep_packet);
+ return rc;
+}
+
+int create_pkt_set_cmd_sys_resource(
+ struct hfi_cmd_sys_set_resource_packet *pkt,
+ struct vidc_resource_hdr *resource_hdr,
+ void *resource_value)
+{
+ int rc = 0;
+ if (!pkt || !resource_hdr || !resource_value)
+ return -EINVAL;
+
+ pkt->packet_type = HFI_CMD_SYS_SET_RESOURCE;
+ pkt->size = sizeof(struct hfi_cmd_sys_set_resource_packet);
+ pkt->resource_handle = resource_hdr->resource_handle;
+
+ switch (resource_hdr->resource_id) {
+ case VIDC_RESOURCE_OCMEM:
+ {
+ struct hfi_resource_ocmem *hfioc_mem =
+ (struct hfi_resource_ocmem *)
+ &pkt->rg_resource_data[0];
+ struct ocmem_buf *ocmem =
+ (struct ocmem_buf *) resource_value;
+
+ pkt->resource_type = HFI_RESOURCE_OCMEM;
+ pkt->size += sizeof(struct hfi_resource_ocmem);
+ hfioc_mem->size = (u32) ocmem->len;
+ hfioc_mem->mem = (u8 *) ocmem->addr;
+ break;
+ }
+ default:
+ dprintk(VIDC_ERR, "Invalid resource_id %d",
+ resource_hdr->resource_id);
+ rc = -EINVAL;
+ }
+
+ return rc;
+}
+
+int create_pkt_cmd_sys_release_resource(
+ struct hfi_cmd_sys_release_resource_packet *pkt,
+ struct vidc_resource_hdr *resource_hdr)
+{
+ int rc = 0;
+ if (!pkt)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct hfi_cmd_sys_release_resource_packet);
+ pkt->packet_type = HFI_CMD_SYS_RELEASE_RESOURCE;
+ pkt->resource_type = resource_hdr->resource_id;
+ pkt->resource_handle = resource_hdr->resource_handle;
+
+ return rc;
+}
+
+int create_pkt_cmd_sys_ping(struct hfi_cmd_sys_ping_packet *pkt)
+{
+ int rc = 0;
+ if (!pkt)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct hfi_cmd_sys_ping_packet);
+ pkt->packet_type = HFI_CMD_SYS_PING;
+
+ return rc;
+}
+
+inline int create_pkt_cmd_sys_session_init(
+ struct hfi_cmd_sys_session_init_packet *pkt,
+ u32 session_id, u32 session_domain, u32 session_codec)
+{
+ int rc = 0;
+ if (!pkt)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct hfi_cmd_sys_session_init_packet);
+ pkt->packet_type = HFI_CMD_SYS_SESSION_INIT;
+ pkt->session_id = session_id;
+ pkt->session_domain = session_domain;
+ pkt->session_codec = session_codec;
+
+ return rc;
+}
+
+int create_pkt_cmd_session_cmd(struct vidc_hal_session_cmd_pkt *pkt,
+ int pkt_type, u32 session_id)
+{
+ int rc = 0;
+ if (!pkt)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct vidc_hal_session_cmd_pkt);
+ pkt->packet_type = pkt_type;
+ pkt->session_id = session_id;
+
+ return rc;
+}
+
+static u32 get_hfi_buffer(int hal_buffer)
+{
+ u32 buffer;
+ switch (hal_buffer) {
+ case HAL_BUFFER_INPUT:
+ buffer = HFI_BUFFER_INPUT;
+ break;
+ case HAL_BUFFER_OUTPUT:
+ buffer = HFI_BUFFER_OUTPUT;
+ break;
+ case HAL_BUFFER_OUTPUT2:
+ buffer = HFI_BUFFER_OUTPUT;
+ break;
+ case HAL_BUFFER_EXTRADATA_INPUT:
+ buffer = HFI_BUFFER_EXTRADATA_INPUT;
+ break;
+ case HAL_BUFFER_EXTRADATA_OUTPUT:
+ buffer = HFI_BUFFER_EXTRADATA_OUTPUT;
+ break;
+ case HAL_BUFFER_EXTRADATA_OUTPUT2:
+ buffer = HFI_BUFFER_EXTRADATA_OUTPUT2;
+ break;
+ case HAL_BUFFER_INTERNAL_SCRATCH:
+ buffer = HFI_BUFFER_INTERNAL_SCRATCH;
+ break;
+ case HAL_BUFFER_INTERNAL_PERSIST:
+ buffer = HFI_BUFFER_INTERNAL_PERSIST;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid buffer :0x%x\n",
+ hal_buffer);
+ buffer = 0;
+ break;
+ }
+ return buffer;
+}
+
+static int get_hfi_extradata_index(enum hal_extradata_id index)
+{
+ int ret = 0;
+ switch (index) {
+ case HAL_EXTRADATA_MB_QUANTIZATION:
+ ret = HFI_PROPERTY_PARAM_VDEC_MB_QUANTIZATION;
+ break;
+ case HAL_EXTRADATA_INTERLACE_VIDEO:
+ ret = HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_VC1_FRAMEDISP:
+ ret = HFI_PROPERTY_PARAM_VDEC_VC1_FRAMEDISP_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_VC1_SEQDISP:
+ ret = HFI_PROPERTY_PARAM_VDEC_VC1_SEQDISP_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_TIMESTAMP:
+ ret = HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_S3D_FRAME_PACKING:
+ ret = HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_FRAME_RATE:
+ ret = HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_PANSCAN_WINDOW:
+ ret = HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_RECOVERY_POINT_SEI:
+ ret = HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_CLOSED_CAPTION_UD:
+ ret = HFI_PROPERTY_PARAM_VDEC_CLOSED_CAPTION_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_AFD_UD:
+ ret = HFI_PROPERTY_PARAM_VDEC_AFD_EXTRADATA;
+ break;
+ case HAL_EXTRADATA_MULTISLICE_INFO:
+ ret = HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_INFO;
+ break;
+ case HAL_EXTRADATA_NUM_CONCEALED_MB:
+ ret = HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB;
+ break;
+ case HAL_EXTRADATA_INDEX:
+ ret = HFI_PROPERTY_PARAM_EXTRA_DATA_HEADER_CONFIG;
+ break;
+ default:
+ dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
+ break;
+ }
+ return ret;
+}
+
+int create_pkt_cmd_session_set_buffers(
+ struct hfi_cmd_session_set_buffers_packet *pkt,
+ u32 session_id,
+ struct vidc_buffer_addr_info *buffer_info)
+{
+ int rc = 0;
+ int i = 0;
+ if (!pkt || !session_id)
+ return -EINVAL;
+
+ pkt->packet_type = HFI_CMD_SESSION_SET_BUFFERS;
+ pkt->session_id = session_id;
+ pkt->buffer_size = buffer_info->buffer_size;
+ pkt->min_buffer_size = buffer_info->buffer_size;
+ pkt->num_buffers = buffer_info->num_buffers;
+
+ if ((buffer_info->buffer_type == HAL_BUFFER_OUTPUT) ||
+ (buffer_info->buffer_type == HAL_BUFFER_OUTPUT2)) {
+ struct hfi_buffer_info *buff;
+ pkt->extra_data_size = buffer_info->extradata_size;
+ pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) -
+ sizeof(u32) + (buffer_info->num_buffers *
+ sizeof(struct hfi_buffer_info));
+ buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
+ for (i = 0; i < pkt->num_buffers; i++) {
+ buff->buffer_addr = buffer_info->align_device_addr;
+ buff->extra_data_addr = buffer_info->extradata_addr;
+ }
+ } else {
+ pkt->extra_data_size = 0;
+ pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) +
+ ((buffer_info->num_buffers - 1) * sizeof(u32));
+ for (i = 0; i < pkt->num_buffers; i++)
+ pkt->rg_buffer_info[i] = buffer_info->align_device_addr;
+ }
+
+ pkt->buffer_type = get_hfi_buffer(buffer_info->buffer_type);
+ if (!pkt->buffer_type)
+ return -EINVAL;
+
+ return rc;
+}
+
+int create_pkt_cmd_session_release_buffers(
+ struct hfi_cmd_session_release_buffer_packet *pkt,
+ u32 session_id, struct vidc_buffer_addr_info *buffer_info)
+{
+ int rc = 0;
+ int i = 0;
+ if (!pkt || !session_id)
+ return -EINVAL;
+
+ pkt->packet_type = HFI_CMD_SESSION_RELEASE_BUFFERS;
+ pkt->session_id = session_id;
+ pkt->buffer_size = buffer_info->buffer_size;
+ pkt->num_buffers = buffer_info->num_buffers;
+
+ if ((buffer_info->buffer_type == HAL_BUFFER_OUTPUT) ||
+ (buffer_info->buffer_type == HAL_BUFFER_OUTPUT2)) {
+ struct hfi_buffer_info *buff;
+ buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
+ for (i = 0; i < pkt->num_buffers; i++) {
+ buff->buffer_addr = buffer_info->align_device_addr;
+ buff->extra_data_addr = buffer_info->extradata_addr;
+ }
+ pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) -
+ sizeof(u32) + (buffer_info->num_buffers *
+ sizeof(struct hfi_buffer_info));
+ } else {
+ for (i = 0; i < pkt->num_buffers; i++)
+ pkt->rg_buffer_info[i] = buffer_info->align_device_addr;
+ pkt->extra_data_size = 0;
+ pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) +
+ ((buffer_info->num_buffers - 1) * sizeof(u32));
+ }
+ pkt->response_req = buffer_info->response_required;
+ pkt->buffer_type = get_hfi_buffer(buffer_info->buffer_type);
+ if (!pkt->buffer_type)
+ return -EINVAL;
+ return rc;
+}
+
+int create_pkt_cmd_session_etb_decoder(
+ struct hfi_cmd_session_empty_buffer_compressed_packet *pkt,
+ u32 session_id, struct vidc_frame_data *input_frame)
+{
+ int rc = 0;
+ if (!pkt || !session_id)
+ return -EINVAL;
+
+ pkt->size =
+ sizeof(struct hfi_cmd_session_empty_buffer_compressed_packet);
+ pkt->packet_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+ pkt->session_id = session_id;
+ pkt->time_stamp_hi = (int) (((u64)input_frame->timestamp) >> 32);
+ pkt->time_stamp_lo = (int) input_frame->timestamp;
+ pkt->flags = input_frame->flags;
+ pkt->mark_target = input_frame->mark_target;
+ pkt->mark_data = input_frame->mark_data;
+ pkt->offset = input_frame->offset;
+ pkt->alloc_len = input_frame->alloc_len;
+ pkt->filled_len = input_frame->filled_len;
+ pkt->input_tag = input_frame->clnt_data;
+ pkt->packet_buffer = (u8 *) input_frame->device_addr;
+
+ if (!pkt->packet_buffer)
+ return -EINVAL;
+ return rc;
+}
+
+int create_pkt_cmd_session_etb_encoder(
+ struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet *pkt,
+ u32 session_id, struct vidc_frame_data *input_frame)
+{
+ int rc = 0;
+ if (!pkt || !session_id)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct
+ hfi_cmd_session_empty_buffer_uncompressed_plane0_packet);
+ pkt->packet_type = HFI_CMD_SESSION_EMPTY_BUFFER;
+ pkt->session_id = session_id;
+ pkt->view_id = 0;
+ pkt->time_stamp_hi = (u32)(((u64)input_frame->timestamp) >> 32);
+ pkt->time_stamp_lo = (u32)input_frame->timestamp;
+ pkt->flags = input_frame->flags;
+ pkt->mark_target = input_frame->mark_target;
+ pkt->mark_data = input_frame->mark_data;
+ pkt->offset = input_frame->offset;
+ pkt->alloc_len = input_frame->alloc_len;
+ pkt->filled_len = input_frame->filled_len;
+ pkt->input_tag = input_frame->clnt_data;
+ pkt->packet_buffer = (u8 *) input_frame->device_addr;
+
+ if (!pkt->packet_buffer)
+ return -EINVAL;
+ return rc;
+}
+
+int create_pkt_cmd_session_ftb(struct hfi_cmd_session_fill_buffer_packet *pkt,
+ u32 session_id, struct vidc_frame_data *output_frame)
+{
+ int rc = 0;
+ if (!pkt || !session_id || !output_frame)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct hfi_cmd_session_fill_buffer_packet);
+ pkt->packet_type = HFI_CMD_SESSION_FILL_BUFFER;
+ pkt->session_id = session_id;
+
+ if (output_frame->buffer_type == HAL_BUFFER_OUTPUT)
+ pkt->stream_id = 0;
+ else if (output_frame->buffer_type == HAL_BUFFER_OUTPUT2)
+ pkt->stream_id = 1;
+
+ if (!output_frame->device_addr)
+ return -EINVAL;
+
+ pkt->packet_buffer = (u8 *) output_frame->device_addr;
+ pkt->extra_data_buffer = (u8 *) output_frame->extradata_addr;
+
+ pkt->alloc_len = output_frame->alloc_len;
+ pkt->filled_len = output_frame->filled_len;
+ pkt->offset = output_frame->offset;
+ dprintk(VIDC_DBG, "### Q OUTPUT BUFFER ###: %d, %d, %d\n",
+ pkt->alloc_len, pkt->filled_len, pkt->offset);
+
+ return rc;
+}
+
+int create_pkt_cmd_session_parse_seq_header(
+ struct hfi_cmd_session_parse_sequence_header_packet *pkt,
+ u32 session_id, struct vidc_seq_hdr *seq_hdr)
+{
+ int rc = 0;
+ if (!pkt || !session_id || seq_hdr)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct hfi_cmd_session_parse_sequence_header_packet);
+ pkt->packet_type = HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER;
+ pkt->session_id = session_id;
+ pkt->header_len = seq_hdr->seq_hdr_len;
+ if (!seq_hdr->seq_hdr)
+ return -EINVAL;
+ pkt->packet_buffer = seq_hdr->seq_hdr;
+
+ return rc;
+}
+
+int create_pkt_cmd_session_get_seq_hdr(
+ struct hfi_cmd_session_get_sequence_header_packet *pkt,
+ u32 session_id, struct vidc_seq_hdr *seq_hdr)
+{
+ int rc = 0;
+
+ if (!pkt || !session_id || !seq_hdr)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct hfi_cmd_session_get_sequence_header_packet);
+ pkt->packet_type = HFI_CMD_SESSION_GET_SEQUENCE_HEADER;
+ pkt->session_id = session_id;
+ pkt->buffer_len = seq_hdr->seq_hdr_len;
+ if (!seq_hdr->seq_hdr)
+ return -EINVAL;
+ pkt->packet_buffer = seq_hdr->seq_hdr;
+
+ return rc;
+}
+
+int create_pkt_cmd_session_get_buf_req(
+ struct hfi_cmd_session_get_property_packet *pkt,
+ u32 session_id)
+{
+ int rc = 0;
+
+ if (!pkt || !session_id)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct hfi_cmd_session_get_property_packet);
+ pkt->packet_type = HFI_CMD_SESSION_GET_PROPERTY;
+ pkt->session_id = session_id;
+ pkt->num_properties = 1;
+ pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS;
+
+ return rc;
+}
+
+int create_pkt_cmd_session_flush(struct hfi_cmd_session_flush_packet *pkt,
+ u32 session_id, enum hal_flush flush_mode)
+{
+ int rc = 0;
+ if (!pkt || !session_id)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct hfi_cmd_session_flush_packet);
+ pkt->packet_type = HFI_CMD_SESSION_FLUSH;
+ pkt->session_id = session_id;
+ switch (flush_mode) {
+ case HAL_FLUSH_INPUT:
+ pkt->flush_type = HFI_FLUSH_INPUT;
+ break;
+ case HAL_FLUSH_OUTPUT:
+ pkt->flush_type = HFI_FLUSH_OUTPUT;
+ break;
+ case HAL_FLUSH_OUTPUT2:
+ pkt->flush_type = HFI_FLUSH_OUTPUT2;
+ break;
+ case HAL_FLUSH_ALL:
+ pkt->flush_type = HFI_FLUSH_ALL;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid flush mode: 0x%x\n", flush_mode);
+ return -EINVAL;
+ }
+ return rc;
+}
+
+int create_pkt_cmd_session_set_property(
+ struct hfi_cmd_session_set_property_packet *pkt,
+ u32 session_id, enum hal_property ptype, void *pdata)
+{
+ int rc = 0;
+ if (!pkt || !session_id)
+ return -EINVAL;
+
+ pkt->size = sizeof(struct hfi_cmd_session_set_property_packet);
+ pkt->packet_type = HFI_CMD_SESSION_SET_PROPERTY;
+ pkt->session_id = session_id;
+ pkt->num_properties = 1;
+
+ switch (ptype) {
+ case HAL_CONFIG_FRAME_RATE:
+ {
+ u32 buffer_type;
+ struct hfi_frame_rate *hfi;
+ struct hal_frame_rate *prop = (struct hal_frame_rate *) pdata;
+
+ pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_FRAME_RATE;
+ hfi = (struct hfi_frame_rate *) &pkt->rg_property_data[1];
+ buffer_type = get_hfi_buffer(prop->buffer_type);
+ if (buffer_type)
+ hfi->buffer_type = buffer_type;
+ else
+ return -EINVAL;
+
+ hfi->frame_rate = prop->frame_rate;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_frame_rate);
+ break;
+ }
+ case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT:
+ {
+ u32 buffer_type;
+ struct hfi_uncompressed_format_select *hfi;
+ struct hal_uncompressed_format_select *prop =
+ (struct hal_uncompressed_format_select *) pdata;
+
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
+
+ hfi = (struct hfi_uncompressed_format_select *)
+ &pkt->rg_property_data[1];
+ buffer_type = get_hfi_buffer(prop->buffer_type);
+ if (buffer_type)
+ hfi->buffer_type = buffer_type;
+ else
+ return -EINVAL;
+ hfi->format = prop->format;
+ pkt->size += sizeof(u32) +
+ sizeof(struct hfi_uncompressed_format_select);
+ break;
+ }
+ case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO:
+ break;
+ case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO:
+ break;
+ case HAL_PARAM_EXTRA_DATA_HEADER_CONFIG:
+ break;
+ case HAL_PARAM_FRAME_SIZE:
+ {
+ struct hfi_frame_size *hfi;
+ struct hal_frame_size *prop = (struct hal_frame_size *) pdata;
+ u32 buffer_type;
+
+ pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_FRAME_SIZE;
+ hfi = (struct hfi_frame_size *) &pkt->rg_property_data[1];
+ buffer_type = get_hfi_buffer(prop->buffer_type);
+ if (buffer_type)
+ hfi->buffer_type = buffer_type;
+ else
+ return -EINVAL;
+
+ hfi->height = prop->height;
+ hfi->width = prop->width;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_frame_size);
+ break;
+ }
+ case HAL_CONFIG_REALTIME:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_REALTIME;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hfi_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_BUFFER_COUNT_ACTUAL:
+ {
+ struct hfi_buffer_count_actual *hfi;
+ struct hal_buffer_count_actual *prop =
+ (struct hal_buffer_count_actual *) pdata;
+ u32 buffer_type;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
+ hfi = (struct hfi_buffer_count_actual *)
+ &pkt->rg_property_data[1];
+ hfi->buffer_count_actual = prop->buffer_count_actual;
+
+ buffer_type = get_hfi_buffer(prop->buffer_type);
+ if (buffer_type)
+ hfi->buffer_type = buffer_type;
+ else
+ return -EINVAL;
+
+ pkt->size += sizeof(u32) + sizeof(struct
+ hfi_buffer_count_actual);
+
+ break;
+ }
+ case HAL_PARAM_NAL_STREAM_FORMAT_SELECT:
+ {
+ struct hal_nal_stream_format_supported *prop =
+ (struct hal_nal_stream_format_supported *)pdata;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT;
+ dprintk(VIDC_DBG, "data is :%d",
+ prop->nal_stream_format_supported);
+
+ switch (prop->nal_stream_format_supported) {
+ case HAL_NAL_FORMAT_STARTCODES:
+ pkt->rg_property_data[1] =
+ HFI_NAL_FORMAT_STARTCODES;
+ break;
+ case HAL_NAL_FORMAT_ONE_NAL_PER_BUFFER:
+ pkt->rg_property_data[1] =
+ HFI_NAL_FORMAT_ONE_NAL_PER_BUFFER;
+ break;
+ case HAL_NAL_FORMAT_ONE_BYTE_LENGTH:
+ pkt->rg_property_data[1] =
+ HFI_NAL_FORMAT_ONE_BYTE_LENGTH;
+ break;
+ case HAL_NAL_FORMAT_TWO_BYTE_LENGTH:
+ pkt->rg_property_data[1] =
+ HFI_NAL_FORMAT_TWO_BYTE_LENGTH;
+ break;
+ case HAL_NAL_FORMAT_FOUR_BYTE_LENGTH:
+ pkt->rg_property_data[1] =
+ HFI_NAL_FORMAT_FOUR_BYTE_LENGTH;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid nal format: 0x%x",
+ prop->nal_stream_format_supported);
+ break;
+ }
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_VDEC_OUTPUT_ORDER:
+ {
+ int *data = (int *) pdata;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER;
+ switch (*data) {
+ case HAL_OUTPUT_ORDER_DECODE:
+ pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DECODE;
+ break;
+ case HAL_OUTPUT_ORDER_DISPLAY:
+ pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DISPLAY;
+ break;
+ default:
+ dprintk(VIDC_ERR, "invalid output order: 0x%x",
+ *data);
+ break;
+ }
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_VDEC_PICTURE_TYPE_DECODE:
+ {
+ struct hfi_enable_picture *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE;
+ hfi = (struct hfi_enable_picture *) &pkt->rg_property_data[1];
+ hfi->picture_type = (u32) pdata;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hfi_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hfi_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_VDEC_MULTI_STREAM:
+ {
+ struct hfi_multi_stream *hfi;
+ struct hal_multi_stream *prop =
+ (struct hal_multi_stream *) pdata;
+ u32 buffer_type;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
+ hfi = (struct hfi_multi_stream *) &pkt->rg_property_data[1];
+
+ buffer_type = get_hfi_buffer(prop->buffer_type);
+ if (buffer_type)
+ hfi->buffer_type = buffer_type;
+ else
+ return -EINVAL;
+ hfi->enable = prop->enable;
+ hfi->width = prop->width;
+ hfi->height = prop->height;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_multi_stream);
+ break;
+ }
+ case HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT:
+ {
+ struct hfi_display_picture_buffer_count *hfi;
+ struct hal_display_picture_buffer_count *prop =
+ (struct hal_display_picture_buffer_count *) pdata;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT;
+ hfi = (struct hfi_display_picture_buffer_count *)
+ &pkt->rg_property_data[1];
+ hfi->count = prop->count;
+ hfi->enable = prop->enable;
+ pkt->size += sizeof(u32) +
+ sizeof(struct hfi_display_picture_buffer_count);
+ break;
+ }
+ case HAL_PARAM_DIVX_FORMAT:
+ {
+ int *data = pdata;
+ pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_DIVX_FORMAT;
+ switch (*data) {
+ case HAL_DIVX_FORMAT_4:
+ pkt->rg_property_data[1] = HFI_DIVX_FORMAT_4;
+ break;
+ case HAL_DIVX_FORMAT_5:
+ pkt->rg_property_data[1] = HFI_DIVX_FORMAT_5;
+ break;
+ case HAL_DIVX_FORMAT_6:
+ pkt->rg_property_data[1] = HFI_DIVX_FORMAT_6;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid divx format: 0x%x", *data);
+ break;
+ }
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP_REPORTING;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hfi_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hfi_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_VDEC_SYNC_FRAME_DECODE:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hfi_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER:
+ {
+ struct hfi_enable *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER;
+ hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
+ hfi->enable = ((struct hfi_enable *) pdata)->enable;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_CONFIG_VENC_REQUEST_IFRAME:
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_CONFIG_VENC_REQUEST_SYNC_FRAME;
+ pkt->size += sizeof(u32);
+ break;
+ case HAL_PARAM_VENC_MPEG4_SHORT_HEADER:
+ break;
+ case HAL_PARAM_VENC_MPEG4_AC_PREDICTION:
+ break;
+ case HAL_CONFIG_VENC_TARGET_BITRATE:
+ {
+ struct hfi_bitrate *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
+ hfi = (struct hfi_bitrate *) &pkt->rg_property_data[1];
+ hfi->bit_rate = ((struct hal_bitrate *)pdata)->bit_rate;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_PROFILE_LEVEL_CURRENT:
+ {
+ struct hfi_profile_level *hfi;
+ struct hal_profile_level *prop =
+ (struct hal_profile_level *) pdata;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;
+ hfi = (struct hfi_profile_level *)
+ &pkt->rg_property_data[1];
+ hfi->level = (u32) prop->level;
+ hfi->profile = prop->profile;
+ if (!hfi->profile)
+ hfi->profile = HFI_H264_PROFILE_HIGH;
+ if (!hfi->level)
+ hfi->level = 1;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_profile_level);
+ break;
+ }
+ case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
+ {
+ struct hfi_h264_entropy_control *hfi;
+ struct hal_h264_entropy_control *prop =
+ (struct hal_h264_entropy_control *) pdata;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
+ hfi = (struct hfi_h264_entropy_control *)
+ &pkt->rg_property_data[1];
+ switch (prop->entropy_mode) {
+ case HAL_H264_ENTROPY_CAVLC:
+ hfi->cabac_model = HFI_H264_ENTROPY_CAVLC;
+ break;
+ case HAL_H264_ENTROPY_CABAC:
+ hfi->cabac_model = HFI_H264_ENTROPY_CABAC;
+ switch (prop->cabac_model) {
+ case HAL_H264_CABAC_MODEL_0:
+ hfi->cabac_model = HFI_H264_CABAC_MODEL_0;
+ break;
+ case HAL_H264_CABAC_MODEL_1:
+ hfi->cabac_model = HFI_H264_CABAC_MODEL_1;
+ break;
+ case HAL_H264_CABAC_MODEL_2:
+ hfi->cabac_model = HFI_H264_CABAC_MODEL_2;
+ break;
+ default:
+ dprintk(VIDC_ERR,
+ "Invalid cabac model 0x%x",
+ prop->entropy_mode);
+ break;
+ }
+ break;
+ default:
+ dprintk(VIDC_ERR,
+ "Invalid entropy selected: 0x%x",
+ prop->cabac_model);
+ break;
+ }
+ pkt->size += sizeof(u32) + sizeof(
+ struct hfi_h264_entropy_control);
+ break;
+ }
+ case HAL_PARAM_VENC_RATE_CONTROL:
+ {
+ u32 *rc;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
+ rc = (u32 *)pdata;
+ switch ((enum hal_rate_control) *rc) {
+ case HAL_RATE_CONTROL_OFF:
+ pkt->rg_property_data[1] = HFI_RATE_CONTROL_OFF;
+ break;
+ case HAL_RATE_CONTROL_CBR_CFR:
+ pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_CFR;
+ break;
+ case HAL_RATE_CONTROL_CBR_VFR:
+ pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_VFR;
+ break;
+ case HAL_RATE_CONTROL_VBR_CFR:
+ pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_CFR;
+ break;
+ case HAL_RATE_CONTROL_VBR_VFR:
+ pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_VFR;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid Rate control setting: 0x%x",
+ (int) pdata);
+ break;
+ }
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION:
+ {
+ struct hfi_mpeg4_time_resolution *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_MPEG4_TIME_RESOLUTION;
+ hfi = (struct hfi_mpeg4_time_resolution *)
+ &pkt->rg_property_data[1];
+ hfi->time_increment_resolution =
+ ((struct hal_mpeg4_time_resolution *)pdata)->
+ time_increment_resolution;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION:
+ {
+ struct hfi_mpeg4_header_extension *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_MPEG4_HEADER_EXTENSION;
+ hfi = (struct hfi_mpeg4_header_extension *)
+ &pkt->rg_property_data[1];
+ hfi->header_extension = (u32) pdata;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_PARAM_VENC_H264_DEBLOCK_CONTROL:
+ {
+ struct hfi_h264_db_control *hfi;
+ struct hal_h264_db_control *prop =
+ (struct hal_h264_db_control *) pdata;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL;
+ hfi = (struct hfi_h264_db_control *) &pkt->rg_property_data[1];
+ switch (prop->mode) {
+ case HAL_H264_DB_MODE_DISABLE:
+ hfi->mode = HFI_H264_DB_MODE_DISABLE;
+ break;
+ case HAL_H264_DB_MODE_SKIP_SLICE_BOUNDARY:
+ hfi->mode = HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
+ break;
+ case HAL_H264_DB_MODE_ALL_BOUNDARY:
+ hfi->mode = HFI_H264_DB_MODE_ALL_BOUNDARY;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid deblocking mode: 0x%x",
+ prop->mode);
+ break;
+ }
+ hfi->slice_alpha_offset = prop->slice_alpha_offset;
+ hfi->slice_beta_offset = prop->slice_beta_offset;
+ pkt->size += sizeof(u32) +
+ sizeof(struct hfi_h264_db_control);
+ break;
+ }
+ case HAL_PARAM_VENC_SESSION_QP:
+ {
+ struct hfi_quantization *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_SESSION_QP;
+ hfi = (struct hfi_quantization *) &pkt->rg_property_data[1];
+ memcpy(hfi, (struct hfi_quantization *) pdata,
+ sizeof(struct hfi_quantization));
+ pkt->size += sizeof(u32) + sizeof(struct hfi_quantization);
+ break;
+ }
+ case HAL_CONFIG_VENC_INTRA_PERIOD:
+ {
+ struct hfi_intra_period *hfi;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD;
+ hfi = (struct hfi_intra_period *) &pkt->rg_property_data[1];
+ memcpy(hfi, (struct hfi_intra_period *) pdata,
+ sizeof(struct hfi_intra_period));
+ pkt->size += sizeof(u32) + sizeof(struct hfi_intra_period);
+ break;
+ }
+ case HAL_CONFIG_VENC_IDR_PERIOD:
+ {
+ struct hfi_idr_period *hfi;
+ pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD;
+ hfi = (struct hfi_idr_period *) &pkt->rg_property_data[1];
+ hfi->idr_period = ((struct hfi_idr_period *) pdata)->idr_period;
+ pkt->size += sizeof(u32) * 2;
+ break;
+ }
+ case HAL_CONFIG_VPE_OPERATIONS:
+ break;
+ case HAL_PARAM_VENC_INTRA_REFRESH:
+ {
+ struct hfi_intra_refresh *hfi;
+ struct hal_intra_refresh *prop =
+ (struct hal_intra_refresh *) pdata;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
+ hfi = (struct hfi_intra_refresh *) &pkt->rg_property_data[1];
+ switch (prop->mode) {
+ case HAL_INTRA_REFRESH_NONE:
+ hfi->mode = HFI_INTRA_REFRESH_NONE;
+ break;
+ case HAL_INTRA_REFRESH_ADAPTIVE:
+ hfi->mode = HFI_INTRA_REFRESH_ADAPTIVE;
+ break;
+ case HAL_INTRA_REFRESH_CYCLIC:
+ hfi->mode = HFI_INTRA_REFRESH_CYCLIC;
+ break;
+ case HAL_INTRA_REFRESH_CYCLIC_ADAPTIVE:
+ hfi->mode = HFI_INTRA_REFRESH_CYCLIC_ADAPTIVE;
+ break;
+ case HAL_INTRA_REFRESH_RANDOM:
+ hfi->mode = HFI_INTRA_REFRESH_RANDOM;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid intra refresh setting: 0x%x",
+ prop->mode);
+ break;
+ }
+ hfi->air_mbs = prop->air_mbs;
+ hfi->air_ref = prop->air_ref;
+ hfi->cir_mbs = prop->cir_mbs;
+ pkt->size += sizeof(u32) + sizeof(struct hfi_intra_refresh);
+ break;
+ }
+ case HAL_PARAM_VENC_MULTI_SLICE_CONTROL:
+ {
+ struct hfi_multi_slice_control *hfi;
+ struct hal_multi_slice_control *prop =
+ (struct hal_multi_slice_control *) pdata;
+ pkt->rg_property_data[0] =
+ HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_CONTROL;
+ hfi = (struct hfi_multi_slice_control *)
+ &pkt->rg_property_data[1];
+ switch (prop->multi_slice) {
+ case HAL_MULTI_SLICE_OFF:
+ hfi->multi_slice = HFI_MULTI_SLICE_OFF;
+ break;
+ case HAL_MULTI_SLICE_GOB:
+ hfi->multi_slice = HFI_MULTI_SLICE_GOB;
+ break;
+ case HAL_MULTI_SLICE_BY_MB_COUNT:
+ hfi->multi_slice = HFI_MULTI_SLICE_BY_MB_COUNT;
+ break;
+ case HAL_MULTI_SLICE_BY_BYTE_COUNT:
+ hfi->multi_slice = HFI_MULTI_SLICE_BY_BYTE_COUNT;
+ break;
+ default:
+ dprintk(VIDC_ERR, "Invalid slice settings: 0x%x",
+ prop->multi_slice);
+ break;
+ }
+ hfi->slice_size = prop->slice_size;
+ pkt->size += sizeof(u32) + sizeof(struct
+ hfi_multi_slice_control);
+ break;
+ }
+ case HAL_PARAM_INDEX_EXTRADATA:
+ {
+ struct hfi_index_extradata_config *hfi;
+ struct hal_extradata_enable *extra = pdata;
+ int index = 0;
+ pkt->rg_property_data[0] =
+ get_hfi_extradata_index(extra->index);
+ hfi =
+ (struct hfi_index_extradata_config *)
+ &pkt->rg_property_data[1];
+ hfi->enable = extra->enable;
+ index = get_hfi_extradata_index(extra->index);
+ if (index)
+ hfi->index_extra_data_id = index;
+ else {
+ dprintk(VIDC_WARN,
+ "Failed to find extradata index: %d\n",
+ index);
+ rc = -EINVAL;
+ }
+ pkt->size += sizeof(u32) +
+ sizeof(struct hfi_index_extradata_config);
+ break;
+ }
+ case HAL_CONFIG_VPE_DEINTERLACE:
+ break;
+ /* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
+ case HAL_CONFIG_BUFFER_REQUIREMENTS:
+ case HAL_CONFIG_PRIORITY:
+ case HAL_CONFIG_BATCH_INFO:
+ case HAL_PARAM_METADATA_PASS_THROUGH:
+ case HAL_SYS_IDLE_INDICATOR:
+ case HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
+ case HAL_PARAM_INTERLACE_FORMAT_SUPPORTED:
+ case HAL_PARAM_CHROMA_SITE:
+ case HAL_PARAM_PROPERTIES_SUPPORTED:
+ case HAL_PARAM_PROFILE_LEVEL_SUPPORTED:
+ case HAL_PARAM_CAPABILITY_SUPPORTED:
+ case HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
+ case HAL_PARAM_MULTI_VIEW_FORMAT:
+ case HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE:
+ case HAL_PARAM_CODEC_SUPPORTED:
+ case HAL_PARAM_VDEC_MULTI_VIEW_SELECT:
+ case HAL_PARAM_VDEC_MB_QUANTIZATION:
+ case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
+ case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
+ case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
+ case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
+ case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
+ case HAL_CONFIG_VDEC_MULTI_STREAM:
+ case HAL_PARAM_VENC_MULTI_SLICE_INFO:
+ case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
+ case HAL_PARAM_VENC_LOW_LATENCY:
+ default:
+ dprintk(VIDC_ERR, "DEFAULT: Calling 0x%x", ptype);
+ break;
+ }
+ return rc;
+}
diff --git a/drivers/media/video/msm_vidc/hfi_packetization.h b/drivers/media/video/msm_vidc/hfi_packetization.h
new file mode 100644
index 0000000..541654f
--- /dev/null
+++ b/drivers/media/video/msm_vidc/hfi_packetization.h
@@ -0,0 +1,83 @@
+/* Copyright (c) 2012, 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 __HFI_PACKETIZATION__
+#define __HFI_PACKETIZATION__
+
+#include <linux/types.h>
+#include "vidc_hfi_helper.h"
+#include "vidc_hfi_api.h"
+#include "venus_hfi.h"
+
+int create_pkt_cmd_sys_init(struct hfi_cmd_sys_init_packet *pkt,
+ u32 arch_type);
+int create_pkt_cmd_sys_pc_prep(struct hfi_cmd_sys_pc_prep_packet *pkt);
+
+int create_pkt_set_cmd_sys_resource(
+ struct hfi_cmd_sys_set_resource_packet *pkt,
+ struct vidc_resource_hdr *resource_hdr,
+ void *resource_value);
+
+int create_pkt_cmd_sys_release_resource(
+ struct hfi_cmd_sys_release_resource_packet *pkt,
+ struct vidc_resource_hdr *resource_hdr);
+
+int create_pkt_cmd_sys_ping(struct hfi_cmd_sys_ping_packet *pkt);
+
+int create_pkt_cmd_sys_session_init(
+ struct hfi_cmd_sys_session_init_packet *pkt,
+ u32 session_id, u32 session_domain, u32 session_codec);
+
+int create_pkt_cmd_session_cmd(struct vidc_hal_session_cmd_pkt *pkt,
+ int pkt_type, u32 session_id);
+
+int create_pkt_cmd_session_set_buffers(
+ struct hfi_cmd_session_set_buffers_packet *pkt,
+ u32 session_id,
+ struct vidc_buffer_addr_info *buffer_info);
+
+int create_pkt_cmd_session_release_buffers(
+ struct hfi_cmd_session_release_buffer_packet *pkt,
+ u32 session_id, struct vidc_buffer_addr_info *buffer_info);
+
+int create_pkt_cmd_session_etb_decoder(
+ struct hfi_cmd_session_empty_buffer_compressed_packet *pkt,
+ u32 session_id, struct vidc_frame_data *input_frame);
+
+int create_pkt_cmd_session_etb_encoder(
+ struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet *pkt,
+ u32 session_id, struct vidc_frame_data *input_frame);
+
+int create_pkt_cmd_session_ftb(struct hfi_cmd_session_fill_buffer_packet *pkt,
+ u32 session_id, struct vidc_frame_data *output_frame);
+
+int create_pkt_cmd_session_parse_seq_header(
+ struct hfi_cmd_session_parse_sequence_header_packet *pkt,
+ u32 session_id, struct vidc_seq_hdr *seq_hdr);
+
+int create_pkt_cmd_session_get_seq_hdr(
+ struct hfi_cmd_session_get_sequence_header_packet *pkt,
+ u32 session_id, struct vidc_seq_hdr *seq_hdr);
+
+int create_pkt_cmd_session_get_buf_req(
+ struct hfi_cmd_session_get_property_packet *pkt,
+ u32 session_id);
+
+int create_pkt_cmd_session_flush(struct hfi_cmd_session_flush_packet *pkt,
+ u32 session_id, enum hal_flush flush_mode);
+
+int create_pkt_cmd_session_set_property(
+ struct hfi_cmd_session_set_property_packet *pkt,
+ u32 session_id, enum hal_property ptype, void *pdata);
+
+#endif
+
diff --git a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c b/drivers/media/video/msm_vidc/hfi_response_handler.c
similarity index 99%
rename from drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
rename to drivers/media/video/msm_vidc/hfi_response_handler.c
index 8201b0e..37605f9 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_interrupt_handler.c
+++ b/drivers/media/video/msm_vidc/hfi_response_handler.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -14,8 +14,8 @@
#include <linux/slab.h>
#include <linux/list.h>
#include <linux/interrupt.h>
-#include "vidc_hal.h"
-#include "vidc_hal_io.h"
+#include "venus_hfi.h"
+#include "vidc_hfi_io.h"
#include "msm_vidc_debug.h"
static enum vidc_status vidc_map_hal_err_status(int hfi_err)
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index eae18c4..8e2aa30 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
diff --git a/drivers/media/video/msm_vidc/msm_smem.h b/drivers/media/video/msm_vidc/msm_smem.h
index 8241fdd..6e40bef 100644
--- a/drivers/media/video/msm_vidc/msm_smem.h
+++ b/drivers/media/video/msm_vidc/msm_smem.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index 0979e99..36ee792 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -27,7 +27,7 @@
#include <media/msm_vidc.h>
#include "msm_vidc_internal.h"
#include "msm_vidc_debug.h"
-#include "vidc_hal_api.h"
+#include "vidc_hfi_api.h"
#include "msm_smem.h"
#define BASE_DEVICE_NUMBER 32
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index 440c704..bc94f45 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -15,7 +15,7 @@
#include "msm_vidc_internal.h"
#include "msm_vidc_common.h"
-#include "vidc_hal_api.h"
+#include "vidc_hfi_api.h"
#include "msm_smem.h"
#include "msm_vidc_debug.h"
diff --git a/drivers/media/video/msm_vidc/msm_vdec.h b/drivers/media/video/msm_vidc/msm_vdec.h
index 73a516e..c7f8427 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.h
+++ b/drivers/media/video/msm_vidc/msm_vdec.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 0fa56b7..0ba216c 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -14,7 +14,7 @@
#include "msm_vidc_internal.h"
#include "msm_vidc_common.h"
-#include "vidc_hal_api.h"
+#include "vidc_hfi_api.h"
#include "msm_smem.h"
#include "msm_vidc_debug.h"
diff --git a/drivers/media/video/msm_vidc/msm_venc.h b/drivers/media/video/msm_vidc/msm_venc.h
index c098773..9020167 100644
--- a/drivers/media/video/msm_vidc/msm_venc.h
+++ b/drivers/media/video/msm_vidc/msm_venc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
diff --git a/drivers/media/video/msm_vidc/msm_vidc.c b/drivers/media/video/msm_vidc/msm_vidc.c
index 13180c5..136d4e5 100644
--- a/drivers/media/video/msm_vidc/msm_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_vidc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index e00528f..042b14c 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -21,7 +21,7 @@
#include <mach/scm.h>
#include "msm_vidc_common.h"
-#include "vidc_hal_api.h"
+#include "vidc_hfi_api.h"
#include "msm_smem.h"
#include "msm_vidc_debug.h"
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.h b/drivers/media/video/msm_vidc/msm_vidc_common.h
index 27eab6f..69f41c7 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.c b/drivers/media/video/msm_vidc/msm_vidc_debug.c
index f91d0dd..133bfb5 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_debug.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_debug.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
diff --git a/drivers/media/video/msm_vidc/msm_vidc_debug.h b/drivers/media/video/msm_vidc/msm_vidc_debug.h
index 995daf0..b3bb6e1 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_debug.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_debug.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index aadb4c2..d8a3304 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -32,7 +32,7 @@
#include <media/msm_vidc.h>
#include <media/msm_media_info.h>
-#include "vidc_hal_api.h"
+#include "vidc_hfi_api.h"
#define MSM_VIDC_DRV_NAME "msm_vidc_driver"
#define MSM_VIDC_VERSION KERNEL_VERSION(0, 0, 1);
diff --git a/drivers/media/video/msm_vidc/venus_hfi.c b/drivers/media/video/msm_vidc/venus_hfi.c
new file mode 100644
index 0000000..4a5f340
--- /dev/null
+++ b/drivers/media/video/msm_vidc/venus_hfi.c
@@ -0,0 +1,1636 @@
+/* Copyright (c) 2012, 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/slab.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <mach/ocmem.h>
+
+#include <asm/memory.h>
+#include "hfi_packetization.h"
+#include "venus_hfi.h"
+#include "vidc_hfi_io.h"
+#include "msm_vidc_debug.h"
+
+#define FIRMWARE_SIZE 0X00A00000
+#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
+
+/*Workaround for virtio */
+#define HFI_VIRTIO_FW_BIAS 0x0
+
+struct hal_device_data hal_ctxt;
+
+static void hal_virtio_modify_cmd_packet(u8 *packet)
+{
+ struct hfi_cmd_sys_session_init_packet *sys_init;
+ struct hal_session *sess;
+ u8 i;
+
+ if (!packet) {
+ dprintk(VIDC_ERR, "Invalid Param");
+ return;
+ }
+
+ sys_init = (struct hfi_cmd_sys_session_init_packet *)packet;
+ sess = (struct hal_session *) sys_init->session_id;
+ switch (sys_init->packet_type) {
+ case HFI_CMD_SESSION_EMPTY_BUFFER:
+ if (sess->is_decoder) {
+ struct hfi_cmd_session_empty_buffer_compressed_packet
+ *pkt = (struct
+ hfi_cmd_session_empty_buffer_compressed_packet
+ *) packet;
+ pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
+ } else {
+ struct
+ hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
+ *pkt = (struct
+ hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
+ *) packet;
+ pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
+ }
+ break;
+ case HFI_CMD_SESSION_FILL_BUFFER:
+ {
+ struct hfi_cmd_session_fill_buffer_packet *pkt =
+ (struct hfi_cmd_session_fill_buffer_packet *)packet;
+ pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
+ break;
+ }
+ case HFI_CMD_SESSION_SET_BUFFERS:
+ {
+ struct hfi_cmd_session_set_buffers_packet *pkt =
+ (struct hfi_cmd_session_set_buffers_packet *)packet;
+ if ((pkt->buffer_type == HFI_BUFFER_OUTPUT) ||
+ (pkt->buffer_type == HFI_BUFFER_OUTPUT2)) {
+ struct hfi_buffer_info *buff;
+ buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
+ buff->buffer_addr -= HFI_VIRTIO_FW_BIAS;
+ buff->extra_data_addr -= HFI_VIRTIO_FW_BIAS;
+ } else {
+ for (i = 0; i < pkt->num_buffers; i++)
+ pkt->rg_buffer_info[i] -= HFI_VIRTIO_FW_BIAS;
+ }
+ break;
+ }
+ case HFI_CMD_SESSION_RELEASE_BUFFERS:
+ {
+ struct hfi_cmd_session_release_buffer_packet *pkt =
+ (struct hfi_cmd_session_release_buffer_packet *)packet;
+ if ((pkt->buffer_type == HFI_BUFFER_OUTPUT) ||
+ (pkt->buffer_type == HFI_BUFFER_OUTPUT2)) {
+ struct hfi_buffer_info *buff;
+ buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
+ buff->buffer_addr -= HFI_VIRTIO_FW_BIAS;
+ buff->extra_data_addr -= HFI_VIRTIO_FW_BIAS;
+ } else {
+ for (i = 0; i < pkt->num_buffers; i++)
+ pkt->rg_buffer_info[i] -= HFI_VIRTIO_FW_BIAS;
+ }
+ break;
+ }
+ case HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER:
+ {
+ struct hfi_cmd_session_parse_sequence_header_packet *pkt =
+ (struct hfi_cmd_session_parse_sequence_header_packet *)
+ packet;
+ pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
+ break;
+ }
+ case HFI_CMD_SESSION_GET_SEQUENCE_HEADER:
+ {
+ struct hfi_cmd_session_get_sequence_header_packet *pkt =
+ (struct hfi_cmd_session_get_sequence_header_packet *)
+ packet;
+ pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static int write_queue(void *info, u8 *packet, u32 *rx_req_is_set)
+{
+ struct hfi_queue_header *queue;
+ u32 packet_size_in_words, new_write_idx;
+ struct vidc_iface_q_info *qinfo;
+ u32 empty_space, read_idx;
+ u32 *write_ptr;
+
+ if (!info || !packet || !rx_req_is_set) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ }
+
+ qinfo = (struct vidc_iface_q_info *) info;
+ hal_virtio_modify_cmd_packet(packet);
+
+ queue = (struct hfi_queue_header *) qinfo->q_hdr;
+
+ if (!queue) {
+ dprintk(VIDC_ERR, "queue not present");
+ return -ENOENT;
+ }
+
+ packet_size_in_words = (*(u32 *)packet) >> 2;
+ dprintk(VIDC_DBG, "Packet_size in words: %d", packet_size_in_words);
+
+ if (packet_size_in_words == 0) {
+ dprintk(VIDC_ERR, "Zero packet size");
+ return -ENODATA;
+ }
+
+ read_idx = queue->qhdr_read_idx;
+
+ empty_space = (queue->qhdr_write_idx >= read_idx) ?
+ (queue->qhdr_q_size - (queue->qhdr_write_idx - read_idx)) :
+ (read_idx - queue->qhdr_write_idx);
+ dprintk(VIDC_DBG, "Empty_space: %d", empty_space);
+ if (empty_space <= packet_size_in_words) {
+ queue->qhdr_tx_req = 1;
+ dprintk(VIDC_ERR, "Insufficient size (%d) to write (%d)",
+ empty_space, packet_size_in_words);
+ return -ENOTEMPTY;
+ }
+
+ queue->qhdr_tx_req = 0;
+
+ new_write_idx = (queue->qhdr_write_idx + packet_size_in_words);
+ write_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
+ (queue->qhdr_write_idx << 2));
+ dprintk(VIDC_DBG, "Write Ptr: %d", (u32) write_ptr);
+ if (new_write_idx < queue->qhdr_q_size) {
+ memcpy(write_ptr, packet, packet_size_in_words << 2);
+ } else {
+ new_write_idx -= queue->qhdr_q_size;
+ memcpy(write_ptr, packet, (packet_size_in_words -
+ new_write_idx) << 2);
+ memcpy((void *)qinfo->q_array.align_virtual_addr,
+ packet + ((packet_size_in_words - new_write_idx) << 2),
+ new_write_idx << 2);
+ }
+ queue->qhdr_write_idx = new_write_idx;
+ *rx_req_is_set = (1 == queue->qhdr_rx_req) ? 1 : 0;
+ dprintk(VIDC_DBG, "Out : ");
+ return 0;
+}
+
+static void hal_virtio_modify_msg_packet(u8 *packet)
+{
+ struct hfi_msg_sys_session_init_done_packet *sys_idle;
+ struct hal_session *sess;
+
+ if (!packet) {
+ dprintk(VIDC_ERR, "Invalid Param: ");
+ return;
+ }
+
+ sys_idle = (struct hfi_msg_sys_session_init_done_packet *)packet;
+ sess = (struct hal_session *) sys_idle->session_id;
+
+ switch (sys_idle->packet_type) {
+ case HFI_MSG_SESSION_FILL_BUFFER_DONE:
+ if (sess->is_decoder) {
+ struct
+ hfi_msg_session_fbd_uncompressed_plane0_packet
+ *pkt_uc = (struct
+ hfi_msg_session_fbd_uncompressed_plane0_packet
+ *) packet;
+ pkt_uc->packet_buffer += HFI_VIRTIO_FW_BIAS;
+ } else {
+ struct
+ hfi_msg_session_fill_buffer_done_compressed_packet
+ *pkt = (struct
+ hfi_msg_session_fill_buffer_done_compressed_packet
+ *) packet;
+ pkt->packet_buffer += HFI_VIRTIO_FW_BIAS;
+ }
+ break;
+ case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
+ {
+ struct hfi_msg_session_empty_buffer_done_packet *pkt =
+ (struct hfi_msg_session_empty_buffer_done_packet *)packet;
+ pkt->packet_buffer += HFI_VIRTIO_FW_BIAS;
+ break;
+ }
+ case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
+ {
+ struct
+ hfi_msg_session_get_sequence_header_done_packet
+ *pkt =
+ (struct hfi_msg_session_get_sequence_header_done_packet *)
+ packet;
+ pkt->sequence_header += HFI_VIRTIO_FW_BIAS;
+ break;
+ }
+ default:
+ break;
+ }
+}
+
+static int read_queue(void *info, u8 *packet, u32 *pb_tx_req_is_set)
+{
+ struct hfi_queue_header *queue;
+ u32 packet_size_in_words, new_read_idx;
+ u32 *read_ptr;
+ struct vidc_iface_q_info *qinfo;
+
+ if (!info || !packet || !pb_tx_req_is_set) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ }
+
+ qinfo = (struct vidc_iface_q_info *) info;
+ queue = (struct hfi_queue_header *) qinfo->q_hdr;
+
+ if (!queue) {
+ dprintk(VIDC_ERR, "Queue memory is not allocated\n");
+ return -ENOMEM;
+ }
+
+ if (queue->qhdr_read_idx == queue->qhdr_write_idx) {
+ queue->qhdr_rx_req = 1;
+ *pb_tx_req_is_set = 0;
+ return -EPERM;
+ }
+
+ read_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
+ (queue->qhdr_read_idx << 2));
+ packet_size_in_words = (*read_ptr) >> 2;
+ dprintk(VIDC_DBG, "packet_size_in_words: %d", packet_size_in_words);
+ if (packet_size_in_words == 0) {
+ dprintk(VIDC_ERR, "Zero packet size");
+ return -ENODATA;
+ }
+
+ new_read_idx = queue->qhdr_read_idx + packet_size_in_words;
+ dprintk(VIDC_DBG, "Read Ptr: %d", (u32) new_read_idx);
+ if (new_read_idx < queue->qhdr_q_size) {
+ memcpy(packet, read_ptr,
+ packet_size_in_words << 2);
+ } else {
+ new_read_idx -= queue->qhdr_q_size;
+ memcpy(packet, read_ptr,
+ (packet_size_in_words - new_read_idx) << 2);
+ memcpy(packet + ((packet_size_in_words -
+ new_read_idx) << 2),
+ (u8 *)qinfo->q_array.align_virtual_addr,
+ new_read_idx << 2);
+ }
+
+ queue->qhdr_read_idx = new_read_idx;
+
+ if (queue->qhdr_read_idx != queue->qhdr_write_idx)
+ queue->qhdr_rx_req = 0;
+ else
+ queue->qhdr_rx_req = 1;
+
+ *pb_tx_req_is_set = (1 == queue->qhdr_tx_req) ? 1 : 0;
+ hal_virtio_modify_msg_packet(packet);
+ dprintk(VIDC_DBG, "Out : ");
+ return 0;
+}
+
+static int vidc_hal_alloc(void *mem, void *clnt, u32 size, u32 align, u32 flags,
+ int domain)
+{
+ struct vidc_mem_addr *vmem;
+ struct msm_smem *alloc;
+ int rc = 0;
+
+ if (!mem || !clnt || !size) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ }
+ vmem = (struct vidc_mem_addr *)mem;
+ dprintk(VIDC_INFO, "start to alloc: size:%d, Flags: %d", size, flags);
+
+ alloc = msm_smem_alloc(clnt, size, align, flags, domain, 1, 1);
+ dprintk(VIDC_DBG, "Alloc done");
+ if (!alloc) {
+ dprintk(VIDC_ERR, "Alloc failed\n");
+ rc = -ENOMEM;
+ goto fail_smem_alloc;
+ }
+ rc = msm_smem_clean_invalidate(clnt, alloc);
+ if (rc) {
+ dprintk(VIDC_ERR, "NOTE: Failed to clean caches\n");
+ goto fail_clean_cache;
+ }
+ dprintk(VIDC_DBG, "vidc_hal_alloc:ptr=%p,size=%d",
+ alloc->kvaddr, size);
+ vmem->mem_size = alloc->size;
+ vmem->mem_data = alloc;
+ vmem->align_virtual_addr = (u8 *) alloc->kvaddr;
+ vmem->align_device_addr = (u8 *)alloc->device_addr;
+ return rc;
+fail_clean_cache:
+ msm_smem_free(clnt, alloc);
+fail_smem_alloc:
+ return rc;
+}
+
+static void vidc_hal_free(struct smem_client *clnt, struct msm_smem *mem)
+{
+ msm_smem_free(clnt, mem);
+}
+
+static void write_register(u8 *base_addr, u32 reg, u32 value, u8 *vaddr)
+{
+ u32 hwiosymaddr = reg;
+
+ reg &= REG_ADDR_OFFSET_BITMASK;
+ if (reg == (u32)VIDC_CPU_CS_SCIACMDARG2) {
+ /* workaround to offset of FW bias */
+ struct hfi_queue_header *qhdr;
+ struct hfi_queue_table_header *qtbl_hdr =
+ (struct hfi_queue_table_header *)vaddr;
+
+ qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 0);
+ qhdr->qhdr_start_addr -= HFI_VIRTIO_FW_BIAS;
+
+ qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 1);
+ qhdr->qhdr_start_addr -= HFI_VIRTIO_FW_BIAS;
+
+ qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 2);
+ qhdr->qhdr_start_addr -= HFI_VIRTIO_FW_BIAS;
+ value -= HFI_VIRTIO_FW_BIAS;
+ }
+
+ hwiosymaddr = ((u32)base_addr + (hwiosymaddr));
+ dprintk(VIDC_DBG, "Base addr: 0x%x, written to: 0x%x, Value: 0x%x...",
+ (u32)base_addr, hwiosymaddr, value);
+ writel_relaxed(value, hwiosymaddr);
+ wmb();
+}
+
+static int read_register(u8 *base_addr, u32 reg)
+{
+ int rc = readl_relaxed((u32)base_addr + reg);
+ rmb();
+ return rc;
+}
+
+static int vidc_hal_iface_cmdq_write(struct hal_device *device, void *pkt)
+{
+ u32 rx_req_is_set = 0;
+ struct vidc_iface_q_info *q_info;
+ int result = -EPERM;
+
+ if (!device || !pkt) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ }
+
+ spin_lock(&device->write_lock);
+ q_info = &device->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
+ if (!q_info) {
+ dprintk(VIDC_ERR, "cannot write to shared Q's");
+ goto err_q_write;
+ }
+
+ if (!write_queue(q_info, (u8 *)pkt, &rx_req_is_set)) {
+ if (rx_req_is_set)
+ write_register(device->hal_data->register_base_addr,
+ VIDC_CPU_IC_SOFTINT,
+ 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
+ result = 0;
+ } else {
+ dprintk(VIDC_ERR, "vidc_hal_iface_cmdq_write:queue_full");
+ }
+err_q_write:
+ spin_unlock(&device->write_lock);
+ return result;
+}
+
+int vidc_hal_iface_msgq_read(struct hal_device *device, void *pkt)
+{
+ u32 tx_req_is_set = 0;
+ int rc = 0;
+ struct vidc_iface_q_info *q_info;
+
+ if (!pkt) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ }
+ spin_lock(&device->read_lock);
+ if (device->iface_queues[VIDC_IFACEQ_MSGQ_IDX].
+ q_array.align_virtual_addr == 0) {
+ dprintk(VIDC_ERR, "cannot read from shared MSG Q's");
+ rc = -ENODATA;
+ goto read_error;
+ }
+ q_info = &device->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
+
+ if (!read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
+ if (tx_req_is_set)
+ write_register(device->hal_data->register_base_addr,
+ VIDC_CPU_IC_SOFTINT,
+ 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
+ rc = 0;
+ } else {
+ dprintk(VIDC_INFO, "vidc_hal_iface_msgq_read:queue_empty");
+ rc = -ENODATA;
+ }
+read_error:
+ spin_unlock(&device->read_lock);
+ return rc;
+}
+
+int vidc_hal_iface_dbgq_read(struct hal_device *device, void *pkt)
+{
+ u32 tx_req_is_set = 0;
+ int rc = 0;
+ struct vidc_iface_q_info *q_info;
+
+ if (!pkt) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ }
+ spin_lock(&device->read_lock);
+ if (device->iface_queues[VIDC_IFACEQ_DBGQ_IDX].
+ q_array.align_virtual_addr == 0) {
+ dprintk(VIDC_ERR, "cannot read from shared DBG Q's");
+ rc = -ENODATA;
+ goto dbg_error;
+ }
+ q_info = &device->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
+ if (!read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
+ if (tx_req_is_set)
+ write_register(device->hal_data->register_base_addr,
+ VIDC_CPU_IC_SOFTINT,
+ 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
+ rc = 0;
+ } else {
+ dprintk(VIDC_INFO, "vidc_hal_iface_dbgq_read:queue_empty");
+ rc = -ENODATA;
+ }
+dbg_error:
+ spin_unlock(&device->read_lock);
+ return rc;
+}
+
+static void vidc_hal_set_queue_hdr_defaults(struct hfi_queue_header *q_hdr)
+{
+ q_hdr->qhdr_status = 0x1;
+ q_hdr->qhdr_type = VIDC_IFACEQ_DFLT_QHDR;
+ q_hdr->qhdr_q_size = VIDC_IFACEQ_QUEUE_SIZE / 4;
+ q_hdr->qhdr_pkt_size = 0;
+ q_hdr->qhdr_rx_wm = 0x1;
+ q_hdr->qhdr_tx_wm = 0x1;
+ q_hdr->qhdr_rx_req = 0x1;
+ q_hdr->qhdr_tx_req = 0x0;
+ q_hdr->qhdr_rx_irq_status = 0x0;
+ q_hdr->qhdr_tx_irq_status = 0x0;
+ q_hdr->qhdr_read_idx = 0x0;
+ q_hdr->qhdr_write_idx = 0x0;
+}
+
+static void vidc_hal_interface_queues_release(struct hal_device *device)
+{
+ int i;
+
+ vidc_hal_free(device->hal_client, device->mem_addr.mem_data);
+
+ for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
+ device->iface_queues[i].q_hdr = NULL;
+ device->iface_queues[i].q_array.mem_data = NULL;
+ device->iface_queues[i].q_array.align_virtual_addr = NULL;
+ device->iface_queues[i].q_array.align_device_addr = NULL;
+ }
+ device->iface_q_table.align_virtual_addr = NULL;
+ device->iface_q_table.align_device_addr = NULL;
+
+ device->qdss.align_virtual_addr = NULL;
+ device->qdss.align_device_addr = NULL;
+
+ device->sfr.align_virtual_addr = NULL;
+ device->sfr.align_device_addr = NULL;
+
+ device->mem_addr.align_virtual_addr = NULL;
+ device->mem_addr.align_device_addr = NULL;
+
+ msm_smem_delete_client(device->hal_client);
+ device->hal_client = NULL;
+}
+
+static int vidc_hal_interface_queues_init(struct hal_device *dev, int domain)
+{
+ struct hfi_queue_table_header *q_tbl_hdr;
+ struct hfi_queue_header *q_hdr;
+ u8 i;
+ int rc = 0;
+ struct vidc_iface_q_info *iface_q;
+ struct hfi_sfr_struct *vsfr;
+ struct vidc_mem_addr *mem_addr;
+ int offset = 0;
+ int size_1m = 1024 * 1024;
+ int uc_size = (UC_SIZE + size_1m - 1) & (~(size_1m - 1));
+ mem_addr = &dev->mem_addr;
+ rc = vidc_hal_alloc((void *) mem_addr,
+ dev->hal_client, uc_size, 1,
+ 0, domain);
+ if (rc) {
+ dprintk(VIDC_ERR, "iface_q_table_alloc_fail");
+ return -ENOMEM;
+ }
+ dev->iface_q_table.align_virtual_addr = mem_addr->align_virtual_addr;
+ dev->iface_q_table.align_device_addr = mem_addr->align_device_addr;
+ dev->iface_q_table.mem_size = VIDC_IFACEQ_TABLE_SIZE;
+ dev->iface_q_table.mem_data = NULL;
+ offset += dev->iface_q_table.mem_size;
+
+ for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
+ iface_q = &dev->iface_queues[i];
+ iface_q->q_array.align_device_addr =
+ mem_addr->align_device_addr + offset;
+ iface_q->q_array.align_virtual_addr =
+ mem_addr->align_virtual_addr + offset;
+ iface_q->q_array.mem_size = VIDC_IFACEQ_QUEUE_SIZE;
+ iface_q->q_array.mem_data = NULL;
+ offset += iface_q->q_array.mem_size;
+ iface_q->q_hdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(
+ dev->iface_q_table.align_virtual_addr, i);
+ vidc_hal_set_queue_hdr_defaults(iface_q->q_hdr);
+ }
+
+ dev->qdss.align_device_addr = mem_addr->align_device_addr + offset;
+ dev->qdss.align_virtual_addr = mem_addr->align_virtual_addr + offset;
+ dev->qdss.mem_size = QDSS_SIZE;
+ dev->qdss.mem_data = NULL;
+ offset += dev->qdss.mem_size;
+
+ dev->sfr.align_device_addr = mem_addr->align_device_addr + offset;
+ dev->sfr.align_virtual_addr = mem_addr->align_virtual_addr + offset;
+ dev->sfr.mem_size = SFR_SIZE;
+ dev->sfr.mem_data = NULL;
+ offset += dev->sfr.mem_size;
+
+ q_tbl_hdr = (struct hfi_queue_table_header *)
+ dev->iface_q_table.align_virtual_addr;
+ q_tbl_hdr->qtbl_version = 0;
+ q_tbl_hdr->qtbl_size = VIDC_IFACEQ_TABLE_SIZE;
+ q_tbl_hdr->qtbl_qhdr0_offset = sizeof(
+ struct hfi_queue_table_header);
+ q_tbl_hdr->qtbl_qhdr_size = sizeof(
+ struct hfi_queue_header);
+ q_tbl_hdr->qtbl_num_q = VIDC_IFACEQ_NUMQ;
+ q_tbl_hdr->qtbl_num_active_q = VIDC_IFACEQ_NUMQ;
+
+ iface_q = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
+ q_hdr = iface_q->q_hdr;
+ q_hdr->qhdr_start_addr = (u32)
+ iface_q->q_array.align_device_addr;
+ q_hdr->qhdr_type |= HFI_Q_ID_HOST_TO_CTRL_CMD_Q;
+
+ iface_q = &dev->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
+ q_hdr = iface_q->q_hdr;
+ q_hdr->qhdr_start_addr = (u32)
+ iface_q->q_array.align_device_addr;
+ q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_MSG_Q;
+
+ iface_q = &dev->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
+ q_hdr = iface_q->q_hdr;
+ q_hdr->qhdr_start_addr = (u32)
+ iface_q->q_array.align_device_addr;
+ q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
+
+ write_register(dev->hal_data->register_base_addr,
+ VIDC_UC_REGION_ADDR,
+ (u32) mem_addr->align_device_addr, 0);
+ write_register(dev->hal_data->register_base_addr,
+ VIDC_UC_REGION_SIZE, mem_addr->mem_size, 0);
+ write_register(dev->hal_data->register_base_addr,
+ VIDC_CPU_CS_SCIACMDARG2,
+ (u32) dev->iface_q_table.align_device_addr,
+ dev->iface_q_table.align_virtual_addr);
+ write_register(dev->hal_data->register_base_addr,
+ VIDC_CPU_CS_SCIACMDARG1, 0x01,
+ dev->iface_q_table.align_virtual_addr);
+ write_register(dev->hal_data->register_base_addr,
+ VIDC_MMAP_ADDR,
+ (u32) dev->qdss.align_device_addr, 0);
+
+ vsfr = (struct hfi_sfr_struct *) dev->sfr.align_virtual_addr;
+ vsfr->bufSize = SFR_SIZE;
+
+ write_register(dev->hal_data->register_base_addr,
+ VIDC_SFR_ADDR, (u32)dev->sfr.align_device_addr , 0);
+ return 0;
+}
+
+static int vidc_hal_core_start_cpu(struct hal_device *device)
+{
+ u32 ctrl_status = 0, count = 0, rc = 0;
+ int max_tries = 100;
+ write_register(device->hal_data->register_base_addr,
+ VIDC_WRAPPER_INTR_MASK, 0x8, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_CPU_CS_SCIACMDARG3, 1, 0);
+
+ while (!ctrl_status && count < max_tries) {
+ ctrl_status = read_register(
+ device->hal_data->register_base_addr,
+ VIDC_CPU_CS_SCIACMDARG0);
+ if ((ctrl_status & 0xFE) == 0x4) {
+ dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
+ break;
+ }
+ usleep_range(500, 1000);
+ count++;
+ }
+ if (count >= max_tries)
+ rc = -ETIME;
+ return rc;
+}
+
+static void set_vbif_registers(struct hal_device *device)
+{
+ /*Disable Dynamic clock gating for Venus VBIF*/
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS_VBIF_CLK_ON, 1, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_OUT_AXI_AOOO_EN, 0x00001FFF, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_OUT_AXI_AOOO, 0x1FFF1FFF, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_IN_RD_LIM_CONF0, 0x10101001, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_IN_RD_LIM_CONF1, 0x10101010, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_IN_RD_LIM_CONF2, 0x10101010, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_IN_RD_LIM_CONF3, 0x00000010, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_IN_WR_LIM_CONF0, 0x1010100f, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_IN_WR_LIM_CONF1, 0x10101010, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_IN_WR_LIM_CONF2, 0x10101010, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_IN_WR_LIM_CONF3, 0x00000010, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_OUT_RD_LIM_CONF0, 0x00001010, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_OUT_WR_LIM_CONF0, 0x00001010, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VBIF_ARB_CTL, 0x00000030, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS_VBIF_DDR_OUT_MAX_BURST, 0x00000707, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS_VBIF_OCMEM_OUT_MAX_BURST, 0x00000707, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000001, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY, 0x5555556, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL, 0, 0);
+}
+
+static int vidc_hal_sys_set_debug(struct hal_device *device, int debug)
+{
+ struct hfi_debug_config *hfi;
+ u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+ struct hfi_cmd_sys_set_property_packet *pkt =
+ (struct hfi_cmd_sys_set_property_packet *) &packet;
+ pkt->size = sizeof(struct hfi_cmd_sys_set_property_packet) +
+ sizeof(struct hfi_debug_config) + sizeof(u32);
+ pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
+ pkt->num_properties = 1;
+ pkt->rg_property_data[0] = HFI_PROPERTY_SYS_DEBUG_CONFIG;
+ hfi = (struct hfi_debug_config *) &pkt->rg_property_data[1];
+ hfi->debug_config = debug;
+ hfi->debug_mode = HFI_DEBUG_MODE_QUEUE;
+ if (vidc_hal_iface_cmdq_write(device, pkt))
+ return -ENOTEMPTY;
+ return 0;
+}
+
+int vidc_hal_core_init(void *device, int domain)
+{
+ struct hfi_cmd_sys_init_packet pkt;
+ int rc = 0;
+ struct hal_device *dev;
+
+ if (device) {
+ dev = device;
+ } else {
+ dprintk(VIDC_ERR, "Invalid device");
+ return -ENODEV;
+ }
+ dev->intr_status = 0;
+ enable_irq(dev->hal_data->irq);
+ INIT_LIST_HEAD(&dev->sess_head);
+ spin_lock_init(&dev->read_lock);
+ spin_lock_init(&dev->write_lock);
+ set_vbif_registers(dev);
+
+ if (!dev->hal_client) {
+ dev->hal_client = msm_smem_new_client(SMEM_ION);
+ if (dev->hal_client == NULL) {
+ dprintk(VIDC_ERR, "Failed to alloc ION_Client");
+ rc = -ENODEV;
+ goto err_core_init;
+ }
+
+ dprintk(VIDC_DBG, "Dev_Virt: 0x%x, Reg_Virt: 0x%x",
+ dev->hal_data->device_base_addr,
+ (u32) dev->hal_data->register_base_addr);
+
+ rc = vidc_hal_interface_queues_init(dev, domain);
+ if (rc) {
+ dprintk(VIDC_ERR, "failed to init queues");
+ rc = -ENOMEM;
+ goto err_core_init;
+ }
+ } else {
+ dprintk(VIDC_ERR, "hal_client exists");
+ rc = -EEXIST;
+ goto err_core_init;
+ }
+ write_register(dev->hal_data->register_base_addr,
+ VIDC_CTRL_INIT, 0x1, 0);
+ rc = vidc_hal_core_start_cpu(dev);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to start core");
+ rc = -ENODEV;
+ goto err_core_init;
+ }
+
+ rc = create_pkt_cmd_sys_init(&pkt, HFI_ARCH_OX_OFFSET);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to create sys init pkt");
+ goto err_core_init;
+ }
+ if (vidc_hal_iface_cmdq_write(dev, &pkt)) {
+ rc = -ENOTEMPTY;
+ goto err_core_init;
+ }
+ return rc;
+err_core_init:
+ disable_irq_nosync(dev->hal_data->irq);
+ return rc;
+}
+
+int vidc_hal_core_release(void *device)
+{
+ struct hal_device *dev;
+ if (device) {
+ dev = device;
+ } else {
+ dprintk(VIDC_ERR, "invalid device");
+ return -ENODEV;
+ }
+ if (dev->hal_client) {
+ write_register(dev->hal_data->register_base_addr,
+ VIDC_CPU_CS_SCIACMDARG3, 0, 0);
+ disable_irq_nosync(dev->hal_data->irq);
+ vidc_hal_interface_queues_release(dev);
+ }
+ dprintk(VIDC_INFO, "HAL exited\n");
+ return 0;
+}
+
+int vidc_hal_core_pc_prep(void *device)
+{
+ struct hfi_cmd_sys_pc_prep_packet pkt;
+ int rc = 0;
+ struct hal_device *dev;
+
+ if (device) {
+ dev = device;
+ } else {
+ dprintk(VIDC_ERR, "invalid device");
+ return -ENODEV;
+ }
+
+ rc = create_pkt_cmd_sys_pc_prep(&pkt);
+ if (rc) {
+ dprintk(VIDC_ERR, "Failed to create sys pc prep pkt");
+ goto err_create_pkt;
+ }
+
+ if (vidc_hal_iface_cmdq_write(dev, &pkt))
+ rc = -ENOTEMPTY;
+
+err_create_pkt:
+ return rc;
+}
+
+static void vidc_hal_core_clear_interrupt(struct hal_device *device)
+{
+ u32 intr_status = 0;
+
+ if (!device->callback)
+ return;
+
+ intr_status = read_register(
+ device->hal_data->register_base_addr,
+ VIDC_WRAPPER_INTR_STATUS);
+
+ if ((intr_status & VIDC_WRAPPER_INTR_STATUS_A2H_BMSK) ||
+ (intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) {
+ device->intr_status |= intr_status;
+ dprintk(VIDC_DBG, "INTERRUPT for device: 0x%x: "
+ "times: %d interrupt_status: %d",
+ (u32) device, ++device->reg_count, intr_status);
+ } else {
+ dprintk(VIDC_INFO, "SPURIOUS_INTR for device: 0x%x: "
+ "times: %d interrupt_status: %d",
+ (u32) device, ++device->spur_count, intr_status);
+ }
+ write_register(device->hal_data->register_base_addr,
+ VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
+ write_register(device->hal_data->register_base_addr,
+ VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
+ dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
+}
+
+int vidc_hal_core_set_resource(void *device,
+ struct vidc_resource_hdr *resource_hdr, void *resource_value)
+{
+ struct hfi_cmd_sys_set_resource_packet *pkt;
+ u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+ int rc = 0;
+ struct hal_device *dev;
+
+ if (!device || !resource_hdr || !resource_value) {
+ dprintk(VIDC_ERR, "set_res: Invalid Params");
+ return -EINVAL;
+ } else {
+ dev = device;
+ }
+
+ pkt = (struct hfi_cmd_sys_set_resource_packet *) packet;
+
+ rc = create_pkt_set_cmd_sys_resource(pkt, resource_hdr,
+ resource_value);
+ if (rc) {
+ dprintk(VIDC_ERR, "set_res: failed to create packet");
+ goto err_create_pkt;
+ }
+ if (vidc_hal_iface_cmdq_write(dev, pkt))
+ rc = -ENOTEMPTY;
+
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_core_release_resource(void *device,
+ struct vidc_resource_hdr *resource_hdr)
+{
+ struct hfi_cmd_sys_release_resource_packet pkt;
+ int rc = 0;
+ struct hal_device *dev;
+
+ if (!device || !resource_hdr) {
+ dprintk(VIDC_ERR, "Inv-Params in rel_res");
+ return -EINVAL;
+ } else {
+ dev = device;
+ }
+
+ rc = create_pkt_cmd_sys_release_resource(&pkt, resource_hdr);
+ if (rc) {
+ dprintk(VIDC_ERR, "release_res: failed to create packet");
+ goto err_create_pkt;
+ }
+
+ if (vidc_hal_iface_cmdq_write(dev, &pkt))
+ rc = -ENOTEMPTY;
+
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_core_ping(void *device)
+{
+ struct hfi_cmd_sys_ping_packet pkt;
+ int rc = 0;
+ struct hal_device *dev;
+
+ if (device) {
+ dev = device;
+ } else {
+ dprintk(VIDC_ERR, "invalid device");
+ return -ENODEV;
+ }
+
+ rc = create_pkt_cmd_sys_ping(&pkt);
+ if (rc) {
+ dprintk(VIDC_ERR, "core_ping: failed to create packet");
+ goto err_create_pkt;
+ }
+
+ if (vidc_hal_iface_cmdq_write(dev, &pkt))
+ rc = -ENOTEMPTY;
+
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_session_set_property(void *sess,
+ enum hal_property ptype, void *pdata)
+{
+ u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
+ struct hfi_cmd_session_set_property_packet *pkt =
+ (struct hfi_cmd_session_set_property_packet *) &packet;
+ struct hal_session *session;
+ int rc = 0;
+
+ if (!sess || !pdata) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ } else {
+ session = sess;
+ }
+
+ dprintk(VIDC_INFO, "in set_prop,with prop id: 0x%x", ptype);
+
+ if (create_pkt_cmd_session_set_property(pkt, (u32)session, ptype,
+ pdata)) {
+ dprintk(VIDC_ERR, "set property: failed to create packet");
+ return -EINVAL;
+ }
+
+ if (vidc_hal_iface_cmdq_write(session->device, pkt))
+ return -ENOTEMPTY;
+
+ return rc;
+}
+
+int vidc_hal_session_get_property(void *sess,
+ enum hal_property ptype, void *pdata)
+{
+ struct hal_session *session;
+
+ if (!sess || !pdata) {
+ dprintk(VIDC_ERR, "Invalid Params in ");
+ return -EINVAL;
+ } else {
+ session = sess;
+ }
+ dprintk(VIDC_INFO, "IN func: , with property id: %d", ptype);
+
+ switch (ptype) {
+ case HAL_CONFIG_FRAME_RATE:
+ break;
+ case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT:
+ break;
+ case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO:
+ break;
+ case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO:
+ break;
+ case HAL_PARAM_EXTRA_DATA_HEADER_CONFIG:
+ break;
+ case HAL_PARAM_FRAME_SIZE:
+ break;
+ case HAL_CONFIG_REALTIME:
+ break;
+ case HAL_PARAM_BUFFER_COUNT_ACTUAL:
+ break;
+ case HAL_PARAM_NAL_STREAM_FORMAT_SELECT:
+ break;
+ case HAL_PARAM_VDEC_OUTPUT_ORDER:
+ break;
+ case HAL_PARAM_VDEC_PICTURE_TYPE_DECODE:
+ break;
+ case HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO:
+ break;
+ case HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
+ break;
+ case HAL_PARAM_VDEC_MULTI_STREAM:
+ break;
+ case HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT:
+ break;
+ case HAL_PARAM_DIVX_FORMAT:
+ break;
+ case HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING:
+ break;
+ case HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER:
+ break;
+ case HAL_CONFIG_VDEC_MB_ERROR_MAP:
+ break;
+ case HAL_CONFIG_VENC_REQUEST_IFRAME:
+ break;
+ case HAL_PARAM_VENC_MPEG4_SHORT_HEADER:
+ break;
+ case HAL_PARAM_VENC_MPEG4_AC_PREDICTION:
+ break;
+ case HAL_CONFIG_VENC_TARGET_BITRATE:
+ break;
+ case HAL_PARAM_PROFILE_LEVEL_CURRENT:
+ break;
+ case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
+ break;
+ case HAL_PARAM_VENC_RATE_CONTROL:
+ break;
+ case HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION:
+ break;
+ case HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION:
+ break;
+ case HAL_PARAM_VENC_H264_DEBLOCK_CONTROL:
+ break;
+ case HAL_PARAM_VENC_SESSION_QP:
+ break;
+ case HAL_CONFIG_VENC_INTRA_PERIOD:
+ break;
+ case HAL_CONFIG_VENC_IDR_PERIOD:
+ break;
+ case HAL_CONFIG_VPE_OPERATIONS:
+ break;
+ case HAL_PARAM_VENC_INTRA_REFRESH:
+ break;
+ case HAL_PARAM_VENC_MULTI_SLICE_CONTROL:
+ break;
+ case HAL_CONFIG_VPE_DEINTERLACE:
+ break;
+ case HAL_SYS_DEBUG_CONFIG:
+ break;
+ /*FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET*/
+ case HAL_CONFIG_BUFFER_REQUIREMENTS:
+ case HAL_CONFIG_PRIORITY:
+ case HAL_CONFIG_BATCH_INFO:
+ case HAL_PARAM_METADATA_PASS_THROUGH:
+ case HAL_SYS_IDLE_INDICATOR:
+ case HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
+ case HAL_PARAM_INTERLACE_FORMAT_SUPPORTED:
+ case HAL_PARAM_CHROMA_SITE:
+ case HAL_PARAM_PROPERTIES_SUPPORTED:
+ case HAL_PARAM_PROFILE_LEVEL_SUPPORTED:
+ case HAL_PARAM_CAPABILITY_SUPPORTED:
+ case HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
+ case HAL_PARAM_MULTI_VIEW_FORMAT:
+ case HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE:
+ case HAL_PARAM_CODEC_SUPPORTED:
+ case HAL_PARAM_VDEC_MULTI_VIEW_SELECT:
+ case HAL_PARAM_VDEC_MB_QUANTIZATION:
+ case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
+ case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
+ case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
+ case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
+
+ case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
+ case HAL_CONFIG_VDEC_MULTI_STREAM:
+ case HAL_PARAM_VENC_MULTI_SLICE_INFO:
+ case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
+ case HAL_PARAM_VENC_LOW_LATENCY:
+ default:
+ dprintk(VIDC_INFO, "DEFAULT: Calling 0x%x", ptype);
+ break;
+ }
+ return 0;
+}
+
+void *vidc_hal_session_init(void *device, u32 session_id,
+ enum hal_domain session_type, enum hal_video_codec codec_type)
+{
+ struct hfi_cmd_sys_session_init_packet pkt;
+ struct hal_session *new_session;
+ struct hal_device *dev;
+
+ if (device) {
+ dev = device;
+ } else {
+ dprintk(VIDC_ERR, "invalid device");
+ return NULL;
+ }
+
+ new_session = (struct hal_session *)
+ kzalloc(sizeof(struct hal_session), GFP_KERNEL);
+ new_session->session_id = (u32) session_id;
+ if (session_type == 1)
+ new_session->is_decoder = 0;
+ else if (session_type == 2)
+ new_session->is_decoder = 1;
+ new_session->device = dev;
+ list_add_tail(&new_session->list, &dev->sess_head);
+
+ if (create_pkt_cmd_sys_session_init(&pkt, (u32)new_session,
+ session_type, codec_type)) {
+ dprintk(VIDC_ERR, "session_init: failed to create packet");
+ goto err_session_init_fail;
+ }
+
+ if (vidc_hal_iface_cmdq_write(dev, &pkt))
+ goto err_session_init_fail;
+ if (vidc_hal_sys_set_debug(dev, msm_fw_debug))
+ dprintk(VIDC_ERR, "Setting fw_debug msg ON failed");
+ return (void *) new_session;
+
+err_session_init_fail:
+ kfree(new_session);
+ return NULL;
+}
+
+static int vidc_hal_send_session_cmd(void *session_id,
+ int pkt_type)
+{
+ struct vidc_hal_session_cmd_pkt pkt;
+ int rc = 0;
+ struct hal_session *session;
+
+ if (session_id) {
+ session = session_id;
+ } else {
+ dprintk(VIDC_ERR, "invalid session");
+ return -ENODEV;
+ }
+
+ rc = create_pkt_cmd_session_cmd(&pkt, pkt_type, (u32)session);
+ if (rc) {
+ dprintk(VIDC_ERR, "send session cmd: create pkt failed");
+ goto err_create_pkt;
+ }
+
+ if (vidc_hal_iface_cmdq_write(session->device, &pkt))
+ rc = -ENOTEMPTY;
+
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_session_end(void *session)
+{
+ return vidc_hal_send_session_cmd(session,
+ HFI_CMD_SYS_SESSION_END);
+}
+
+int vidc_hal_session_abort(void *session)
+{
+ return vidc_hal_send_session_cmd(session,
+ HFI_CMD_SYS_SESSION_ABORT);
+}
+
+int vidc_hal_session_set_buffers(void *sess,
+ struct vidc_buffer_addr_info *buffer_info)
+{
+ struct hfi_cmd_session_set_buffers_packet *pkt;
+ u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
+ int rc = 0;
+ struct hal_session *session;
+
+ if (!sess || !buffer_info) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ } else {
+ session = sess;
+ }
+
+ if (buffer_info->buffer_type == HAL_BUFFER_INPUT)
+ return 0;
+
+ pkt = (struct hfi_cmd_session_set_buffers_packet *)packet;
+
+ rc = create_pkt_cmd_session_set_buffers(pkt,
+ (u32)session, buffer_info);
+ if (rc) {
+ dprintk(VIDC_ERR, "set buffers: failed to create packet");
+ goto err_create_pkt;
+ }
+
+ dprintk(VIDC_INFO, "set buffers: 0x%x", buffer_info->buffer_type);
+ if (vidc_hal_iface_cmdq_write(session->device, pkt))
+ rc = -ENOTEMPTY;
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_session_release_buffers(void *sess,
+ struct vidc_buffer_addr_info *buffer_info)
+{
+ struct hfi_cmd_session_release_buffer_packet *pkt;
+ u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
+ int rc = 0;
+ struct hal_session *session;
+
+ if (!sess || !buffer_info) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ } else {
+ session = sess;
+ }
+
+ if (buffer_info->buffer_type == HAL_BUFFER_INPUT)
+ return 0;
+
+ pkt = (struct hfi_cmd_session_release_buffer_packet *) packet;
+
+ rc = create_pkt_cmd_session_release_buffers(pkt,
+ (u32)session, buffer_info);
+ if (rc) {
+ dprintk(VIDC_ERR, "release buffers: failed to create packet");
+ goto err_create_pkt;
+ }
+
+ dprintk(VIDC_INFO, "Release buffers: 0x%x", buffer_info->buffer_type);
+ if (vidc_hal_iface_cmdq_write(session->device, pkt))
+ rc = -ENOTEMPTY;
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_session_load_res(void *sess)
+{
+ return vidc_hal_send_session_cmd(sess,
+ HFI_CMD_SESSION_LOAD_RESOURCES);
+}
+
+int vidc_hal_session_release_res(void *sess)
+{
+ return vidc_hal_send_session_cmd(sess,
+ HFI_CMD_SESSION_RELEASE_RESOURCES);
+}
+
+int vidc_hal_session_start(void *sess)
+{
+ return vidc_hal_send_session_cmd(sess,
+ HFI_CMD_SESSION_START);
+}
+
+int vidc_hal_session_stop(void *sess)
+{
+ return vidc_hal_send_session_cmd(sess,
+ HFI_CMD_SESSION_STOP);
+}
+
+int vidc_hal_session_suspend(void *sess)
+{
+ return vidc_hal_send_session_cmd(sess,
+ HFI_CMD_SESSION_SUSPEND);
+}
+
+int vidc_hal_session_resume(void *sess)
+{
+ return vidc_hal_send_session_cmd(sess,
+ HFI_CMD_SESSION_RESUME);
+}
+
+int vidc_hal_session_etb(void *sess, struct vidc_frame_data *input_frame)
+{
+ int rc = 0;
+ struct hal_session *session;
+
+ if (!sess || !input_frame) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ } else {
+ session = sess;
+ }
+
+ if (session->is_decoder) {
+ struct hfi_cmd_session_empty_buffer_compressed_packet pkt;
+
+ rc = create_pkt_cmd_session_etb_decoder(&pkt,
+ (u32)session, input_frame);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Session etb decoder: failed to create pkt");
+ goto err_create_pkt;
+ }
+ dprintk(VIDC_DBG, "Q DECODER INPUT BUFFER");
+ if (vidc_hal_iface_cmdq_write(session->device, &pkt))
+ rc = -ENOTEMPTY;
+ } else {
+ struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
+ pkt;
+
+ rc = create_pkt_cmd_session_etb_encoder(&pkt,
+ (u32)session, input_frame);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Session etb encoder: failed to create pkt");
+ goto err_create_pkt;
+ }
+ dprintk(VIDC_DBG, "Q ENCODER INPUT BUFFER");
+ if (vidc_hal_iface_cmdq_write(session->device, &pkt))
+ rc = -ENOTEMPTY;
+ }
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_session_ftb(void *sess,
+ struct vidc_frame_data *output_frame)
+{
+ struct hfi_cmd_session_fill_buffer_packet pkt;
+ int rc = 0;
+ struct hal_session *session;
+
+ if (!sess || !output_frame) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ } else {
+ session = sess;
+ }
+
+ rc = create_pkt_cmd_session_ftb(&pkt, (u32)session, output_frame);
+ if (rc) {
+ dprintk(VIDC_ERR, "Session ftb: failed to create pkt");
+ goto err_create_pkt;
+ }
+
+ if (vidc_hal_iface_cmdq_write(session->device, &pkt))
+ rc = -ENOTEMPTY;
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_session_parse_seq_hdr(void *sess,
+ struct vidc_seq_hdr *seq_hdr)
+{
+ struct hfi_cmd_session_parse_sequence_header_packet *pkt;
+ int rc = 0;
+ u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+ struct hal_session *session;
+
+ if (!sess || !seq_hdr) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ } else {
+ session = sess;
+ }
+
+ pkt = (struct hfi_cmd_session_parse_sequence_header_packet *) packet;
+
+ rc = create_pkt_cmd_session_parse_seq_header(pkt, (u32)session,
+ seq_hdr);
+ if (rc) {
+ dprintk(VIDC_ERR,
+ "Session parse seq hdr: failed to create pkt");
+ goto err_create_pkt;
+ }
+
+ if (vidc_hal_iface_cmdq_write(session->device, pkt))
+ rc = -ENOTEMPTY;
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_session_get_seq_hdr(void *sess,
+ struct vidc_seq_hdr *seq_hdr)
+{
+ struct hfi_cmd_session_get_sequence_header_packet *pkt;
+ int rc = 0;
+ u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
+ struct hal_session *session;
+
+ if (!sess || !seq_hdr) {
+ dprintk(VIDC_ERR, "Invalid Params");
+ return -EINVAL;
+ } else {
+ session = sess;
+ }
+
+ pkt = (struct hfi_cmd_session_get_sequence_header_packet *) packet;
+ rc = create_pkt_cmd_session_get_seq_hdr(pkt, (u32)session, seq_hdr);
+ if (rc) {
+ dprintk(VIDC_ERR, "Session get seq hdr: failed to create pkt");
+ goto err_create_pkt;
+ }
+
+ if (vidc_hal_iface_cmdq_write(session->device, pkt))
+ rc = -ENOTEMPTY;
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_session_get_buf_req(void *sess)
+{
+ struct hfi_cmd_session_get_property_packet pkt;
+ int rc = 0;
+ struct hal_session *session;
+
+ if (sess) {
+ session = sess;
+ } else {
+ dprintk(VIDC_ERR, "invalid session");
+ return -ENODEV;
+ }
+
+ rc = create_pkt_cmd_session_get_buf_req(&pkt, (u32)session);
+ if (rc) {
+ dprintk(VIDC_ERR, "Session get buf req: failed to create pkt");
+ goto err_create_pkt;
+ }
+
+ if (vidc_hal_iface_cmdq_write(session->device, &pkt))
+ rc = -ENOTEMPTY;
+err_create_pkt:
+ return rc;
+}
+
+int vidc_hal_session_flush(void *sess, enum hal_flush flush_mode)
+{
+ struct hfi_cmd_session_flush_packet pkt;
+ int rc = 0;
+ struct hal_session *session;
+
+ if (sess) {
+ session = sess;
+ } else {
+ dprintk(VIDC_ERR, "invalid session");
+ return -ENODEV;
+ }
+
+ rc = create_pkt_cmd_session_flush(&pkt, (u32)session, flush_mode);
+ if (rc) {
+ dprintk(VIDC_ERR, "Session flush: failed to create pkt");
+ goto err_create_pkt;
+ }
+
+ if (vidc_hal_iface_cmdq_write(session->device, &pkt))
+ rc = -ENOTEMPTY;
+err_create_pkt:
+ return rc;
+}
+
+static int vidc_hal_check_core_registered(
+ struct hal_device_data core, u32 fw_addr,
+ u32 reg_addr, u32 reg_size, u32 irq)
+{
+ struct hal_device *device;
+ struct list_head *curr, *next;
+
+ if (core.dev_count) {
+ list_for_each_safe(curr, next, &core.dev_head) {
+ device = list_entry(curr, struct hal_device, list);
+ if (device && device->hal_data->irq == irq &&
+ (CONTAINS(device->hal_data->
+ device_base_addr,
+ FIRMWARE_SIZE, fw_addr) ||
+ CONTAINS(fw_addr, FIRMWARE_SIZE,
+ device->hal_data->
+ device_base_addr) ||
+ CONTAINS((u32)device->hal_data->
+ register_base_addr,
+ reg_size, reg_addr) ||
+ CONTAINS(reg_addr, reg_size,
+ (u32)device->hal_data->
+ register_base_addr) ||
+ OVERLAPS((u32)device->hal_data->
+ register_base_addr,
+ reg_size, reg_addr, reg_size) ||
+ OVERLAPS(reg_addr, reg_size,
+ (u32)device->hal_data->
+ register_base_addr, reg_size) ||
+ OVERLAPS(device->hal_data->
+ device_base_addr,
+ FIRMWARE_SIZE, fw_addr,
+ FIRMWARE_SIZE) ||
+ OVERLAPS(fw_addr, FIRMWARE_SIZE,
+ device->hal_data->
+ device_base_addr,
+ FIRMWARE_SIZE))) {
+ return 0;
+ } else {
+ dprintk(VIDC_INFO, "Device not registered");
+ return -EINVAL;
+ }
+ }
+ } else {
+ dprintk(VIDC_INFO, "no device Registered");
+ }
+ return -EINVAL;
+}
+
+static void vidc_hal_core_work_handler(struct work_struct *work)
+{
+ struct hal_device *device = list_first_entry(
+ &hal_ctxt.dev_head, struct hal_device, list);
+
+ dprintk(VIDC_INFO, " GOT INTERRUPT () ");
+ if (!device->callback) {
+ dprintk(VIDC_ERR, "No interrupt callback function: %p\n",
+ device);
+ return;
+ }
+ vidc_hal_core_clear_interrupt(device);
+ vidc_hal_response_handler(device);
+ enable_irq(device->hal_data->irq);
+}
+static DECLARE_WORK(vidc_hal_work, vidc_hal_core_work_handler);
+
+static irqreturn_t vidc_hal_isr(int irq, void *dev)
+{
+ struct hal_device *device = dev;
+ dprintk(VIDC_INFO, "vidc_hal_isr() %d ", irq);
+ disable_irq_nosync(irq);
+ queue_work(device->vidc_workq, &vidc_hal_work);
+ dprintk(VIDC_INFO, "vidc_hal_isr() %d ", irq);
+ return IRQ_HANDLED;
+}
+
+void *vidc_hal_add_device(u32 device_id, u32 fw_base_addr, u32 reg_base,
+ u32 reg_size, u32 irq,
+ void (*callback) (enum command_response cmd, void *data))
+{
+ struct hal_device *hdevice = NULL;
+ struct hal_data *hal = NULL;
+ int rc = 0;
+
+ if (device_id || !reg_base || !reg_size ||
+ !irq || !callback) {
+ dprintk(VIDC_ERR, "Invalid Paramters");
+ return NULL;
+ } else {
+ dprintk(VIDC_INFO, "entered , device_id: %d", device_id);
+ }
+
+ if (vidc_hal_check_core_registered(hal_ctxt, fw_base_addr,
+ reg_base, reg_size, irq)) {
+ dprintk(VIDC_DBG, "HAL_DATA will be assigned now");
+ hal = (struct hal_data *)
+ kzalloc(sizeof(struct hal_data), GFP_KERNEL);
+ if (!hal) {
+ dprintk(VIDC_ERR, "Failed to alloc");
+ return NULL;
+ }
+ hal->irq = irq;
+ hal->device_base_addr = fw_base_addr;
+ hal->register_base_addr =
+ ioremap_nocache(reg_base, reg_size);
+ if (!hal->register_base_addr) {
+ dprintk(VIDC_ERR,
+ "could not map reg addr %d of size %d",
+ reg_base, reg_size);
+ goto err_map;
+ }
+ INIT_LIST_HEAD(&hal_ctxt.dev_head);
+ } else {
+ dprintk(VIDC_ERR, "Core present/Already added");
+ return NULL;
+ }
+
+ hdevice = (struct hal_device *)
+ kzalloc(sizeof(struct hal_device), GFP_KERNEL);
+ if (!hdevice) {
+ dprintk(VIDC_ERR, "failed to allocate new device");
+ goto err_map;
+ }
+
+ INIT_LIST_HEAD(&hdevice->list);
+ list_add_tail(&hdevice->list, &hal_ctxt.dev_head);
+ hal_ctxt.dev_count++;
+ hdevice->device_id = device_id;
+ hdevice->hal_data = hal;
+ hdevice->callback = callback;
+
+ hdevice->vidc_workq = create_singlethread_workqueue(
+ "msm_vidc_workerq");
+ if (!hdevice->vidc_workq) {
+ dprintk(VIDC_ERR, ": create workq failed\n");
+ goto error_createq;
+ }
+
+ rc = request_irq(irq, vidc_hal_isr, IRQF_TRIGGER_HIGH,
+ "msm_vidc", hdevice);
+ if (unlikely(rc)) {
+ dprintk(VIDC_ERR, "() :request_irq failed\n");
+ goto error_irq_fail;
+ }
+ disable_irq_nosync(irq);
+ return (void *) hdevice;
+error_irq_fail:
+ destroy_workqueue(hdevice->vidc_workq);
+error_createq:
+ hal_ctxt.dev_count--;
+ list_del(&hal_ctxt.dev_head);
+err_map:
+ kfree(hal);
+ return NULL;
+}
+
+void vidc_hal_delete_device(void *device)
+{
+ struct hal_device *close, *dev;
+
+ if (device) {
+ dev = (struct hal_device *) device;
+ list_for_each_entry(close, &hal_ctxt.dev_head, list) {
+ if (close->hal_data->irq == dev->hal_data->irq) {
+ hal_ctxt.dev_count--;
+ free_irq(dev->hal_data->irq, close);
+ list_del(&close->list);
+ destroy_workqueue(close->vidc_workq);
+ kfree(close->hal_data);
+ kfree(close);
+ break;
+ }
+ }
+
+ }
+}
diff --git a/drivers/media/video/msm_vidc/vidc_hal.h b/drivers/media/video/msm_vidc/venus_hfi.h
similarity index 98%
rename from drivers/media/video/msm_vidc/vidc_hal.h
rename to drivers/media/video/msm_vidc/venus_hfi.h
index c8a7d43..6b904fd 100644
--- a/drivers/media/video/msm_vidc/vidc_hal.h
+++ b/drivers/media/video/msm_vidc/venus_hfi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -11,14 +11,14 @@
*
*/
-#ifndef __H_VIDC_HAL_H__
-#define __H_VIDC_HAL_H__
+#ifndef __H_VENUS_HFI_H__
+#define __H_VENUS_HFI_H__
#include <linux/spinlock.h>
#include <linux/mutex.h>
-#include "vidc_hal_api.h"
+#include "vidc_hfi_api.h"
#include "msm_smem.h"
-#include "vidc_hal_helper.h"
+#include "vidc_hfi_helper.h"
#define HFI_MASK_QHDR_TX_TYPE 0xFF000000
#define HFI_MASK_QHDR_RX_TYPE 0x00FF0000
diff --git a/drivers/media/video/msm_vidc/vidc_hal.c b/drivers/media/video/msm_vidc/vidc_hal.c
deleted file mode 100644
index 8283fac..0000000
--- a/drivers/media/video/msm_vidc/vidc_hal.c
+++ /dev/null
@@ -1,2389 +0,0 @@
-/* Copyright (c) 2012, Code Aurora Forum. 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/slab.h>
-#include <linux/workqueue.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <mach/ocmem.h>
-
-#include <asm/memory.h>
-#include "vidc_hal.h"
-#include "vidc_hal_io.h"
-#include "msm_vidc_debug.h"
-
-#define FIRMWARE_SIZE 0X00A00000
-#define REG_ADDR_OFFSET_BITMASK 0x000FFFFF
-
-/*Workaround for virtio */
-#define HFI_VIRTIO_FW_BIAS 0x0
-
-struct hal_device_data hal_ctxt;
-
-static void hal_virtio_modify_cmd_packet(u8 *packet)
-{
- struct hfi_cmd_sys_session_init_packet *sys_init;
- struct hal_session *sess;
- u8 i;
-
- if (!packet) {
- dprintk(VIDC_ERR, "Invalid Param");
- return;
- }
-
- sys_init = (struct hfi_cmd_sys_session_init_packet *)packet;
- sess = (struct hal_session *) sys_init->session_id;
- switch (sys_init->packet_type) {
- case HFI_CMD_SESSION_EMPTY_BUFFER:
- if (sess->is_decoder) {
- struct hfi_cmd_session_empty_buffer_compressed_packet
- *pkt = (struct
- hfi_cmd_session_empty_buffer_compressed_packet
- *) packet;
- pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
- } else {
- struct
- hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
- *pkt = (struct
- hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
- *) packet;
- pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
- }
- break;
- case HFI_CMD_SESSION_FILL_BUFFER:
- {
- struct hfi_cmd_session_fill_buffer_packet *pkt =
- (struct hfi_cmd_session_fill_buffer_packet *)packet;
- pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
- break;
- }
- case HFI_CMD_SESSION_SET_BUFFERS:
- {
- struct hfi_cmd_session_set_buffers_packet *pkt =
- (struct hfi_cmd_session_set_buffers_packet *)packet;
- if ((pkt->buffer_type == HFI_BUFFER_OUTPUT) ||
- (pkt->buffer_type == HFI_BUFFER_OUTPUT2)) {
- struct hfi_buffer_info *buff;
- buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
- buff->buffer_addr -= HFI_VIRTIO_FW_BIAS;
- buff->extra_data_addr -= HFI_VIRTIO_FW_BIAS;
- } else {
- for (i = 0; i < pkt->num_buffers; i++)
- pkt->rg_buffer_info[i] -= HFI_VIRTIO_FW_BIAS;
- }
- break;
- }
- case HFI_CMD_SESSION_RELEASE_BUFFERS:
- {
- struct hfi_cmd_session_release_buffer_packet *pkt =
- (struct hfi_cmd_session_release_buffer_packet *)packet;
- if ((pkt->buffer_type == HFI_BUFFER_OUTPUT) ||
- (pkt->buffer_type == HFI_BUFFER_OUTPUT2)) {
- struct hfi_buffer_info *buff;
- buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
- buff->buffer_addr -= HFI_VIRTIO_FW_BIAS;
- buff->extra_data_addr -= HFI_VIRTIO_FW_BIAS;
- } else {
- for (i = 0; i < pkt->num_buffers; i++)
- pkt->rg_buffer_info[i] -= HFI_VIRTIO_FW_BIAS;
- }
- break;
- }
- case HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER:
- {
- struct hfi_cmd_session_parse_sequence_header_packet *pkt =
- (struct hfi_cmd_session_parse_sequence_header_packet *)
- packet;
- pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
- break;
- }
- case HFI_CMD_SESSION_GET_SEQUENCE_HEADER:
- {
- struct hfi_cmd_session_get_sequence_header_packet *pkt =
- (struct hfi_cmd_session_get_sequence_header_packet *)
- packet;
- pkt->packet_buffer -= HFI_VIRTIO_FW_BIAS;
- break;
- }
- default:
- break;
- }
-}
-
-static int write_queue(void *info, u8 *packet, u32 *rx_req_is_set)
-{
- struct hfi_queue_header *queue;
- u32 packet_size_in_words, new_write_idx;
- struct vidc_iface_q_info *qinfo;
- u32 empty_space, read_idx;
- u32 *write_ptr;
-
- if (!info || !packet || !rx_req_is_set) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- }
-
- qinfo = (struct vidc_iface_q_info *) info;
- hal_virtio_modify_cmd_packet(packet);
-
- queue = (struct hfi_queue_header *) qinfo->q_hdr;
-
- if (!queue) {
- dprintk(VIDC_ERR, "queue not present");
- return -ENOENT;
- }
-
- packet_size_in_words = (*(u32 *)packet) >> 2;
- dprintk(VIDC_DBG, "Packet_size in words: %d", packet_size_in_words);
-
- if (packet_size_in_words == 0) {
- dprintk(VIDC_ERR, "Zero packet size");
- return -ENODATA;
- }
-
- read_idx = queue->qhdr_read_idx;
-
- empty_space = (queue->qhdr_write_idx >= read_idx) ?
- (queue->qhdr_q_size - (queue->qhdr_write_idx - read_idx)) :
- (read_idx - queue->qhdr_write_idx);
- dprintk(VIDC_DBG, "Empty_space: %d", empty_space);
- if (empty_space <= packet_size_in_words) {
- queue->qhdr_tx_req = 1;
- dprintk(VIDC_ERR, "Insufficient size (%d) to write (%d)",
- empty_space, packet_size_in_words);
- return -ENOTEMPTY;
- }
-
- queue->qhdr_tx_req = 0;
-
- new_write_idx = (queue->qhdr_write_idx + packet_size_in_words);
- write_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
- (queue->qhdr_write_idx << 2));
- dprintk(VIDC_DBG, "Write Ptr: %d", (u32) write_ptr);
- if (new_write_idx < queue->qhdr_q_size) {
- memcpy(write_ptr, packet, packet_size_in_words << 2);
- } else {
- new_write_idx -= queue->qhdr_q_size;
- memcpy(write_ptr, packet, (packet_size_in_words -
- new_write_idx) << 2);
- memcpy((void *)qinfo->q_array.align_virtual_addr,
- packet + ((packet_size_in_words - new_write_idx) << 2),
- new_write_idx << 2);
- }
- queue->qhdr_write_idx = new_write_idx;
- *rx_req_is_set = (1 == queue->qhdr_rx_req) ? 1 : 0;
- dprintk(VIDC_DBG, "Out : ");
- return 0;
-}
-
-static void hal_virtio_modify_msg_packet(u8 *packet)
-{
- struct hfi_msg_sys_session_init_done_packet *sys_idle;
- struct hal_session *sess;
-
- if (!packet) {
- dprintk(VIDC_ERR, "Invalid Param: ");
- return;
- }
-
- sys_idle = (struct hfi_msg_sys_session_init_done_packet *)packet;
- sess = (struct hal_session *) sys_idle->session_id;
-
- switch (sys_idle->packet_type) {
- case HFI_MSG_SESSION_FILL_BUFFER_DONE:
- if (sess->is_decoder) {
- struct
- hfi_msg_session_fbd_uncompressed_plane0_packet
- *pkt_uc = (struct
- hfi_msg_session_fbd_uncompressed_plane0_packet
- *) packet;
- pkt_uc->packet_buffer += HFI_VIRTIO_FW_BIAS;
- } else {
- struct
- hfi_msg_session_fill_buffer_done_compressed_packet
- *pkt = (struct
- hfi_msg_session_fill_buffer_done_compressed_packet
- *) packet;
- pkt->packet_buffer += HFI_VIRTIO_FW_BIAS;
- }
- break;
- case HFI_MSG_SESSION_EMPTY_BUFFER_DONE:
- {
- struct hfi_msg_session_empty_buffer_done_packet *pkt =
- (struct hfi_msg_session_empty_buffer_done_packet *)packet;
- pkt->packet_buffer += HFI_VIRTIO_FW_BIAS;
- break;
- }
- case HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE:
- {
- struct
- hfi_msg_session_get_sequence_header_done_packet
- *pkt =
- (struct hfi_msg_session_get_sequence_header_done_packet *)
- packet;
- pkt->sequence_header += HFI_VIRTIO_FW_BIAS;
- break;
- }
- default:
- break;
- }
-}
-
-static int read_queue(void *info, u8 *packet, u32 *pb_tx_req_is_set)
-{
- struct hfi_queue_header *queue;
- u32 packet_size_in_words, new_read_idx;
- u32 *read_ptr;
- struct vidc_iface_q_info *qinfo;
-
- if (!info || !packet || !pb_tx_req_is_set) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- }
-
- qinfo = (struct vidc_iface_q_info *) info;
- queue = (struct hfi_queue_header *) qinfo->q_hdr;
-
- if (!queue) {
- dprintk(VIDC_ERR, "Queue memory is not allocated\n");
- return -ENOMEM;
- }
-
- if (queue->qhdr_read_idx == queue->qhdr_write_idx) {
- queue->qhdr_rx_req = 1;
- *pb_tx_req_is_set = 0;
- return -EPERM;
- }
-
- read_ptr = (u32 *)((qinfo->q_array.align_virtual_addr) +
- (queue->qhdr_read_idx << 2));
- packet_size_in_words = (*read_ptr) >> 2;
- dprintk(VIDC_DBG, "packet_size_in_words: %d", packet_size_in_words);
- if (packet_size_in_words == 0) {
- dprintk(VIDC_ERR, "Zero packet size");
- return -ENODATA;
- }
-
- new_read_idx = queue->qhdr_read_idx + packet_size_in_words;
- dprintk(VIDC_DBG, "Read Ptr: %d", (u32) new_read_idx);
- if (new_read_idx < queue->qhdr_q_size) {
- memcpy(packet, read_ptr,
- packet_size_in_words << 2);
- } else {
- new_read_idx -= queue->qhdr_q_size;
- memcpy(packet, read_ptr,
- (packet_size_in_words - new_read_idx) << 2);
- memcpy(packet + ((packet_size_in_words -
- new_read_idx) << 2),
- (u8 *)qinfo->q_array.align_virtual_addr,
- new_read_idx << 2);
- }
-
- queue->qhdr_read_idx = new_read_idx;
-
- if (queue->qhdr_read_idx != queue->qhdr_write_idx)
- queue->qhdr_rx_req = 0;
- else
- queue->qhdr_rx_req = 1;
-
- *pb_tx_req_is_set = (1 == queue->qhdr_tx_req) ? 1 : 0;
- hal_virtio_modify_msg_packet(packet);
- dprintk(VIDC_DBG, "Out : ");
- return 0;
-}
-
-static int vidc_hal_alloc(void *mem, void *clnt, u32 size, u32 align, u32 flags,
- int domain)
-{
- struct vidc_mem_addr *vmem;
- struct msm_smem *alloc;
- int rc = 0;
-
- if (!mem || !clnt || !size) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- }
- vmem = (struct vidc_mem_addr *)mem;
- dprintk(VIDC_INFO, "start to alloc: size:%d, Flags: %d", size, flags);
-
- alloc = msm_smem_alloc(clnt, size, align, flags, domain, 1, 1);
- dprintk(VIDC_DBG, "Alloc done");
- if (!alloc) {
- dprintk(VIDC_ERR, "Alloc failed\n");
- rc = -ENOMEM;
- goto fail_smem_alloc;
- }
- rc = msm_smem_clean_invalidate(clnt, alloc);
- if (rc) {
- dprintk(VIDC_ERR, "NOTE: Failed to clean caches\n");
- goto fail_clean_cache;
- }
- dprintk(VIDC_DBG, "vidc_hal_alloc:ptr=%p,size=%d",
- alloc->kvaddr, size);
- vmem->mem_size = alloc->size;
- vmem->mem_data = alloc;
- vmem->align_virtual_addr = (u8 *) alloc->kvaddr;
- vmem->align_device_addr = (u8 *)alloc->device_addr;
- return rc;
-fail_clean_cache:
- msm_smem_free(clnt, alloc);
-fail_smem_alloc:
- return rc;
-}
-
-static void vidc_hal_free(struct smem_client *clnt, struct msm_smem *mem)
-{
- msm_smem_free(clnt, mem);
-}
-
-static void write_register(u8 *base_addr, u32 reg, u32 value, u8 *vaddr)
-{
- u32 hwiosymaddr = reg;
-
- reg &= REG_ADDR_OFFSET_BITMASK;
- if (reg == (u32)VIDC_CPU_CS_SCIACMDARG2) {
- /* workaround to offset of FW bias */
- struct hfi_queue_header *qhdr;
- struct hfi_queue_table_header *qtbl_hdr =
- (struct hfi_queue_table_header *)vaddr;
-
- qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 0);
- qhdr->qhdr_start_addr -= HFI_VIRTIO_FW_BIAS;
-
- qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 1);
- qhdr->qhdr_start_addr -= HFI_VIRTIO_FW_BIAS;
-
- qhdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(qtbl_hdr, 2);
- qhdr->qhdr_start_addr -= HFI_VIRTIO_FW_BIAS;
- value -= HFI_VIRTIO_FW_BIAS;
- }
-
- hwiosymaddr = ((u32)base_addr + (hwiosymaddr));
- dprintk(VIDC_DBG, "Base addr: 0x%x, written to: 0x%x, Value: 0x%x...",
- (u32)base_addr, hwiosymaddr, value);
- writel_relaxed(value, hwiosymaddr);
- wmb();
-}
-
-static int read_register(u8 *base_addr, u32 reg)
-{
- int rc = readl_relaxed((u32)base_addr + reg);
- rmb();
- return rc;
-}
-
-static int vidc_hal_iface_cmdq_write(struct hal_device *device, void *pkt)
-{
- u32 rx_req_is_set = 0;
- struct vidc_iface_q_info *q_info;
- int result = -EPERM;
-
- if (!device || !pkt) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- }
-
- spin_lock(&device->write_lock);
- q_info = &device->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
- if (!q_info) {
- dprintk(VIDC_ERR, "cannot write to shared Q's");
- goto err_q_write;
- }
-
- if (!write_queue(q_info, (u8 *)pkt, &rx_req_is_set)) {
- if (rx_req_is_set)
- write_register(device->hal_data->register_base_addr,
- VIDC_CPU_IC_SOFTINT,
- 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
- result = 0;
- } else {
- dprintk(VIDC_ERR, "vidc_hal_iface_cmdq_write:queue_full");
- }
-err_q_write:
- spin_unlock(&device->write_lock);
- return result;
-}
-
-int vidc_hal_iface_msgq_read(struct hal_device *device, void *pkt)
-{
- u32 tx_req_is_set = 0;
- int rc = 0;
- struct vidc_iface_q_info *q_info;
-
- if (!pkt) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- }
- spin_lock(&device->read_lock);
- if (device->iface_queues[VIDC_IFACEQ_MSGQ_IDX].
- q_array.align_virtual_addr == 0) {
- dprintk(VIDC_ERR, "cannot read from shared MSG Q's");
- rc = -ENODATA;
- goto read_error;
- }
- q_info = &device->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
-
- if (!read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
- if (tx_req_is_set)
- write_register(device->hal_data->register_base_addr,
- VIDC_CPU_IC_SOFTINT,
- 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
- rc = 0;
- } else {
- dprintk(VIDC_INFO, "vidc_hal_iface_msgq_read:queue_empty");
- rc = -ENODATA;
- }
-read_error:
- spin_unlock(&device->read_lock);
- return rc;
-}
-
-int vidc_hal_iface_dbgq_read(struct hal_device *device, void *pkt)
-{
- u32 tx_req_is_set = 0;
- int rc = 0;
- struct vidc_iface_q_info *q_info;
-
- if (!pkt) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- }
- spin_lock(&device->read_lock);
- if (device->iface_queues[VIDC_IFACEQ_DBGQ_IDX].
- q_array.align_virtual_addr == 0) {
- dprintk(VIDC_ERR, "cannot read from shared DBG Q's");
- rc = -ENODATA;
- goto dbg_error;
- }
- q_info = &device->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
- if (!read_queue(q_info, (u8 *)pkt, &tx_req_is_set)) {
- if (tx_req_is_set)
- write_register(device->hal_data->register_base_addr,
- VIDC_CPU_IC_SOFTINT,
- 1 << VIDC_CPU_IC_SOFTINT_H2A_SHFT, 0);
- rc = 0;
- } else {
- dprintk(VIDC_INFO, "vidc_hal_iface_dbgq_read:queue_empty");
- rc = -ENODATA;
- }
-dbg_error:
- spin_unlock(&device->read_lock);
- return rc;
-}
-
-static void vidc_hal_set_queue_hdr_defaults(struct hfi_queue_header *q_hdr)
-{
- q_hdr->qhdr_status = 0x1;
- q_hdr->qhdr_type = VIDC_IFACEQ_DFLT_QHDR;
- q_hdr->qhdr_q_size = VIDC_IFACEQ_QUEUE_SIZE / 4;
- q_hdr->qhdr_pkt_size = 0;
- q_hdr->qhdr_rx_wm = 0x1;
- q_hdr->qhdr_tx_wm = 0x1;
- q_hdr->qhdr_rx_req = 0x1;
- q_hdr->qhdr_tx_req = 0x0;
- q_hdr->qhdr_rx_irq_status = 0x0;
- q_hdr->qhdr_tx_irq_status = 0x0;
- q_hdr->qhdr_read_idx = 0x0;
- q_hdr->qhdr_write_idx = 0x0;
-}
-
-static void vidc_hal_interface_queues_release(struct hal_device *device)
-{
- int i;
-
- vidc_hal_free(device->hal_client, device->mem_addr.mem_data);
-
- for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
- device->iface_queues[i].q_hdr = NULL;
- device->iface_queues[i].q_array.mem_data = NULL;
- device->iface_queues[i].q_array.align_virtual_addr = NULL;
- device->iface_queues[i].q_array.align_device_addr = NULL;
- }
- device->iface_q_table.align_virtual_addr = NULL;
- device->iface_q_table.align_device_addr = NULL;
-
- device->qdss.align_virtual_addr = NULL;
- device->qdss.align_device_addr = NULL;
-
- device->sfr.align_virtual_addr = NULL;
- device->sfr.align_device_addr = NULL;
-
- device->mem_addr.align_virtual_addr = NULL;
- device->mem_addr.align_device_addr = NULL;
-
- msm_smem_delete_client(device->hal_client);
- device->hal_client = NULL;
-}
-
-static int vidc_hal_interface_queues_init(struct hal_device *dev, int domain)
-{
- struct hfi_queue_table_header *q_tbl_hdr;
- struct hfi_queue_header *q_hdr;
- u8 i;
- int rc = 0;
- struct vidc_iface_q_info *iface_q;
- struct hfi_sfr_struct *vsfr;
- struct vidc_mem_addr *mem_addr;
- int offset = 0;
- int size_1m = 1024 * 1024;
- int uc_size = (UC_SIZE + size_1m - 1) & (~(size_1m - 1));
- mem_addr = &dev->mem_addr;
- rc = vidc_hal_alloc((void *) mem_addr,
- dev->hal_client, uc_size, 1,
- 0, domain);
- if (rc) {
- dprintk(VIDC_ERR, "iface_q_table_alloc_fail");
- return -ENOMEM;
- }
- dev->iface_q_table.align_virtual_addr = mem_addr->align_virtual_addr;
- dev->iface_q_table.align_device_addr = mem_addr->align_device_addr;
- dev->iface_q_table.mem_size = VIDC_IFACEQ_TABLE_SIZE;
- dev->iface_q_table.mem_data = NULL;
- offset += dev->iface_q_table.mem_size;
-
- for (i = 0; i < VIDC_IFACEQ_NUMQ; i++) {
- iface_q = &dev->iface_queues[i];
- iface_q->q_array.align_device_addr =
- mem_addr->align_device_addr + offset;
- iface_q->q_array.align_virtual_addr =
- mem_addr->align_virtual_addr + offset;
- iface_q->q_array.mem_size = VIDC_IFACEQ_QUEUE_SIZE;
- iface_q->q_array.mem_data = NULL;
- offset += iface_q->q_array.mem_size;
- iface_q->q_hdr = VIDC_IFACEQ_GET_QHDR_START_ADDR(
- dev->iface_q_table.align_virtual_addr, i);
- vidc_hal_set_queue_hdr_defaults(iface_q->q_hdr);
- }
-
- dev->qdss.align_device_addr = mem_addr->align_device_addr + offset;
- dev->qdss.align_virtual_addr = mem_addr->align_virtual_addr + offset;
- dev->qdss.mem_size = QDSS_SIZE;
- dev->qdss.mem_data = NULL;
- offset += dev->qdss.mem_size;
-
- dev->sfr.align_device_addr = mem_addr->align_device_addr + offset;
- dev->sfr.align_virtual_addr = mem_addr->align_virtual_addr + offset;
- dev->sfr.mem_size = SFR_SIZE;
- dev->sfr.mem_data = NULL;
- offset += dev->sfr.mem_size;
-
- q_tbl_hdr = (struct hfi_queue_table_header *)
- dev->iface_q_table.align_virtual_addr;
- q_tbl_hdr->qtbl_version = 0;
- q_tbl_hdr->qtbl_size = VIDC_IFACEQ_TABLE_SIZE;
- q_tbl_hdr->qtbl_qhdr0_offset = sizeof(
- struct hfi_queue_table_header);
- q_tbl_hdr->qtbl_qhdr_size = sizeof(
- struct hfi_queue_header);
- q_tbl_hdr->qtbl_num_q = VIDC_IFACEQ_NUMQ;
- q_tbl_hdr->qtbl_num_active_q = VIDC_IFACEQ_NUMQ;
-
- iface_q = &dev->iface_queues[VIDC_IFACEQ_CMDQ_IDX];
- q_hdr = iface_q->q_hdr;
- q_hdr->qhdr_start_addr = (u32)
- iface_q->q_array.align_device_addr;
- q_hdr->qhdr_type |= HFI_Q_ID_HOST_TO_CTRL_CMD_Q;
-
- iface_q = &dev->iface_queues[VIDC_IFACEQ_MSGQ_IDX];
- q_hdr = iface_q->q_hdr;
- q_hdr->qhdr_start_addr = (u32)
- iface_q->q_array.align_device_addr;
- q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_MSG_Q;
-
- iface_q = &dev->iface_queues[VIDC_IFACEQ_DBGQ_IDX];
- q_hdr = iface_q->q_hdr;
- q_hdr->qhdr_start_addr = (u32)
- iface_q->q_array.align_device_addr;
- q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
-
- write_register(dev->hal_data->register_base_addr,
- VIDC_UC_REGION_ADDR,
- (u32) mem_addr->align_device_addr, 0);
- write_register(dev->hal_data->register_base_addr,
- VIDC_UC_REGION_SIZE, mem_addr->mem_size, 0);
- write_register(dev->hal_data->register_base_addr,
- VIDC_CPU_CS_SCIACMDARG2,
- (u32) dev->iface_q_table.align_device_addr,
- dev->iface_q_table.align_virtual_addr);
- write_register(dev->hal_data->register_base_addr,
- VIDC_CPU_CS_SCIACMDARG1, 0x01,
- dev->iface_q_table.align_virtual_addr);
- write_register(dev->hal_data->register_base_addr,
- VIDC_MMAP_ADDR,
- (u32) dev->qdss.align_device_addr, 0);
-
- vsfr = (struct hfi_sfr_struct *) dev->sfr.align_virtual_addr;
- vsfr->bufSize = SFR_SIZE;
-
- write_register(dev->hal_data->register_base_addr,
- VIDC_SFR_ADDR, (u32)dev->sfr.align_device_addr , 0);
- return 0;
-}
-
-static int vidc_hal_core_start_cpu(struct hal_device *device)
-{
- u32 ctrl_status = 0, count = 0, rc = 0;
- int max_tries = 100;
- write_register(device->hal_data->register_base_addr,
- VIDC_WRAPPER_INTR_MASK, 0x8, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_CPU_CS_SCIACMDARG3, 1, 0);
-
- while (!ctrl_status && count < max_tries) {
- ctrl_status = read_register(
- device->hal_data->register_base_addr,
- VIDC_CPU_CS_SCIACMDARG0);
- if ((ctrl_status & 0xFE) == 0x4) {
- dprintk(VIDC_ERR, "invalid setting for UC_REGION\n");
- break;
- }
- usleep_range(500, 1000);
- count++;
- }
- if (count >= max_tries)
- rc = -ETIME;
- return rc;
-}
-
-static void set_vbif_registers(struct hal_device *device)
-{
- /*Disable Dynamic clock gating for Venus VBIF*/
- write_register(device->hal_data->register_base_addr,
- VIDC_VENUS_VBIF_CLK_ON, 1, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_OUT_AXI_AOOO_EN, 0x00001FFF, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_OUT_AXI_AOOO, 0x1FFF1FFF, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_IN_RD_LIM_CONF0, 0x10101001, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_IN_RD_LIM_CONF1, 0x10101010, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_IN_RD_LIM_CONF2, 0x10101010, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_IN_RD_LIM_CONF3, 0x00000010, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_IN_WR_LIM_CONF0, 0x1010100f, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_IN_WR_LIM_CONF1, 0x10101010, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_IN_WR_LIM_CONF2, 0x10101010, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_IN_WR_LIM_CONF3, 0x00000010, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_OUT_RD_LIM_CONF0, 0x00001010, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_OUT_WR_LIM_CONF0, 0x00001010, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VBIF_ARB_CTL, 0x00000030, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VENUS_VBIF_DDR_OUT_MAX_BURST, 0x00000707, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VENUS_VBIF_OCMEM_OUT_MAX_BURST, 0x00000707, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VENUS_VBIF_ROUND_ROBIN_QOS_ARB, 0x00000001, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VENUS0_WRAPPER_VBIF_REQ_PRIORITY, 0x5555556, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_VENUS0_WRAPPER_VBIF_PRIORITY_LEVEL, 0, 0);
-}
-
-static int vidc_hal_sys_set_debug(struct hal_device *device, int debug)
-{
- struct hfi_debug_config *hfi;
- u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
- struct hfi_cmd_sys_set_property_packet *pkt =
- (struct hfi_cmd_sys_set_property_packet *) &packet;
- pkt->size = sizeof(struct hfi_cmd_sys_set_property_packet) +
- sizeof(struct hfi_debug_config) + sizeof(u32);
- pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
- pkt->num_properties = 1;
- pkt->rg_property_data[0] = HFI_PROPERTY_SYS_DEBUG_CONFIG;
- hfi = (struct hfi_debug_config *) &pkt->rg_property_data[1];
- hfi->debug_config = debug;
- hfi->debug_mode = HFI_DEBUG_MODE_QUEUE;
- if (vidc_hal_iface_cmdq_write(device, pkt))
- return -ENOTEMPTY;
- return 0;
-}
-
-int vidc_hal_core_init(void *device, int domain)
-{
- struct hfi_cmd_sys_init_packet pkt;
- int rc = 0;
- struct hal_device *dev;
-
- if (device) {
- dev = device;
- } else {
- dprintk(VIDC_ERR, "Invalid device");
- return -ENODEV;
- }
- dev->intr_status = 0;
- enable_irq(dev->hal_data->irq);
- INIT_LIST_HEAD(&dev->sess_head);
- spin_lock_init(&dev->read_lock);
- spin_lock_init(&dev->write_lock);
- set_vbif_registers(dev);
-
- if (!dev->hal_client) {
- dev->hal_client = msm_smem_new_client(SMEM_ION);
- if (dev->hal_client == NULL) {
- dprintk(VIDC_ERR, "Failed to alloc ION_Client");
- rc = -ENODEV;
- goto err_no_mem;
- }
-
- dprintk(VIDC_DBG, "Dev_Virt: 0x%x, Reg_Virt: 0x%x",
- dev->hal_data->device_base_addr,
- (u32) dev->hal_data->register_base_addr);
-
- rc = vidc_hal_interface_queues_init(dev, domain);
- if (rc) {
- dprintk(VIDC_ERR, "failed to init queues");
- rc = -ENOMEM;
- goto err_no_mem;
- }
- } else {
- dprintk(VIDC_ERR, "hal_client exists");
- rc = -EEXIST;
- goto err_no_mem;
- }
- write_register(dev->hal_data->register_base_addr,
- VIDC_CTRL_INIT, 0x1, 0);
- rc = vidc_hal_core_start_cpu(dev);
- if (rc) {
- dprintk(VIDC_ERR, "Failed to start core");
- rc = -ENODEV;
- goto err_no_dev;
- }
-
- pkt.size = sizeof(struct hfi_cmd_sys_init_packet);
- pkt.packet_type = HFI_CMD_SYS_INIT;
- pkt.arch_type = HFI_ARCH_OX_OFFSET;
- if (vidc_hal_iface_cmdq_write(dev, &pkt)) {
- rc = -ENOTEMPTY;
- goto err_write_fail;
- }
- return rc;
-err_no_dev:
-err_write_fail:
-err_no_mem:
- disable_irq_nosync(dev->hal_data->irq);
- return rc;
-}
-
-int vidc_hal_core_release(void *device)
-{
- struct hal_device *dev;
- if (device) {
- dev = device;
- } else {
- dprintk(VIDC_ERR, "invalid device");
- return -ENODEV;
- }
- if (dev->hal_client) {
- write_register(dev->hal_data->register_base_addr,
- VIDC_CPU_CS_SCIACMDARG3, 0, 0);
- disable_irq_nosync(dev->hal_data->irq);
- vidc_hal_interface_queues_release(dev);
- }
- dprintk(VIDC_INFO, "HAL exited\n");
- return 0;
-}
-
-int vidc_hal_core_pc_prep(void *device)
-{
- struct hfi_cmd_sys_pc_prep_packet pkt;
- int rc = 0;
- struct hal_device *dev;
-
- if (device) {
- dev = device;
- } else {
- dprintk(VIDC_ERR, "invalid device");
- return -ENODEV;
- }
- pkt.size = sizeof(struct hfi_cmd_sys_pc_prep_packet);
- pkt.packet_type = HFI_CMD_SYS_PC_PREP;
- if (vidc_hal_iface_cmdq_write(dev, &pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-
-static void vidc_hal_core_clear_interrupt(struct hal_device *device)
-{
- u32 intr_status = 0;
-
- if (!device->callback)
- return;
-
- intr_status = read_register(
- device->hal_data->register_base_addr,
- VIDC_WRAPPER_INTR_STATUS);
-
- if ((intr_status & VIDC_WRAPPER_INTR_STATUS_A2H_BMSK) ||
- (intr_status & VIDC_WRAPPER_INTR_STATUS_A2HWD_BMSK)) {
- device->intr_status |= intr_status;
- dprintk(VIDC_DBG, "INTERRUPT for device: 0x%x: "
- "times: %d interrupt_status: %d",
- (u32) device, ++device->reg_count, intr_status);
- } else {
- dprintk(VIDC_INFO, "SPURIOUS_INTR for device: 0x%x: "
- "times: %d interrupt_status: %d",
- (u32) device, ++device->spur_count, intr_status);
- }
- write_register(device->hal_data->register_base_addr,
- VIDC_CPU_CS_A2HSOFTINTCLR, 1, 0);
- write_register(device->hal_data->register_base_addr,
- VIDC_WRAPPER_INTR_CLEAR, intr_status, 0);
- dprintk(VIDC_DBG, "Cleared WRAPPER/A2H interrupt");
-}
-
-int vidc_hal_core_set_resource(void *device,
- struct vidc_resource_hdr *resource_hdr, void *resource_value)
-{
- struct hfi_cmd_sys_set_resource_packet *pkt;
- u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
- int rc = 0;
- struct hal_device *dev;
-
- if (!device || !resource_hdr || !resource_value) {
- dprintk(VIDC_ERR, "set_res: Invalid Params");
- return -EINVAL;
- } else {
- dev = device;
- }
-
- pkt = (struct hfi_cmd_sys_set_resource_packet *) packet;
-
- pkt->size = sizeof(struct hfi_cmd_sys_set_resource_packet);
- pkt->packet_type = HFI_CMD_SYS_SET_RESOURCE;
- pkt->resource_handle = resource_hdr->resource_handle;
-
- switch (resource_hdr->resource_id) {
- case VIDC_RESOURCE_OCMEM:
- {
- struct hfi_resource_ocmem *hfioc_mem =
- (struct hfi_resource_ocmem *)
- &pkt->rg_resource_data[0];
- struct ocmem_buf *ocmem =
- (struct ocmem_buf *) resource_value;
-
- pkt->resource_type = HFI_RESOURCE_OCMEM;
- hfioc_mem->size = (u32) ocmem->len;
- hfioc_mem->mem = (u8 *) ocmem->addr;
- pkt->size += sizeof(struct hfi_resource_ocmem);
- if (vidc_hal_iface_cmdq_write(dev, pkt))
- rc = -ENOTEMPTY;
- break;
- }
- default:
- dprintk(VIDC_INFO, "Invalid res_id in set_res %d",
- resource_hdr->resource_id);
- break;
- }
- return rc;
-}
-
-int vidc_hal_core_release_resource(void *device,
- struct vidc_resource_hdr *resource_hdr)
-{
- struct hfi_cmd_sys_release_resource_packet pkt;
- int rc = 0;
- struct hal_device *dev;
-
- if (!device || !resource_hdr) {
- dprintk(VIDC_ERR, "Inv-Params in rel_res");
- return -EINVAL;
- } else {
- dev = device;
- }
-
- pkt.size = sizeof(struct hfi_cmd_sys_release_resource_packet);
- pkt.packet_type = HFI_CMD_SYS_RELEASE_RESOURCE;
- pkt.resource_type = resource_hdr->resource_id;
- pkt.resource_handle = resource_hdr->resource_handle;
-
- if (vidc_hal_iface_cmdq_write(dev, &pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-
-int vidc_hal_core_ping(void *device)
-{
- struct hfi_cmd_sys_ping_packet pkt;
- int rc = 0;
- struct hal_device *dev;
-
- if (device) {
- dev = device;
- } else {
- dprintk(VIDC_ERR, "invalid device");
- return -ENODEV;
- }
- pkt.size = sizeof(struct hfi_cmd_sys_ping_packet);
- pkt.packet_type = HFI_CMD_SYS_PING;
-
- if (vidc_hal_iface_cmdq_write(dev, &pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-static u32 get_hfi_buffer(int hal_buffer)
-{
- u32 buffer;
- switch (hal_buffer) {
- case HAL_BUFFER_INPUT:
- buffer = HFI_BUFFER_INPUT;
- break;
- case HAL_BUFFER_OUTPUT:
- buffer = HFI_BUFFER_OUTPUT;
- break;
- case HAL_BUFFER_OUTPUT2:
- buffer = HFI_BUFFER_OUTPUT;
- break;
- case HAL_BUFFER_EXTRADATA_INPUT:
- buffer = HFI_BUFFER_EXTRADATA_INPUT;
- break;
- case HAL_BUFFER_EXTRADATA_OUTPUT:
- buffer = HFI_BUFFER_EXTRADATA_OUTPUT;
- break;
- case HAL_BUFFER_EXTRADATA_OUTPUT2:
- buffer = HFI_BUFFER_EXTRADATA_OUTPUT2;
- break;
- case HAL_BUFFER_INTERNAL_SCRATCH:
- buffer = HFI_BUFFER_INTERNAL_SCRATCH;
- break;
- case HAL_BUFFER_INTERNAL_PERSIST:
- buffer = HFI_BUFFER_INTERNAL_PERSIST;
- break;
- default:
- dprintk(VIDC_ERR, "Invalid buffer :0x%x\n",
- hal_buffer);
- buffer = 0;
- break;
- }
- return buffer;
-}
-
-
-static int get_hfi_extradata_index(enum hal_extradata_id index)
-{
- int ret = 0;
- switch (index) {
- case HAL_EXTRADATA_MB_QUANTIZATION:
- ret = HFI_PROPERTY_PARAM_VDEC_MB_QUANTIZATION;
- break;
- case HAL_EXTRADATA_INTERLACE_VIDEO:
- ret = HFI_PROPERTY_PARAM_VDEC_INTERLACE_VIDEO_EXTRADATA;
- break;
- case HAL_EXTRADATA_VC1_FRAMEDISP:
- ret = HFI_PROPERTY_PARAM_VDEC_VC1_FRAMEDISP_EXTRADATA;
- break;
- case HAL_EXTRADATA_VC1_SEQDISP:
- ret = HFI_PROPERTY_PARAM_VDEC_VC1_SEQDISP_EXTRADATA;
- break;
- case HAL_EXTRADATA_TIMESTAMP:
- ret = HFI_PROPERTY_PARAM_VDEC_TIMESTAMP_EXTRADATA;
- break;
- case HAL_EXTRADATA_S3D_FRAME_PACKING:
- ret = HFI_PROPERTY_PARAM_S3D_FRAME_PACKING_EXTRADATA;
- break;
- case HAL_EXTRADATA_FRAME_RATE:
- ret = HFI_PROPERTY_PARAM_VDEC_FRAME_RATE_EXTRADATA;
- break;
- case HAL_EXTRADATA_PANSCAN_WINDOW:
- ret = HFI_PROPERTY_PARAM_VDEC_PANSCAN_WNDW_EXTRADATA;
- break;
- case HAL_EXTRADATA_RECOVERY_POINT_SEI:
- ret = HFI_PROPERTY_PARAM_VDEC_RECOVERY_POINT_SEI_EXTRADATA;
- break;
- case HAL_EXTRADATA_CLOSED_CAPTION_UD:
- ret = HFI_PROPERTY_PARAM_VDEC_CLOSED_CAPTION_EXTRADATA;
- break;
- case HAL_EXTRADATA_AFD_UD:
- ret = HFI_PROPERTY_PARAM_VDEC_AFD_EXTRADATA;
- break;
- case HAL_EXTRADATA_MULTISLICE_INFO:
- ret = HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_INFO;
- break;
- case HAL_EXTRADATA_NUM_CONCEALED_MB:
- ret = HFI_PROPERTY_PARAM_VDEC_NUM_CONCEALED_MB;
- break;
- case HAL_EXTRADATA_INDEX:
- ret = HFI_PROPERTY_PARAM_EXTRA_DATA_HEADER_CONFIG;
- break;
- default:
- dprintk(VIDC_WARN, "Extradata index not found: %d\n", index);
- break;
- }
- return ret;
-}
-
-int vidc_hal_session_set_property(void *sess,
- enum hal_property ptype, void *pdata)
-{
- u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
- struct hfi_cmd_session_set_property_packet *pkt =
- (struct hfi_cmd_session_set_property_packet *) &packet;
- struct hal_session *session;
- int rc = 0;
-
- if (!sess || !pdata) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- } else {
- session = sess;
- }
-
- dprintk(VIDC_INFO, "in set_prop,with prop id: 0x%x", ptype);
- pkt->size = sizeof(struct hfi_cmd_session_set_property_packet);
- pkt->packet_type = HFI_CMD_SESSION_SET_PROPERTY;
- pkt->session_id = (u32) session;
- pkt->num_properties = 1;
-
- switch (ptype) {
- case HAL_CONFIG_FRAME_RATE:
- {
- struct hfi_frame_rate *hfi;
- u32 buffer;
- struct hal_frame_rate *prop =
- (struct hal_frame_rate *) pdata;
- pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_FRAME_RATE;
- hfi = (struct hfi_frame_rate *) &pkt->rg_property_data[1];
- buffer = get_hfi_buffer(prop->buffer_type);
- if (buffer)
- hfi->buffer_type = buffer;
- else
- return -EINVAL;
- hfi->frame_rate = prop->frame_rate;
- pkt->size += sizeof(u32) + sizeof(struct hfi_frame_rate);
- break;
- }
- case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT:
- {
- u32 buffer;
- struct hfi_uncompressed_format_select *hfi;
- struct hal_uncompressed_format_select *prop =
- (struct hal_uncompressed_format_select *) pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_UNCOMPRESSED_FORMAT_SELECT;
- hfi = (struct hfi_uncompressed_format_select *)
- &pkt->rg_property_data[1];
- buffer = get_hfi_buffer(prop->buffer_type);
- if (buffer)
- hfi->buffer_type = buffer;
- else
- return -EINVAL;
- hfi->format = prop->format;
- pkt->size += sizeof(u32) + sizeof(struct
- hfi_uncompressed_format_select);
- break;
- }
- case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO:
- break;
- case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO:
- break;
- case HAL_PARAM_EXTRA_DATA_HEADER_CONFIG:
- break;
- case HAL_PARAM_FRAME_SIZE:
- {
- u32 buffer;
- struct hfi_frame_size *hfi;
- struct hal_frame_size *prop = (struct hal_frame_size *) pdata;
- pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_FRAME_SIZE;
- hfi = (struct hfi_frame_size *) &pkt->rg_property_data[1];
- buffer = get_hfi_buffer(prop->buffer_type);
- if (buffer)
- hfi->buffer_type = buffer;
- else
- return -EINVAL;
- hfi->height = prop->height;
- hfi->width = prop->width;
- pkt->size += sizeof(u32) + sizeof(struct hfi_frame_size);
- break;
- }
- case HAL_CONFIG_REALTIME:
- {
- struct hfi_enable *hfi;
- pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_REALTIME;
- hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
- hfi->enable = ((struct hfi_enable *) pdata)->enable;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_BUFFER_COUNT_ACTUAL:
- {
- u32 buffer;
- struct hfi_buffer_count_actual *hfi;
- struct hal_buffer_count_actual *prop =
- (struct hal_buffer_count_actual *) pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_BUFFER_COUNT_ACTUAL;
- hfi = (struct hfi_buffer_count_actual *)
- &pkt->rg_property_data[1];
- hfi->buffer_count_actual = prop->buffer_count_actual;
- buffer = get_hfi_buffer(prop->buffer_type);
- if (buffer)
- hfi->buffer_type = buffer;
- else
- return -EINVAL;
- pkt->size += sizeof(u32) + sizeof(struct
- hfi_buffer_count_actual);
- break;
- }
- case HAL_PARAM_NAL_STREAM_FORMAT_SELECT:
- {
- struct hal_nal_stream_format_supported *prop =
- (struct hal_nal_stream_format_supported *)pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SELECT;
- dprintk(VIDC_DBG, "data is :%d",
- prop->nal_stream_format_supported);
- switch (prop->nal_stream_format_supported) {
- case HAL_NAL_FORMAT_STARTCODES:
- pkt->rg_property_data[1] =
- HFI_NAL_FORMAT_STARTCODES;
- break;
- case HAL_NAL_FORMAT_ONE_NAL_PER_BUFFER:
- pkt->rg_property_data[1] =
- HFI_NAL_FORMAT_ONE_NAL_PER_BUFFER;
- break;
- case HAL_NAL_FORMAT_ONE_BYTE_LENGTH:
- pkt->rg_property_data[1] =
- HFI_NAL_FORMAT_ONE_BYTE_LENGTH;
- break;
- case HAL_NAL_FORMAT_TWO_BYTE_LENGTH:
- pkt->rg_property_data[1] =
- HFI_NAL_FORMAT_TWO_BYTE_LENGTH;
- break;
- case HAL_NAL_FORMAT_FOUR_BYTE_LENGTH:
- pkt->rg_property_data[1] =
- HFI_NAL_FORMAT_FOUR_BYTE_LENGTH;
- break;
- default:
- dprintk(VIDC_ERR, "Invalid nal format: 0x%x",
- prop->nal_stream_format_supported);
- break;
- }
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_VDEC_OUTPUT_ORDER:
- {
- int *data = (int *) pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VDEC_OUTPUT_ORDER;
- switch (*data) {
- case HAL_OUTPUT_ORDER_DECODE:
- pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DECODE;
- break;
- case HAL_OUTPUT_ORDER_DISPLAY:
- pkt->rg_property_data[1] = HFI_OUTPUT_ORDER_DISPLAY;
- break;
- default:
- dprintk(VIDC_ERR, "invalid output order: 0x%x",
- *data);
- break;
- }
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_VDEC_PICTURE_TYPE_DECODE:
- {
- struct hfi_enable_picture *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VDEC_PICTURE_TYPE_DECODE;
- hfi = (struct hfi_enable_picture *) &pkt->rg_property_data[1];
- hfi->picture_type = (u32) pdata;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO:
- {
- struct hfi_enable *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO;
- hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
- hfi->enable = ((struct hfi_enable *) pdata)->enable;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
- {
- struct hfi_enable *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_CONFIG_VDEC_POST_LOOP_DEBLOCKER;
- hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
- hfi->enable = ((struct hfi_enable *) pdata)->enable;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_VDEC_MULTI_STREAM:
- {
- u32 buffer;
- struct hfi_multi_stream *hfi;
- struct hal_multi_stream *prop =
- (struct hal_multi_stream *) pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VDEC_MULTI_STREAM;
- hfi = (struct hfi_multi_stream *) &pkt->rg_property_data[1];
- buffer = get_hfi_buffer(prop->buffer_type);
- if (buffer)
- hfi->buffer_type = buffer;
- else
- return -EINVAL;
- hfi->enable = prop->enable;
- hfi->width = prop->width;
- hfi->height = prop->height;
- pkt->size += sizeof(u32) + sizeof(struct hfi_multi_stream);
- break;
- }
- case HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT:
- {
- struct hfi_display_picture_buffer_count *hfi;
- struct hal_display_picture_buffer_count *prop =
- (struct hal_display_picture_buffer_count *) pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT;
- hfi = (struct hfi_display_picture_buffer_count *)
- &pkt->rg_property_data[1];
- hfi->count = prop->count;
- hfi->enable = prop->enable;
- pkt->size += sizeof(u32) +
- sizeof(struct hfi_display_picture_buffer_count);
- break;
- }
- case HAL_PARAM_DIVX_FORMAT:
- {
- int *data = pdata;
- pkt->rg_property_data[0] = HFI_PROPERTY_PARAM_DIVX_FORMAT;
- switch (*data) {
- case HAL_DIVX_FORMAT_4:
- pkt->rg_property_data[1] = HFI_DIVX_FORMAT_4;
- break;
- case HAL_DIVX_FORMAT_5:
- pkt->rg_property_data[1] = HFI_DIVX_FORMAT_5;
- break;
- case HAL_DIVX_FORMAT_6:
- pkt->rg_property_data[1] = HFI_DIVX_FORMAT_6;
- break;
- default:
- dprintk(VIDC_ERR, "Invalid divx format: 0x%x", *data);
- break;
- }
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING:
- {
- struct hfi_enable *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_CONFIG_VDEC_MB_ERROR_MAP_REPORTING;
- hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
- hfi->enable = ((struct hfi_enable *) pdata)->enable;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER:
- {
- struct hfi_enable *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VDEC_CONTINUE_DATA_TRANSFER;
- hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
- hfi->enable = ((struct hfi_enable *) pdata)->enable;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_VDEC_SYNC_FRAME_DECODE:
- {
- struct hfi_enable *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VDEC_THUMBNAIL_MODE;
- hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
- hfi->enable = ((struct hfi_enable *) pdata)->enable;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_VENC_SYNC_FRAME_SEQUENCE_HEADER:
- {
- struct hfi_enable *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_CONFIG_VENC_SYNC_FRAME_SEQUENCE_HEADER;
- hfi = (struct hfi_enable *) &pkt->rg_property_data[1];
- hfi->enable = ((struct hfi_enable *) pdata)->enable;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_CONFIG_VENC_REQUEST_IFRAME:
- pkt->rg_property_data[0] =
- HFI_PROPERTY_CONFIG_VENC_REQUEST_SYNC_FRAME;
- pkt->size += sizeof(u32);
- break;
- case HAL_PARAM_VENC_MPEG4_SHORT_HEADER:
- break;
- case HAL_PARAM_VENC_MPEG4_AC_PREDICTION:
- break;
- case HAL_CONFIG_VENC_TARGET_BITRATE:
- {
- struct hfi_bitrate *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_CONFIG_VENC_TARGET_BITRATE;
- hfi = (struct hfi_bitrate *) &pkt->rg_property_data[1];
- hfi->bit_rate = ((struct hal_bitrate *)pdata)->bit_rate;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_PROFILE_LEVEL_CURRENT:
- {
- struct hfi_profile_level *hfi;
- struct hal_profile_level *prop =
- (struct hal_profile_level *) pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_PROFILE_LEVEL_CURRENT;
- hfi = (struct hfi_profile_level *)
- &pkt->rg_property_data[1];
- hfi->level = (u32) prop->level;
- hfi->profile = prop->profile;
- if (!hfi->profile)
- hfi->profile = HFI_H264_PROFILE_HIGH;
- if (!hfi->level)
- hfi->level = 1;
- pkt->size += sizeof(u32) + sizeof(struct hfi_profile_level);
- break;
- }
- case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
- {
- struct hfi_h264_entropy_control *hfi;
- struct hal_h264_entropy_control *prop =
- (struct hal_h264_entropy_control *) pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VENC_H264_ENTROPY_CONTROL;
- hfi = (struct hfi_h264_entropy_control *)
- &pkt->rg_property_data[1];
- switch (prop->entropy_mode) {
- case HAL_H264_ENTROPY_CAVLC:
- hfi->cabac_model = HFI_H264_ENTROPY_CAVLC;
- break;
- case HAL_H264_ENTROPY_CABAC:
- hfi->cabac_model = HFI_H264_ENTROPY_CABAC;
- switch (prop->cabac_model) {
- case HAL_H264_CABAC_MODEL_0:
- hfi->cabac_model = HFI_H264_CABAC_MODEL_0;
- break;
- case HAL_H264_CABAC_MODEL_1:
- hfi->cabac_model = HFI_H264_CABAC_MODEL_1;
- break;
- case HAL_H264_CABAC_MODEL_2:
- hfi->cabac_model = HFI_H264_CABAC_MODEL_2;
- break;
- default:
- dprintk(VIDC_ERR,
- "Invalid cabac model 0x%x",
- prop->entropy_mode);
- break;
- }
- break;
- default:
- dprintk(VIDC_ERR,
- "Invalid entropy selected: 0x%x",
- prop->cabac_model);
- break;
- }
- pkt->size += sizeof(u32) + sizeof(
- struct hfi_h264_entropy_control);
- break;
- }
- case HAL_PARAM_VENC_RATE_CONTROL:
- {
- u32 *rc;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VENC_RATE_CONTROL;
- rc = (u32 *)pdata;
- switch ((enum hal_rate_control) *rc) {
- case HAL_RATE_CONTROL_OFF:
- pkt->rg_property_data[1] = HFI_RATE_CONTROL_OFF;
- break;
- case HAL_RATE_CONTROL_CBR_CFR:
- pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_CFR;
- break;
- case HAL_RATE_CONTROL_CBR_VFR:
- pkt->rg_property_data[1] = HFI_RATE_CONTROL_CBR_VFR;
- break;
- case HAL_RATE_CONTROL_VBR_CFR:
- pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_CFR;
- break;
- case HAL_RATE_CONTROL_VBR_VFR:
- pkt->rg_property_data[1] = HFI_RATE_CONTROL_VBR_VFR;
- break;
- default:
- dprintk(VIDC_ERR, "Invalid Rate control setting: 0x%x",
- (int) pdata);
- break;
- }
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION:
- {
- struct hfi_mpeg4_time_resolution *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VENC_MPEG4_TIME_RESOLUTION;
- hfi = (struct hfi_mpeg4_time_resolution *)
- &pkt->rg_property_data[1];
- hfi->time_increment_resolution =
- ((struct hal_mpeg4_time_resolution *)pdata)->
- time_increment_resolution;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION:
- {
- struct hfi_mpeg4_header_extension *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VENC_MPEG4_HEADER_EXTENSION;
- hfi = (struct hfi_mpeg4_header_extension *)
- &pkt->rg_property_data[1];
- hfi->header_extension = (u32) pdata;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_PARAM_VENC_H264_DEBLOCK_CONTROL:
- {
- struct hfi_h264_db_control *hfi;
- struct hal_h264_db_control *prop =
- (struct hal_h264_db_control *) pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VENC_H264_DEBLOCK_CONTROL;
- hfi = (struct hfi_h264_db_control *) &pkt->rg_property_data[1];
- switch (prop->mode) {
- case HAL_H264_DB_MODE_DISABLE:
- hfi->mode = HFI_H264_DB_MODE_DISABLE;
- break;
- case HAL_H264_DB_MODE_SKIP_SLICE_BOUNDARY:
- hfi->mode = HFI_H264_DB_MODE_SKIP_SLICE_BOUNDARY;
- break;
- case HAL_H264_DB_MODE_ALL_BOUNDARY:
- hfi->mode = HFI_H264_DB_MODE_ALL_BOUNDARY;
- break;
- default:
- dprintk(VIDC_ERR, "Invalid deblocking mode: 0x%x",
- prop->mode);
- break;
- }
- hfi->slice_alpha_offset = prop->slice_alpha_offset;
- hfi->slice_beta_offset = prop->slice_beta_offset;
- pkt->size += sizeof(u32) +
- sizeof(struct hfi_h264_db_control);
- break;
- }
- case HAL_PARAM_VENC_SESSION_QP:
- {
- struct hfi_quantization *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VENC_SESSION_QP;
- hfi = (struct hfi_quantization *) &pkt->rg_property_data[1];
- memcpy(hfi, (struct hfi_quantization *) pdata,
- sizeof(struct hfi_quantization));
- pkt->size += sizeof(u32) + sizeof(struct hfi_quantization);
- break;
- }
- case HAL_CONFIG_VENC_INTRA_PERIOD:
- {
- struct hfi_intra_period *hfi;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_CONFIG_VENC_INTRA_PERIOD;
- hfi = (struct hfi_intra_period *) &pkt->rg_property_data[1];
- memcpy(hfi, (struct hfi_intra_period *) pdata,
- sizeof(struct hfi_intra_period));
- pkt->size += sizeof(u32) + sizeof(struct hfi_intra_period);
- break;
- }
- case HAL_CONFIG_VENC_IDR_PERIOD:
- {
- struct hfi_idr_period *hfi;
- pkt->rg_property_data[0] = HFI_PROPERTY_CONFIG_VENC_IDR_PERIOD;
- hfi = (struct hfi_idr_period *) &pkt->rg_property_data[1];
- hfi->idr_period = ((struct hfi_idr_period *) pdata)->idr_period;
- pkt->size += sizeof(u32) * 2;
- break;
- }
- case HAL_CONFIG_VPE_OPERATIONS:
- break;
- case HAL_PARAM_VENC_INTRA_REFRESH:
- {
- struct hfi_intra_refresh *hfi;
- struct hal_intra_refresh *prop =
- (struct hal_intra_refresh *) pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VENC_INTRA_REFRESH;
- hfi = (struct hfi_intra_refresh *) &pkt->rg_property_data[1];
- switch (prop->mode) {
- case HAL_INTRA_REFRESH_NONE:
- hfi->mode = HFI_INTRA_REFRESH_NONE;
- break;
- case HAL_INTRA_REFRESH_ADAPTIVE:
- hfi->mode = HFI_INTRA_REFRESH_ADAPTIVE;
- break;
- case HAL_INTRA_REFRESH_CYCLIC:
- hfi->mode = HFI_INTRA_REFRESH_CYCLIC;
- break;
- case HAL_INTRA_REFRESH_CYCLIC_ADAPTIVE:
- hfi->mode = HFI_INTRA_REFRESH_CYCLIC_ADAPTIVE;
- break;
- case HAL_INTRA_REFRESH_RANDOM:
- hfi->mode = HFI_INTRA_REFRESH_RANDOM;
- break;
- default:
- dprintk(VIDC_ERR, "Invalid intra refresh setting: 0x%x",
- prop->mode);
- break;
- }
- hfi->air_mbs = prop->air_mbs;
- hfi->air_ref = prop->air_ref;
- hfi->cir_mbs = prop->cir_mbs;
- pkt->size += sizeof(u32) + sizeof(struct hfi_intra_refresh);
- break;
- }
- case HAL_PARAM_VENC_MULTI_SLICE_CONTROL:
- {
- struct hfi_multi_slice_control *hfi;
- struct hal_multi_slice_control *prop =
- (struct hal_multi_slice_control *) pdata;
- pkt->rg_property_data[0] =
- HFI_PROPERTY_PARAM_VENC_MULTI_SLICE_CONTROL;
- hfi = (struct hfi_multi_slice_control *)
- &pkt->rg_property_data[1];
- switch (prop->multi_slice) {
- case HAL_MULTI_SLICE_OFF:
- hfi->multi_slice = HFI_MULTI_SLICE_OFF;
- break;
- case HAL_MULTI_SLICE_GOB:
- hfi->multi_slice = HFI_MULTI_SLICE_GOB;
- break;
- case HAL_MULTI_SLICE_BY_MB_COUNT:
- hfi->multi_slice = HFI_MULTI_SLICE_BY_MB_COUNT;
- break;
- case HAL_MULTI_SLICE_BY_BYTE_COUNT:
- hfi->multi_slice = HFI_MULTI_SLICE_BY_BYTE_COUNT;
- break;
- default:
- dprintk(VIDC_ERR, "Invalid slice settings: 0x%x",
- prop->multi_slice);
- break;
- }
- hfi->slice_size = prop->slice_size;
- pkt->size += sizeof(u32) + sizeof(struct
- hfi_multi_slice_control);
- break;
- }
- case HAL_PARAM_INDEX_EXTRADATA:
- {
- struct hfi_index_extradata_config *hfi;
- struct hal_extradata_enable *extra = pdata;
- int index = 0;
- pkt->rg_property_data[0] =
- get_hfi_extradata_index(extra->index);
- hfi =
- (struct hfi_index_extradata_config *)
- &pkt->rg_property_data[1];
- hfi->enable = extra->enable;
- index = get_hfi_extradata_index(extra->index);
- if (index)
- hfi->index_extra_data_id = index;
- else {
- dprintk(VIDC_WARN,
- "Failed to find extradata index: %d\n",
- index);
- rc = -EINVAL;
- }
- pkt->size += sizeof(u32) +
- sizeof(struct hfi_index_extradata_config);
- break;
- }
- case HAL_CONFIG_VPE_DEINTERLACE:
- break;
- /* FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET */
- case HAL_CONFIG_BUFFER_REQUIREMENTS:
- case HAL_CONFIG_PRIORITY:
- case HAL_CONFIG_BATCH_INFO:
- case HAL_PARAM_METADATA_PASS_THROUGH:
- case HAL_SYS_IDLE_INDICATOR:
- case HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
- case HAL_PARAM_INTERLACE_FORMAT_SUPPORTED:
- case HAL_PARAM_CHROMA_SITE:
- case HAL_PARAM_PROPERTIES_SUPPORTED:
- case HAL_PARAM_PROFILE_LEVEL_SUPPORTED:
- case HAL_PARAM_CAPABILITY_SUPPORTED:
- case HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
- case HAL_PARAM_MULTI_VIEW_FORMAT:
- case HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE:
- case HAL_PARAM_CODEC_SUPPORTED:
- case HAL_PARAM_VDEC_MULTI_VIEW_SELECT:
- case HAL_PARAM_VDEC_MB_QUANTIZATION:
- case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
- case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
- case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
- case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
-
- case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
- case HAL_CONFIG_VDEC_MULTI_STREAM:
- case HAL_PARAM_VENC_MULTI_SLICE_INFO:
- case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
- case HAL_PARAM_VENC_LOW_LATENCY:
- default:
- dprintk(VIDC_INFO, "DEFAULT: Calling 0x%x", ptype);
- break;
- }
- if (!rc)
- rc = vidc_hal_iface_cmdq_write(session->device, pkt);
-
- return rc;
-}
-
-int vidc_hal_session_get_property(void *sess,
- enum hal_property ptype, void *pdata)
-{
- struct hal_session *session;
-
- if (!sess || !pdata) {
- dprintk(VIDC_ERR, "Invalid Params in ");
- return -EINVAL;
- } else {
- session = sess;
- }
- dprintk(VIDC_INFO, "IN func: , with property id: %d", ptype);
-
- switch (ptype) {
- case HAL_CONFIG_FRAME_RATE:
- break;
- case HAL_PARAM_UNCOMPRESSED_FORMAT_SELECT:
- break;
- case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_CONSTRAINTS_INFO:
- break;
- case HAL_PARAM_UNCOMPRESSED_PLANE_ACTUAL_INFO:
- break;
- case HAL_PARAM_EXTRA_DATA_HEADER_CONFIG:
- break;
- case HAL_PARAM_FRAME_SIZE:
- break;
- case HAL_CONFIG_REALTIME:
- break;
- case HAL_PARAM_BUFFER_COUNT_ACTUAL:
- break;
- case HAL_PARAM_NAL_STREAM_FORMAT_SELECT:
- break;
- case HAL_PARAM_VDEC_OUTPUT_ORDER:
- break;
- case HAL_PARAM_VDEC_PICTURE_TYPE_DECODE:
- break;
- case HAL_PARAM_VDEC_OUTPUT2_KEEP_ASPECT_RATIO:
- break;
- case HAL_CONFIG_VDEC_POST_LOOP_DEBLOCKER:
- break;
- case HAL_PARAM_VDEC_MULTI_STREAM:
- break;
- case HAL_PARAM_VDEC_DISPLAY_PICTURE_BUFFER_COUNT:
- break;
- case HAL_PARAM_DIVX_FORMAT:
- break;
- case HAL_CONFIG_VDEC_MB_ERROR_MAP_REPORTING:
- break;
- case HAL_PARAM_VDEC_CONTINUE_DATA_TRANSFER:
- break;
- case HAL_CONFIG_VDEC_MB_ERROR_MAP:
- break;
- case HAL_CONFIG_VENC_REQUEST_IFRAME:
- break;
- case HAL_PARAM_VENC_MPEG4_SHORT_HEADER:
- break;
- case HAL_PARAM_VENC_MPEG4_AC_PREDICTION:
- break;
- case HAL_CONFIG_VENC_TARGET_BITRATE:
- break;
- case HAL_PARAM_PROFILE_LEVEL_CURRENT:
- break;
- case HAL_PARAM_VENC_H264_ENTROPY_CONTROL:
- break;
- case HAL_PARAM_VENC_RATE_CONTROL:
- break;
- case HAL_PARAM_VENC_MPEG4_TIME_RESOLUTION:
- break;
- case HAL_PARAM_VENC_MPEG4_HEADER_EXTENSION:
- break;
- case HAL_PARAM_VENC_H264_DEBLOCK_CONTROL:
- break;
- case HAL_PARAM_VENC_SESSION_QP:
- break;
- case HAL_CONFIG_VENC_INTRA_PERIOD:
- break;
- case HAL_CONFIG_VENC_IDR_PERIOD:
- break;
- case HAL_CONFIG_VPE_OPERATIONS:
- break;
- case HAL_PARAM_VENC_INTRA_REFRESH:
- break;
- case HAL_PARAM_VENC_MULTI_SLICE_CONTROL:
- break;
- case HAL_CONFIG_VPE_DEINTERLACE:
- break;
- case HAL_SYS_DEBUG_CONFIG:
- break;
- /*FOLLOWING PROPERTIES ARE NOT IMPLEMENTED IN CORE YET*/
- case HAL_CONFIG_BUFFER_REQUIREMENTS:
- case HAL_CONFIG_PRIORITY:
- case HAL_CONFIG_BATCH_INFO:
- case HAL_PARAM_METADATA_PASS_THROUGH:
- case HAL_SYS_IDLE_INDICATOR:
- case HAL_PARAM_UNCOMPRESSED_FORMAT_SUPPORTED:
- case HAL_PARAM_INTERLACE_FORMAT_SUPPORTED:
- case HAL_PARAM_CHROMA_SITE:
- case HAL_PARAM_PROPERTIES_SUPPORTED:
- case HAL_PARAM_PROFILE_LEVEL_SUPPORTED:
- case HAL_PARAM_CAPABILITY_SUPPORTED:
- case HAL_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
- case HAL_PARAM_MULTI_VIEW_FORMAT:
- case HAL_PARAM_MAX_SEQUENCE_HEADER_SIZE:
- case HAL_PARAM_CODEC_SUPPORTED:
- case HAL_PARAM_VDEC_MULTI_VIEW_SELECT:
- case HAL_PARAM_VDEC_MB_QUANTIZATION:
- case HAL_PARAM_VDEC_NUM_CONCEALED_MB:
- case HAL_PARAM_VDEC_H264_ENTROPY_SWITCHING:
- case HAL_PARAM_VENC_SLICE_DELIVERY_MODE:
- case HAL_PARAM_VENC_MPEG4_DATA_PARTITIONING:
-
- case HAL_CONFIG_BUFFER_COUNT_ACTUAL:
- case HAL_CONFIG_VDEC_MULTI_STREAM:
- case HAL_PARAM_VENC_MULTI_SLICE_INFO:
- case HAL_CONFIG_VENC_TIMESTAMP_SCALE:
- case HAL_PARAM_VENC_LOW_LATENCY:
- default:
- dprintk(VIDC_INFO, "DEFAULT: Calling 0x%x", ptype);
- break;
- }
- return 0;
-}
-
-void *vidc_hal_session_init(void *device, u32 session_id,
- enum hal_domain session_type, enum hal_video_codec codec_type)
-{
- struct hfi_cmd_sys_session_init_packet pkt;
- struct hal_session *new_session;
- struct hal_device *dev;
-
- if (device) {
- dev = device;
- } else {
- dprintk(VIDC_ERR, "invalid device");
- return NULL;
- }
-
- new_session = (struct hal_session *)
- kzalloc(sizeof(struct hal_session), GFP_KERNEL);
- new_session->session_id = (u32) session_id;
- if (session_type == 1)
- new_session->is_decoder = 0;
- else if (session_type == 2)
- new_session->is_decoder = 1;
- new_session->device = dev;
- list_add_tail(&new_session->list, &dev->sess_head);
- pkt.size = sizeof(struct hfi_cmd_sys_session_init_packet);
- pkt.packet_type = HFI_CMD_SYS_SESSION_INIT;
- pkt.session_id = (u32) new_session;
- pkt.session_domain = session_type;
- pkt.session_codec = codec_type;
- if (vidc_hal_iface_cmdq_write(dev, &pkt))
- return NULL;
- if (vidc_hal_sys_set_debug(dev, msm_fw_debug))
- dprintk(VIDC_ERR, "Setting fw_debug msg ON failed");
- return (void *) new_session;
-}
-
-static int vidc_hal_send_session_cmd(void *session_id,
- int pkt_type)
-{
- struct vidc_hal_session_cmd_pkt pkt;
- int rc = 0;
- struct hal_session *session;
-
- if (session_id) {
- session = session_id;
- } else {
- dprintk(VIDC_ERR, "invalid session");
- return -ENODEV;
- }
-
- pkt.size = sizeof(struct vidc_hal_session_cmd_pkt);
- pkt.packet_type = pkt_type;
- pkt.session_id = (u32) session;
-
- if (vidc_hal_iface_cmdq_write(session->device, &pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-
-int vidc_hal_session_end(void *session)
-{
- return vidc_hal_send_session_cmd(session,
- HFI_CMD_SYS_SESSION_END);
-}
-
-int vidc_hal_session_abort(void *session)
-{
- return vidc_hal_send_session_cmd(session,
- HFI_CMD_SYS_SESSION_ABORT);
-}
-
-int vidc_hal_session_set_buffers(void *sess,
- struct vidc_buffer_addr_info *buffer_info)
-{
- u32 buffer;
- struct hfi_cmd_session_set_buffers_packet *pkt;
- u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
- int rc = 0;
- u16 i;
- struct hal_session *session;
-
- if (!sess || !buffer_info) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- } else {
- session = sess;
- }
-
- if (buffer_info->buffer_type == HAL_BUFFER_INPUT)
- return 0;
-
- pkt = (struct hfi_cmd_session_set_buffers_packet *)packet;
-
- pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) +
- ((buffer_info->num_buffers - 1) * sizeof(u32));
- pkt->packet_type = HFI_CMD_SESSION_SET_BUFFERS;
- pkt->session_id = (u32) session;
- pkt->buffer_size = buffer_info->buffer_size;
- pkt->min_buffer_size = buffer_info->buffer_size;
- pkt->num_buffers = buffer_info->num_buffers;
-
- if ((buffer_info->buffer_type == HAL_BUFFER_OUTPUT) ||
- (buffer_info->buffer_type == HAL_BUFFER_OUTPUT2)) {
- struct hfi_buffer_info *buff;
- pkt->extra_data_size = buffer_info->extradata_size;
- pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) -
- sizeof(u32) + ((buffer_info->num_buffers) *
- sizeof(struct hfi_buffer_info));
- buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
- for (i = 0; i < pkt->num_buffers; i++) {
- buff->buffer_addr =
- buffer_info->align_device_addr;
- buff->extra_data_addr =
- buffer_info->extradata_addr;
- }
- } else {
- pkt->extra_data_size = 0;
- pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) +
- ((buffer_info->num_buffers - 1) * sizeof(u32));
- for (i = 0; i < pkt->num_buffers; i++)
- pkt->rg_buffer_info[i] =
- buffer_info->align_device_addr;
- }
- buffer = get_hfi_buffer(buffer_info->buffer_type);
- if (buffer)
- pkt->buffer_type = buffer;
- else
- return -EINVAL;
- dprintk(VIDC_INFO, "set buffers: 0x%x", buffer_info->buffer_type);
- if (vidc_hal_iface_cmdq_write(session->device, pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-
-int vidc_hal_session_release_buffers(void *sess,
- struct vidc_buffer_addr_info *buffer_info)
-{
- u32 buffer;
- struct hfi_cmd_session_release_buffer_packet *pkt;
- u8 packet[VIDC_IFACEQ_VAR_LARGE_PKT_SIZE];
- int rc = 0;
- u32 i;
- struct hal_session *session;
-
- if (!sess || !buffer_info) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- } else {
- session = sess;
- }
-
- if (buffer_info->buffer_type == HAL_BUFFER_INPUT)
- return 0;
-
- pkt = (struct hfi_cmd_session_release_buffer_packet *) packet;
- pkt->size = sizeof(struct hfi_cmd_session_release_buffer_packet) +
- ((buffer_info->num_buffers - 1) * sizeof(u32));
- pkt->packet_type = HFI_CMD_SESSION_RELEASE_BUFFERS;
- pkt->session_id = (u32) session;
- pkt->buffer_size = buffer_info->buffer_size;
- pkt->num_buffers = buffer_info->num_buffers;
-
- if ((buffer_info->buffer_type == HAL_BUFFER_OUTPUT) ||
- (buffer_info->buffer_type == HAL_BUFFER_OUTPUT2)) {
- struct hfi_buffer_info *buff;
- buff = (struct hfi_buffer_info *) pkt->rg_buffer_info;
- for (i = 0; i < pkt->num_buffers; i++) {
- buff->buffer_addr =
- buffer_info->align_device_addr;
- buff->extra_data_addr =
- buffer_info->extradata_addr;
- }
- pkt->extra_data_size = buffer_info->extradata_size;
- pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) -
- sizeof(u32) + ((buffer_info->num_buffers) *
- sizeof(struct hfi_buffer_info));
- } else {
- for (i = 0; i < pkt->num_buffers; i++)
- pkt->rg_buffer_info[i] =
- buffer_info->align_device_addr;
- pkt->extra_data_size = 0;
- pkt->size = sizeof(struct hfi_cmd_session_set_buffers_packet) +
- ((buffer_info->num_buffers - 1) * sizeof(u32));
- }
- pkt->response_req = buffer_info->response_required;
- buffer = get_hfi_buffer(buffer_info->buffer_type);
- if (buffer)
- pkt->buffer_type = buffer;
- else
- return -EINVAL;
- dprintk(VIDC_INFO, "Release buffers: 0x%x", buffer_info->buffer_type);
- if (vidc_hal_iface_cmdq_write(session->device, pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-
-int vidc_hal_session_load_res(void *sess)
-{
- return vidc_hal_send_session_cmd(sess,
- HFI_CMD_SESSION_LOAD_RESOURCES);
-}
-
-int vidc_hal_session_release_res(void *sess)
-{
- return vidc_hal_send_session_cmd(sess,
- HFI_CMD_SESSION_RELEASE_RESOURCES);
-}
-
-int vidc_hal_session_start(void *sess)
-{
- return vidc_hal_send_session_cmd(sess,
- HFI_CMD_SESSION_START);
-}
-
-int vidc_hal_session_stop(void *sess)
-{
- return vidc_hal_send_session_cmd(sess,
- HFI_CMD_SESSION_STOP);
-}
-
-int vidc_hal_session_suspend(void *sess)
-{
- return vidc_hal_send_session_cmd(sess,
- HFI_CMD_SESSION_SUSPEND);
-}
-
-int vidc_hal_session_resume(void *sess)
-{
- return vidc_hal_send_session_cmd(sess,
- HFI_CMD_SESSION_RESUME);
-}
-
-int vidc_hal_session_etb(void *sess, struct vidc_frame_data *input_frame)
-{
- int rc = 0;
- struct hal_session *session;
-
- if (!sess || !input_frame) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- } else {
- session = sess;
- }
-
- if (session->is_decoder) {
- struct hfi_cmd_session_empty_buffer_compressed_packet pkt;
- pkt.size = sizeof(
- struct hfi_cmd_session_empty_buffer_compressed_packet);
- pkt.packet_type = HFI_CMD_SESSION_EMPTY_BUFFER;
- pkt.session_id = (u32) session;
- pkt.time_stamp_hi = (int) (((u64)input_frame->timestamp) >> 32);
- pkt.time_stamp_lo = (int) input_frame->timestamp;
- pkt.flags = input_frame->flags;
- pkt.mark_target = input_frame->mark_target;
- pkt.mark_data = input_frame->mark_data;
- pkt.offset = input_frame->offset;
- pkt.alloc_len = input_frame->alloc_len;
- pkt.filled_len = input_frame->filled_len;
- pkt.input_tag = input_frame->clnt_data;
- pkt.packet_buffer = (u8 *) input_frame->device_addr;
- dprintk(VIDC_DBG, "Q DECODER INPUT BUFFER");
- if (vidc_hal_iface_cmdq_write(session->device, &pkt))
- rc = -ENOTEMPTY;
- } else {
- struct hfi_cmd_session_empty_buffer_uncompressed_plane0_packet
- pkt;
- pkt.size = sizeof(struct
- hfi_cmd_session_empty_buffer_uncompressed_plane0_packet);
- pkt.packet_type = HFI_CMD_SESSION_EMPTY_BUFFER;
- pkt.session_id = (u32) session;
- pkt.view_id = 0;
- pkt.time_stamp_hi = (u32) (((u64)input_frame->timestamp) >> 32);
- pkt.time_stamp_lo = (u32) input_frame->timestamp;
- pkt.flags = input_frame->flags;
- pkt.mark_target = input_frame->mark_target;
- pkt.mark_data = input_frame->mark_data;
- pkt.offset = input_frame->offset;
- pkt.alloc_len = input_frame->alloc_len;
- pkt.filled_len = input_frame->filled_len;
- pkt.input_tag = input_frame->clnt_data;
- pkt.packet_buffer = (u8 *) input_frame->device_addr;
- dprintk(VIDC_DBG, "Q ENCODER INPUT BUFFER");
- if (vidc_hal_iface_cmdq_write(session->device, &pkt))
- rc = -ENOTEMPTY;
- }
- return rc;
-}
-
-int vidc_hal_session_ftb(void *sess,
- struct vidc_frame_data *output_frame)
-{
- struct hfi_cmd_session_fill_buffer_packet pkt;
- int rc = 0;
- struct hal_session *session;
-
- if (!sess || !output_frame) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- } else {
- session = sess;
- }
-
- pkt.size = sizeof(struct hfi_cmd_session_fill_buffer_packet);
- pkt.packet_type = HFI_CMD_SESSION_FILL_BUFFER;
- pkt.session_id = (u32) session;
- if (output_frame->buffer_type == HAL_BUFFER_OUTPUT)
- pkt.stream_id = 0;
- else if (output_frame->buffer_type == HAL_BUFFER_OUTPUT2)
- pkt.stream_id = 1;
- pkt.packet_buffer = (u8 *) output_frame->device_addr;
- pkt.extra_data_buffer =
- (u8 *) output_frame->extradata_addr;
- pkt.alloc_len = output_frame->alloc_len;
- pkt.filled_len = output_frame->filled_len;
- pkt.offset = output_frame->offset;
- dprintk(VIDC_DBG, "### Q OUTPUT BUFFER ###: %d, %d, %d\n",
- pkt.alloc_len, pkt.filled_len, pkt.offset);
- if (vidc_hal_iface_cmdq_write(session->device, &pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-
-int vidc_hal_session_parse_seq_hdr(void *sess,
- struct vidc_seq_hdr *seq_hdr)
-{
- struct hfi_cmd_session_parse_sequence_header_packet *pkt;
- int rc = 0;
- u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
- struct hal_session *session;
-
- if (!sess || !seq_hdr) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- } else {
- session = sess;
- }
-
- pkt = (struct hfi_cmd_session_parse_sequence_header_packet *) packet;
- pkt->size = sizeof(struct hfi_cmd_session_parse_sequence_header_packet);
- pkt->packet_type = HFI_CMD_SESSION_PARSE_SEQUENCE_HEADER;
- pkt->session_id = (u32) session;
- pkt->header_len = seq_hdr->seq_hdr_len;
- pkt->packet_buffer = seq_hdr->seq_hdr;
-
- if (vidc_hal_iface_cmdq_write(session->device, pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-
-int vidc_hal_session_get_seq_hdr(void *sess,
- struct vidc_seq_hdr *seq_hdr)
-{
- struct hfi_cmd_session_get_sequence_header_packet *pkt;
- int rc = 0;
- u8 packet[VIDC_IFACEQ_VAR_SMALL_PKT_SIZE];
- struct hal_session *session;
-
- if (!sess || !seq_hdr) {
- dprintk(VIDC_ERR, "Invalid Params");
- return -EINVAL;
- } else {
- session = sess;
- }
-
- pkt = (struct hfi_cmd_session_get_sequence_header_packet *) packet;
- pkt->size = sizeof(struct hfi_cmd_session_get_sequence_header_packet);
- pkt->packet_type = HFI_CMD_SESSION_GET_SEQUENCE_HEADER;
- pkt->session_id = (u32) session;
- pkt->buffer_len = seq_hdr->seq_hdr_len;
- pkt->packet_buffer = seq_hdr->seq_hdr;
-
- if (vidc_hal_iface_cmdq_write(session->device, pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-
-int vidc_hal_session_get_buf_req(void *sess)
-{
- struct hfi_cmd_session_get_property_packet pkt;
- int rc = 0;
- struct hal_session *session;
-
- if (sess) {
- session = sess;
- } else {
- dprintk(VIDC_ERR, "invalid session");
- return -ENODEV;
- }
-
- pkt.size = sizeof(struct hfi_cmd_session_get_property_packet);
- pkt.packet_type = HFI_CMD_SESSION_GET_PROPERTY;
- pkt.session_id = (u32) session;
- pkt.num_properties = 1;
- pkt.rg_property_data[0] = HFI_PROPERTY_CONFIG_BUFFER_REQUIREMENTS;
- if (vidc_hal_iface_cmdq_write(session->device, &pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-
-int vidc_hal_session_flush(void *sess, enum hal_flush flush_mode)
-{
- struct hfi_cmd_session_flush_packet pkt;
- int rc = 0;
- struct hal_session *session;
-
- if (sess) {
- session = sess;
- } else {
- dprintk(VIDC_ERR, "invalid session");
- return -ENODEV;
- }
-
- pkt.size = sizeof(struct hfi_cmd_session_flush_packet);
- pkt.packet_type = HFI_CMD_SESSION_FLUSH;
- pkt.session_id = (u32) session;
- switch (flush_mode) {
- case HAL_FLUSH_INPUT:
- pkt.flush_type = HFI_FLUSH_INPUT;
- break;
- case HAL_FLUSH_OUTPUT:
- pkt.flush_type = HFI_FLUSH_OUTPUT;
- break;
- case HAL_FLUSH_OUTPUT2:
- pkt.flush_type = HFI_FLUSH_OUTPUT2;
- break;
- case HAL_FLUSH_ALL:
- pkt.flush_type = HFI_FLUSH_ALL;
- break;
- default:
- dprintk(VIDC_ERR, "Invalid flush mode: 0x%x\n", flush_mode);
- break;
- }
- if (vidc_hal_iface_cmdq_write(session->device, &pkt))
- rc = -ENOTEMPTY;
- return rc;
-}
-
-static int vidc_hal_check_core_registered(
- struct hal_device_data core, u32 fw_addr,
- u32 reg_addr, u32 reg_size, u32 irq)
-{
- struct hal_device *device;
- struct list_head *curr, *next;
-
- if (core.dev_count) {
- list_for_each_safe(curr, next, &core.dev_head) {
- device = list_entry(curr, struct hal_device, list);
- if (device && device->hal_data->irq == irq &&
- (CONTAINS(device->hal_data->
- device_base_addr,
- FIRMWARE_SIZE, fw_addr) ||
- CONTAINS(fw_addr, FIRMWARE_SIZE,
- device->hal_data->
- device_base_addr) ||
- CONTAINS((u32)device->hal_data->
- register_base_addr,
- reg_size, reg_addr) ||
- CONTAINS(reg_addr, reg_size,
- (u32)device->hal_data->
- register_base_addr) ||
- OVERLAPS((u32)device->hal_data->
- register_base_addr,
- reg_size, reg_addr, reg_size) ||
- OVERLAPS(reg_addr, reg_size,
- (u32)device->hal_data->
- register_base_addr, reg_size) ||
- OVERLAPS(device->hal_data->
- device_base_addr,
- FIRMWARE_SIZE, fw_addr,
- FIRMWARE_SIZE) ||
- OVERLAPS(fw_addr, FIRMWARE_SIZE,
- device->hal_data->
- device_base_addr,
- FIRMWARE_SIZE))) {
- return 0;
- } else {
- dprintk(VIDC_INFO, "Device not registered");
- return -EINVAL;
- }
- }
- } else {
- dprintk(VIDC_INFO, "no device Registered");
- }
- return -EINVAL;
-}
-
-static void vidc_hal_core_work_handler(struct work_struct *work)
-{
- struct hal_device *device = list_first_entry(
- &hal_ctxt.dev_head, struct hal_device, list);
-
- dprintk(VIDC_INFO, " GOT INTERRUPT () ");
- if (!device->callback) {
- dprintk(VIDC_ERR, "No interrupt callback function: %p\n",
- device);
- return;
- }
- vidc_hal_core_clear_interrupt(device);
- vidc_hal_response_handler(device);
- enable_irq(device->hal_data->irq);
-}
-static DECLARE_WORK(vidc_hal_work, vidc_hal_core_work_handler);
-
-static irqreturn_t vidc_hal_isr(int irq, void *dev)
-{
- struct hal_device *device = dev;
- dprintk(VIDC_INFO, "vidc_hal_isr() %d ", irq);
- disable_irq_nosync(irq);
- queue_work(device->vidc_workq, &vidc_hal_work);
- dprintk(VIDC_INFO, "vidc_hal_isr() %d ", irq);
- return IRQ_HANDLED;
-}
-
-void *vidc_hal_add_device(u32 device_id, u32 fw_base_addr, u32 reg_base,
- u32 reg_size, u32 irq,
- void (*callback) (enum command_response cmd, void *data))
-{
- struct hal_device *hdevice = NULL;
- struct hal_data *hal = NULL;
- int rc = 0;
-
- if (device_id || !reg_base || !reg_size ||
- !irq || !callback) {
- dprintk(VIDC_ERR, "Invalid Paramters");
- return NULL;
- } else {
- dprintk(VIDC_INFO, "entered , device_id: %d", device_id);
- }
-
- if (vidc_hal_check_core_registered(hal_ctxt, fw_base_addr,
- reg_base, reg_size, irq)) {
- dprintk(VIDC_DBG, "HAL_DATA will be assigned now");
- hal = (struct hal_data *)
- kzalloc(sizeof(struct hal_data), GFP_KERNEL);
- if (!hal) {
- dprintk(VIDC_ERR, "Failed to alloc");
- return NULL;
- }
- hal->irq = irq;
- hal->device_base_addr = fw_base_addr;
- hal->register_base_addr =
- ioremap_nocache(reg_base, reg_size);
- if (!hal->register_base_addr) {
- dprintk(VIDC_ERR,
- "could not map reg addr %d of size %d",
- reg_base, reg_size);
- goto err_map;
- }
- INIT_LIST_HEAD(&hal_ctxt.dev_head);
- } else {
- dprintk(VIDC_ERR, "Core present/Already added");
- return NULL;
- }
-
- hdevice = (struct hal_device *)
- kzalloc(sizeof(struct hal_device), GFP_KERNEL);
- if (!hdevice) {
- dprintk(VIDC_ERR, "failed to allocate new device");
- goto err_map;
- }
-
- INIT_LIST_HEAD(&hdevice->list);
- list_add_tail(&hdevice->list, &hal_ctxt.dev_head);
- hal_ctxt.dev_count++;
- hdevice->device_id = device_id;
- hdevice->hal_data = hal;
- hdevice->callback = callback;
-
- hdevice->vidc_workq = create_singlethread_workqueue(
- "msm_vidc_workerq");
- if (!hdevice->vidc_workq) {
- dprintk(VIDC_ERR, ": create workq failed\n");
- goto error_createq;
- }
-
- rc = request_irq(irq, vidc_hal_isr, IRQF_TRIGGER_HIGH,
- "msm_vidc", hdevice);
- if (unlikely(rc)) {
- dprintk(VIDC_ERR, "() :request_irq failed\n");
- goto error_irq_fail;
- }
- disable_irq_nosync(irq);
- return (void *) hdevice;
-error_irq_fail:
- destroy_workqueue(hdevice->vidc_workq);
-error_createq:
- hal_ctxt.dev_count--;
- list_del(&hal_ctxt.dev_head);
-err_map:
- kfree(hal);
- return NULL;
-}
-
-void vidc_hal_delete_device(void *device)
-{
- struct hal_device *close, *dev;
-
- if (device) {
- dev = (struct hal_device *) device;
- list_for_each_entry(close, &hal_ctxt.dev_head, list) {
- if (close->hal_data->irq == dev->hal_data->irq) {
- hal_ctxt.dev_count--;
- free_irq(dev->hal_data->irq, close);
- list_del(&close->list);
- destroy_workqueue(close->vidc_workq);
- kfree(close->hal_data);
- kfree(close);
- break;
- }
- }
-
- }
-}
diff --git a/drivers/media/video/msm_vidc/vidc_hal_api.h b/drivers/media/video/msm_vidc/vidc_hfi_api.h
similarity index 99%
rename from drivers/media/video/msm_vidc/vidc_hal_api.h
rename to drivers/media/video/msm_vidc/vidc_hfi_api.h
index 3e70342..02f474c 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_api.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -11,8 +11,8 @@
*
*/
-#ifndef __VIDC_HAL_API_H__
-#define __VIDC_HAL_API_H__
+#ifndef __VIDC_HFI_API_H__
+#define __VIDC_HFI_API_H__
#include <linux/types.h>
@@ -1023,4 +1023,4 @@
void (*callback) (enum command_response cmd, void *data));
void vidc_hal_delete_device(void *device);
-#endif /*__VIDC_HAL_API_H__ */
+#endif /*__VIDC_HFI_API_H__ */
diff --git a/drivers/media/video/msm_vidc/vidc_hal_helper.h b/drivers/media/video/msm_vidc/vidc_hfi_helper.h
similarity index 99%
rename from drivers/media/video/msm_vidc/vidc_hal_helper.h
rename to drivers/media/video/msm_vidc/vidc_hfi_helper.h
index 9f805d7..7531811 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_helper.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi_helper.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -11,8 +11,8 @@
*
*/
-#ifndef __H_VIDC_HAL_HELPER_H__
-#define __H_VIDC_HAL_HELPER_H__
+#ifndef __H_VIDC_HFI_HELPER_H__
+#define __H_VIDC_HFI_HELPER_H__
#define HFI_COMMON_BASE (0)
#define HFI_OX_BASE (0x01000000)
diff --git a/drivers/media/video/msm_vidc/vidc_hal_io.h b/drivers/media/video/msm_vidc/vidc_hfi_io.h
similarity index 98%
rename from drivers/media/video/msm_vidc/vidc_hal_io.h
rename to drivers/media/video/msm_vidc/vidc_hfi_io.h
index 9888adb..2bc8e6a 100644
--- a/drivers/media/video/msm_vidc/vidc_hal_io.h
+++ b/drivers/media/video/msm_vidc/vidc_hfi_io.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, 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
@@ -11,8 +11,8 @@
*
*/
-#ifndef __VIDCHALIO_H__
-#define __VIDCHALIO_H__
+#ifndef __VIDC_HFI_IO_H__
+#define __VIDC_HFI_IO_H__
#include <linux/io.h>
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index eebaab9..d4ff38b 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -1005,7 +1005,7 @@
TSPP_CONFIG_PS_CONT_ERR_MASK);
TSPP_CONFIG_SET_PACKET_LENGTH(val, TSPP_PACKET_LENGTH);
writel_relaxed(val, pdev->base + TSPP_CONFIG);
- writel_relaxed(0x000fffff, pdev->base + TSPP_IRQ_MASK);
+ writel_relaxed(0x0007ffff, pdev->base + TSPP_IRQ_MASK);
writel_relaxed(0x000fffff, pdev->base + TSPP_IRQ_CLEAR);
writel_relaxed(0, pdev->base + TSPP_RST);
wmb();
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index b748228..0f4cc6d 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -331,48 +331,6 @@
return ret;
}
-static ssize_t
-min_sectors_to_check_bkops_status_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
- unsigned int min_sectors_to_check_bkops_status;
- struct mmc_card *card = md->queue.card;
- int ret;
-
- if (!card)
- ret = -EINVAL;
- else {
- min_sectors_to_check_bkops_status =
- card->bkops_info.min_sectors_to_queue_delayed_work;
- ret = snprintf(buf, PAGE_SIZE, "%d\n",
- min_sectors_to_check_bkops_status);
- }
-
- mmc_blk_put(md);
- return ret;
-}
-
-static ssize_t
-min_sectors_to_check_bkops_status_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- int value;
- struct mmc_blk_data *md = mmc_blk_get(dev_to_disk(dev));
- struct mmc_card *card = md->queue.card;
-
- if (!card)
- return -EINVAL;
-
- sscanf(buf, "%d", &value);
- if (value >= 0)
- card->bkops_info.min_sectors_to_queue_delayed_work = value;
-
- mmc_blk_put(md);
- return count;
-}
-
static int mmc_blk_open(struct block_device *bdev, fmode_t mode)
{
struct mmc_blk_data *md = mmc_blk_get(bdev->bd_disk);
@@ -1000,9 +958,6 @@
from = blk_rq_pos(req);
nr = blk_rq_sectors(req);
- if (card->ext_csd.bkops_en)
- card->bkops_info.sectors_changed += blk_rq_sectors(req);
-
if (mmc_can_discard(card))
arg = MMC_DISCARD_ARG;
else if (mmc_can_trim(card))
@@ -1702,12 +1657,8 @@
break;
}
- if (rq_data_dir(next) == WRITE) {
+ if (rq_data_dir(next) == WRITE)
mq->num_of_potential_packed_wr_reqs++;
- if (card->ext_csd.bkops_en)
- card->bkops_info.sectors_changed +=
- blk_rq_sectors(next);
- }
list_add_tail(&next->queuelist, &mq->mqrq_cur->packed_list);
cur = next;
reqs++;
@@ -1940,8 +1891,6 @@
return 0;
if (rqc) {
- if ((card->ext_csd.bkops_en) && (rq_data_dir(rqc) == WRITE))
- card->bkops_info.sectors_changed += blk_rq_sectors(rqc);
reqs = mmc_blk_prep_packed_list(mq, rqc);
}
@@ -2110,9 +2059,15 @@
}
#endif
- if (req && !mq->mqrq_prev->req)
+ if (req && !mq->mqrq_prev->req) {
/* claim host only for the first request */
mmc_claim_host(card->host);
+ if (card->ext_csd.bkops_en &&
+ card->bkops_info.started_delayed_bkops) {
+ card->bkops_info.started_delayed_bkops = false;
+ mmc_stop_bkops(card);
+ }
+ }
ret = mmc_blk_part_switch(card, md);
if (ret) {
@@ -2442,24 +2397,8 @@
if (ret)
goto num_wr_reqs_to_start_packing_fail;
- md->min_sectors_to_check_bkops_status.show =
- min_sectors_to_check_bkops_status_show;
- md->min_sectors_to_check_bkops_status.store =
- min_sectors_to_check_bkops_status_store;
- sysfs_attr_init(&md->min_sectors_to_check_bkops_status.attr);
- md->min_sectors_to_check_bkops_status.attr.name =
- "min_sectors_to_check_bkops_status";
- md->min_sectors_to_check_bkops_status.attr.mode = S_IRUGO | S_IWUSR;
- ret = device_create_file(disk_to_dev(md->disk),
- &md->min_sectors_to_check_bkops_status);
- if (ret)
- goto min_sectors_to_check_bkops_status_fails;
-
return ret;
-min_sectors_to_check_bkops_status_fails:
- device_remove_file(disk_to_dev(md->disk),
- &md->num_wr_reqs_to_start_packing);
num_wr_reqs_to_start_packing_fail:
device_remove_file(disk_to_dev(md->disk), &md->power_ro_lock);
power_ro_lock_fail:
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 08c75a0..5d571a5 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -1244,9 +1244,9 @@
break;
case TEST_PACKING_NOT_EXP_LESS_THAN_TRIGGER_REQUESTS:
case TEST_PACKING_NOT_EXP_TRIGGER_REQUESTS:
- mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 1;
break;
default:
+ BUG_ON(num_packed_reqs < 0);
mbtd->exp_packed_stats.pack_stop_reason[EMPTY_QUEUE] = 1;
mbtd->exp_packed_stats.packing_events[num_packed_reqs] = 1;
}
@@ -1893,8 +1893,6 @@
case BKOPS_DELAYED_WORK_LEVEL_1:
bkops_stat->ignore_card_bkops_status = true;
card->ext_csd.raw_bkops_status = 1;
- card->bkops_info.sectors_changed =
- card->bkops_info.min_sectors_to_queue_delayed_work + 1;
mbtd->bkops_stage = BKOPS_STAGE_1;
__blk_run_queue(q);
@@ -1911,8 +1909,6 @@
case BKOPS_DELAYED_WORK_LEVEL_1_HPI:
bkops_stat->ignore_card_bkops_status = true;
card->ext_csd.raw_bkops_status = 1;
- card->bkops_info.sectors_changed =
- card->bkops_info.min_sectors_to_queue_delayed_work + 1;
mbtd->bkops_stage = BKOPS_STAGE_1;
__blk_run_queue(q);
@@ -1941,8 +1937,6 @@
case BKOPS_CANCEL_DELAYED_WORK:
bkops_stat->ignore_card_bkops_status = true;
card->ext_csd.raw_bkops_status = 1;
- card->bkops_info.sectors_changed =
- card->bkops_info.min_sectors_to_queue_delayed_work + 1;
mbtd->bkops_stage = BKOPS_STAGE_1;
__blk_run_queue(q);
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c
index 7b80dfb..dc27db6 100644
--- a/drivers/mmc/card/queue.c
+++ b/drivers/mmc/card/queue.c
@@ -89,17 +89,6 @@
spin_unlock_irq(q->queue_lock);
if (req || mq->mqrq_prev->req) {
- /*
- * If this is the first request, BKOPs might be in
- * progress and needs to be stopped before issuing the
- * request
- */
- if (card->ext_csd.bkops_en &&
- card->bkops_info.started_delayed_bkops) {
- card->bkops_info.started_delayed_bkops = false;
- mmc_stop_bkops(card);
- }
-
set_current_state(TASK_RUNNING);
mq->issue_fn(mq, req);
if (mq->flags & MMC_QUEUE_NEW_REQUEST) {
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 1ea580e..864dfa7 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -357,15 +357,9 @@
if (!card || !card->ext_csd.bkops_en || mmc_card_doing_bkops(card))
return;
- if (card->bkops_info.sectors_changed <
- card->bkops_info.min_sectors_to_queue_delayed_work)
- return;
-
pr_debug("%s: %s: queueing delayed_bkops_work\n",
mmc_hostname(card->host), __func__);
- card->bkops_info.sectors_changed = 0;
-
/*
* cancel_delayed_bkops_work will prevent a race condition between
* fetching a request by the mmcqd and the delayed work, in case
@@ -931,8 +925,6 @@
BUG_ON(!card);
- mmc_claim_host(card->host);
-
/*
* Notify the delayed work to be cancelled, in case it was already
* removed from the queue, but was not started yet
@@ -957,7 +949,6 @@
MMC_UPDATE_BKOPS_STATS_HPI(card->bkops_info.bkops_stats);
out:
- mmc_release_host(card->host);
return err;
}
EXPORT_SYMBOL(mmc_stop_bkops);
@@ -3238,7 +3229,9 @@
case PM_HIBERNATION_PREPARE:
case PM_SUSPEND_PREPARE:
if (host->card && mmc_card_mmc(host->card)) {
+ mmc_claim_host(host);
err = mmc_stop_bkops(host->card);
+ mmc_release_host(host);
if (err) {
pr_err("%s: didn't stop bkops\n",
mmc_hostname(host));
diff --git a/drivers/mmc/core/debugfs.c b/drivers/mmc/core/debugfs.c
index 9642a06..ae8a619 100644
--- a/drivers/mmc/core/debugfs.c
+++ b/drivers/mmc/core/debugfs.c
@@ -812,7 +812,7 @@
&mmc_dbg_new_req_stats_fops))
goto err;
- if (mmc_card_mmc(card) && (card->ext_csd.rev >= 6) &&
+ if (mmc_card_mmc(card) && (card->ext_csd.rev >= 5) &&
card->ext_csd.bkops_en)
if (!debugfs_create_file("bkops_stats", S_IRUSR, root, card,
&mmc_dbg_bkops_stats_fops))
diff --git a/drivers/mmc/core/mmc.c b/drivers/mmc/core/mmc.c
index c1a6b28..f3653b8 100644
--- a/drivers/mmc/core/mmc.c
+++ b/drivers/mmc/core/mmc.c
@@ -1413,9 +1413,6 @@
card->bkops_info.delay_ms = min(
card->bkops_info.delay_ms,
card->bkops_info.host_suspend_tout_ms/2);
-
- card->bkops_info.min_sectors_to_queue_delayed_work =
- BKOPS_MIN_SECTORS_TO_QUEUE_DELAYED_WORK;
}
}
diff --git a/drivers/platform/msm/ipa/ipa.c b/drivers/platform/msm/ipa/ipa.c
index 7973cfe..288de52 100644
--- a/drivers/platform/msm/ipa/ipa.c
+++ b/drivers/platform/msm/ipa/ipa.c
@@ -73,6 +73,7 @@
static struct clk *ipa_clk;
static struct clk *sys_noc_ipa_axi_clk;
static struct clk *ipa_cnoc_clk;
+static struct clk *ipa_inactivity_clk;
static struct device *ipa_dev;
struct ipa_context *ipa_ctx;
@@ -1158,6 +1159,13 @@
return -ENODEV;
}
+ ipa_inactivity_clk = clk_get(dev, "inactivity_clk");
+ if (IS_ERR(ipa_inactivity_clk)) {
+ ipa_inactivity_clk = NULL;
+ IPAERR("fail to get inactivity clk\n");
+ return -ENODEV;
+ }
+
return 0;
}
@@ -1192,6 +1200,11 @@
else
WARN_ON(1);
+ if (ipa_inactivity_clk)
+ clk_prepare(ipa_inactivity_clk);
+ else
+ WARN_ON(1);
+
if (ipa_clk)
clk_enable(ipa_clk);
else
@@ -1201,6 +1214,11 @@
clk_enable(sys_noc_ipa_axi_clk);
else
WARN_ON(1);
+
+ if (ipa_inactivity_clk)
+ clk_enable(ipa_inactivity_clk);
+ else
+ WARN_ON(1);
}
/**
@@ -1211,6 +1229,11 @@
*/
void ipa_disable_clks(void)
{
+ if (ipa_inactivity_clk)
+ clk_disable_unprepare(ipa_inactivity_clk);
+ else
+ WARN_ON(1);
+
if (sys_noc_ipa_axi_clk)
clk_disable_unprepare(sys_noc_ipa_axi_clk);
else
@@ -1511,10 +1534,6 @@
ipa_replenish_rx_cache();
- /* init the filtering block */
- ipa_commit_flt(IPA_IP_v4);
- ipa_commit_flt(IPA_IP_v6);
-
/*
* setup an empty routing table in system memory, this will be used
* to delete a routing table cleanly and safely
diff --git a/drivers/power/pm8921-bms.c b/drivers/power/pm8921-bms.c
index 12bdf30..874ef0d 100644
--- a/drivers/power/pm8921-bms.c
+++ b/drivers/power/pm8921-bms.c
@@ -1716,6 +1716,8 @@
chg_time_sec = DIV_ROUND_UP(the_chip->charge_time_us, USEC_PER_SEC);
catch_up_sec = DIV_ROUND_UP(the_chip->catch_up_time_us, USEC_PER_SEC);
+ if (catch_up_sec == 0)
+ return new_soc;
pr_debug("cts= %d catch_up_sec = %d\n", chg_time_sec, catch_up_sec);
/*
@@ -2012,8 +2014,7 @@
}
/* last_soc < soc ... scale and catch up */
- if (last_soc != -EINVAL && last_soc < soc && soc != 100
- && chip->catch_up_time_us != 0)
+ if (last_soc != -EINVAL && last_soc < soc && soc != 100)
soc = scale_soc_while_chg(chip, delta_time_us, soc, last_soc);
last_soc = soc;
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index bd62cf1..77db1f6 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -2538,7 +2538,11 @@
break;
}
}
- pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x2);
+ if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917)
+ pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x6);
+ else
+ pm_chg_masked_write(chip, ovpreg, OVP_DEBOUNCE_TIME, 0x2);
+
pr_debug("Exit count=%d chg_gone=%d, active_valid=%d\n",
count, chg_gone, active_chg_plugged_in);
return;
@@ -4237,8 +4241,16 @@
pm_chg_write(chip, CHG_BUCK_CTRL_TEST3, 0xAC);
}
- /* Enable isub_fine resolution AICL for PM8917 */
if (pm8xxx_get_version(chip->dev->parent) == PM8XXX_VERSION_8917) {
+ /* Set PM8917 USB_OVP debounce time to 15 ms */
+ rc = pm_chg_masked_write(chip, USB_OVP_CONTROL,
+ OVP_DEBOUNCE_TIME, 0x6);
+ if (rc) {
+ pr_err("Failed to set USB OVP db rc=%d\n", rc);
+ return rc;
+ }
+
+ /* Enable isub_fine resolution AICL for PM8917 */
chip->iusb_fine_res = true;
if (chip->uvd_voltage_mv) {
rc = pm_chg_uvd_threshold_set(chip,
diff --git a/drivers/power/qpnp-bms.c b/drivers/power/qpnp-bms.c
index 5dbf3c2..1bc027c 100644
--- a/drivers/power/qpnp-bms.c
+++ b/drivers/power/qpnp-bms.c
@@ -89,7 +89,7 @@
struct soc_params {
int fcc_uah;
int cc_uah;
- int rbatt;
+ int rbatt_mohm;
int iavg_ua;
int uuc_uah;
int ocv_charge_uah;
@@ -174,6 +174,7 @@
unsigned int vadc_v0625;
unsigned int vadc_v1250;
+ int ibat_max_ua;
int prev_iavg_ua;
int prev_uuc_iavg_ma;
int prev_pc_unusable;
@@ -199,6 +200,7 @@
POWER_SUPPLY_PROP_ONLINE,
POWER_SUPPLY_PROP_CAPACITY,
POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CURRENT_MAX,
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
};
@@ -855,7 +857,7 @@
new_unusable_mv = chip->v_cutoff_uv/1000;
new_iavg_ma = (new_unusable_mv * 1000 - chip->v_cutoff_uv)
- / params->rbatt;
+ / params->rbatt_mohm;
if (new_iavg_ma == 0)
new_iavg_ma = 1;
chip->prev_uuc_iavg_ma = new_iavg_ma;
@@ -1002,7 +1004,7 @@
/ params->fcc_uah;
if (soc_rbatt < 0)
soc_rbatt = 0;
- params->rbatt = get_rbatt(chip, soc_rbatt, batt_temp);
+ params->rbatt_mohm = get_rbatt(chip, soc_rbatt, batt_temp);
calculate_iavg(chip, params->cc_uah, ¶ms->iavg_ua);
@@ -1213,7 +1215,11 @@
delta_ocv_uv_limit = DIV_ROUND_CLOSEST(ibat_ua, 1000);
- ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt)/1000;
+ ocv_est_uv = vbat_uv + (ibat_ua * params->rbatt_mohm)/1000;
+
+ chip->ibat_max_ua = (ocv_est_uv - chip->v_cutoff_uv) * 1000
+ / (params->rbatt_mohm);
+
pc_est = calculate_pc(chip, ocv_est_uv, batt_temp);
soc_est = div_s64((s64)params->fcc_uah * pc_est - params->uuc_uah*100,
(s64)params->fcc_uah - params->uuc_uah);
@@ -1308,7 +1314,7 @@
pr_debug("ibat_ua = %d, vbat_uv = %d, ocv_est_uv = %d, pc_est = %d, soc_est = %d, n = %d, delta_ocv_uv = %d, last_ocv_uv = %d, pc_new = %d, soc_new = %d, rbatt = %d, slope = %d\n",
ibat_ua, vbat_uv, ocv_est_uv, pc_est,
soc_est, n, delta_ocv_uv, chip->last_ocv_uv,
- pc_new, soc_new, params->rbatt, slope);
+ pc_new, soc_new, params->rbatt_mohm, slope);
return soc;
}
@@ -1713,10 +1719,15 @@
return report_state_of_charge(chip);
}
+/* Returns estimated max current that the battery can supply in uA */
+static int get_prop_bms_current_max(struct qpnp_bms_chip *chip)
+{
+ return chip->ibat_max_ua;
+}
+
/* Returns instantaneous current in uA */
static int get_prop_bms_current_now(struct qpnp_bms_chip *chip)
{
- /* temporarily return 0 until a real algorithm is put in */
int rc, result_ua;
rc = get_battery_current(chip, &result_ua);
@@ -1771,6 +1782,9 @@
case POWER_SUPPLY_PROP_CURRENT_NOW:
val->intval = get_prop_bms_current_now(chip);
break;
+ case POWER_SUPPLY_PROP_CURRENT_MAX:
+ val->intval = get_prop_bms_current_max(chip);
+ break;
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
val->intval = get_prop_bms_charge_full_design(chip);
break;
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 005f789..510071a 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -1157,14 +1157,6 @@
case SMBB_BUCK_SUBTYPE:
break;
case SMBB_BAT_IF_SUBTYPE:
- /* HACK: Unlock secure access to override temp comparator */
- rc = qpnp_chg_masked_write(chip,
- chip->bat_if_base + SEC_ACCESS,
- 0xA5, 0xA5, 1);
- pr_debug("override hot cold\n");
- rc = qpnp_chg_masked_write(chip,
- chip->bat_if_base + 0xE5,
- 0xFF, 0x28, 1);
break;
case SMBB_USB_CHGPTH_SUBTYPE:
chip->usbin_valid_irq = spmi_get_irq_byname(chip->spmi,
diff --git a/drivers/thermal/qpnp-adc-tm.c b/drivers/thermal/qpnp-adc-tm.c
index bcc85f3..20481ac 100644
--- a/drivers/thermal/qpnp-adc-tm.c
+++ b/drivers/thermal/qpnp-adc-tm.c
@@ -944,6 +944,9 @@
u8 thr_int_disable = 0;
int rc = 0, sensor_notify_num = 0;
+ if (!adc_tm || !adc_tm->adc_tm_initialized)
+ return -ENODEV;
+
rc = qpnp_adc_tm_read_reg(QPNP_ADC_TM_STATUS_LOW, &status_low);
if (rc) {
pr_err("adc-tm-tm read status low failed with %d\n", rc);
@@ -1364,7 +1367,8 @@
GFP_KERNEL);
if (!adc_qpnp) {
dev_err(&spmi->dev, "Unable to allocate memory\n");
- return -ENOMEM;
+ rc = -ENOMEM;
+ goto fail;
}
adc_tm->adc = adc_qpnp;
@@ -1372,7 +1376,7 @@
rc = qpnp_adc_get_devicetree_data(spmi, adc_tm->adc);
if (rc) {
dev_err(&spmi->dev, "failed to read device tree\n");
- return rc;
+ goto fail;
}
/* Register the ADC peripheral interrupt */
@@ -1380,14 +1384,16 @@
NULL, "high-thr-en-set");
if (adc_tm->adc->adc_high_thr_irq < 0) {
pr_err("Invalid irq\n");
- return -ENXIO;
+ rc = -ENXIO;
+ goto fail;
}
adc_tm->adc->adc_low_thr_irq = spmi_get_irq_byname(spmi,
NULL, "low-thr-en-set");
if (adc_tm->adc->adc_low_thr_irq < 0) {
pr_err("Invalid irq\n");
- return -ENXIO;
+ rc = -ENXIO;
+ goto fail;
}
rc = devm_request_irq(&spmi->dev, adc_tm->adc->adc_irq_eoc,
@@ -1396,7 +1402,7 @@
if (rc) {
dev_err(&spmi->dev,
"failed to request adc irq with error %d\n", rc);
- return rc;
+ goto fail;
} else {
enable_irq_wake(adc_tm->adc->adc_irq_eoc);
}
@@ -1406,7 +1412,7 @@
IRQF_TRIGGER_RISING, "qpnp_adc_tm_high_interrupt", adc_tm);
if (rc) {
dev_err(&spmi->dev, "failed to request adc irq\n");
- return rc;
+ goto fail;
} else {
enable_irq_wake(adc_tm->adc->adc_high_thr_irq);
}
@@ -1416,7 +1422,7 @@
IRQF_TRIGGER_RISING, "qpnp_adc_tm_low_interrupt", adc_tm);
if (rc) {
dev_err(&spmi->dev, "failed to request adc irq\n");
- return rc;
+ goto fail;
} else {
enable_irq_wake(adc_tm->adc->adc_low_thr_irq);
}
@@ -1428,7 +1434,7 @@
"qcom,btm-channel-number", &btm_channel_num);
if (rc) {
pr_err("Invalid btm channel number\n");
- return -EINVAL;
+ goto fail;
}
if ((btm_channel_num != QPNP_ADC_TM_M0_ADC_CH_SEL_CTL) &&
@@ -1463,24 +1469,27 @@
rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_HIGH_THR_INT_EN, thr_init);
if (rc < 0) {
pr_err("high thr init failed\n");
- return rc;
+ goto fail;
}
rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_LOW_THR_INT_EN, thr_init);
if (rc < 0) {
pr_err("low thr init failed\n");
- return rc;
+ goto fail;
}
rc = qpnp_adc_tm_write_reg(QPNP_ADC_TM_MULTI_MEAS_EN, thr_init);
if (rc < 0) {
pr_err("multi meas en failed\n");
- return rc;
+ goto fail;
}
adc_tm->adc_tm_initialized = true;
return 0;
+fail:
+ adc_qpnp = NULL;
+ return rc;
}
static int __devexit qpnp_adc_tm_remove(struct spmi_device *spmi)
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index f577fdb..ccb9aa3 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -59,6 +59,10 @@
module_param(adc_meas_interval, int, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(adc_meas_interval, "ADC ID polling period");
+static int override_phy_init;
+module_param(override_phy_init, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(override_phy_init, "Override HSPHY Init Seq");
+
/**
* USB DBM Hardware registers.
*
@@ -124,6 +128,7 @@
#define QSCRATCH_REG_OFFSET (0x000F8800)
#define QSCRATCH_GENERAL_CFG (QSCRATCH_REG_OFFSET + 0x08)
#define HS_PHY_CTRL_REG (QSCRATCH_REG_OFFSET + 0x10)
+#define PARAMETER_OVERRIDE_X_REG (QSCRATCH_REG_OFFSET + 0x14)
#define CHARGING_DET_CTRL_REG (QSCRATCH_REG_OFFSET + 0x18)
#define CHARGING_DET_OUTPUT_REG (QSCRATCH_REG_OFFSET + 0x1C)
#define ALT_INTERRUPT_EN_REG (QSCRATCH_REG_OFFSET + 0x20)
@@ -169,6 +174,7 @@
atomic_t pm_suspended;
atomic_t in_lpm;
int hs_phy_irq;
+ int hsphy_init_seq;
bool lpm_irq_seen;
struct delayed_work resume_work;
struct wake_lock wlock;
@@ -584,7 +590,6 @@
static void dwc3_msm_req_complete_func(struct usb_ep *ep,
struct usb_request *request)
{
- struct dwc3_request *req = to_dwc3_request(request);
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct dwc3_msm_req_complete *req_complete = NULL;
@@ -607,8 +612,7 @@
* (normal and link), and the dwc3/gadget.c :: dwc3_gadget_giveback
* released only one.
*/
- if (req->queued)
- dep->busy_slot++;
+ dep->busy_slot++;
/* Unconfigure dbm ep */
dwc3_msm_dbm_ep_unconfig(dep->number);
@@ -854,6 +858,10 @@
struct dwc3_ep *dep = to_dwc3_ep(ep);
struct usb_ep_ops *new_ep_ops;
+ dwc3_msm_event_buffer_config(dwc3_msm_read_reg(context->base,
+ DWC3_GEVNTADRLO(0)),
+ dwc3_msm_read_reg(context->base, DWC3_GEVNTSIZ(0)));
+
/* Save original ep ops for future restore*/
if (context->original_ep_ops[dep->number]) {
dev_err(context->dev,
@@ -1204,6 +1212,17 @@
usleep_range(2000, 2200);
/* Disable (bypass) VBUS and ID filters */
dwc3_msm_write_reg(msm->base, QSCRATCH_GENERAL_CFG, 0x78);
+ /*
+ * write HSPHY init value to QSCRATCH reg to set HSPHY parameters like
+ * VBUS valid threshold, disconnect valid threshold, DC voltage level,
+ * preempasis and rise/fall time.
+ */
+ if (override_phy_init)
+ msm->hsphy_init_seq = override_phy_init;
+ if (msm->hsphy_init_seq)
+ dwc3_msm_write_readback(msm->base,
+ PARAMETER_OVERRIDE_X_REG, 0x03FFFFFF,
+ msm->hsphy_init_seq & 0x03FFFFFF);
/* Enable master clock for RAMs to allow BAM to access RAMs when
* RAM clock gating is enabled via DWC3's GCTL. Otherwise, issues
@@ -1245,6 +1264,11 @@
/* Reinitialize QSCRATCH registers after block reset */
dwc3_msm_qscratch_reg_init(mdwc);
+
+ /* Reset the DBM */
+ dwc3_msm_dbm_soft_reset(1);
+ usleep_range(1000, 1200);
+ dwc3_msm_dbm_soft_reset(0);
}
static void dwc3_chg_enable_secondary_det(struct dwc3_msm *mdwc)
@@ -2174,6 +2198,12 @@
msm->resource_size = resource_size(res);
msm->dwc3 = dwc3;
+ if (of_property_read_u32(node, "qcom,dwc-hsphy-init",
+ &msm->hsphy_init_seq))
+ dev_dbg(&pdev->dev, "unable to read hsphy init seq\n");
+ else if (!msm->hsphy_init_seq)
+ dev_warn(&pdev->dev, "incorrect hsphyinitseq.Using PORvalue\n");
+
dwc3_msm_qscratch_reg_init(msm);
pm_runtime_set_active(msm->dev);
@@ -2238,15 +2268,6 @@
dev_err(&pdev->dev, "Failed to vote for bus scaling\n");
}
- /* Reset the DBM */
- dwc3_msm_dbm_soft_reset(1);
- usleep_range(1000, 1200);
- dwc3_msm_dbm_soft_reset(0);
-
- dwc3_msm_event_buffer_config(dwc3_msm_read_reg(msm->base,
- DWC3_GEVNTADRLO(0)),
- dwc3_msm_read_reg(msm->base, DWC3_GEVNTSIZ(0)));
-
msm->otg_xceiv = usb_get_transceiver();
if (msm->otg_xceiv) {
msm->charger.start_detection = dwc3_start_chg_det;
diff --git a/drivers/usb/dwc3/dwc3_otg.c b/drivers/usb/dwc3/dwc3_otg.c
index 361aa32..eb879e3 100644
--- a/drivers/usb/dwc3/dwc3_otg.c
+++ b/drivers/usb/dwc3/dwc3_otg.c
@@ -179,16 +179,6 @@
return ret;
}
dwc3_otg_notify_host_mode(otg, on);
-
- /* Do block reset for Host <-> peripheral switching to work */
- if (ext_xceiv && ext_xceiv->otg_capability &&
- ext_xceiv->ext_block_reset)
- ext_xceiv->ext_block_reset();
-
- /* re-init core and OTG register as XHCI reset clears it */
- dwc3_post_host_reset_core_init(dwc);
- if (ext_xceiv && !ext_xceiv->otg_capability)
- dwc3_otg_reset(dotg);
}
return 0;
@@ -235,6 +225,8 @@
static int dwc3_otg_start_peripheral(struct usb_otg *otg, int on)
{
struct dwc3_otg *dotg = container_of(otg, struct dwc3_otg, otg);
+ struct dwc3_ext_xceiv *ext_xceiv = dotg->ext_xceiv;
+ struct dwc3 *dwc = dotg->dwc;
if (!otg->gadget)
return -EINVAL;
@@ -242,6 +234,22 @@
if (on) {
dev_dbg(otg->phy->dev, "%s: turn on gadget %s\n",
__func__, otg->gadget->name);
+
+ /*
+ * Hardware reset is required to support below scenarios:
+ * 1. Host <-> peripheral switching
+ * 2. Once an endpoint is configured in DBM (BAM) mode, it
+ * can be unconfigured only after RESET
+ */
+ if (ext_xceiv && ext_xceiv->otg_capability &&
+ ext_xceiv->ext_block_reset)
+ ext_xceiv->ext_block_reset();
+
+ /* re-init core and OTG registers as block reset clears these */
+ dwc3_post_host_reset_core_init(dwc);
+ if (ext_xceiv && !ext_xceiv->otg_capability)
+ dwc3_otg_reset(dotg);
+
dwc3_otg_set_peripheral_regs(dotg);
usb_gadget_vbus_connect(otg->gadget);
} else {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index c2bc3f3..0cce630 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -244,6 +244,8 @@
struct dwc3 *dwc = dep->dwc;
if (req->queued) {
+ req->queued = false;
+
if (req->request.num_mapped_sgs)
dep->busy_slot += req->request.num_mapped_sgs;
else
diff --git a/drivers/usb/gadget/f_mbim.c b/drivers/usb/gadget/f_mbim.c
index 98c6dbc..408fa6d 100644
--- a/drivers/usb/gadget/f_mbim.c
+++ b/drivers/usb/gadget/f_mbim.c
@@ -91,6 +91,7 @@
struct mbim_ep_descs hs;
u8 ctrl_id, data_id;
+ u8 data_alt_int;
struct ndp_parser_opts *parser_opts;
@@ -1319,6 +1320,7 @@
}
}
+ mbim->data_alt_int = alt;
spin_lock(&mbim->lock);
mbim_notify(mbim);
spin_unlock(&mbim->lock);
@@ -1351,7 +1353,10 @@
if (intf == mbim->ctrl_id)
return 0;
- return mbim->bam_port.in->driver_data ? 1 : 0;
+ else if (intf == mbim->data_id)
+ return mbim->data_alt_int;
+
+ return -EINVAL;
}
static void mbim_disable(struct usb_function *f)
@@ -1418,6 +1423,7 @@
if (status < 0)
goto fail;
mbim->data_id = status;
+ mbim->data_alt_int = 0;
mbim_data_nop_intf.bInterfaceNumber = status;
mbim_data_intf.bInterfaceNumber = status;
diff --git a/drivers/usb/gadget/f_qdss.c b/drivers/usb/gadget/f_qdss.c
index c3eddcc..085d0bd 100644
--- a/drivers/usb/gadget/f_qdss.c
+++ b/drivers/usb/gadget/f_qdss.c
@@ -420,19 +420,16 @@
if (qdss->ctrl_in_enabled) {
usb_ep_disable(qdss->ctrl_in);
qdss->ctrl_in_enabled = 0;
- qdss->ctrl_in->driver_data = NULL;
}
if (qdss->ctrl_out_enabled) {
usb_ep_disable(qdss->ctrl_out);
qdss->ctrl_out_enabled = 0;
- qdss->ctrl_out->driver_data = NULL;
}
if (qdss->data_enabled) {
usb_ep_disable(qdss->data);
qdss->data_enabled = 0;
- qdss->data->driver_data = NULL;
}
}
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index 57598c8..1141a24 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -575,20 +575,53 @@
{
int ret;
- ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
- if (ret) {
- dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
- return;
+ /* alt_core_clk exists in targets that do not use asynchronous reset */
+ if (!IS_ERR(mehci->alt_core_clk)) {
+ ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
+ if (ret) {
+ dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
+ return;
+ }
+
+ /* Since a hw bug, turn off the clock before complete reset */
+ clk_disable(mehci->core_clk);
+
+ ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
+ if (ret)
+ dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
+ ret);
+
+ usleep_range(10000, 12000);
+
+ clk_enable(mehci->core_clk);
+ } else {
+ /* Using asynchronous block reset to the hardware */
+ clk_disable_unprepare(mehci->core_clk);
+ clk_disable_unprepare(mehci->phy_clk);
+ clk_disable_unprepare(mehci->cal_clk);
+ clk_disable_unprepare(mehci->ahb_clk);
+
+ ret = clk_reset(mehci->core_clk, CLK_RESET_ASSERT);
+ if (ret) {
+ dev_err(mehci->dev, "hsic clk assert failed:%d\n", ret);
+ return;
+ }
+ usleep_range(10000, 12000);
+
+ ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
+ if (ret)
+ dev_err(mehci->dev, "hsic clk deassert failed:%d\n",
+ ret);
+ /*
+ * Required delay between the deassertion and
+ * clock enablement.
+ */
+ ndelay(200);
+ clk_prepare_enable(mehci->core_clk);
+ clk_prepare_enable(mehci->phy_clk);
+ clk_prepare_enable(mehci->cal_clk);
+ clk_prepare_enable(mehci->ahb_clk);
}
- clk_disable(mehci->core_clk);
-
- ret = clk_reset(mehci->core_clk, CLK_RESET_DEASSERT);
- if (ret)
- dev_err(mehci->dev, "hsic clk deassert failed:%d\n", ret);
-
- usleep_range(10000, 12000);
-
- clk_enable(mehci->core_clk);
}
#define HSIC_STROBE_GPIO_PAD_CTL (MSM_TLMM_BASE+0x20C0)
@@ -1286,7 +1319,8 @@
return ret;
}
- /* alt_core_clk is for LINK to be used during PHY RESET
+ /* alt_core_clk is for LINK to be used during PHY RESET in
+ * targets on which link does NOT use asynchronous reset methodology.
* clock rate appropriately set by target specific clock driver */
mehci->alt_core_clk = clk_get(mehci->dev, "alt_core_clk");
if (IS_ERR(mehci->alt_core_clk))
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 9cb2b34..1d38fb0 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -687,7 +687,10 @@
msecs_to_jiffies(VSYNC_PERIOD * 4));
if (ret <= 0) {
vctrl->wait_vsync_cnt = 0;
- return -EBUSY;
+ vsync_tick = ktime_to_ns(ktime_get());
+ ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
+ buf[strlen(buf) + 1] = '\0';
+ return ret;
}
spin_lock_irqsave(&vctrl->spin_lock, flags);
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index a4d2b77..e22fb6d 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -390,7 +390,10 @@
msecs_to_jiffies(VSYNC_PERIOD * 4));
if (ret <= 0) {
vctrl->wait_vsync_cnt = 0;
- return -EBUSY;
+ vsync_tick = ktime_to_ns(ktime_get());
+ ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
+ buf[strlen(buf) + 1] = '\0';
+ return ret;
}
spin_lock_irqsave(&vctrl->spin_lock, flags);
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index b13239c..6ee1efa 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -376,7 +376,10 @@
msecs_to_jiffies(VSYNC_PERIOD * 4));
if (ret <= 0) {
vctrl->wait_vsync_cnt = 0;
- return -EBUSY;
+ vsync_tick = ktime_to_ns(ktime_get());
+ ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
+ buf[strlen(buf) + 1] = '\0';
+ return ret;
}
spin_lock_irqsave(&vctrl->spin_lock, flags);
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 4a46d72..7c751ff 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -386,7 +386,10 @@
msecs_to_jiffies(VSYNC_PERIOD * 4));
if (ret <= 0) {
vctrl->wait_vsync_cnt = 0;
- return -EBUSY;
+ vsync_tick = ktime_to_ns(ktime_get());
+ ret = snprintf(buf, PAGE_SIZE, "VSYNC=%llu", vsync_tick);
+ buf[strlen(buf) + 1] = '\0';
+ return ret;
}
spin_lock_irqsave(&vctrl->spin_lock, flags);
diff --git a/drivers/video/msm/mdss/mdss_fb.c b/drivers/video/msm/mdss/mdss_fb.c
index 0db47f4..50723e7 100644
--- a/drivers/video/msm/mdss/mdss_fb.c
+++ b/drivers/video/msm/mdss/mdss_fb.c
@@ -40,6 +40,9 @@
#include <linux/uaccess.h>
#include <linux/version.h>
#include <linux/vmalloc.h>
+#include <linux/sync.h>
+#include <linux/sw_sync.h>
+#include <linux/file.h>
#include <mach/board.h>
#include <mach/memory.h>
@@ -80,6 +83,10 @@
static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg);
static int mdss_fb_mmap(struct fb_info *info, struct vm_area_struct *vma);
+static void mdss_fb_release_fences(struct msm_fb_data_type *mfd);
+
+static void mdss_fb_commit_wq_handler(struct work_struct *work);
+static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd);
void mdss_fb_no_update_notify_timer_cb(unsigned long data)
{
@@ -278,6 +285,19 @@
mdss_fb_create_sysfs(mfd);
+ if (mfd->timeline == NULL) {
+ char timeline_name[16];
+ snprintf(timeline_name, sizeof(timeline_name),
+ "mdss_fb_%d", mfd->index);
+ mfd->timeline = sw_sync_timeline_create(timeline_name);
+ if (mfd->timeline == NULL) {
+ pr_err("%s: cannot create time line", __func__);
+ return -ENOMEM;
+ } else {
+ mfd->timeline_value = 0;
+ }
+ }
+
return 0;
}
@@ -340,6 +360,7 @@
pr_debug("mdss_fb suspend index=%d\n", mfd->index);
+ mdss_fb_pan_idle(mfd);
ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_SUSPEND, NULL);
if (ret) {
pr_warn("unable to suspend fb%d (%d)\n", mfd->index, ret);
@@ -372,8 +393,11 @@
if ((!mfd) || (mfd->key != MFD_KEY))
return 0;
+ INIT_COMPLETION(mfd->power_set_comp);
+ mfd->is_power_setting = true;
pr_debug("mdss_fb resume index=%d\n", mfd->index);
+ mdss_fb_pan_idle(mfd);
ret = mdss_fb_send_panel_event(mfd, MDSS_EVENT_RESUME, NULL);
if (ret) {
pr_warn("unable to resume fb%d (%d)\n", mfd->index, ret);
@@ -392,6 +416,8 @@
if (mfd->vsync_pending)
mdss_mdp_overlay_vsync_ctrl(mfd, mfd->vsync_pending);
}
+ mfd->is_power_setting = false;
+ complete_all(&mfd->power_set_comp);
return ret;
}
@@ -562,9 +588,10 @@
msleep(20);
ret = mfd->off_fnc(mfd);
- if (ret)
+ if (ret) {
mfd->panel_power_on = curr_pwr_state;
-
+ mdss_fb_release_fences(mfd);
+ }
mfd->op_enable = true;
}
break;
@@ -576,6 +603,14 @@
static int mdss_fb_blank(int blank_mode, struct fb_info *info)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ mdss_fb_pan_idle(mfd);
+ if (mfd->op_enable == 0) {
+ if (blank_mode == FB_BLANK_UNBLANK)
+ mfd->suspend.panel_power_on = true;
+ else
+ mfd->suspend.panel_power_on = false;
+ return 0;
+ }
return mdss_fb_blank_sub(blank_mode, info, mfd->op_enable);
}
@@ -592,6 +627,7 @@
unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ mdss_fb_pan_idle(mfd);
if (off >= len) {
/* memory mapped io */
off -= len;
@@ -889,12 +925,21 @@
mfd->op_enable = true;
mutex_init(&mfd->no_update.lock);
+ mutex_init(&mfd->sync_mutex);
init_timer(&mfd->no_update.timer);
mfd->no_update.timer.function = mdss_fb_no_update_notify_timer_cb;
mfd->no_update.timer.data = (unsigned long)mfd;
init_completion(&mfd->update.comp);
init_completion(&mfd->no_update.comp);
-
+ init_completion(&mfd->commit_comp);
+ init_completion(&mfd->power_set_comp);
+ INIT_WORK(&mfd->commit_work, mdss_fb_commit_wq_handler);
+ mfd->msm_fb_backup = kzalloc(sizeof(struct msm_fb_backup_type),
+ GFP_KERNEL);
+ if (mfd->msm_fb_backup == 0) {
+ pr_err("error: not enough memory!\n");
+ return -ENOMEM;
+ }
if (mfd->lut_update) {
ret = fb_alloc_cmap(&fbi->cmap, 256, 0);
if (ret)
@@ -952,6 +997,7 @@
return -EINVAL;
}
+ mdss_fb_pan_idle(mfd);
mfd->ref_cnt--;
if (!mfd->ref_cnt) {
@@ -967,7 +1013,140 @@
return ret;
}
+static void mdss_fb_power_setting_idle(struct msm_fb_data_type *mfd)
+{
+ int ret;
+
+ if (mfd->is_power_setting) {
+ ret = wait_for_completion_timeout(
+ &mfd->power_set_comp,
+ msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT));
+ if (ret < 0)
+ ret = -ERESTARTSYS;
+ else if (!ret)
+ pr_err("%s wait for power_set_comp timeout %d %d",
+ __func__, ret, mfd->is_power_setting);
+ if (ret <= 0) {
+ mfd->is_power_setting = false;
+ complete_all(&mfd->power_set_comp);
+ }
+ }
+}
+
+void mdss_fb_wait_for_fence(struct msm_fb_data_type *mfd)
+{
+ int i, ret;
+ /* buf sync */
+ for (i = 0; i < mfd->acq_fen_cnt; i++) {
+ ret = sync_fence_wait(mfd->acq_fen[i], WAIT_FENCE_TIMEOUT);
+ sync_fence_put(mfd->acq_fen[i]);
+ if (ret < 0) {
+ pr_err("%s: sync_fence_wait failed! ret = %x\n",
+ __func__, ret);
+ break;
+ }
+ }
+ mfd->acq_fen_cnt = 0;
+}
+
+void mdss_fb_signal_timeline(struct msm_fb_data_type *mfd)
+{
+ mutex_lock(&mfd->sync_mutex);
+ if (mfd->timeline) {
+ sw_sync_timeline_inc(mfd->timeline, 1);
+ mfd->timeline_value++;
+ }
+ mfd->last_rel_fence = mfd->cur_rel_fence;
+ mfd->cur_rel_fence = 0;
+ mutex_unlock(&mfd->sync_mutex);
+}
+
+static void mdss_fb_release_fences(struct msm_fb_data_type *mfd)
+{
+ mutex_lock(&mfd->sync_mutex);
+ if (mfd->timeline) {
+ sw_sync_timeline_inc(mfd->timeline, 2);
+ mfd->timeline_value += 2;
+ }
+ mfd->last_rel_fence = 0;
+ mfd->cur_rel_fence = 0;
+ mutex_unlock(&mfd->sync_mutex);
+}
+
+static void mdss_fb_pan_idle(struct msm_fb_data_type *mfd)
+{
+ int ret;
+
+ if (mfd->is_committing) {
+ ret = wait_for_completion_timeout(
+ &mfd->commit_comp,
+ msecs_to_jiffies(WAIT_DISP_OP_TIMEOUT));
+ if (ret < 0)
+ ret = -ERESTARTSYS;
+ else if (!ret)
+ pr_err("%s wait for commit_comp timeout %d %d",
+ __func__, ret, mfd->is_committing);
+ if (ret <= 0) {
+ mutex_lock(&mfd->sync_mutex);
+ mfd->is_committing = 0;
+ complete_all(&mfd->commit_comp);
+ mutex_unlock(&mfd->sync_mutex);
+ }
+ }
+}
+
+static int mdss_fb_pan_display_ex(struct fb_info *info,
+ struct mdp_display_commit *disp_commit)
+{
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+ struct msm_fb_backup_type *fb_backup;
+ struct fb_var_screeninfo *var = &disp_commit->var;
+ u32 wait_for_finish = disp_commit->wait_for_finish;
+ int ret = 0;
+
+ if ((!mfd->op_enable) || (!mfd->panel_power_on))
+ return -EPERM;
+
+ if (var->xoffset > (info->var.xres_virtual - info->var.xres))
+ return -EINVAL;
+
+ if (var->yoffset > (info->var.yres_virtual - info->var.yres))
+ return -EINVAL;
+
+ mdss_fb_pan_idle(mfd);
+
+ mutex_lock(&mfd->sync_mutex);
+ if (info->fix.xpanstep)
+ info->var.xoffset =
+ (var->xoffset / info->fix.xpanstep) * info->fix.xpanstep;
+
+ if (info->fix.ypanstep)
+ info->var.yoffset =
+ (var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+
+ fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
+ memcpy(&fb_backup->info, info, sizeof(struct fb_info));
+ memcpy(&fb_backup->disp_commit, disp_commit,
+ sizeof(struct mdp_display_commit));
+ INIT_COMPLETION(mfd->commit_comp);
+ mfd->is_committing = 1;
+ schedule_work(&mfd->commit_work);
+ mutex_unlock(&mfd->sync_mutex);
+ if (wait_for_finish)
+ mdss_fb_pan_idle(mfd);
+ return ret;
+}
+
static int mdss_fb_pan_display(struct fb_var_screeninfo *var,
+ struct fb_info *info)
+{
+ struct mdp_display_commit disp_commit;
+ memset(&disp_commit, 0, sizeof(disp_commit));
+ disp_commit.wait_for_finish = true;
+ return mdss_fb_pan_display_ex(info, &disp_commit);
+}
+
+static int mdss_fb_pan_display_sub(struct fb_var_screeninfo *var,
struct fb_info *info)
{
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
@@ -989,12 +1168,13 @@
info->var.yoffset =
(var->yoffset / info->fix.ypanstep) * info->fix.ypanstep;
+ mdss_fb_wait_for_fence(mfd);
if (mfd->dma_fnc)
mfd->dma_fnc(mfd);
else
pr_warn("dma function not set for panel type=%d\n",
mfd->panel.type);
-
+ mdss_fb_signal_timeline(mfd);
mdss_fb_update_backlight(mfd);
return 0;
}
@@ -1015,6 +1195,34 @@
pinfo->vic = var->reserved[3];
}
+static void mdss_fb_commit_wq_handler(struct work_struct *work)
+{
+ struct msm_fb_data_type *mfd;
+ struct fb_var_screeninfo *var;
+ struct fb_info *info;
+ struct msm_fb_backup_type *fb_backup;
+ int ret;
+
+ mfd = container_of(work, struct msm_fb_data_type, commit_work);
+ fb_backup = (struct msm_fb_backup_type *)mfd->msm_fb_backup;
+ info = &fb_backup->info;
+ if (fb_backup->disp_commit.flags &
+ MDP_DISPLAY_COMMIT_OVERLAY) {
+ mdss_fb_wait_for_fence(mfd);
+ mdss_mdp_overlay_kickoff(mfd->ctl);
+ mdss_fb_signal_timeline(mfd);
+ } else {
+ var = &fb_backup->disp_commit.var;
+ ret = mdss_fb_pan_display_sub(var, info);
+ if (ret)
+ pr_err("%s fails: ret = %x", __func__, ret);
+ }
+ mutex_lock(&mfd->sync_mutex);
+ mfd->is_committing = 0;
+ complete_all(&mfd->commit_comp);
+ mutex_unlock(&mfd->sync_mutex);
+}
+
static int mdss_fb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info)
{
@@ -1135,6 +1343,7 @@
struct fb_var_screeninfo *var = &info->var;
int old_imgType;
+ mdss_fb_pan_idle(mfd);
old_imgType = mfd->fb_imgType;
switch (var->bits_per_pixel) {
case 16:
@@ -1280,6 +1489,105 @@
ret = copy_to_user(argp, &mdp_pp, sizeof(struct msmfb_mdp_pp));
return ret;
}
+static int mdss_fb_handle_buf_sync_ioctl(struct msm_fb_data_type *mfd,
+ struct mdp_buf_sync *buf_sync)
+{
+ int i, fence_cnt = 0, ret = 0;
+ int acq_fen_fd[MDP_MAX_FENCE_FD];
+ struct sync_fence *fence;
+
+ if ((buf_sync->acq_fen_fd_cnt > MDP_MAX_FENCE_FD) ||
+ (mfd->timeline == NULL))
+ return -EINVAL;
+
+ if ((!mfd->op_enable) || (!mfd->panel_power_on))
+ return -EPERM;
+
+ if (buf_sync->acq_fen_fd_cnt)
+ ret = copy_from_user(acq_fen_fd, buf_sync->acq_fen_fd,
+ buf_sync->acq_fen_fd_cnt * sizeof(int));
+ if (ret) {
+ pr_err("%s:copy_from_user failed", __func__);
+ return ret;
+ }
+ mutex_lock(&mfd->sync_mutex);
+ for (i = 0; i < buf_sync->acq_fen_fd_cnt; i++) {
+ fence = sync_fence_fdget(acq_fen_fd[i]);
+ if (fence == NULL) {
+ pr_info("%s: null fence! i=%d fd=%d\n", __func__, i,
+ acq_fen_fd[i]);
+ ret = -EINVAL;
+ break;
+ }
+ mfd->acq_fen[i] = fence;
+ }
+ fence_cnt = i;
+ if (ret)
+ goto buf_sync_err_1;
+ mfd->acq_fen_cnt = fence_cnt;
+ if (buf_sync->flags & MDP_BUF_SYNC_FLAG_WAIT)
+ mdss_fb_wait_for_fence(mfd);
+
+ mfd->cur_rel_sync_pt = sw_sync_pt_create(mfd->timeline,
+ mfd->timeline_value + 2);
+ if (mfd->cur_rel_sync_pt == NULL) {
+ pr_err("%s: cannot create sync point", __func__);
+ ret = -ENOMEM;
+ goto buf_sync_err_1;
+ }
+ /* create fence */
+ mfd->cur_rel_fence = sync_fence_create("mdp-fence",
+ mfd->cur_rel_sync_pt);
+ if (mfd->cur_rel_fence == NULL) {
+ sync_pt_free(mfd->cur_rel_sync_pt);
+ mfd->cur_rel_sync_pt = NULL;
+ pr_err("%s: cannot create fence", __func__);
+ ret = -ENOMEM;
+ goto buf_sync_err_1;
+ }
+ /* create fd */
+ mfd->cur_rel_fen_fd = get_unused_fd_flags(0);
+ if (mfd->cur_rel_fen_fd < 0) {
+ pr_err("%s: get_unused_fd_flags failed", __func__);
+ ret = -EIO;
+ goto buf_sync_err_2;
+ }
+ sync_fence_install(mfd->cur_rel_fence, mfd->cur_rel_fen_fd);
+ ret = copy_to_user(buf_sync->rel_fen_fd,
+ &mfd->cur_rel_fen_fd, sizeof(int));
+ if (ret) {
+ pr_err("%s:copy_to_user failed", __func__);
+ goto buf_sync_err_3;
+ }
+ mutex_unlock(&mfd->sync_mutex);
+ return ret;
+buf_sync_err_3:
+ put_unused_fd(mfd->cur_rel_fen_fd);
+buf_sync_err_2:
+ sync_fence_put(mfd->cur_rel_fence);
+ mfd->cur_rel_fence = NULL;
+ mfd->cur_rel_fen_fd = 0;
+buf_sync_err_1:
+ for (i = 0; i < fence_cnt; i++)
+ sync_fence_put(mfd->acq_fen[i]);
+ mfd->acq_fen_cnt = 0;
+ mutex_unlock(&mfd->sync_mutex);
+ return ret;
+}
+static int mdss_fb_display_commit(struct fb_info *info,
+ unsigned long *argp)
+{
+ int ret;
+ struct mdp_display_commit disp_commit;
+ ret = copy_from_user(&disp_commit, argp,
+ sizeof(disp_commit));
+ if (ret) {
+ pr_err("%s:copy_from_user failed", __func__);
+ return ret;
+ }
+ ret = mdss_fb_pan_display_ex(info, &disp_commit);
+ return ret;
+}
static int mdss_fb_ioctl(struct fb_info *info, unsigned int cmd,
unsigned long arg)
@@ -1291,6 +1599,11 @@
u32 block, hist_data_addr = 0;
struct mdp_page_protection fb_page_protection;
int ret = -ENOSYS;
+ struct mdp_buf_sync buf_sync;
+
+ mdss_fb_power_setting_idle(mfd);
+
+ mdss_fb_pan_idle(mfd);
switch (cmd) {
case MSMFB_CURSOR:
@@ -1351,10 +1664,25 @@
ret = mdss_fb_handle_pp_ioctl(mfd, argp);
break;
+ case MSMFB_BUFFER_SYNC:
+ ret = copy_from_user(&buf_sync, argp, sizeof(buf_sync));
+ if (ret)
+ return ret;
+
+ ret = mdss_fb_handle_buf_sync_ioctl(mfd, &buf_sync);
+
+ if (!ret)
+ ret = copy_to_user(argp, &buf_sync, sizeof(buf_sync));
+ break;
+
case MSMFB_NOTIFY_UPDATE:
ret = mdss_fb_notify_update(mfd, argp);
break;
+ case MSMFB_DISPLAY_COMMIT:
+ ret = mdss_fb_display_commit(info, argp);
+ break;
+
default:
if (mfd->ioctl_handler)
ret = mfd->ioctl_handler(mfd, cmd, argp);
diff --git a/drivers/video/msm/mdss/mdss_fb.h b/drivers/video/msm/mdss/mdss_fb.h
index 11bb859..f651b44 100644
--- a/drivers/video/msm/mdss/mdss_fb.h
+++ b/drivers/video/msm/mdss/mdss_fb.h
@@ -27,6 +27,10 @@
#define MSM_FB_MAX_DEV_LIST 32
#define MSM_FB_ENABLE_DBGFS
+/* 900 ms for fence time out */
+#define WAIT_FENCE_TIMEOUT 900
+/* 950 ms for display operation time out */
+#define WAIT_DISP_OP_TIMEOUT 950
#ifndef MAX
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
@@ -69,6 +73,7 @@
ktime_t vsync_time;
struct completion vsync_comp;
spinlock_t vsync_lock;
+ int borderfill_enable;
int hw_refresh;
@@ -111,6 +116,30 @@
struct list_head pipes_cleanup;
struct disp_info_notify update;
struct disp_info_notify no_update;
+
+ u32 acq_fen_cnt;
+ struct sync_fence *acq_fen[MDP_MAX_FENCE_FD];
+ int cur_rel_fen_fd;
+ struct sync_pt *cur_rel_sync_pt;
+ struct sync_fence *cur_rel_fence;
+ struct sync_fence *last_rel_fence;
+ struct sw_sync_timeline *timeline;
+ int timeline_value;
+ u32 last_acq_fen_cnt;
+ struct sync_fence *last_acq_fen[MDP_MAX_FENCE_FD];
+ struct mutex sync_mutex;
+ /* for non-blocking */
+ struct completion commit_comp;
+ u32 is_committing;
+ struct work_struct commit_work;
+ void *msm_fb_backup;
+ struct completion power_set_comp;
+ u32 is_power_setting;
+};
+
+struct msm_fb_backup_type {
+ struct fb_info info;
+ struct mdp_display_commit disp_commit;
};
int mdss_fb_get_phys_info(unsigned long *start, unsigned long *len, int fb_num);
@@ -118,4 +147,7 @@
void mdss_fb_update_backlight(struct msm_fb_data_type *mfd);
int mdss_fb_suspend_all(void);
int mdss_fb_resume_all(void);
+void mdss_fb_wait_for_fence(struct msm_fb_data_type *mfd);
+void mdss_fb_signal_timeline(struct msm_fb_data_type *mfd);
+
#endif /* MDSS_FB_H */
diff --git a/drivers/video/msm/mdss/mdss_mdp.h b/drivers/video/msm/mdss/mdss_mdp.h
index d273201..9503489 100644
--- a/drivers/video/msm/mdss/mdss_mdp.h
+++ b/drivers/video/msm/mdss/mdss_mdp.h
@@ -129,7 +129,6 @@
u32 bus_ab_quota;
u32 bus_ib_quota;
- u32 bus_quota;
u32 clk_rate;
struct msm_fb_data_type *mfd;
@@ -291,6 +290,7 @@
int mdss_mdp_overlay_vsync_ctrl(struct msm_fb_data_type *mfd, int en);
int mdss_mdp_video_start(struct mdss_mdp_ctl *ctl);
int mdss_mdp_writeback_start(struct mdss_mdp_ctl *ctl);
+int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl);
int mdss_mdp_ctl_on(struct msm_fb_data_type *mfd);
int mdss_mdp_ctl_off(struct msm_fb_data_type *mfd);
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index bd0f6c9..f62dd24 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -599,6 +599,9 @@
mutex_lock(&ctl->lock);
ctl->power_on = true;
+ ctl->bus_ab_quota = 0;
+ ctl->bus_ib_quota = 0;
+ ctl->clk_rate = 0;
mdss_mdp_clk_ctrl(MDP_BLOCK_POWER_ON, false);
ret = mdss_mdp_ctl_intf_event(ctl, MDSS_EVENT_RESET, NULL);
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index 5b6d009..d278554 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -27,10 +27,12 @@
#include "mdss_mdp_rotator.h"
#define VSYNC_PERIOD 16
+#define BORDERFILL_NDX 0x0BF000BF
#define CHECK_BOUNDS(offset, size, max_size) \
(((size) > (max_size)) || ((offset) > ((max_size) - (size))))
static atomic_t ov_active_panels = ATOMIC_INIT(0);
+static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd);
static int mdss_mdp_overlay_get(struct msm_fb_data_type *mfd,
struct mdp_overlay *req)
@@ -359,7 +361,7 @@
static int mdss_mdp_overlay_set(struct msm_fb_data_type *mfd,
struct mdp_overlay *req)
{
- int ret;
+ int ret = 0;
ret = mutex_lock_interruptible(&mfd->ov_lock);
if (ret)
@@ -372,6 +374,8 @@
if (req->flags & MDSS_MDP_ROT_ONLY) {
ret = mdss_mdp_overlay_rotator_setup(mfd, req);
+ } else if (req->src.format == MDP_RGB_BORDERFILL) {
+ req->id = BORDERFILL_NDX;
} else {
struct mdss_mdp_pipe *pipe;
@@ -452,7 +456,7 @@
return 0;
}
-static int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
+int mdss_mdp_overlay_kickoff(struct mdss_mdp_ctl *ctl)
{
struct msm_fb_data_type *mfd = ctl->mfd;
int ret;
@@ -520,6 +524,12 @@
if (ret)
return ret;
+ if (ndx == BORDERFILL_NDX) {
+ pr_debug("borderfill disable\n");
+ mfd->borderfill_enable = false;
+ return 0;
+ }
+
if (!mfd->panel_power_on) {
mutex_unlock(&mfd->ov_lock);
return -EPERM;
@@ -677,6 +687,10 @@
if (req->id & MDSS_MDP_ROT_SESSION_MASK) {
ret = mdss_mdp_overlay_rotate(mfd, req);
+ } else if (req->id == BORDERFILL_NDX) {
+ pr_debug("borderfill enable\n");
+ mfd->borderfill_enable = true;
+ ret = mdss_mdp_overlay_free_fb_pipe(mfd);
} else {
ret = mdss_mdp_overlay_queue(mfd, req);
@@ -692,6 +706,29 @@
return ret;
}
+static int mdss_mdp_overlay_free_fb_pipe(struct msm_fb_data_type *mfd)
+{
+ struct mdss_mdp_pipe *pipe;
+ u32 fb_ndx = 0;
+
+ pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, MDSS_MDP_MIXER_MUX_LEFT,
+ MDSS_MDP_STAGE_BASE);
+ if (pipe)
+ fb_ndx |= pipe->ndx;
+
+ pipe = mdss_mdp_mixer_stage_pipe(mfd->ctl, MDSS_MDP_MIXER_MUX_RIGHT,
+ MDSS_MDP_STAGE_BASE);
+ if (pipe)
+ fb_ndx |= pipe->ndx;
+
+ if (fb_ndx) {
+ pr_debug("unstaging framebuffer pipes %x\n", fb_ndx);
+ mdss_mdp_overlay_unset(mfd, fb_ndx);
+ mdss_mdp_overlay_kickoff(mfd->ctl);
+ }
+ return 0;
+}
+
static int mdss_mdp_overlay_get_fb_pipe(struct msm_fb_data_type *mfd,
struct mdss_mdp_pipe **ppipe,
int mixer_mux)
@@ -767,7 +804,7 @@
fbi = mfd->fbi;
- if (fbi->fix.smem_len == 0) {
+ if (fbi->fix.smem_len == 0 || mfd->borderfill_enable) {
mdss_mdp_overlay_kickoff(mfd->ctl);
return;
}
@@ -1162,7 +1199,9 @@
}
break;
case MSMFB_OVERLAY_COMMIT:
+ mdss_fb_wait_for_fence(mfd);
ret = mdss_mdp_overlay_kickoff(mfd->ctl);
+ mdss_fb_signal_timeline(mfd);
break;
default:
if (mfd->panel.type == WRITEBACK_PANEL)
@@ -1192,6 +1231,9 @@
rc = mdss_mdp_ctl_off(mfd);
if (rc == 0) {
+ if (!mfd->ref_cnt)
+ mfd->borderfill_enable = false;
+
if (atomic_dec_return(&ov_active_panels) == 0)
mdss_mdp_rotator_release_all();
}
diff --git a/drivers/video/msm/mdss/mhl_sii8334.c b/drivers/video/msm/mdss/mhl_sii8334.c
index aa3a827..0227e70 100644
--- a/drivers/video/msm/mdss/mhl_sii8334.c
+++ b/drivers/video/msm/mdss/mhl_sii8334.c
@@ -62,6 +62,7 @@
struct completion rgnd_done;
void (*notify_usb_online)(int online);
struct usb_ext_notification *mhl_info;
+ bool disc_enabled;
};
@@ -203,11 +204,29 @@
return 0;
}
+
+static int mhl_sii_wait_for_rgnd(struct mhl_tx_ctrl *mhl_ctrl)
+{
+ int timeout;
+ /* let isr handle RGND interrupt */
+ pr_debug("%s:%u\n", __func__, __LINE__);
+ INIT_COMPLETION(mhl_ctrl->rgnd_done);
+ timeout = wait_for_completion_interruptible_timeout
+ (&mhl_ctrl->rgnd_done, HZ/2);
+ if (!timeout) {
+ /* most likely nothing plugged in USB */
+ /* USB HOST connected or already in USB mode */
+ pr_warn("%s:%u timedout\n", __func__, __LINE__);
+ return -ENODEV;
+ }
+ return mhl_ctrl->mhl_mode ? 0 : 1;
+}
+
/* USB_HANDSHAKING FUNCTIONS */
static int mhl_sii_device_discovery(void *data, int id,
void (*usb_notify_cb)(int online))
{
- int timeout, rc;
+ int rc;
struct mhl_tx_ctrl *mhl_ctrl = data;
if (id) {
@@ -227,30 +246,24 @@
if (!mhl_ctrl->notify_usb_online)
mhl_ctrl->notify_usb_online = usb_notify_cb;
- mhl_sii_reset_pin(mhl_ctrl, 0);
- msleep(50);
- mhl_sii_reset_pin(mhl_ctrl, 1);
- /* TX PR-guide requires a 100 ms wait here */
-
- msleep(100);
- mhl_init_reg_settings(mhl_ctrl, true);
-
- if (mhl_ctrl->cur_state == POWER_STATE_D3) {
- /* give MHL driver chance to handle RGND interrupt */
- INIT_COMPLETION(mhl_ctrl->rgnd_done);
- timeout = wait_for_completion_interruptible_timeout
- (&mhl_ctrl->rgnd_done, HZ/2);
- if (!timeout) {
- /* most likely nothing plugged in USB */
- /* USB HOST connected or already in USB mode */
- pr_debug("Timedout Returning from discovery mode\n");
- return 0;
- }
- rc = mhl_ctrl->mhl_mode ? 0 : 1;
+ if (!mhl_ctrl->disc_enabled) {
+ mhl_sii_reset_pin(mhl_ctrl, 0);
+ msleep(50);
+ mhl_sii_reset_pin(mhl_ctrl, 1);
+ /* TX PR-guide requires a 100 ms wait here */
+ msleep(100);
+ mhl_init_reg_settings(mhl_ctrl, true);
+ rc = mhl_sii_wait_for_rgnd(mhl_ctrl);
} else {
- /* not in D3. already in MHL mode */
- rc = 0;
+ if (mhl_ctrl->cur_state == POWER_STATE_D3) {
+ rc = mhl_sii_wait_for_rgnd(mhl_ctrl);
+ } else {
+ /* in MHL mode */
+ pr_debug("%s:%u\n", __func__, __LINE__);
+ rc = 0;
+ }
}
+ pr_debug("%s: ret result: %s\n", __func__, rc ? "usb" : " mhl");
return rc;
}
@@ -506,7 +519,8 @@
*/
MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0xD0);
msleep(50);
- MHL_SII_REG_NAME_MOD(REG_DISC_CTRL1, BIT1 | BIT0, 0x00);
+ if (!mhl_ctrl->disc_enabled)
+ MHL_SII_REG_NAME_MOD(REG_DISC_CTRL1, BIT1 | BIT0, 0x00);
MHL_SII_PAGE3_MOD(0x003D, BIT0, 0x00);
mhl_ctrl->cur_state = POWER_STATE_D3;
break;
@@ -1216,6 +1230,7 @@
* Other initializations
* such tx specific
*/
+ mhl_ctrl->disc_enabled = false;
rc = mhl_tx_chip_init(mhl_ctrl);
if (rc) {
pr_err("%s: tx chip init failed [%d]\n",
@@ -1257,6 +1272,8 @@
mhl_ctrl->mhl_info = mhl_info;
return 0;
failed_probe:
+ mhl_gpio_config(mhl_ctrl, 0);
+ mhl_vreg_config(mhl_ctrl, 0);
/* do not deep-free */
if (mhl_info)
devm_kfree(&client->dev, mhl_info);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
index a82feb9..f8c26ff 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.c
@@ -280,6 +280,25 @@
return VCD_ERR_ILLEGAL_OP;
}
encoder = &ddl->codec_data.encoder;
+ if (DDL_IS_LTR_ENABLED(encoder)) {
+ DDL_MSG_HIGH("LTR enabled, mode %u count %u",
+ (u32)encoder->ltr_control.ltrmode.ltr_mode,
+ (u32)encoder->ltr_control.ltr_count);
+ status = ddl_allocate_ltr_list(&encoder->ltr_control);
+ if (status) {
+ DDL_MSG_ERROR("%s: allocate ltr list failed",
+ __func__);
+ return status;
+ } else {
+ ddl_clear_ltr_list(&encoder->ltr_control, false);
+ }
+ encoder->num_references_for_p_frame = 2;
+ encoder->ltr_control.callback_reqd = false;
+ encoder->ltr_control.curr_ltr_id = (u32)DDL_LTR_FRAME_START_ID;
+ DDL_MSG_HIGH("num_ref_for_p_frames %u, curr_ltr_id = %u",
+ (u32)encoder->num_references_for_p_frame,
+ (u32)encoder->ltr_control.curr_ltr_id);
+ }
status = ddl_allocate_enc_hw_buffers(ddl);
if (status)
return status;
@@ -393,7 +412,7 @@
(struct ddl_client_context *) ddl_handle;
struct ddl_context *ddl_context;
struct ddl_decoder_data *decoder;
- DDL_MSG_HIGH("ddl_decode_frame");
+ DDL_MSG_MED("ddl_decode_frame");
ddl_context = ddl_get_context();
if (!DDL_IS_INITIALIZED(ddl_context)) {
DDL_MSG_ERROR("ddl_dec_frame:Not_inited");
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
index 8836b33..0404e82 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl.h
@@ -52,6 +52,19 @@
#define DDLCLIENT_STATE_IS(ddl, state) \
(state == (ddl)->client_state)
+#define DDL_IS_LTR_ENABLED(encoder) \
+ ((encoder->ltr_control.ltrmode.ltr_mode == \
+ VCD_LTR_MODE_AUTO || \
+ encoder->ltr_control.ltrmode.ltr_mode == \
+ VCD_LTR_MODE_MANUAL) && \
+ (encoder->ltr_control.ltr_count > 0))
+
+#define DDL_IS_LTR_IN_AUTO_MODE(encoder) \
+ ((encoder->ltr_control.ltrmode.ltr_mode == \
+ VCD_LTR_MODE_AUTO) && \
+ (encoder->ltr_control.ltr_count > 0) && \
+ (encoder->ltr_control.ltr_period > 0))
+
#define DDL_DPB_OP_INIT 1
#define DDL_DPB_OP_MARK_FREE 2
#define DDL_DPB_OP_MARK_BUSY 3
@@ -72,6 +85,7 @@
#define DDL_ENC_CHANGE_BITRATE 0x04
#define DDL_ENC_CHANGE_FRAMERATE 0x08
#define DDL_ENC_CHANGE_CIR 0x10
+#define DDL_ENC_LTR_USE_FRAME 0x20
#define DDL_DEC_REQ_OUTPUT_FLUSH 0x1
@@ -86,6 +100,9 @@
#define MDP_MIN_TILE_HEIGHT 96
+#define DDL_MAX_NUM_LTR_FRAMES 2
+#define DDL_LTR_FRAME_START_ID 1
+
enum ddl_mem_area {
DDL_FW_MEM = 0x0,
DDL_MM_MEM = 0x1,
@@ -242,6 +259,43 @@
u32 seqdisp_extdump_enable;
u32 seq_extdump_enable;
};
+
+
+struct ddl_ltrlist {
+ bool ltr_in_use;
+ u32 ltr_id;
+};
+
+struct ddl_ltr_encoding_type {
+ struct vcd_property_ltrmode_type ltrmode;
+ struct vcd_property_ltruse_type failed_use_cmd;
+ struct ddl_ltrlist *ltr_list;
+ u32 ltr_count;
+ u32 ltr_period;
+ u32 ltr_use_frames;
+ u32 curr_ltr_id;
+ u32 storing_idx;
+ u32 out_frame_cnt_to_use_this_ltr;
+ u32 out_frame_cnt_before_next_idr;
+ bool storing;
+ bool callback_reqd;
+ bool meta_data_reqd;
+ bool using;
+ bool first_ltr_use_arvd;
+ bool use_ltr_reqd;
+ bool store_for_intraframe_insertion;
+ bool pending_chg_ltr_useframes; /* True if
+ * corresponding driver context of
+ * out_frame_cnt_to_use_this_ltr
+ * is pending to be changed with
+ * client settings
+ */
+ bool store_ltr0;
+ bool store_ltr1;
+ bool use_ltr0;
+ bool use_ltr1;
+};
+
struct ddl_encoder_data{
struct ddl_codec_data_hdr hdr;
struct vcd_property_codec codec;
@@ -275,6 +329,7 @@
struct ddl_enc_buffers hw_bufs;
struct ddl_yuv_buffer_size input_buf_size;
struct vidc_1080p_enc_frame_info enc_frame_info;
+ struct ddl_ltr_encoding_type ltr_control;
u32 plusptype_enable;
u32 meta_data_enable_flag;
u32 suffix;
@@ -291,6 +346,7 @@
u32 num_references_for_p_frame;
u32 closed_gop;
u32 num_slices_comp;
+ bool intra_period_changed;
struct vcd_property_slice_delivery_info slice_delivery_info;
struct ddl_batch_frame_data batch_frame;
u32 avc_delimiter_enable;
@@ -496,7 +552,7 @@
#ifdef DDL_BUF_LOG
void ddl_list_buffers(struct ddl_client_context *ddl);
#endif
-#ifdef DDL_MSG_LOG
+#if DDL_MSG_LOG
s8 *ddl_get_state_string(enum ddl_client_state client_state);
#endif
extern unsigned char *vidc_video_codec_fw;
@@ -510,4 +566,21 @@
void ddl_vidc_decode_reset_avg_time(struct ddl_client_context *ddl);
void ddl_calc_core_proc_time(const char *func_name, u32 index,
struct ddl_client_context *ddl);
+s32 ddl_encoder_ltr_control(struct ddl_client_context *ddl);
+void ddl_encoder_use_ltr_fail_callback(
+ struct ddl_client_context *ddl);
+void ddl_handle_ltr_in_framedone(struct ddl_client_context *ddl);
+s32 ddl_clear_ltr_list(struct ddl_ltr_encoding_type *ltr_control,
+ bool only_use_flag);
+s32 ddl_find_oldest_ltr_not_in_use(
+ struct ddl_ltr_encoding_type *ltr_control);
+s32 ddl_find_ltr_in_use(struct ddl_ltr_encoding_type *ltr_control);
+s32 ddl_find_ltr_from_list(struct ddl_ltr_encoding_type *ltr_control,
+ u32 ltr_id);
+s32 ddl_use_ltr_from_list(struct ddl_ltr_encoding_type *ltr_control,
+ u32 ltr_idx);
+s32 ddl_allocate_ltr_list(struct ddl_ltr_encoding_type *ltr_control);
+s32 ddl_free_ltr_list(struct ddl_ltr_encoding_type *ltr_control);
+void ddl_print_ltr_list(struct ddl_ltr_encoding_type *ltr_control);
+
#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
index db8a777..ddfd7e8 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_core.h
@@ -154,4 +154,10 @@
#define VIDC_SM_ERR_CONCEALMENT_INTER_SLICE_MB_COPY 2
#define VIDC_SM_ERR_CONCEALMENT_INTRA_SLICE_COLOR_CONCEALMENT 1
+#define DDL_MAX_P_FRAMES_IN_INTRA_INTERVAL 0xffff
+
+#define DDL_SATURATE_P_FRAMES_IN_INTRA_INTERVAL(p_rames) \
+ (((p_rames) > (DDL_MAX_P_FRAMES_IN_INTRA_INTERVAL - 1)) ? \
+ (DDL_MAX_P_FRAMES_IN_INTRA_INTERVAL) : (p_rames))
+
#endif
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
index 1782fd2..15b37a1b 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_helper.c
@@ -22,7 +22,7 @@
return &ddl_context;
}
-#ifdef DDL_MSG_LOG
+#if DDL_MSG_LOG
s8 *ddl_get_state_string(enum ddl_client_state client_state)
{
s8 *ptr;
@@ -265,7 +265,7 @@
luma_size = ddl_get_yuv_buf_size(decoder->frame_size.width,
decoder->frame_size.height, DDL_YUV_BUF_TYPE_TILE);
dpb = decoder->dp_buf.no_of_dec_pic_buf;
- DDL_MSG_LOW("%s Decoder num DPB buffers = %u Luma Size = %u"
+ DDL_MSG_LOW("%s Decoder num DPB buffers = %u Luma Size = %u",
__func__, dpb, luma_size);
if (dpb > DDL_MAX_BUFFER_COUNT)
dpb = DDL_MAX_BUFFER_COUNT;
@@ -298,7 +298,7 @@
luma[i] = DDL_OFFSET(ddl_context->dram_base_a.
align_physical_addr, frame[i].vcd_frm.physical);
chroma[i] = luma[i] + luma_size;
- DDL_MSG_LOW("%s Decoder Luma address = %x Chroma address = %x"
+ DDL_MSG_LOW("%s Decoder Luma address = %x Chroma address = %x",
__func__, luma[i], chroma[i]);
}
switch (decoder->codec.codec) {
@@ -403,6 +403,7 @@
ddl_vidc_encode_dynamic_property(ddl, false);
encoder->dynamic_prop_change = 0;
ddl_free_enc_hw_buffers(ddl);
+ ddl_free_ltr_list(&encoder->ltr_control);
}
ddl_pmem_free(&ddl->shared_mem[0]);
ddl_pmem_free(&ddl->shared_mem[1]);
@@ -999,7 +1000,7 @@
u32 luma_size, i, dpb;
luma_size = decoder->dpb_buf_size.size_y;
dpb = decoder->dp_buf.no_of_dec_pic_buf;
- DDL_MSG_HIGH("%s Decoder num DPB buffers = %u Luma Size = %u"
+ DDL_MSG_HIGH("%s Decoder num DPB buffers = %u Luma Size = %u",
__func__, dpb, luma_size);
if (dpb > DDL_MAX_BUFFER_COUNT)
dpb = DDL_MAX_BUFFER_COUNT;
@@ -1137,8 +1138,295 @@
vidc_time_out = temp;
}
}
- DDL_MSG_HIGH("%s Video core time out value = 0x%x",
+ DDL_MSG_LOW("%s Video core time out value = 0x%x",
__func__, vidc_time_out);
vidc_sm_set_video_core_timeout_value(
&ddl->shared_mem[ddl->command_channel], vidc_time_out);
}
+
+void ddl_handle_ltr_in_framedone(struct ddl_client_context *ddl)
+{
+ struct ddl_ltr_encoding_type *ltr_control =
+ &ddl->codec_data.encoder.ltr_control;
+ DDL_MSG_LOW("%s:", __func__);
+ if (ltr_control->storing) {
+ ltr_control->ltr_list[ltr_control->storing_idx].ltr_id =
+ ltr_control->curr_ltr_id;
+ DDL_MSG_MED("Encoder output stores LTR ID %d into entry %d",
+ ltr_control->curr_ltr_id, ltr_control->storing_idx);
+ ltr_control->meta_data_reqd = true;
+ ltr_control->storing = false;
+ }
+ ltr_control->out_frame_cnt_before_next_idr++;
+ if (ltr_control->out_frame_cnt_to_use_this_ltr) {
+ ltr_control->out_frame_cnt_to_use_this_ltr--;
+ if (!ltr_control->out_frame_cnt_to_use_this_ltr)
+ ddl_clear_ltr_list(ltr_control, true);
+ }
+}
+
+s32 ddl_encoder_ltr_control(struct ddl_client_context *ddl)
+{
+ s32 vcd_status = VCD_S_SUCCESS;
+ struct ddl_encoder_data *encoder = &ddl->codec_data.encoder;
+ struct ddl_ltr_encoding_type *ltr_ctrl = &encoder->ltr_control;
+ bool intra_period_reached = false;
+
+ DDL_MSG_LOW("%s:", __func__);
+ ddl_print_ltr_list(ltr_ctrl);
+
+ if (DDL_IS_LTR_IN_AUTO_MODE(encoder)) {
+ bool finite_i_period, infinite_i_period;
+ DDL_MSG_LOW("%s: before LTR encoding: output "\
+ "count before next IDR %d", __func__,
+ ltr_ctrl->out_frame_cnt_before_next_idr);
+ finite_i_period =
+ (DDL_MAX_P_FRAMES_IN_INTRA_INTERVAL !=
+ encoder->i_period.p_frames) &&
+ (!(ltr_ctrl->out_frame_cnt_before_next_idr %
+ (encoder->i_period.p_frames + 1)));
+ infinite_i_period =
+ ((DDL_MAX_P_FRAMES_IN_INTRA_INTERVAL ==
+ encoder->i_period.p_frames) &&
+ (!ltr_ctrl->out_frame_cnt_before_next_idr));
+ if (finite_i_period || infinite_i_period) {
+ DDL_MSG_HIGH("%s: Intra period reached. "\
+ "finite_i_period (%u), infinite_i_period (%u)",
+ __func__, (u32)finite_i_period,
+ (u32)infinite_i_period);
+ intra_period_reached = true;
+ }
+ if (intra_period_reached ||
+ ltr_ctrl->store_for_intraframe_insertion ||
+ encoder->intra_period_changed) {
+ ddl_clear_ltr_list(ltr_ctrl, false);
+ ltr_ctrl->out_frame_cnt_before_next_idr = 0;
+ ltr_ctrl->first_ltr_use_arvd = false;
+ ltr_ctrl->store_for_intraframe_insertion = false;
+ } else {
+ if (ltr_ctrl->first_ltr_use_arvd == false) {
+ ddl_use_ltr_from_list(ltr_ctrl, 0);
+ ltr_ctrl->out_frame_cnt_to_use_this_ltr =
+ 0xFFFFFFFF;
+ ltr_ctrl->use_ltr_reqd = true;
+ }
+ }
+ if (!(ltr_ctrl->out_frame_cnt_before_next_idr %
+ ltr_ctrl->ltr_period)) {
+ s32 idx;
+ DDL_MSG_HIGH("%s: reached LTR period "\
+ "out_frame_cnt_before_next_idr %d",
+ __func__, ltr_ctrl->\
+ out_frame_cnt_before_next_idr);
+ idx = ddl_find_oldest_ltr_not_in_use(
+ ltr_ctrl);
+ if (idx >= 0) {
+ ltr_ctrl->storing = true;
+ ltr_ctrl->storing_idx = idx;
+ if (idx == 0)
+ ltr_ctrl->store_ltr0 = true;
+ else if (idx == 1)
+ ltr_ctrl->store_ltr1 = true;
+ }
+ }
+ }
+ if (encoder->intra_frame_insertion) {
+ DDL_MSG_HIGH("%s: I-frame insertion requested, "\
+ "delay LTR store for one frame", __func__);
+ ltr_ctrl->store_for_intraframe_insertion = true;
+ }
+ if (ltr_ctrl->pending_chg_ltr_useframes) {
+ ltr_ctrl->out_frame_cnt_to_use_this_ltr =
+ ltr_ctrl->ltr_use_frames;
+ ltr_ctrl->pending_chg_ltr_useframes = false;
+ }
+ if (ltr_ctrl->out_frame_cnt_to_use_this_ltr)
+ ltr_ctrl->use_ltr_reqd = true;
+ if (ltr_ctrl->use_ltr_reqd) {
+ s32 idx;
+ idx = ddl_find_ltr_in_use(ltr_ctrl);
+ if (idx == 0)
+ ltr_ctrl->use_ltr0 = true;
+ else if (idx == 1)
+ ltr_ctrl->use_ltr1 = true;
+ ltr_ctrl->using = true;
+ ltr_ctrl->use_ltr_reqd = false;
+ } else {
+ DDL_MSG_HIGH("%s: use_ltr_reqd skipped", __func__);
+ }
+
+ return vcd_status;
+}
+
+
+s32 ddl_allocate_ltr_list(struct ddl_ltr_encoding_type *ltr_control)
+{
+ s32 vcd_status = VCD_S_SUCCESS;
+
+ DDL_MSG_LOW("%s: lrr_cout = %u", __func__, ltr_control->ltr_count);
+ if (!ltr_control->ltr_list) {
+ if (ltr_control->ltr_count) {
+ ltr_control->ltr_list = (struct ddl_ltrlist *)
+ kmalloc(sizeof(struct ddl_ltrlist)*
+ ltr_control->ltr_count, GFP_KERNEL);
+ if (!ltr_control->ltr_list) {
+ DDL_MSG_ERROR("ddl_allocate_ltr_list failed");
+ vcd_status = VCD_ERR_ALLOC_FAIL;
+ }
+ } else {
+ DDL_MSG_ERROR("%s: failed, zero LTR count", __func__);
+ vcd_status = VCD_ERR_FAIL;
+ }
+ } else {
+ DDL_MSG_HIGH("WARN: ltr_list already allocated");
+ }
+
+ return vcd_status;
+}
+
+s32 ddl_free_ltr_list(struct ddl_ltr_encoding_type *ltr_control)
+{
+ s32 vcd_status = VCD_S_SUCCESS;
+
+ DDL_MSG_LOW("%s:", __func__);
+ kfree(ltr_control->ltr_list);
+ ltr_control->ltr_list = NULL;
+
+ return vcd_status;
+}
+
+s32 ddl_clear_ltr_list(struct ddl_ltr_encoding_type *ltr_control,
+ bool only_use_flag)
+{
+ s32 vcd_status = VCD_S_SUCCESS;
+ u32 i;
+
+ DDL_MSG_LOW("%s:", __func__);
+ for (i = 0; i < ltr_control->ltr_count; i++) {
+ ltr_control->ltr_list[i].ltr_in_use = false;
+ if (!only_use_flag)
+ ltr_control->ltr_list[i].ltr_id = 0;
+ }
+
+ return vcd_status;
+}
+
+s32 ddl_find_oldest_ltr_not_in_use(struct ddl_ltr_encoding_type *ltr_control)
+{
+ s32 found_idx = -1;
+ u32 i;
+
+ if (ltr_control->ltr_list) {
+ if (ltr_control->ltr_count == 1)
+ found_idx = 0;
+ else {
+ for (i = 0; i < ltr_control->ltr_count; i++) {
+ if ((ltr_control->ltr_list[i].ltr_in_use ==
+ false) && (found_idx < 0)) {
+ found_idx = i;
+ }
+ if ((found_idx >= 0) &&
+ (ltr_control->ltr_list[i].\
+ ltr_in_use == false) &&
+ (ltr_control->ltr_list[i].ltr_id <
+ ltr_control->ltr_list[found_idx].\
+ ltr_id)) {
+ found_idx = i;
+ }
+ }
+ }
+ }
+
+ DDL_MSG_LOW("%s: found_idx = %d", __func__, found_idx);
+ return found_idx;
+}
+
+s32 ddl_find_ltr_in_use(struct ddl_ltr_encoding_type *ltr_control)
+{
+ s32 found_idx = -1;
+ u32 i;
+
+ if (ltr_control->ltr_list) {
+ for (i = 0; i < ltr_control->ltr_count; i++) {
+ if (ltr_control->ltr_list[i].ltr_in_use == true)
+ found_idx = i;
+ }
+ }
+
+ DDL_MSG_LOW("%s: found_idx = %d", __func__, found_idx);
+ return found_idx;
+}
+
+s32 ddl_find_ltr_from_list(struct ddl_ltr_encoding_type *ltr_control,
+ u32 ltr_id)
+{
+ s32 found_idx = -1;
+ u32 i;
+
+ if (ltr_control->ltr_list) {
+ for (i = 0; i < ltr_control->ltr_count; i++) {
+ if (ltr_control->ltr_list[i].ltr_id == ltr_id) {
+ found_idx = i;
+ break;
+ }
+ }
+ } else {
+ DDL_MSG_ERROR("%s: ltr_list is NULL", __func__);
+ }
+
+ DDL_MSG_LOW("%s: found_idx = %d", __func__, found_idx);
+ return found_idx;
+}
+
+s32 ddl_use_ltr_from_list(struct ddl_ltr_encoding_type *ltr_control,
+ u32 ltr_idx)
+{
+ s32 vcd_status = VCD_S_SUCCESS;
+ u32 i;
+
+ DDL_MSG_LOW("%s: ltr_idx = %u", __func__, ltr_idx);
+ if (ltr_idx > ltr_control->ltr_count) {
+ DDL_MSG_ERROR("%s: fail, idx %d larger than "\
+ "the list array count %d", __func__,
+ ltr_idx, ltr_control->ltr_count);
+ vcd_status = VCD_ERR_FAIL;
+ } else {
+ for (i = 0; i < ltr_control->ltr_count; i++) {
+ if (i == ltr_idx)
+ ltr_control->ltr_list[ltr_idx].ltr_in_use =
+ true;
+ else
+ ltr_control->ltr_list[i].ltr_in_use = false;
+ }
+ }
+
+ return vcd_status;
+}
+
+void ddl_encoder_use_ltr_fail_callback(struct ddl_client_context *ddl)
+{
+ struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
+ struct ddl_context *ddl_context = ddl->ddl_context;
+
+ DDL_MSG_ERROR("%s: LTR use failed, callback "\
+ "requested with LTR ID %d", __func__,
+ encoder->ltr_control.failed_use_cmd.ltr_id);
+
+ ddl_context->ddl_callback(VCD_EVT_IND_INFO_LTRUSE_FAILED,
+ VCD_ERR_ILLEGAL_PARM,
+ &(encoder->ltr_control.failed_use_cmd),
+ sizeof(struct vcd_property_ltruse_type),
+ (u32 *)ddl,
+ ddl->client_data);
+}
+
+void ddl_print_ltr_list(struct ddl_ltr_encoding_type *ltr_control)
+{
+ u32 i;
+
+ for (i = 0; i < ltr_control->ltr_count; i++) {
+ DDL_MSG_MED("%s: ltr_id: %d, ltr_in_use: %d",
+ __func__, ltr_control->ltr_list[i].ltr_id,
+ ltr_control->ltr_list[i].ltr_in_use);
+ }
+}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
index d189408..163af21 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_interrupt_handler.c
@@ -822,13 +822,13 @@
pixel_cache_stats;
vidc_pix_cache_get_statistics(&pixel_cache_stats);
- DDL_MSG_HIGH(" pixel cache hits = %d,"
+ DDL_MSG_LOW(" pixel cache hits = %d,"
"miss = %d", pixel_cache_stats.access_hit,
pixel_cache_stats.access_miss);
- DDL_MSG_HIGH(" pixel cache core reqs = %d,"
+ DDL_MSG_LOW(" pixel cache core reqs = %d,"
"axi reqs = %d", pixel_cache_stats.core_req,
pixel_cache_stats.axi_req);
- DDL_MSG_HIGH(" pixel cache core bus stats = %d,"
+ DDL_MSG_LOW(" pixel cache core bus stats = %d,"
"axi bus stats = %d", pixel_cache_stats.core_bus,
pixel_cache_stats.axi_bus);
}
@@ -1313,7 +1313,7 @@
DDL_MSG_LOW("%s y_cb_cr_size = %u "
"actual_output_buf_req.sz = %u"
"min_output_buf_req.sz = %u\n",
- decoder->y_cb_cr_size,
+ __func__, decoder->y_cb_cr_size,
decoder->actual_output_buf_req.sz,
decoder->min_output_buf_req.sz);
vidc_sm_set_chroma_addr_change(
@@ -1474,7 +1474,7 @@
}
} else
status = false;
- DDL_MSG_HIGH("Enc Frame Type %u", (u32)frame->frame);
+ DDL_MSG_LOW("Enc Frame Type %u", (u32)frame->frame);
return status;
}
@@ -1764,7 +1764,17 @@
(unsigned long) output_frame->alloc_len,
ION_IOC_INV_CACHES);
}
- ddl_process_encoder_metadata(ddl);
+
+ if ((VIDC_1080P_ENCODE_FRAMETYPE_SKIPPED !=
+ encoder->enc_frame_info.enc_frame) &&
+ (VIDC_1080P_ENCODE_FRAMETYPE_NOT_CODED !=
+ encoder->enc_frame_info.enc_frame)) {
+ if (DDL_IS_LTR_ENABLED(encoder))
+ ddl_handle_ltr_in_framedone(ddl);
+ ddl_process_encoder_metadata(ddl);
+ encoder->ltr_control.meta_data_reqd = false;
+ }
+ encoder->ltr_control.using = false;
ddl_vidc_encode_dynamic_property(ddl, false);
ddl->input_frame.frm_trans_end = false;
input_buffer_address = ddl_context->dram_base_a.align_physical_addr +
@@ -1828,9 +1838,9 @@
encoder->batch_frame.output_frame[actual_idx].vcd_frm);
DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
"frmbfr(physical) 0x%x\n",
- &output_frame,
- output_frame.virtual_base_addr,
- output_frame.physical_base_addr);
+ (u32)output_frame,
+ (u32)output_frame->virtual,
+ (u32)output_frame->physical);
vidc_1080p_get_encode_frame_info(&encoder->enc_frame_info);
vidc_sm_get_frame_tags(&ddl->shared_mem
[ddl->command_channel],
@@ -1908,17 +1918,17 @@
actual_idx =
slice_output->slice_info[start_bfr_idx+index]. \
stream_buffer_idx;
- DDL_MSG_LOW("Slice Info: OutBfrIndex %d SliceSize %d",
+ DDL_MSG_LOW("Slice Info: OutBfrIndex %u SliceSize %u",
actual_idx,
slice_output->slice_info[start_bfr_idx+index]. \
- stream_buffer_size, 0);
+ stream_buffer_size);
output_frame =
&(encoder->batch_frame.output_frame[actual_idx].vcd_frm);
DDL_MSG_LOW("OutBfr: vcd_frm 0x%x frmbfr(virtual) 0x%x"
"frmbfr(physical) 0x%x",
- &output_frame,
- output_frame.virtual_base_addr,
- output_frame.physical_base_addr);
+ (u32)output_frame,
+ (u32)output_frame->virtual,
+ (u32)output_frame->physical);
vidc_1080p_get_encode_frame_info(
&encoder->enc_frame_info);
vidc_sm_get_frame_tags(&ddl->shared_mem
@@ -1936,8 +1946,8 @@
slice_output->slice_info[actual_idx].stream_buffer_size;
ddl->output_frame =
encoder->batch_frame.output_frame[actual_idx];
- DDL_MSG_LOW(" %s actual_idx = %d"
- "encoder->batch_frame.num_output_frames = %d\n", __func__,
+ DDL_MSG_LOW("%s: actual_idx = %u "\
+ "encoder->batch_frame.num_output_frames = %u\n", __func__,
actual_idx, encoder->batch_frame.num_output_frames);
if (encoder->batch_frame.num_output_frames == (actual_idx+1)) {
output_frame->flags |= VCD_FRAME_FLAG_ENDOFFRAME;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
index f70c47c..1aee3d9 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
@@ -75,6 +75,9 @@
case VCD_METADATA_QCOMFILLER:
skip_words = 6;
break;
+ case VCD_METADATA_LTR_INFO:
+ skip_words = 9;
+ break;
}
}
buffer += skip_words;
@@ -146,17 +149,21 @@
hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_ENC_SLICE;
+
+ hdr_entry = ddl_metadata_hdr_entry(ddl, VCD_METADATA_LTR_INFO);
+ hdr_entry[DDL_METADATA_HDR_VERSION_INDEX] = 0x00000101;
+ hdr_entry[DDL_METADATA_HDR_PORT_INDEX] = 1;
+ hdr_entry[DDL_METADATA_HDR_TYPE_INDEX] = VCD_METADATA_LTR_INFO;
}
}
static u32 ddl_supported_metadata_flag(struct ddl_client_context *ddl)
{
u32 flag = 0;
+ enum vcd_codec codec =
+ ddl->codec_data.decoder.codec.codec;
if (ddl->decoding) {
- enum vcd_codec codec =
- ddl->codec_data.decoder.codec.codec;
-
flag |= (VCD_METADATA_CONCEALMB | VCD_METADATA_PASSTHROUGH |
VCD_METADATA_QPARRAY);
if (codec == VCD_CODEC_H264)
@@ -167,8 +174,12 @@
else if (codec == VCD_CODEC_MPEG2)
flag |= (VCD_METADATA_USER_DATA |
VCD_METADATA_EXT_DATA);
- } else
- flag |= VCD_METADATA_ENC_SLICE;
+ } else {
+ if (codec == VCD_CODEC_H264)
+ flag |= VCD_METADATA_ENC_SLICE | VCD_METADATA_LTR_INFO;
+ else
+ flag |= VCD_METADATA_ENC_SLICE;
+ }
return flag;
}
@@ -272,6 +283,12 @@
DDL_METADATA_ALIGNSIZE(size);
suffix += size;
}
+ if (flag & VCD_METADATA_LTR_INFO) {
+ size = DDL_METADATA_HDR_SIZE;
+ size += DDL_METADATA_LTR_INFO_PAYLOAD_SIZE;
+ DDL_METADATA_ALIGNSIZE(size);
+ suffix += size;
+ }
size = DDL_METADATA_EXTRADATANONE_SIZE;
DDL_METADATA_ALIGNSIZE(size);
suffix += (size);
@@ -497,27 +514,92 @@
&(ddl->output_frame.vcd_frm);
u32 *qfiller_hdr, *qfiller, start_addr;
u32 qfiller_size;
+ u8 *extradata_addr;
+ u32 metadata_available = false;
+
+ out_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
if (!encoder->meta_data_enable_flag) {
- out_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
- return;
+ DDL_MSG_HIGH("meta_data is not enabled");
+ goto exit;
}
- if (!encoder->enc_frame_info.meta_data_exists) {
- out_frame->flags &= ~(VCD_FRAME_FLAG_EXTRADATA);
- return;
- }
- out_frame->flags |= VCD_FRAME_FLAG_EXTRADATA;
- DDL_MSG_LOW("processing metadata for encoder");
start_addr = (u32) ((u8 *)out_frame->virtual + out_frame->offset);
- qfiller = (u32 *)((out_frame->data_len +
+ extradata_addr = (u8 *)((out_frame->data_len +
start_addr + 3) & ~3);
+ qfiller = (u32 *)extradata_addr;
qfiller_size = (u32)((encoder->meta_data_offset +
(u8 *) out_frame->virtual) - (u8 *) qfiller);
+ if (qfiller_size & 3) {
+ DDL_MSG_ERROR("qfiller_size is not 4 bytes aligned");
+ goto exit;
+ }
qfiller_hdr = ddl_metadata_hdr_entry(ddl, VCD_METADATA_QCOMFILLER);
*qfiller++ = qfiller_size;
*qfiller++ = qfiller_hdr[DDL_METADATA_HDR_VERSION_INDEX];
*qfiller++ = qfiller_hdr[DDL_METADATA_HDR_PORT_INDEX];
*qfiller++ = qfiller_hdr[DDL_METADATA_HDR_TYPE_INDEX];
*qfiller = (u32)(qfiller_size - DDL_METADATA_HDR_SIZE);
+ extradata_addr += qfiller_size;
+ if ((u32)extradata_addr !=
+ (u32)((u8 *)start_addr + encoder->meta_data_offset)) {
+ DDL_MSG_ERROR("wrong qfiller size");
+ goto exit;
+ }
+ if (encoder->meta_data_enable_flag & VCD_METADATA_ENC_SLICE) {
+ u32 *sliceinfo = (u32 *)extradata_addr;
+ if (sliceinfo[3] != VCD_METADATA_ENC_SLICE) {
+ DDL_MSG_ERROR("wrong slice info extradata. " \
+ "data: 0x%x, 0x%x, 0x%x, 0x%x, 0x%x, 0x%x",
+ sliceinfo[0], sliceinfo[1], sliceinfo[2],
+ sliceinfo[3], sliceinfo[4], sliceinfo[5]);
+ goto metadata_end;
+ }
+ extradata_addr += sliceinfo[0];
+ metadata_available = true;
+ DDL_MSG_HIGH("%s: Send %u slices info in metadata",
+ __func__, sliceinfo[5]);
+ }
+ if ((encoder->meta_data_enable_flag & VCD_METADATA_LTR_INFO) &&
+ (encoder->ltr_control.meta_data_reqd == true)) {
+ u32 *ltrinfo_hdr = ddl_metadata_hdr_entry(ddl,
+ VCD_METADATA_LTR_INFO);
+ u32 *ltrinfo = (u32 *)extradata_addr;
+ if ((u32)extradata_addr > (u32)((u8 *)out_frame->virtual +
+ out_frame->alloc_len)) {
+ metadata_available = false;
+ DDL_MSG_ERROR("Error: extradata_addr = 0x%p, "\
+ "buffer_start = 0x%p, size = %u",
+ extradata_addr, out_frame->virtual,
+ out_frame->alloc_len);
+ goto metadata_end;
+ }
+ ltrinfo[0] = DDL_METADATA_LTR_INFO_PAYLOAD_SIZE +
+ DDL_METADATA_HDR_SIZE;
+ ltrinfo[1] = ltrinfo_hdr[DDL_METADATA_HDR_VERSION_INDEX];
+ ltrinfo[2] = ltrinfo_hdr[DDL_METADATA_HDR_PORT_INDEX];
+ ltrinfo[3] = ltrinfo_hdr[DDL_METADATA_HDR_TYPE_INDEX];
+ ltrinfo[4] = DDL_METADATA_LTR_INFO_PAYLOAD_SIZE;
+ ltrinfo[5] = encoder->ltr_control.curr_ltr_id;
+ extradata_addr += ltrinfo[0];
+ encoder->ltr_control.curr_ltr_id++;
+ metadata_available = true;
+ DDL_MSG_HIGH("%s: Send curr_ltr_id = %u in metadata",
+ __func__, (u32)encoder->ltr_control.curr_ltr_id);
+ }
+metadata_end:
+ if (metadata_available == true) {
+ u32 *data_none_hdr = ddl_metadata_hdr_entry(ddl,
+ VCD_METADATA_DATANONE);
+ u32 *data_none = (u32 *)extradata_addr;
+ DDL_MSG_LOW("prepare metadata_none header");
+ data_none[0] = DDL_METADATA_EXTRADATANONE_SIZE;
+ data_none[1] = data_none_hdr[DDL_METADATA_HDR_VERSION_INDEX];
+ data_none[2] = data_none_hdr[DDL_METADATA_HDR_PORT_INDEX];
+ data_none[3] = data_none_hdr[DDL_METADATA_HDR_TYPE_INDEX];
+ data_none[4] = 0;
+ out_frame->flags |= VCD_FRAME_FLAG_EXTRADATA;
+ }
+exit:
+ return;
}
void ddl_process_decoder_metadata(struct ddl_client_context *ddl)
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
index e03a9b7..4426828 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.h
@@ -26,6 +26,7 @@
#define DDL_METADATA_SEI_PAYLOAD_SIZE 100
#define DDL_METADATA_SEI_MAX 5
#define DDL_METADATA_VUI_PAYLOAD_SIZE 256
+#define DDL_METADATA_LTR_INFO_PAYLOAD_SIZE (4)
#define DDL_METADATA_PASSTHROUGH_PAYLOAD_SIZE 68
#define DDL_METADATA_EXT_PAYLOAD_SIZE (640)
#define DDL_METADATA_USER_PAYLOAD_SIZE (2048)
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 2b65d7e..94ec12e 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -163,6 +163,28 @@
DDL_MSG_ERROR("H264BaseLineCABAC!!");
return false;
}
+ if (DDL_IS_LTR_ENABLED(encoder)) {
+ if ((encoder->codec.codec != VCD_CODEC_H264) ||
+ (encoder->i_period.b_frames)) {
+ DDL_MSG_ERROR("%s: Only support LTR encoding "\
+ "for H264 without B frame. Current "\
+ "codec %d, B-frame %d", __func__,
+ encoder->codec.codec,
+ encoder->i_period.b_frames);
+ return false;
+ }
+ if (encoder->ltr_control.ltrmode.ltr_mode ==
+ VCD_LTR_MODE_MANUAL) {
+ DDL_MSG_ERROR("%s: Manual LTR mode not supported!",
+ __func__);
+ return false;
+ }
+ DDL_MSG_HIGH("%s: LTR: mode = %u, count = %u, period = %u",
+ __func__, (u32)encoder->ltr_control.ltrmode.ltr_mode,
+ encoder->ltr_control.ltr_count,
+ encoder->ltr_control.ltr_period);
+ }
+
return true;
}
@@ -617,8 +639,9 @@
struct vcd_property_multi_slice *multi_slice =
(struct vcd_property_multi_slice *)
property_value;
- DDL_MSG_HIGH("VCD_I_MULTI_SLICE eMSliceSel %d nMSliceSize %d"
- "Tot#of MB %d encoder->frame_size.width = %d"
+ DDL_MSG_HIGH("VCD_I_MULTI_SLICE eMSliceSel %d "\
+ "nMSliceSize %d Tot#of MB %d "\
+ "encoder->frame_size.width = %d "\
"encoder->frame_size.height = %d",
(int)multi_slice->m_slice_sel,
multi_slice->m_slice_size,
@@ -1044,6 +1067,41 @@
}
break;
}
+ case VCD_I_LTR_MODE:
+ if (sizeof(struct vcd_property_ltrmode_type) ==
+ property_hdr->sz && encoder->codec.codec ==
+ VCD_CODEC_H264) {
+ struct vcd_property_ltrmode_type *ltrmode =
+ (struct vcd_property_ltrmode_type *)
+ property_value;
+ encoder->ltr_control.ltrmode.ltr_mode =
+ ltrmode->ltr_mode;
+ DDL_MSG_HIGH("%s: set LTR mode = %u", __func__,
+ (u32)encoder->ltr_control.ltrmode.ltr_mode);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_LTR_COUNT:
+ if (sizeof(struct vcd_property_ltrcount_type) ==
+ property_hdr->sz && encoder->codec.codec ==
+ VCD_CODEC_H264) {
+ struct vcd_property_ltrcount_type *ltrcount =
+ (struct vcd_property_ltrcount_type *)
+ property_value;
+ if (ltrcount->ltr_count > DDL_MAX_NUM_LTR_FRAMES) {
+ DDL_MSG_ERROR("%s: set LTR count failed. "\
+ "LTR count %u beyond maximum of %u",
+ __func__, ltrcount->ltr_count,
+ (u32)DDL_MAX_NUM_LTR_FRAMES);
+ } else {
+ encoder->ltr_control.ltr_count =
+ ltrcount->ltr_count;
+ DDL_MSG_HIGH("%s: set LTR count = %u", __func__,
+ encoder->ltr_control.ltr_count);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
case VCD_REQ_PERF_LEVEL:
vcd_status = VCD_S_SUCCESS;
break;
@@ -1091,7 +1149,8 @@
break;
}
default:
- DDL_MSG_ERROR("INVALID ID %d\n", (int)property_hdr->prop_id);
+ DDL_MSG_ERROR("%s: unknown prop_id = 0x%x", __func__,
+ property_hdr->prop_id);
vcd_status = VCD_ERR_ILLEGAL_OP;
break;
}
@@ -1552,7 +1611,7 @@
break;
case VCD_I_METADATA_ENABLE:
case VCD_I_METADATA_HEADER:
- DDL_MSG_ERROR("Meta Data Interface is Requested");
+ DDL_MSG_HIGH("Meta Data Interface is Requested");
vcd_status = ddl_get_metadata_params(ddl, property_hdr,
property_value);
vcd_status = VCD_S_SUCCESS;
@@ -1591,7 +1650,67 @@
vcd_status = VCD_S_SUCCESS;
}
break;
+ case VCD_I_CAPABILITY_LTR_COUNT:
+ if (sizeof(struct vcd_property_range_type) ==
+ property_hdr->sz) {
+ struct vcd_property_range_type capability_ltr_range;
+ capability_ltr_range.max = DDL_MAX_NUM_LTR_FRAMES;
+ capability_ltr_range.min = 1;
+ capability_ltr_range.step_size = 1;
+ *(struct vcd_property_range_type *)property_value =
+ capability_ltr_range;
+ DDL_MSG_HIGH("%s: capability_ltr_count = %u",
+ __func__, ((struct vcd_property_range_type *)
+ property_value)->max);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_LTR_MODE:
+ if (sizeof(struct vcd_property_ltrmode_type) ==
+ property_hdr->sz) {
+ ((struct vcd_property_ltrmode_type *)
+ property_value)->ltr_mode =
+ encoder->ltr_control.ltrmode.ltr_mode;
+ DDL_MSG_HIGH("%s: ltr_mode = %u", __func__,
+ (u32)(((struct vcd_property_ltrmode_type *)
+ property_value)->ltr_mode));
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_LTR_COUNT:
+ if (sizeof(struct vcd_property_ltrcount_type) ==
+ property_hdr->sz) {
+ struct vcd_property_ltrcount_type ltr_count;
+ ltr_count.ltr_count =
+ encoder->ltr_control.ltr_count;
+ *(struct vcd_property_ltrcount_type *)property_value =
+ ltr_count;
+ DDL_MSG_HIGH("%s: ltr_count = %u", __func__,
+ ((struct vcd_property_ltrcount_type *)
+ property_value)->ltr_count);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
+ case VCD_I_LTR_PERIOD:
+ if (sizeof(struct vcd_property_ltrperiod_type) ==
+ property_hdr->sz) {
+ struct vcd_property_ltrperiod_type ltr_period;
+ if (!encoder->ltr_control.ltr_period)
+ ltr_period.ltr_period = 0;
+ else
+ ltr_period.ltr_period =
+ encoder->ltr_control.ltr_period - 1;
+ *(struct vcd_property_ltrperiod_type *)property_value =
+ ltr_period;
+ DDL_MSG_HIGH("%s: ltr_period = %u", __func__,
+ ((struct vcd_property_ltrperiod_type *)
+ property_value)->ltr_period);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ break;
default:
+ DDL_MSG_ERROR("%s: unknown prop_id = 0x%x", __func__,
+ property_hdr->prop_id);
vcd_status = VCD_ERR_ILLEGAL_OP;
break;
}
@@ -1680,6 +1799,77 @@
}
}
break;
+ case VCD_I_LTR_PERIOD:
+ {
+ if (sizeof(struct vcd_property_ltrperiod_type) ==
+ property_hdr->sz) {
+ struct vcd_property_ltrperiod_type *ltrperiod =
+ (struct vcd_property_ltrperiod_type *)
+ property_value;
+ encoder->ltr_control.ltr_period =
+ (ltrperiod->ltr_period == 0xFFFFFFFF) ?
+ 0xFFFFFFFF : (ltrperiod->ltr_period + 1);
+ DDL_MSG_HIGH("%s: set ltr_period = %u", __func__,
+ encoder->ltr_control.ltr_period);
+ vcd_status = VCD_S_SUCCESS;
+ }
+ }
+ break;
+ case VCD_I_LTR_USE:
+ {
+ if (sizeof(struct vcd_property_ltruse_type) ==
+ property_hdr->sz) {
+ struct vcd_property_ltruse_type *ltruse =
+ (struct vcd_property_ltruse_type *)
+ property_value;
+ if (ltruse->ltr_id >= DDL_LTR_FRAME_START_ID) {
+ struct ddl_ltr_encoding_type *ltr_ctrl =
+ &encoder->ltr_control;
+ s32 idx;
+ idx = ddl_find_ltr_from_list(ltr_ctrl,
+ ltruse->ltr_id);
+ if (idx < 0) {
+ ltr_ctrl->callback_reqd = true;
+ ltr_ctrl->failed_use_cmd.ltr_id =
+ ltruse->ltr_id;
+ ltr_ctrl->failed_use_cmd.ltr_frames =
+ ltruse->ltr_frames;
+ DDL_MSG_ERROR("%s: index (%d) "\
+ "not found. Callback requested. "\
+ "ltr_id = %u, ltr_frames = %u",
+ __func__, idx, ltruse->ltr_id,
+ ltruse->ltr_frames);
+ } else {
+ ddl_use_ltr_from_list(ltr_ctrl, idx);
+ ltr_ctrl->ltr_use_frames =
+ ltruse->ltr_frames;
+ if (ltr_ctrl->using == false)
+ ltr_ctrl->\
+ out_frame_cnt_to_use_this_ltr =
+ ltruse->ltr_frames;
+ else
+ ltr_ctrl->\
+ pending_chg_ltr_useframes =
+ true;
+ ltr_ctrl->first_ltr_use_arvd = true;
+ ltr_ctrl->use_ltr_reqd = true;
+ DDL_MSG_HIGH("%s: index (%d) found. "\
+ "num frames to use this ltr_id (%u) "\
+ "is %u", __func__, idx,
+ ltruse->ltr_id, ltruse->ltr_frames);
+ }
+ dynamic_prop_change = DDL_ENC_LTR_USE_FRAME;
+ vcd_status = VCD_S_SUCCESS;
+ } else {
+ DDL_MSG_ERROR("%s: LTRUse ID %d failed. "\
+ "LTR ID starts from %d", __func__,
+ ltruse->ltr_id,
+ (u32)DDL_LTR_FRAME_START_ID);
+ vcd_status = VCD_ERR_ILLEGAL_OP;
+ }
+ }
+ }
+ break;
default:
vcd_status = VCD_ERR_ILLEGAL_OP;
break;
@@ -1747,6 +1937,9 @@
encoder->num_references_for_p_frame = DDL_MIN_NUM_REF_FOR_P_FRAME;
if (encoder->codec.codec == VCD_CODEC_MPEG4)
encoder->closed_gop = true;
+ encoder->intra_period_changed = false;
+ memset(&encoder->ltr_control, 0,
+ sizeof(struct ddl_ltr_encoding_type));
ddl_set_default_metadata_flag(ddl);
ddl_set_default_encoder_buffer_req(encoder);
encoder->slice_delivery_info.enable = 0;
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index de3fc4f..4c73bef 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -87,6 +87,8 @@
#define VIDC_SM_ENC_EXT_CTRL_TIMING_INFO_EN_SHFT 14
#define VIDC_SM_ENC_EXT_CTRL_AU_DELIMITER_EN_BMSK 0x00000800
#define VIDC_SM_ENC_EXT_CTRL_AU_DELIMITER_EN_SHFT 11
+#define VIDC_SM_ENC_EXT_CTRL_LONG_TERM_REF_ENABLE_BMSK 0x00000400
+#define VIDC_SM_ENC_EXT_CTRL_LONG_TERM_REF_ENABLE_SHFT 10
#define VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_BMSK 0x80
#define VIDC_SM_ENC_EXT_CTRL_H263_CPCFC_ENABLE_SHFT 7
#define VIDC_SM_ENC_EXT_CTRL_SPS_PPS_CONTROL_BMSK 0X100
@@ -458,8 +460,8 @@
enum VIDC_SM_frame_skip frame_skip_mode,
u32 seq_hdr_in_band, u32 vbv_buffer_size, u32 cpcfc_enable,
u32 sps_pps_control, u32 closed_gop_enable,
- u32 au_delim_enable,
- u32 vui_timing_info_enable)
+ u32 au_delim_enable, u32 vui_timing_info_enable,
+ u32 ltr_enable)
{
u32 enc_ctrl;
enc_ctrl = VIDC_SETFIELD((hec_enable) ? 1 : 0,
@@ -488,8 +490,10 @@
VIDC_SM_ENC_EXT_CTRL_AU_DELIMITER_EN_BMSK) |
VIDC_SETFIELD((vui_timing_info_enable) ? 1 : 0,
VIDC_SM_ENC_EXT_CTRL_TIMING_INFO_EN_SHFT,
- VIDC_SM_ENC_EXT_CTRL_TIMING_INFO_EN_BMSK);
-
+ VIDC_SM_ENC_EXT_CTRL_TIMING_INFO_EN_BMSK) |
+ VIDC_SETFIELD((ltr_enable) ? 1 : 0,
+ VIDC_SM_ENC_EXT_CTRL_LONG_TERM_REF_ENABLE_SHFT,
+ VIDC_SM_ENC_EXT_CTRL_LONG_TERM_REF_ENABLE_BMSK);
DDL_MEM_WRITE_32(shared_mem, VIDC_SM_ENC_EXT_CTRL_ADDR, enc_ctrl);
}
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
index 2eef99d..f344460 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.h
@@ -106,7 +106,8 @@
struct ddl_buf_addr *shared_mem, u32 hec_enable,
enum VIDC_SM_frame_skip frame_skip_mode, u32 seq_hdr_in_band,
u32 vbv_buffer_size, u32 cpcfc_enable, u32 sps_pps_control,
- u32 closed_gop_enable, u32 au_delim_enable, u32 vui_timing_info_enable);
+ u32 closed_gop_enable, u32 au_delim_enable, u32 vui_timing_info_enable,
+ u32 ltr_enable);
void vidc_sm_set_encoder_param_change(struct ddl_buf_addr *shared_mem,
u32 bit_rate_chg, u32 frame_rate_chg, u32 i_period_chg);
void vidc_sm_set_encoder_vop_time(struct ddl_buf_addr *shared_mem,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
index 4963874..a099ade 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_utils.h
@@ -34,7 +34,7 @@
printk(KERN_DEBUG x); \
} while (0)
-#ifdef DDL_MSG_LOG
+#if DDL_MSG_LOG
#define DDL_MSG_LOW(x...) printk(KERN_INFO x)
#define DDL_MSG_MED(x...) printk(KERN_INFO x)
#define DDL_MSG_HIGH(x...) printk(KERN_INFO x)
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
index 1bf242d..b84ec66 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_vidc.c
@@ -331,7 +331,7 @@
{
struct ddl_encoder_data *encoder = &(ddl->codec_data.encoder);
u32 frame_rate_change = false, bit_rate_change = false;
- u32 i_period_change = false, reset_req = false;
+ u32 reset_req = false;
if (!enable) {
if (encoder->dynmic_prop_change_req) {
@@ -344,6 +344,17 @@
encoder->dynamic_prop_change &=
~(DDL_ENC_REQ_IFRAME);
}
+ if (encoder->dynamic_prop_change & DDL_ENC_LTR_USE_FRAME) {
+ if (encoder->ltr_control.callback_reqd) {
+ DDL_MSG_ERROR("%s: LTR use failed", __func__);
+ ddl_encoder_use_ltr_fail_callback(ddl);
+ encoder->ltr_control.callback_reqd = false;
+ } else {
+ encoder->ltr_control.use_ltr_reqd = true;
+ }
+ encoder->dynamic_prop_change &=
+ ~(DDL_ENC_LTR_USE_FRAME);
+ }
if ((encoder->dynamic_prop_change &
DDL_ENC_CHANGE_BITRATE)) {
bit_rate_change = true;
@@ -355,7 +366,7 @@
}
if ((encoder->dynamic_prop_change
& DDL_ENC_CHANGE_IPERIOD)) {
- i_period_change = true;
+ encoder->intra_period_changed = true;
vidc_sm_set_encoder_new_i_period(
&ddl->shared_mem[ddl->command_channel],
encoder->i_period.p_frames);
@@ -387,7 +398,7 @@
vidc_sm_set_encoder_param_change(
&ddl->shared_mem[ddl->command_channel],
bit_rate_change, frame_rate_change,
- i_period_change);
+ encoder->intra_period_changed);
}
}
@@ -580,7 +591,7 @@
u32 index, luma[4], chroma[4], hdr_ext_control = false;
const u32 recon_bufs = 4;
u32 h263_cpfc_enable = false;
- u32 scaled_frame_rate;
+ u32 scaled_frame_rate, ltr_enable;
ddl_vidc_encode_set_profile_level(ddl);
vidc_1080p_set_encode_frame_size(encoder->frame_size.width,
@@ -601,12 +612,14 @@
(DDL_FRAMERATE_SCALE(DDL_INITIAL_FRAME_RATE)
!= scaled_frame_rate) && encoder->plusptype_enable)
h263_cpfc_enable = true;
+ ltr_enable = DDL_IS_LTR_ENABLED(encoder);
+ DDL_MSG_HIGH("ltr_enable = %u", ltr_enable);
vidc_sm_set_extended_encoder_control(&ddl->shared_mem
[ddl->command_channel], hdr_ext_control,
r_cframe_skip, false, 0,
h263_cpfc_enable, encoder->sps_pps.sps_pps_for_idr_enable_flag,
encoder->closed_gop, encoder->avc_delimiter_enable,
- encoder->vui_timinginfo_enable);
+ encoder->vui_timinginfo_enable, ltr_enable);
if (encoder->vui_timinginfo_enable) {
vidc_sm_set_h264_encoder_timing_info(
&ddl->shared_mem[ddl->command_channel],
@@ -809,7 +822,8 @@
encoder->dynmic_prop_change_req = true;
ddl_vidc_encode_dynamic_property(ddl, true);
}
-
+ if (DDL_IS_LTR_ENABLED(encoder))
+ ddl_encoder_ltr_control(ddl);
vidc_1080p_set_encode_circular_intra_refresh(
encoder->intra_refresh.cir_mb_number);
ddl_vidc_encode_set_multi_slice_info(encoder);
@@ -824,13 +838,21 @@
ddl_context->dram_base_a.align_physical_addr, stream->physical);
enc_param.stream_buffer_size =
encoder->client_output_buf_req.sz;
-
enc_param.intra_frame = encoder->intra_frame_insertion;
- if (encoder->intra_frame_insertion)
- encoder->intra_frame_insertion = false;
enc_param.input_flush = false;
enc_param.slice_enable = false;
- vidc_sm_set_encoder_vop_time(
+ enc_param.store_ltr0 = encoder->ltr_control.store_ltr0;
+ enc_param.store_ltr1 = encoder->ltr_control.store_ltr1;
+ enc_param.use_ltr0 = encoder->ltr_control.use_ltr0;
+ enc_param.use_ltr1 = encoder->ltr_control.use_ltr1;
+
+ encoder->intra_frame_insertion = false;
+ encoder->intra_period_changed = false;
+ encoder->ltr_control.store_ltr0 = false;
+ encoder->ltr_control.store_ltr1 = false;
+ encoder->ltr_control.use_ltr0 = false;
+ encoder->ltr_control.use_ltr1 = false;
+ vidc_sm_set_encoder_vop_time(
&ddl->shared_mem[ddl->command_channel], true,
encoder->vop_timing.vop_time_resolution,
ddl->input_frame.frm_delta);
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.c b/drivers/video/msm/vidc/1080p/ddl/vidc.c
index 3c445bc..396adaf 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.c
@@ -83,6 +83,17 @@
#define VIDC_1080P_SI_RG10_ENCODE_SLICE_IF_ENABLE_SHFT 31
#define VIDC_1080P_MAX_INTRA_PERIOD 0xffff
+#define VIDC_1080P_COMMON_CHX_RG6_I_FRAME_BMASK 0x00000001
+#define VIDC_1080P_COMMON_CHX_RG6_I_FRAME_SHIFT 0
+#define VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_BMASK 0x00000008
+#define VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_SHIFT 3
+#define VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_BMASK 0x00000010
+#define VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_SHIFT 4
+#define VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_BMASK 0x00000020
+#define VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_SHIFT 5
+#define VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_BMASK 0x00000040
+#define VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_SHIFT 6
+
u8 *VIDC_BASE_PTR;
void vidc_1080p_do_sw_reset(enum vidc_1080p_reset init_flag)
@@ -787,7 +798,9 @@
void vidc_1080p_encode_frame_start_ch0(
struct vidc_1080p_enc_frame_start_param *param)
{
- u32 input_flush;
+ u32 input_flush = 0;
+ u32 frame_insertion = 0;
+
VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
VIDC_HWIO_OUT(REG_666957, VIDC_1080P_INIT_CH_INST_ID);
VIDC_HWIO_OUT(REG_117192,
@@ -798,7 +811,22 @@
VIDC_1080P_BASE_OFFSET_SHIFT);
VIDC_HWIO_OUT(REG_175608, param->current_c_addr_offset >>
VIDC_1080P_BASE_OFFSET_SHIFT);
- VIDC_HWIO_OUT(REG_190381, param->intra_frame);
+ frame_insertion = VIDC_SETFIELD(param->intra_frame,
+ VIDC_1080P_COMMON_CHX_RG6_I_FRAME_SHIFT,
+ VIDC_1080P_COMMON_CHX_RG6_I_FRAME_BMASK);
+ frame_insertion |= VIDC_SETFIELD(param->store_ltr0,
+ VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_SHIFT,
+ VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_BMASK);
+ frame_insertion |= VIDC_SETFIELD(param->store_ltr1,
+ VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_SHIFT,
+ VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_BMASK);
+ frame_insertion |= VIDC_SETFIELD(param->use_ltr0,
+ VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_SHIFT,
+ VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_BMASK);
+ frame_insertion |= VIDC_SETFIELD(param->use_ltr1,
+ VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_SHIFT,
+ VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_BMASK);
+ VIDC_HWIO_OUT(REG_190381, frame_insertion);
VIDC_HWIO_OUT(REG_889944, param->shared_mem_addr_offset);
input_flush = VIDC_SETFIELD(param->input_flush,
VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
@@ -816,7 +844,9 @@
void vidc_1080p_encode_frame_start_ch1(
struct vidc_1080p_enc_frame_start_param *param)
{
- u32 input_flush;
+ u32 input_flush = 0;
+ u32 frame_insertion = 0;
+
VIDC_HWIO_OUT(REG_695082, VIDC_1080P_RISC2HOST_CMD_EMPTY);
VIDC_HWIO_OUT(REG_313350, VIDC_1080P_INIT_CH_INST_ID);
VIDC_HWIO_OUT(REG_980194,
@@ -827,7 +857,22 @@
VIDC_1080P_BASE_OFFSET_SHIFT);
VIDC_HWIO_OUT(REG_548308, param->current_c_addr_offset >>
VIDC_1080P_BASE_OFFSET_SHIFT);
- VIDC_HWIO_OUT(REG_887095, param->intra_frame);
+ frame_insertion = VIDC_SETFIELD(param->intra_frame,
+ VIDC_1080P_COMMON_CHX_RG6_I_FRAME_SHIFT,
+ VIDC_1080P_COMMON_CHX_RG6_I_FRAME_BMASK);
+ frame_insertion |= VIDC_SETFIELD(param->store_ltr0,
+ VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_SHIFT,
+ VIDC_1080P_COMMON_CHX_RG6_STORE_LTR0_BMASK);
+ frame_insertion |= VIDC_SETFIELD(param->store_ltr1,
+ VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_SHIFT,
+ VIDC_1080P_COMMON_CHX_RG6_STORE_LTR1_BMASK);
+ frame_insertion |= VIDC_SETFIELD(param->use_ltr0,
+ VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_SHIFT,
+ VIDC_1080P_COMMON_CHX_RG6_USE_LTR0_BMASK);
+ frame_insertion |= VIDC_SETFIELD(param->use_ltr1,
+ VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_SHIFT,
+ VIDC_1080P_COMMON_CHX_RG6_USE_LTR1_BMASK);
+ VIDC_HWIO_OUT(REG_887095, frame_insertion);
VIDC_HWIO_OUT(REG_652528, param->shared_mem_addr_offset);
input_flush = VIDC_SETFIELD(param->input_flush,
VIDC_1080P_SI_RG10_ENCODE_INPUT_BUFFER_FLUSH_SHFT,
diff --git a/drivers/video/msm/vidc/1080p/ddl/vidc.h b/drivers/video/msm/vidc/1080p/ddl/vidc.h
index 117612b..be4c35b 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vidc.h
+++ b/drivers/video/msm/vidc/1080p/ddl/vidc.h
@@ -400,6 +400,10 @@
u32 intra_frame;
u32 input_flush;
u32 slice_enable;
+ u32 store_ltr0;
+ u32 store_ltr1;
+ u32 use_ltr0;
+ u32 use_ltr1;
enum vidc_1080p_encode encode;
};
struct vidc_1080p_enc_frame_info{
diff --git a/drivers/video/msm/vidc/common/enc/venc.c b/drivers/video/msm/vidc/common/enc/venc.c
index 763fbda..c05e568 100644
--- a/drivers/video/msm/vidc/common/enc/venc.c
+++ b/drivers/video/msm/vidc/common/enc/venc.c
@@ -218,15 +218,15 @@
switch (event) {
case VCD_EVT_RESP_OUTPUT_DONE:
- DBG("Send INPUT_DON message to client = %p\n",
+ DBG("Send OUTPUT_DON message to client = %p\n",
client_ctx);
break;
case VCD_EVT_RESP_OUTPUT_FLUSHED:
- DBG("Send INPUT_FLUSHED message to client = %p\n",
+ DBG("Send OUTPUT_FLUSHED message to client = %p\n",
client_ctx);
break;
default:
- ERR("QVD: vid_enc_output_frame_done invalid cmd type: %d\n", event);
+ ERR("vid_enc_output_frame_done: invalid cmd type: %d\n", event);
venc_msg->venc_msg_info.statuscode = VEN_S_EFATAL;
break;
}
@@ -336,6 +336,12 @@
venc_msg->venc_msg_info.msgcode =
VEN_MSG_PAUSE;
break;
+ case VCD_EVT_IND_INFO_LTRUSE_FAILED:
+ INFO("\n msm_vidc_enc: Sending VEN_MSG_LTRUSE_FAILED"\
+ " to client");
+ venc_msg->venc_msg_info.msgcode =
+ VEN_MSG_LTRUSE_FAILED;
+ break;
default:
ERR("%s() : unknown event type %u\n",
@@ -394,6 +400,7 @@
case VCD_EVT_IND_OUTPUT_RECONFIG:
case VCD_EVT_IND_HWERRFATAL:
case VCD_EVT_IND_RESOURCES_LOST:
+ case VCD_EVT_IND_INFO_LTRUSE_FAILED:
vid_enc_lean_event(client_ctx, event, status);
break;
@@ -790,17 +797,18 @@
struct venc_buffer enc_buffer;
if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
return -EFAULT;
- DBG("VEN_IOCTL_CMD_ENCODE_FRAME"
- "/VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER\n");
if (copy_from_user(&enc_buffer, venc_msg.in,
sizeof(enc_buffer)))
return -EFAULT;
- if (cmd == VEN_IOCTL_CMD_ENCODE_FRAME)
+ if (cmd == VEN_IOCTL_CMD_ENCODE_FRAME) {
+ DBG("VEN_IOCTL_CMD_ENCODE_FRAME\n");
result = vid_enc_encode_frame(client_ctx,
&enc_buffer);
- else
+ } else {
+ DBG("VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER\n");
result = vid_enc_fill_output_buffer(client_ctx,
&enc_buffer);
+ }
if (!result) {
DBG("\n VEN_IOCTL_CMD_ENCODE_FRAME/"
"VEN_IOCTL_CMD_FILL_OUTPUT_BUFFER failed");
@@ -866,19 +874,19 @@
if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
return -EFAULT;
- DBG("VEN_IOCTL_SET_INPUT_BUFFER_REQ"
- "/VEN_IOCTL_SET_OUTPUT_BUFFER_REQ\n");
-
if (copy_from_user(&allocatorproperty, venc_msg.in,
sizeof(allocatorproperty)))
return -EFAULT;
- if (cmd == VEN_IOCTL_SET_OUTPUT_BUFFER_REQ)
- result = vid_enc_set_buffer_req(client_ctx,
- &allocatorproperty, false);
- else
+ if (cmd == VEN_IOCTL_SET_OUTPUT_BUFFER_REQ) {
+ DBG("VEN_IOCTL_SET_OUTPUT_BUFFER_REQ\n");
+ result = vid_enc_set_buffer_req(client_ctx,
+ &allocatorproperty, false);
+ } else {
+ DBG("VEN_IOCTL_SET_INPUT_BUFFER_REQ\n");
result = vid_enc_set_buffer_req(client_ctx,
&allocatorproperty, true);
+ }
if (!result) {
DBG("setting VEN_IOCTL_SET_OUTPUT_BUFFER_REQ/"
"VEN_IOCTL_SET_INPUT_BUFFER_REQ failed\n");
@@ -893,15 +901,15 @@
if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
return -EFAULT;
- DBG("VEN_IOCTL_GET_INPUT_BUFFER_REQ/"
- "VEN_IOCTL_GET_OUTPUT_BUFFER_REQ\n");
-
- if (cmd == VEN_IOCTL_GET_OUTPUT_BUFFER_REQ)
+ if (cmd == VEN_IOCTL_GET_OUTPUT_BUFFER_REQ) {
+ DBG("VEN_IOCTL_GET_OUTPUT_BUFFER_REQ\n");
result = vid_enc_get_buffer_req(client_ctx,
&allocatorproperty, false);
- else
+ } else {
+ DBG("VEN_IOCTL_GET_INPUT_BUFFER_REQ\n");
result = vid_enc_get_buffer_req(client_ctx,
&allocatorproperty, true);
+ }
if (!result)
return -EIO;
if (copy_to_user(venc_msg.out, &allocatorproperty,
@@ -1342,6 +1350,7 @@
}
case VEN_IOCTL_CMD_REQUEST_IFRAME:
{
+ DBG("VEN_IOCTL_CMD_REQUEST_IFRAME\n");
result = vid_enc_request_iframe(client_ctx);
if (!result) {
ERR("setting VEN_IOCTL_CMD_REQUEST_IFRAME failed\n");
@@ -1565,6 +1574,7 @@
struct vcd_property_hdr vcd_property_hdr;
struct vcd_property_live live_mode;
+ DBG("VEN_IOCTL_SET_METABUFFER_MODE\n");
if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
return -EFAULT;
if (copy_from_user(&metabuffer_mode, venc_msg.in,
@@ -1614,6 +1624,7 @@
struct vcd_property_hdr vcd_property_hdr;
u32 vcd_status = VCD_ERR_FAIL;
u32 enable = true;
+ DBG("VEN_IOCTL_SET_SLICE_DELIVERY_MODE\n");
vcd_property_hdr.prop_id = VCD_I_SLICE_DELIVERY_MODE;
vcd_property_hdr.sz = sizeof(u32);
vcd_status = vcd_set_property(client_ctx->vcd_handle,
@@ -1647,6 +1658,143 @@
}
break;
}
+ case VEN_IOCTL_SET_LTRMODE:
+ case VEN_IOCTL_GET_LTRMODE:
+ {
+ struct venc_ltrmode encoder_ltrmode;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ if (cmd == VEN_IOCTL_SET_LTRMODE) {
+ DBG("VEN_IOCTL_SET_LTRMODE\n");
+ if (copy_from_user(&encoder_ltrmode, venc_msg.in,
+ sizeof(encoder_ltrmode)))
+ return -EFAULT;
+ result = vid_enc_set_get_ltrmode(client_ctx,
+ &encoder_ltrmode, true);
+ } else {
+ DBG("VEN_IOCTL_GET_LTRMODE\n");
+ result = vid_enc_set_get_ltrmode(client_ctx,
+ &encoder_ltrmode, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &encoder_ltrmode,
+ sizeof(encoder_ltrmode)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("VEN_IOCTL_(G)SET_LTRMODE failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_LTRCOUNT:
+ case VEN_IOCTL_GET_LTRCOUNT:
+ {
+ struct venc_ltrcount encoder_ltrcount;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ if (cmd == VEN_IOCTL_SET_LTRCOUNT) {
+ DBG("VEN_IOCTL_SET_LTRCOUNT\n");
+ if (copy_from_user(&encoder_ltrcount, venc_msg.in,
+ sizeof(encoder_ltrcount)))
+ return -EFAULT;
+ result = vid_enc_set_get_ltrcount(client_ctx,
+ &encoder_ltrcount, true);
+ } else {
+ DBG("VEN_IOCTL_GET_LTRCOUNT\n");
+ result = vid_enc_set_get_ltrcount(client_ctx,
+ &encoder_ltrcount, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out,
+ &encoder_ltrcount,
+ sizeof(encoder_ltrcount)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("VEN_IOCTL_(G)SET_LTRCOUNT failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_LTRPERIOD:
+ case VEN_IOCTL_GET_LTRPERIOD:
+ {
+ struct venc_ltrperiod encoder_ltrperiod;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ if (cmd == VEN_IOCTL_SET_LTRPERIOD) {
+ DBG("VEN_IOCTL_SET_LTRPERIOD\n");
+ if (copy_from_user(&encoder_ltrperiod, venc_msg.in,
+ sizeof(encoder_ltrperiod)))
+ return -EFAULT;
+ result = vid_enc_set_get_ltrperiod(client_ctx,
+ &encoder_ltrperiod, true);
+ } else {
+ DBG("VEN_IOCTL_GET_LTRPERIOD\n");
+ result = vid_enc_set_get_ltrperiod(client_ctx,
+ &encoder_ltrperiod, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out,
+ &encoder_ltrperiod,
+ sizeof(encoder_ltrperiod)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("VEN_IOCTL_(G)SET_LTRPERIOD failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_GET_CAPABILITY_LTRCOUNT:
+ {
+ struct venc_range venc_capltrcount;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ DBG("VEN_IOCTL_GET_CAPABILITY_LTRCOUNT\n");
+ result = vid_enc_get_capability_ltrcount(client_ctx,
+ &venc_capltrcount);
+ if (result) {
+ if (copy_to_user(venc_msg.out, &venc_capltrcount,
+ sizeof(venc_capltrcount)))
+ return -EFAULT;
+ } else {
+ ERR("VEN_IOCTL_GET_CAPABILITY_LTRCOUNT failed\n");
+ return -EIO;
+ }
+ break;
+ }
+ case VEN_IOCTL_SET_LTRUSE:
+ case VEN_IOCTL_GET_LTRUSE:
+ {
+ struct venc_ltruse encoder_ltruse;
+ if (copy_from_user(&venc_msg, arg, sizeof(venc_msg)))
+ return -EFAULT;
+ if (cmd == VEN_IOCTL_SET_LTRUSE) {
+ DBG("VEN_IOCTL_SET_LTRUSE\n");
+ if (copy_from_user(&encoder_ltruse, venc_msg.in,
+ sizeof(encoder_ltruse)))
+ return -EFAULT;
+ result = vid_enc_set_get_ltruse(client_ctx,
+ &encoder_ltruse, true);
+ } else {
+ DBG("VEN_IOCTL_GET_LTRUSE\n");
+ result = vid_enc_set_get_ltruse(client_ctx,
+ &encoder_ltruse, false);
+ if (result) {
+ if (copy_to_user(venc_msg.out,
+ &encoder_ltruse,
+ sizeof(encoder_ltruse)))
+ return -EFAULT;
+ }
+ }
+ if (!result) {
+ ERR("VEN_IOCTL_(G)SET_LTRUSE failed\n");
+ return -EIO;
+ }
+ break;
+ }
case VEN_IOCTL_SET_AC_PREDICTION:
case VEN_IOCTL_GET_AC_PREDICTION:
case VEN_IOCTL_SET_RVLC:
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.c b/drivers/video/msm/vidc/common/enc/venc_internal.c
index 8779432..7a26d2e 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.c
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.c
@@ -328,6 +328,42 @@
vcd_property_hdr.prop_id = VCD_I_METADATA_ENABLE;
vcd_property_hdr.sz = sizeof(struct vcd_property_meta_data_enable);
if (set_flag) {
+ DBG("vcd_set_property: VCD_I_METADATA_ENABLE = %x\n",
+ (u32)*extradata_flag);
+ vcd_meta_data.meta_data_enable_flag = *extradata_flag;
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_meta_data);
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_METADATA_ENABLE Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_meta_data);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_METADATA_ENABLE Failed\n",
+ __func__);
+ return false;
+ }
+ *extradata_flag = vcd_meta_data.meta_data_enable_flag;
+ DBG("vcd_get_property: VCD_I_METADATA_ENABLE = 0x%x\n",
+ (u32)*extradata_flag);
+ }
+ return true;
+}
+
+u32 vid_enc_set_get_extradata_cfg(struct video_client_ctx *client_ctx,
+ u32 *extradata_flag, u32 set_flag)
+{
+ struct vcd_property_hdr vcd_property_hdr;
+ struct vcd_property_meta_data_enable vcd_meta_data;
+ u32 vcd_status = VCD_ERR_FAIL;
+ if (!client_ctx || !extradata_flag)
+ return false;
+ vcd_property_hdr.prop_id = VCD_I_METADATA_ENABLE;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_meta_data_enable);
+ if (set_flag) {
DBG("vcd_set_property: VCD_I_METADATA_ENABLE = %d\n",
*extradata_flag);
vcd_meta_data.meta_data_enable_flag = *extradata_flag;
@@ -1995,3 +2031,215 @@
return false;
}
}
+
+u32 vid_enc_set_get_ltrmode(struct video_client_ctx *client_ctx,
+ struct venc_ltrmode *venc_ltrmode, u32 set_flag)
+{
+ struct vcd_property_ltrmode_type vcd_property_ltrmode;
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !venc_ltrmode)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_LTR_MODE;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_ltrmode_type);
+
+ if (set_flag) {
+ vcd_property_ltrmode.ltr_mode = (enum vcd_property_ltrmode)
+ venc_ltrmode->ltr_mode;
+ DBG("%s: Set ltr_mode = %u", __func__,
+ (u32)vcd_property_ltrmode.ltr_mode);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_ltrmode);
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_LTR_MODE Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_ltrmode);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_LTR_MODE Failed\n",
+ __func__);
+ return false;
+ } else {
+ venc_ltrmode->ltr_mode = (unsigned long)
+ vcd_property_ltrmode.ltr_mode;
+ DBG("%s: Got ltr_mode = %u", __func__,
+ (u32)vcd_property_ltrmode.ltr_mode);
+ }
+ }
+
+ return true;
+}
+
+u32 vid_enc_set_get_ltrcount(struct video_client_ctx *client_ctx,
+ struct venc_ltrcount *venc_ltrcount, u32 set_flag)
+{
+ struct vcd_property_ltrcount_type vcd_property_ltrcount;
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !venc_ltrcount)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_LTR_COUNT;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_ltrcount_type);
+
+ if (set_flag) {
+ vcd_property_ltrcount.ltr_count = (u32)
+ venc_ltrcount->ltr_count;
+ DBG("%s: Set ltr_count = %u", __func__,
+ (u32)vcd_property_ltrcount.ltr_count);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_ltrcount);
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_LTR_COUNT Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_ltrcount);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_LTR_COUNT Failed\n",
+ __func__);
+ return false;
+ } else {
+ venc_ltrcount->ltr_count = (unsigned long)
+ vcd_property_ltrcount.ltr_count;
+ DBG("%s: Got ltr_count = %u", __func__,
+ (u32)vcd_property_ltrcount.ltr_count);
+ }
+ }
+
+ return true;
+}
+
+u32 vid_enc_set_get_ltrperiod(struct video_client_ctx *client_ctx,
+ struct venc_ltrperiod *venc_ltrperiod, u32 set_flag)
+{
+ struct vcd_property_ltrperiod_type vcd_property_ltrperiod;
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !venc_ltrperiod)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_LTR_PERIOD;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_ltrperiod_type);
+
+ if (set_flag) {
+ vcd_property_ltrperiod.ltr_period = (u32)
+ venc_ltrperiod->ltr_period;
+ DBG("%s: Set ltr_period = %u", __func__,
+ (u32)vcd_property_ltrperiod.ltr_period);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_ltrperiod);
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_LTR_PERIOD Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_ltrperiod);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_LTR_PERIOD Failed\n",
+ __func__);
+ return false;
+ } else {
+ venc_ltrperiod->ltr_period = (unsigned long)
+ vcd_property_ltrperiod.ltr_period;
+ DBG("%s: Got ltr_period = %u", __func__,
+ (u32)vcd_property_ltrperiod.ltr_period);
+ }
+ }
+
+ return true;
+}
+
+u32 vid_enc_set_get_ltruse(struct video_client_ctx *client_ctx,
+ struct venc_ltruse *venc_ltruse, u32 set_flag)
+{
+ struct vcd_property_ltruse_type vcd_property_ltruse;
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !venc_ltruse)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_LTR_USE;
+ vcd_property_hdr.sz =
+ sizeof(struct vcd_property_ltruse_type);
+
+ if (set_flag) {
+ vcd_property_ltruse.ltr_id = (u32)
+ venc_ltruse->ltr_id;
+ vcd_property_ltruse.ltr_frames = (u32)
+ venc_ltruse->ltr_frames;
+ DBG("%s: Set ltr_id = %u, ltr_frames = %u",
+ __func__, vcd_property_ltruse.ltr_id,
+ vcd_property_ltruse.ltr_frames);
+ vcd_status = vcd_set_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_ltruse);
+ if (vcd_status) {
+ ERR("%s(): Set VCD_I_LTR_USE Failed\n",
+ __func__);
+ return false;
+ }
+ } else {
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_ltruse);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_LTR_USE Failed\n",
+ __func__);
+ return false;
+ } else {
+ venc_ltruse->ltr_id = (unsigned long)
+ vcd_property_ltruse.ltr_id;
+ venc_ltruse->ltr_frames = (unsigned long)
+ vcd_property_ltruse.ltr_frames;
+ DBG("%s: Got ltr_id = %u, ltr_frames = %u",
+ __func__, vcd_property_ltruse.ltr_id,
+ vcd_property_ltruse.ltr_frames);
+ }
+ }
+
+ return true;
+}
+
+u32 vid_enc_get_capability_ltrcount(struct video_client_ctx *client_ctx,
+ struct venc_range *venc_capltrcount)
+{
+ struct vcd_property_range_type vcd_property_range;
+ struct vcd_property_hdr vcd_property_hdr;
+ u32 vcd_status = VCD_ERR_FAIL;
+
+ if (!client_ctx || !venc_capltrcount)
+ return false;
+
+ vcd_property_hdr.prop_id = VCD_I_CAPABILITY_LTR_COUNT;
+ vcd_property_hdr.sz = sizeof(struct vcd_property_range_type);
+ vcd_status = vcd_get_property(client_ctx->vcd_handle,
+ &vcd_property_hdr, &vcd_property_range);
+ if (vcd_status) {
+ ERR("%s(): Get VCD_I_CAPABILITY_LTR_COUNT Failed\n",
+ __func__);
+ return false;
+ } else {
+ venc_capltrcount->min = vcd_property_range.min;
+ venc_capltrcount->max = vcd_property_range.max;
+ venc_capltrcount->step_size = vcd_property_range.step_size;
+ DBG("%s: Got min: %lu, max: %lu, step_size: %lu", __func__,
+ venc_capltrcount->min, venc_capltrcount->max,
+ venc_capltrcount->step_size);
+ }
+
+ return true;
+}
diff --git a/drivers/video/msm/vidc/common/enc/venc_internal.h b/drivers/video/msm/vidc/common/enc/venc_internal.h
index 8a07fdb..17cefbb 100644
--- a/drivers/video/msm/vidc/common/enc/venc_internal.h
+++ b/drivers/video/msm/vidc/common/enc/venc_internal.h
@@ -151,4 +151,19 @@
u32 vid_enc_get_recon_buffer_size(struct video_client_ctx *client_ctx,
struct venc_recon_buff_size *venc_recon_size);
+u32 vid_enc_set_get_ltrmode(struct video_client_ctx *client_ctx,
+ struct venc_ltrmode *encoder_ltrmode, u32 set_flag);
+
+u32 vid_enc_set_get_ltrcount(struct video_client_ctx *client_ctx,
+ struct venc_ltrcount *encoder_ltrcount, u32 set_flag);
+
+u32 vid_enc_set_get_ltrperiod(struct video_client_ctx *client_ctx,
+ struct venc_ltrperiod *encoder_ltrperiod, u32 set_flag);
+
+u32 vid_enc_get_capability_ltrcount(struct video_client_ctx *client_ctx,
+ struct venc_range *venc_capltrcount);
+
+u32 vid_enc_set_get_ltruse(struct video_client_ctx *client_ctx,
+ struct venc_ltruse *encoder_ltruse, u32 set_flag);
+
#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd.h b/drivers/video/msm/vidc/common/vcd/vcd.h
index a22adeb..5b2450e 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd.h
+++ b/drivers/video/msm/vidc/common/vcd/vcd.h
@@ -402,4 +402,7 @@
struct vcd_transc *vcd_get_first_in_use_trans_for_clnt(
struct vcd_clnt_ctxt *cctxt);
+u32 vcd_handle_ltr_use_failed(struct vcd_clnt_ctxt *cctxt,
+ void *payload, size_t sz, u32 status);
+
#endif
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
index 8f52f83..983923b 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_client_sm.c
@@ -964,6 +964,12 @@
vcd_handle_ind_info_output_reconfig(cctxt, status);
break;
}
+ case VCD_EVT_IND_INFO_LTRUSE_FAILED:
+ {
+ rc = vcd_handle_ltr_use_failed(cctxt,
+ payload, sz, status);
+ break;
+ }
default:
{
VCD_MSG_ERROR
diff --git a/drivers/video/msm/vidc/common/vcd/vcd_sub.c b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
index a4c44f3..78d77d1 100644
--- a/drivers/video/msm/vidc/common/vcd/vcd_sub.c
+++ b/drivers/video/msm/vidc/common/vcd/vcd_sub.c
@@ -3516,3 +3516,14 @@
}
return rc;
}
+
+u32 vcd_handle_ltr_use_failed(struct vcd_clnt_ctxt *cctxt,
+ void *payload, size_t sz, u32 status)
+{
+ u32 rc = VCD_S_SUCCESS;
+ if (payload && cctxt) {
+ cctxt->callback(VCD_EVT_IND_INFO_LTRUSE_FAILED,
+ status, payload, sz, cctxt, cctxt->client_data);
+ }
+ return rc;
+}
diff --git a/include/linux/mmc/card.h b/include/linux/mmc/card.h
index d2f8faf..3e5c8cb 100644
--- a/include/linux/mmc/card.h
+++ b/include/linux/mmc/card.h
@@ -270,14 +270,11 @@
* should be cancelled
* @started_delayed_bkops: A flag to indicate if the delayed
* work was scheduled
- * @sectors_changed: number of sectors written or
- * discard since the last idle BKOPS were scheduled
*/
struct mmc_bkops_info {
struct delayed_work dw;
unsigned int host_suspend_tout_ms;
unsigned int delay_ms;
- unsigned int min_sectors_to_queue_delayed_work;
struct mmc_bkops_stats bkops_stats; /* BKOPS statistics */
/*
* A default time for checking the need for non urgent BKOPS once mmcqd
@@ -290,16 +287,6 @@
#define BKOPS_COMPLETION_POLLING_INTERVAL_MS 1000 /* in ms */
bool cancel_delayed_work;
bool started_delayed_bkops;
- unsigned int sectors_changed;
-/*
- * Since canceling the delayed work might have significant effect on the
- * performance of small requests we won't queue the delayed work every time
- * mmcqd thread is idle.
- * The delayed work for idle BKOPS will be scheduled only after a significant
- * amount of write or discard data.
- * 100MB is chosen based on benchmark tests.
- */
-#define BKOPS_MIN_SECTORS_TO_QUEUE_DELAYED_WORK 204800 /* 100MB */
};
/**
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index d3f6792..abd4f3a 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -72,6 +72,9 @@
#define MSMFB_VSYNC_CTRL _IOW(MSMFB_IOCTL_MAGIC, 161, unsigned int)
#define MSMFB_METADATA_SET _IOW(MSMFB_IOCTL_MAGIC, 162, struct msmfb_metadata)
#define MSMFB_OVERLAY_COMMIT _IO(MSMFB_IOCTL_MAGIC, 163)
+#define MSMFB_BUFFER_SYNC _IOW(MSMFB_IOCTL_MAGIC, 164, struct mdp_buf_sync)
+#define MSMFB_DISPLAY_COMMIT _IOW(MSMFB_IOCTL_MAGIC, 165, \
+ struct mdp_display_commit)
#define FB_TYPE_3D_PANEL 0x10101010
#define MDP_IMGTYPE2_START 0x10000
@@ -551,6 +554,25 @@
struct mdp_blend_cfg blend_cfg;
} data;
};
+
+#define MDP_MAX_FENCE_FD 10
+#define MDP_BUF_SYNC_FLAG_WAIT 1
+
+struct mdp_buf_sync {
+ uint32_t flags;
+ uint32_t acq_fen_fd_cnt;
+ int *acq_fen_fd;
+ int *rel_fen_fd;
+};
+
+#define MDP_DISPLAY_COMMIT_OVERLAY 1
+
+struct mdp_display_commit {
+ uint32_t flags;
+ uint32_t wait_for_finish;
+ struct fb_var_screeninfo var;
+};
+
struct mdp_page_protection {
uint32_t page_protection;
};
diff --git a/include/linux/msm_vidc_enc.h b/include/linux/msm_vidc_enc.h
index ea7db81..dde126c 100644
--- a/include/linux/msm_vidc_enc.h
+++ b/include/linux/msm_vidc_enc.h
@@ -44,6 +44,8 @@
#define VEN_MSG_PAUSE 8
#define VEN_MSG_RESUME 9
#define VEN_MSG_STOP_READING_MSG 10
+#define VEN_MSG_LTRUSE_FAILED 11
+
/*Buffer flags bits masks*/
#define VEN_BUFFLAG_EOS 0x00000001
@@ -56,6 +58,7 @@
#define VEN_EXTRADATA_NONE 0x001
#define VEN_EXTRADATA_QCOMFILLER 0x002
#define VEN_EXTRADATA_SLICEINFO 0x100
+#define VEN_EXTRADATA_LTRINFO 0x200
/*ENCODER CONFIGURATION CONSTANTS*/
@@ -461,6 +464,55 @@
#define VEN_IOCTL_SET_H263_PLUSPTYPE \
_IOW(VEN_IOCTLBASE_ENC, 51, struct venc_ioctl_msg)
+/*IOCTL params:SET: InputData - venc_range, OutputData - NULL.*/
+#define VEN_IOCTL_SET_CAPABILITY_LTRCOUNT \
+ _IOW(VEN_IOCTLBASE_ENC, 52, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_range.*/
+#define VEN_IOCTL_GET_CAPABILITY_LTRCOUNT \
+ _IOR(VEN_IOCTLBASE_ENC, 53, struct venc_ioctl_msg)
+
+/*IOCTL params:SET: InputData - venc_ltrmode, OutputData - NULL.*/
+#define VEN_IOCTL_SET_LTRMODE \
+ _IOW(VEN_IOCTLBASE_ENC, 54, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_ltrmode.*/
+#define VEN_IOCTL_GET_LTRMODE \
+ _IOR(VEN_IOCTLBASE_ENC, 55, struct venc_ioctl_msg)
+
+/*IOCTL params:SET: InputData - venc_ltrcount, OutputData - NULL.*/
+#define VEN_IOCTL_SET_LTRCOUNT \
+ _IOW(VEN_IOCTLBASE_ENC, 56, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_ltrcount.*/
+#define VEN_IOCTL_GET_LTRCOUNT \
+ _IOR(VEN_IOCTLBASE_ENC, 57, struct venc_ioctl_msg)
+
+/*IOCTL params:SET: InputData - venc_ltrperiod, OutputData - NULL.*/
+#define VEN_IOCTL_SET_LTRPERIOD \
+ _IOW(VEN_IOCTLBASE_ENC, 58, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_ltrperiod.*/
+#define VEN_IOCTL_GET_LTRPERIOD \
+ _IOR(VEN_IOCTLBASE_ENC, 59, struct venc_ioctl_msg)
+
+/*IOCTL params:SET: InputData - venc_ltruse, OutputData - NULL.*/
+#define VEN_IOCTL_SET_LTRUSE \
+ _IOW(VEN_IOCTLBASE_ENC, 60, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_ltruse.*/
+#define VEN_IOCTL_GET_LTRUSE \
+ _IOR(VEN_IOCTLBASE_ENC, 61, struct venc_ioctl_msg)
+
+/*IOCTL params:SET: InputData - venc_ltrmark, OutputData - NULL.*/
+#define VEN_IOCTL_SET_LTRMARK \
+ _IOW(VEN_IOCTLBASE_ENC, 62, struct venc_ioctl_msg)
+/*IOCTL params:GET: InputData - NULL, OutputData - venc_ltrmark.*/
+#define VEN_IOCTL_GET_LTRMARK \
+ _IOR(VEN_IOCTLBASE_ENC, 63, struct venc_ioctl_msg)
+
+
+struct venc_range {
+ unsigned long max;
+ unsigned long min;
+ unsigned long step_size;
+};
+
struct venc_switch{
unsigned char status;
};
@@ -622,4 +674,21 @@
int alignment;
};
+struct venc_ltrmode {
+ unsigned long ltr_mode;
+};
+
+struct venc_ltrcount {
+ unsigned long ltr_count;
+};
+
+struct venc_ltrperiod {
+ unsigned long ltr_period;
+};
+
+struct venc_ltruse {
+ unsigned long ltr_id;
+ unsigned long ltr_frames;
+};
+
#endif /* _MSM_VIDC_ENC_H_ */
diff --git a/include/media/msm/vcd_property.h b/include/media/msm/vcd_property.h
index 2ce1a88..ed9bffb 100644
--- a/include/media/msm/vcd_property.h
+++ b/include/media/msm/vcd_property.h
@@ -58,7 +58,12 @@
#define VCD_I_ENABLE_DELIMITER_FLAG (VCD_START_BASE + 0x2A)
#define VCD_I_ENABLE_VUI_TIMING_INFO (VCD_START_BASE + 0x2B)
#define VCD_I_H263_PLUSPTYPE (VCD_START_BASE + 0x2C)
-
+#define VCD_I_LTR_MODE (VCD_START_BASE + 0x2D)
+#define VCD_I_LTR_COUNT (VCD_START_BASE + 0x2E)
+#define VCD_I_LTR_PERIOD (VCD_START_BASE + 0x2F)
+#define VCD_I_LTR_USE (VCD_START_BASE + 0x30)
+#define VCD_I_CAPABILITY_LTR_COUNT (VCD_START_BASE + 0x31)
+#define VCD_I_LTR_MARK (VCD_START_BASE + 0x32)
#define VCD_START_REQ (VCD_START_BASE + 0x1000)
#define VCD_I_REQ_IFRAME (VCD_START_REQ + 0x1)
@@ -116,10 +121,11 @@
#define VCD_METADATA_VC1 0x040
#define VCD_METADATA_PASSTHROUGH 0x080
#define VCD_METADATA_ENC_SLICE 0x100
-
+#define VCD_METADATA_LTR_INFO 0x200
#define VCD_METADATA_EXT_DATA 0x0800
#define VCD_METADATA_USER_DATA 0x1000
+
struct vcd_property_meta_data_enable {
u32 meta_data_enable_flag;
};
@@ -389,4 +395,34 @@
u32 vui_timing_info;
};
+struct vcd_property_range_type {
+ u32 min;
+ u32 max;
+ u32 step_size;
+};
+
+enum vcd_property_ltrmode {
+ VCD_LTR_MODE_DISABLE = 0,
+ VCD_LTR_MODE_MANUAL = 1,
+ VCD_LTR_MODE_AUTO = 2,
+ VCD_LTR_MODE_MAX = 0x7fffffff
+};
+
+struct vcd_property_ltrmode_type {
+ enum vcd_property_ltrmode ltr_mode;
+};
+
+struct vcd_property_ltrcount_type {
+ u32 ltr_count;
+};
+
+struct vcd_property_ltrperiod_type {
+ u32 ltr_period;
+};
+
+struct vcd_property_ltruse_type {
+ u32 ltr_id;
+ u32 ltr_frames;
+};
+
#endif
diff --git a/include/media/msm/vcd_status.h b/include/media/msm/vcd_status.h
index 7e8ec0b..631501d 100644
--- a/include/media/msm/vcd_status.h
+++ b/include/media/msm/vcd_status.h
@@ -33,6 +33,7 @@
#define VCD_EVT_IND_RESOURCES_LOST (VCD_EVT_IND_BASE + 0x4)
#define VCD_EVT_IND_INFO_OUTPUT_RECONFIG (VCD_EVT_IND_BASE + 0x5)
#define VCD_EVT_IND_INFO_FIELD_DROPPED (VCD_EVT_IND_BASE + 0x6)
+#define VCD_EVT_IND_INFO_LTRUSE_FAILED (VCD_EVT_IND_BASE + 0x7)
#define VCD_S_SUCCESS 0x0
diff --git a/include/media/msm/vidc_type.h b/include/media/msm/vidc_type.h
index d4db0a0..809ec00 100644
--- a/include/media/msm/vidc_type.h
+++ b/include/media/msm/vidc_type.h
@@ -23,8 +23,9 @@
#include <linux/dma-mapping.h>
#include <linux/android_pmem.h>
-#define DEBUG 0
+#define DDL_MSG_LOG 0
+#define DEBUG 0
#define VIDC_ENABLE_DBGFS
-
#define USE_RES_TRACKER
+
#endif
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index 80f36e0..3a7cd5d 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -412,6 +412,11 @@
__le16 handle;
} __packed;
+#define HCI_OP_READ_CLOCK_OFFSET 0x041f
+struct hci_cp_read_clock_offset {
+ __le16 handle;
+} __packed;
+
#define HCI_OP_SETUP_SYNC_CONN 0x0428
struct hci_cp_setup_sync_conn {
__le16 handle;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 544f3bf..d55ec26 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -383,7 +383,7 @@
/* ----- Inquiry cache ----- */
#define INQUIRY_CACHE_AGE_MAX (HZ*30) /* 30 seconds */
-#define INQUIRY_ENTRY_AGE_MAX (HZ*60) /* 60 seconds */
+#define INQUIRY_ENTRY_AGE_MAX (HZ*60*60) /* 1 Hour */
#define inquiry_cache_lock(c) spin_lock(&c->lock)
#define inquiry_cache_unlock(c) spin_unlock(&c->lock)
diff --git a/mm/madvise.c b/mm/madvise.c
index 1ccbba5..55f645c 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -13,6 +13,7 @@
#include <linux/hugetlb.h>
#include <linux/sched.h>
#include <linux/ksm.h>
+#include <linux/file.h>
/*
* Any behaviour which results in changes to the vma->vm_flags needs to
@@ -203,14 +204,16 @@
struct address_space *mapping;
loff_t offset, endoff;
int error;
+ struct file *f;
*prev = NULL; /* tell sys_madvise we drop mmap_sem */
if (vma->vm_flags & (VM_LOCKED|VM_NONLINEAR|VM_HUGETLB))
return -EINVAL;
- if (!vma->vm_file || !vma->vm_file->f_mapping
- || !vma->vm_file->f_mapping->host) {
+ f = vma->vm_file;
+
+ if (!f || !f->f_mapping || !f->f_mapping->host) {
return -EINVAL;
}
@@ -224,9 +227,16 @@
endoff = (loff_t)(end - vma->vm_start - 1)
+ ((loff_t)vma->vm_pgoff << PAGE_SHIFT);
- /* vmtruncate_range needs to take i_mutex */
+ /*
+ * vmtruncate_range may need to take i_mutex. We need to
+ * explicitly grab a reference because the vma (and hence the
+ * vma's reference to the file) can go away as soon as we drop
+ * mmap_sem.
+ */
+ get_file(f);
up_read(¤t->mm->mmap_sem);
error = vmtruncate_range(mapping->host, offset, endoff);
+ fput(f);
down_read(¤t->mm->mmap_sem);
return error;
}
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 5ac5c52..f504921 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -56,9 +56,6 @@
#include "bnep.h"
#define VERSION "1.3"
-/* As this feature is dummy for BNEP net device
-** disabling support */
-#undef CONFIG_BT_BNEP_MC_FILTER
static bool compress_src = 1;
static bool compress_dst = 1;
diff --git a/net/bluetooth/bnep/netdev.c b/net/bluetooth/bnep/netdev.c
index a8e5449..155ff74 100644
--- a/net/bluetooth/bnep/netdev.c
+++ b/net/bluetooth/bnep/netdev.c
@@ -44,9 +44,6 @@
#include "bnep.h"
#define BNEP_TX_QUEUE_LEN 20
-/* As this feature is dummy for BNEP net device
-** disabling support */
-#undef CONFIG_BT_BNEP_MC_FILTER
static int bnep_net_open(struct net_device *dev)
{
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index ea116e9..3b59e4e 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -1669,6 +1669,8 @@
if (conn->type == ACL_LINK) {
struct hci_cp_read_remote_version cp;
cp.handle = ev->handle;
+ hci_send_cmd(hdev, HCI_OP_READ_CLOCK_OFFSET,
+ sizeof(cp), &cp);
hci_send_cmd(hdev, HCI_OP_READ_REMOTE_VERSION,
sizeof(cp), &cp);
}
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 3fc3f32..0d5771b 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -1919,7 +1919,7 @@
int mask)
{
/* XXX: wake_lock_timeout()? */
- snd_soc_jack_report(jack, status, mask);
+ snd_soc_jack_report_no_dapm(jack, status, mask);
}
static void hphocp_off_report(struct sitar_priv *sitar,
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 76623b1..73a39d5 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -37,6 +37,19 @@
#include "wcd9320.h"
#include "wcd9xxx-resmgr.h"
+static atomic_t kp_taiko_priv;
+static int spkr_drv_wrnd_param_set(const char *val,
+ const struct kernel_param *kp);
+static int spkr_drv_wrnd = 1;
+
+static struct kernel_param_ops spkr_drv_wrnd_param_ops = {
+ .set = spkr_drv_wrnd_param_set,
+ .get = param_get_int,
+};
+module_param_cb(spkr_drv_wrnd, &spkr_drv_wrnd_param_ops, &spkr_drv_wrnd, 0644);
+MODULE_PARM_DESC(spkr_drv_wrnd,
+ "Run software workaround to avoid leakage on the speaker drive");
+
#define WCD9320_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
@@ -212,6 +225,8 @@
u8 aux_l_gain;
u8 aux_r_gain;
+ bool spkr_pa_widget_on;
+
/* resmgr module */
struct wcd9xxx_resmgr resmgr;
/* mbhc module */
@@ -298,6 +313,45 @@
TAIKO_A_CDC_TX10_VOL_CTL_GAIN,
};
+static int spkr_drv_wrnd_param_set(const char *val,
+ const struct kernel_param *kp)
+{
+ struct snd_soc_codec *codec;
+ int ret, old;
+ struct taiko_priv *priv;
+
+ priv = (struct taiko_priv *)atomic_read(&kp_taiko_priv);
+ if (!priv) {
+ pr_debug("%s: codec isn't yet registered\n", __func__);
+ return 0;
+ }
+
+ WCD9XXX_BCL_LOCK(&priv->resmgr);
+ old = spkr_drv_wrnd;
+ ret = param_set_int(val, kp);
+ if (ret) {
+ WCD9XXX_BCL_UNLOCK(&priv->resmgr);
+ return ret;
+ }
+
+ pr_debug("%s: spkr_drv_wrnd %d -> %d\n", __func__, old, spkr_drv_wrnd);
+ codec = priv->codec;
+ if (old == 0 && spkr_drv_wrnd == 1) {
+ wcd9xxx_resmgr_get_bandgap(&priv->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
+ } else if (old == 1 && spkr_drv_wrnd == 0) {
+ wcd9xxx_resmgr_put_bandgap(&priv->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ if (!priv->spkr_pa_widget_on)
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
+ 0x00);
+ }
+
+ WCD9XXX_BCL_UNLOCK(&priv->resmgr);
+ return 0;
+}
+
static int taiko_codec_enable_class_h_clk(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -1876,7 +1930,22 @@
static int taiko_codec_enable_spk_pa(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- pr_debug("%s %d %s\n", __func__, event, w->name);
+ struct snd_soc_codec *codec = w->codec;
+ struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+
+ pr_debug("%s: %d %s\n", __func__, event, w->name);
+ WCD9XXX_BCL_LOCK(&taiko->resmgr);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ taiko->spkr_pa_widget_on = true;
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x80);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ taiko->spkr_pa_widget_on = false;
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80, 0x00);
+ break;
+ }
+ WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
return 0;
}
@@ -2288,6 +2357,42 @@
return ret;
}
+static int taiko_codec_enable_vdd_spkr(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ int ret = 0;
+ struct snd_soc_codec *codec = w->codec;
+ struct wcd9xxx *core = dev_get_drvdata(codec->dev->parent);
+
+ pr_debug("%s: %d %s\n", __func__, event, w->name);
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (spkr_drv_wrnd > 0) {
+ WARN_ON(!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
+ 0x80));
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
+ 0x00);
+ }
+ if (TAIKO_IS_1_0(core->version))
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_DBG_PWRSTG,
+ 0x24, 0x00);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (TAIKO_IS_1_0(core->version))
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_DBG_PWRSTG,
+ 0x24, 0x24);
+ if (spkr_drv_wrnd > 0) {
+ WARN_ON(!!(snd_soc_read(codec, TAIKO_A_SPKR_DRV_EN) &
+ 0x80));
+ snd_soc_update_bits(codec, TAIKO_A_SPKR_DRV_EN, 0x80,
+ 0x80);
+ }
+ break;
+ }
+
+ return ret;
+}
+
static int taiko_codec_enable_interpolator(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -2671,6 +2776,7 @@
{"SPK PA", NULL, "SPK DAC"},
{"SPK DAC", NULL, "RX7 MIX2"},
+ {"SPK DAC", NULL, "VDD_SPKDRV"},
{"RX1 CHAIN", NULL, "RX1 MIX2"},
{"RX2 CHAIN", NULL, "RX2 MIX2"},
@@ -3866,9 +3972,9 @@
SND_SOC_DAPM_PGA_E("LINEOUT4 PA", TAIKO_A_RX_LINE_CNP_EN, 3, 0, NULL,
0, taiko_codec_enable_lineout, SND_SOC_DAPM_PRE_PMU |
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_PGA_E("SPK PA", TAIKO_A_SPKR_DRV_EN, 7, 0 , NULL,
- 0, taiko_codec_enable_spk_pa, SND_SOC_DAPM_PRE_PMU |
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_PGA_E("SPK PA", SND_SOC_NOPM, 0, 0 , NULL,
+ 0, taiko_codec_enable_spk_pa,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_DAC_E("LINEOUT1 DAC", NULL, TAIKO_A_RX_LINE_1_DAC_CTL, 7, 0
, taiko_lineout_dac_event,
@@ -3891,6 +3997,10 @@
taiko_spk_dac_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("VDD_SPKDRV", SND_SOC_NOPM, 0, 0,
+ taiko_codec_enable_vdd_spkr,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
SND_SOC_DAPM_MIXER("RX1 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("RX2 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_MIXER("RX7 MIX1", SND_SOC_NOPM, 0, 0, NULL, 0),
@@ -4610,6 +4720,9 @@
TAIKO_REG_VAL(TAIKO_A_TX_SUP_SWITCH_CTRL_1, 0xBF),
/* Enable MICB 4 VDDIO switch to prevent leakage */
TAIKO_REG_VAL(TAIKO_A_MICB_4_MBHC, 0x81),
+
+ /* Close leakage on the spkdrv */
+ TAIKO_REG_VAL(TAIKO_A_SPKR_DRV_DBG_PWRSTG, 0x24),
};
static void taiko_update_reg_defaults(struct snd_soc_codec *codec)
@@ -4626,6 +4739,11 @@
snd_soc_write(codec, taiko_1_0_reg_defaults[i].reg,
taiko_1_0_reg_defaults[i].val);
}
+
+ if (!TAIKO_IS_1_0(taiko_core->version))
+ spkr_drv_wrnd = -1;
+ else if (spkr_drv_wrnd == 1)
+ snd_soc_write(codec, TAIKO_A_SPKR_DRV_EN, 0xEF);
}
static const struct taiko_reg_mask_val taiko_codec_reg_init_val[] = {
@@ -4819,6 +4937,13 @@
goto err_pdata;
}
+ if (spkr_drv_wrnd > 0) {
+ WCD9XXX_BCL_LOCK(&taiko->resmgr);
+ wcd9xxx_resmgr_get_bandgap(&taiko->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
+ }
+
ptr = kmalloc((sizeof(taiko_rx_chs) +
sizeof(taiko_tx_chs)), GFP_KERNEL);
if (!ptr) {
@@ -4852,6 +4977,8 @@
(void) taiko_setup_irqs(taiko);
+ atomic_set(&kp_taiko_priv, (unsigned long)taiko);
+
codec->ignore_pmdown_time = 1;
return ret;
@@ -4865,6 +4992,14 @@
{
struct taiko_priv *taiko = snd_soc_codec_get_drvdata(codec);
+ WCD9XXX_BCL_LOCK(&taiko->resmgr);
+ atomic_set(&kp_taiko_priv, 0);
+
+ if (spkr_drv_wrnd > 0)
+ wcd9xxx_resmgr_put_bandgap(&taiko->resmgr,
+ WCD9XXX_BANDGAP_AUDIO_MODE);
+ WCD9XXX_BCL_UNLOCK(&taiko->resmgr);
+
/* cleanup MBHC */
wcd9xxx_mbhc_deinit(&taiko->mbhc);
/* cleanup resmgr */