diff options
43 files changed, 1148 insertions, 139 deletions
diff --git a/Documentation/devicetree/bindings/drm/msm/hdmi-display.txt b/Documentation/devicetree/bindings/drm/msm/hdmi-display.txt index aaa3722659ab..9329fb74dea0 100644 --- a/Documentation/devicetree/bindings/drm/msm/hdmi-display.txt +++ b/Documentation/devicetree/bindings/drm/msm/hdmi-display.txt @@ -50,7 +50,7 @@ Example: qcom,mode-v-pulse-width = <10>; qcom,mode-v-back-porch = <72>; qcom,mode-v-active-high; - qcom,mode-refersh-rate = <30>; + qcom,mode-refresh-rate = <30>; qcom,mode-clock-in-khz = <297000>; }; }; diff --git a/Documentation/devicetree/bindings/media/video/msm-csid.txt b/Documentation/devicetree/bindings/media/video/msm-csid.txt index 340d98688b76..e580c056b3eb 100644 --- a/Documentation/devicetree/bindings/media/video/msm-csid.txt +++ b/Documentation/devicetree/bindings/media/video/msm-csid.txt @@ -12,8 +12,8 @@ Required properties: - "qcom,csid-v3.5" - "qcom,csid-v4.0" - "qcom,csid-v3.4.2" - - "qcom,csid-v3.5.1" - "qcom,csid-v3.4.3" + - "qcom,csid-v3.5.1" - "qcom,csid-v5.0" - reg : offset and length of the register set for the device for the csid operating in compatible mode. diff --git a/arch/arm/boot/dts/qcom/Makefile b/arch/arm/boot/dts/qcom/Makefile index 8829ef5fd221..f7ba268b233e 100644 --- a/arch/arm/boot/dts/qcom/Makefile +++ b/arch/arm/boot/dts/qcom/Makefile @@ -113,7 +113,8 @@ dtb-$(CONFIG_ARCH_MSM8996) += msm8996-v2-pmi8994-cdp.dtb \ apq8096-v3-pmi8994-mdm9x55-slimbus-mtp.dtb \ apq8096-v3-pmi8996-mdm9x55-i2s-mtp.dtb \ apq8096-v3-pmi8996-mdm9x55-slimbus-mtp.dtb \ - apq8096-v3-pmi8996-dragonboard.dtb + apq8096-v3-pmi8996-dragonboard.dtb \ + msm8996-auto-mizar.dtb dtb-$(CONFIG_MSM_GVM_QUIN) += vplatform-lfv-msm8996-telematics.dtb \ vplatform-lfv-msm8996-ivi.dtb diff --git a/arch/arm/boot/dts/qcom/msm8996-auto-mizar.dts b/arch/arm/boot/dts/qcom/msm8996-auto-mizar.dts new file mode 100644 index 000000000000..3a7d009c12a4 --- /dev/null +++ b/arch/arm/boot/dts/qcom/msm8996-auto-mizar.dts @@ -0,0 +1,328 @@ +/* Copyright (c) 2017, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +/dts-v1/; + +#include <dt-bindings/gpio/gpio.h> +#include "msm8996pro.dtsi" +#include "msm8996-pm8994.dtsi" +#include "msm8996-agave-adp.dtsi" +#include "msm8996pro-auto.dtsi" + +/ { + model = "Qualcomm Technologies, Inc. MSM 8996pro AUTO ADP"; + compatible = "qcom,msm8996-adp", "qcom,msm8996", "qcom,adp"; + qcom,msm-id = <315 0x10001>; + qcom,board-id = <0x06010019 0>, <0x00010001 0>; +}; + +&spi_9 { + status = "ok"; + can-controller@0 { + compatible = "renesas,rh850"; + reg = <0>; + interrupt-parent = <&tlmm>; + interrupts = <122 0>; + spi-max-frequency = <5000000>; + }; +}; + +&soc { + qcom,msm-ssc-sensors { + status = "disabled"; + }; + + qcom,msm-thermal { + qcom,hotplug-temp = <115>; + qcom,hotplug-temp-hysteresis = <25>; + qcom,therm-reset-temp = <119>; + }; + + qcom,adv7481@70 { + status = "disabled"; + }; + + qcom,ntn_avb { + qcom,ntn-rc-num = <2>; + }; + + i2c@75b6000 { /* BLSP8 */ + /* ADV7533 HDMI Bridge Chip removed on ADP Lite */ + adv7533@39 { + status = "disabled"; + }; + + adv7533@3d { + status = "disabled"; + }; + }; + +}; + +&cci { + qcom,camera@0 { + pinctrl-names = "cam_default", "cam_suspend","default"; + pinctrl-2 = <&mx9296_pwr>; + qcom,cci-master = <0>; + }; +}; + +&tlmm { + pcie2 { + pcie2_perst_default: pcie2_perst_default { + mux { + pins = "gpio90"; + function = "gpio"; + }; + + config { + pins = "gpio90"; + drive-strength = <2>; + bias-pull-down; + }; + }; + + pcie2_wake_default: pcie2_wake_default { + mux { + pins = "gpio54"; + function = "gpio"; + }; + + config { + pins = "gpio54"; + drive-strength = <2>; + bias-pull-down; + }; + }; + }; + + mx9296_pwr: mx9296_pwr { + mux { + pins = "gpio21"; + function = "gpio"; + }; + + config { + pins = "gpio21"; + drive-strength = <2>; + bias-pull-up; + output-high; + }; + }; +}; + +&pil_modem { + pinctrl-names = "default"; + pinctrl-0 = <&modem_mux>; +}; + +&slim_msm { + status = "disabled"; +}; + +&pm8994_mpps { + mpp@a500 { /* MPP 6 */ + qcom,mode = <1>; /* Digital output */ + qcom,output-type = <0>; /* CMOS logic */ + qcom,vin-sel = <2>; /* S4 1.8V */ + qcom,src-sel = <0>; /* Constant */ + qcom,master-en = <1>; /* Enable GPIO */ + status = "okay"; + }; +}; + +&sdhc_2 { + cd-gpios = <&tlmm 38 GPIO_ACTIVE_LOW>; + pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on_sbc>; + pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off + &sdc2_cd_on_sbc>; +}; + +&i2c_7 { + silabs4705@11 { /* SiLabs FM chip, slave id 0x11*/ + status = "disabled"; + }; +}; + +&pcie0 { + qcom,phy-sequence = <0x404 0x01 0x00 + 0x034 0x1c 0x00 + 0x038 0x10 0x00 + 0x174 0x33 0x00 + 0x194 0x06 0x00 + 0x0c8 0x42 0x00 + 0x128 0x00 0x00 + 0x144 0xff 0x00 + 0x148 0x1f 0x00 + 0x178 0x01 0x00 + 0x19c 0x01 0x00 + 0x18c 0x00 0x00 + 0x184 0x0a 0x00 + 0x00c 0x09 0x00 + 0x0d0 0x82 0x00 + 0x0e4 0x03 0x00 + 0x0e0 0x55 0x00 + 0x0dc 0x55 0x00 + 0x054 0x00 0x00 + 0x050 0x1a 0x00 + 0x04c 0x0a 0x00 + 0x174 0x33 0x00 + 0x03c 0x02 0x00 + 0x040 0x1f 0x00 + 0x0ac 0x04 0x00 + 0x078 0x0b 0x00 + 0x084 0x16 0x00 + 0x090 0x28 0x00 + 0x10c 0x00 0x00 + 0x108 0x80 0x00 + 0x010 0x00 0x00 + 0x01c 0x31 0x00 + 0x020 0x01 0x00 + 0x014 0x02 0x00 + 0x018 0x00 0x00 + 0x024 0x2f 0x00 + 0x028 0x19 0x00 + 0x0c4 0x15 0x00 + 0x070 0x0f 0x00 + 0x048 0x0f 0x00 + 0x074 0x19 0x00 + 0x038 0x10 0x00 + 0x178 0x00 0x00 + 0x0c4 0x40 0x00 + 0x400 0x00 0x00 + 0x408 0x03 0x00>; + + qcom,port-phy-sequence = <0x1068 0x45 0x00 + 0x1094 0x06 0x00 + 0x1310 0x1c 0x00 + 0x1318 0x17 0x00 + 0x12d8 0x01 0x00 + 0x12dc 0x00 0x00 + 0x12e0 0xdb 0x00 + 0x1320 0x18 0x00 + 0x121c 0x04 0x00 + 0x1210 0x04 0x00 + 0x1458 0x4c 0x00 + 0x14a0 0x00 0x00 + 0x14a4 0x01 0x00 + 0x14a8 0x05 0x00 + 0x1248 0x4b 0x00 + 0x131c 0x14 0x00 + 0x1454 0x05 0x00 + 0x1404 0x02 0x00 + 0x146c 0x00 0x00 + 0x1460 0xa3 0x00 + 0x1318 0x19 0x00 + 0x1428 0x0e 0x00 + 0x1054 0x08 0x00 + 0x14f8 0x04 0x00 + 0x14ec 0x06 0x00 + 0x104c 0x2e 0x00 + 0x1404 0x03 0x0a + 0x1400 0x00 0x00 + 0x1408 0x0a 0x00>; + + /delete-property/qcom,l1-supported; + /delete-property/qcom,l1ss-supported; + qcom,aux-clk-sync; + qcom,boot-option = <0x0>; +}; + +&pcie1 { + qcom,phy-sequence = <0x404 0x01 0x00 + 0x034 0x1c 0x00 + 0x038 0x10 0x00 + 0x174 0x33 0x00 + 0x194 0x06 0x00 + 0x0c8 0x42 0x00 + 0x128 0x00 0x00 + 0x144 0xff 0x00 + 0x148 0x1f 0x00 + 0x178 0x01 0x00 + 0x19c 0x01 0x00 + 0x18c 0x00 0x00 + 0x184 0x0a 0x00 + 0x00c 0x09 0x00 + 0x0d0 0x82 0x00 + 0x0e4 0x03 0x00 + 0x0e0 0x55 0x00 + 0x0dc 0x55 0x00 + 0x054 0x00 0x00 + 0x050 0x1a 0x00 + 0x04c 0x0a 0x00 + 0x174 0x33 0x00 + 0x03c 0x02 0x00 + 0x040 0x1f 0x00 + 0x0ac 0x04 0x00 + 0x078 0x0b 0x00 + 0x084 0x16 0x00 + 0x090 0x28 0x00 + 0x10c 0x00 0x00 + 0x108 0x80 0x00 + 0x010 0x00 0x00 + 0x01c 0x31 0x00 + 0x020 0x01 0x00 + 0x014 0x02 0x00 + 0x018 0x00 0x00 + 0x024 0x2f 0x00 + 0x028 0x19 0x00 + 0x0c4 0x15 0x00 + 0x070 0x0f 0x00 + 0x048 0x0f 0x00 + 0x074 0x19 0x00 + 0x038 0x10 0x00 + 0x178 0x00 0x00 + 0x0c4 0x40 0x00 + 0x400 0x00 0x00 + 0x408 0x03 0x00>; + + qcom,port-phy-sequence = <0x2068 0x45 0x00 + 0x2094 0x06 0x00 + 0x2310 0x1c 0x00 + 0x2318 0x17 0x00 + 0x22d8 0x01 0x00 + 0x22dc 0x00 0x00 + 0x22e0 0xdb 0x00 + 0x2320 0x18 0x00 + 0x221c 0x04 0x00 + 0x2210 0x04 0x00 + 0x2458 0x4c 0x00 + 0x24a0 0x00 0x00 + 0x24a4 0x01 0x00 + 0x24a8 0x05 0x00 + 0x2248 0x4b 0x00 + 0x231c 0x14 0x00 + 0x2454 0x05 0x00 + 0x2404 0x02 0x00 + 0x246c 0x00 0x00 + 0x2460 0xa3 0x00 + 0x2318 0x19 0x00 + 0x2428 0x0e 0x00 + 0x2054 0x08 0x00 + 0x24f8 0x04 0x00 + 0x24ec 0x06 0x00 + 0x204c 0x2e 0x00 + 0x2404 0x03 0x0a + 0x2400 0x00 0x00 + 0x2408 0x0a 0x00>; + + /delete-property/qcom,l1-supported; + /delete-property/qcom,l1ss-supported; + /delete-property/qcom,aux-clk-sync; + qcom,boot-option = <0x0>; +}; + +&pcie2 { + qcom,boot-option = <0x0>; + perst-gpio = <&tlmm 90 0>; + wake-gpio = <&tlmm 54 0>; +}; diff --git a/arch/arm/boot/dts/qcom/sdm660-mtp.dts b/arch/arm/boot/dts/qcom/sdm660-mtp.dts index 32b294ee6883..68e4491193d5 100644 --- a/arch/arm/boot/dts/qcom/sdm660-mtp.dts +++ b/arch/arm/boot/dts/qcom/sdm660-mtp.dts @@ -29,3 +29,12 @@ &tavil_snd { qcom,msm-mbhc-moist-cfg = <0>, <0>, <3>; }; + +&slim_aud { + /delete-node/tasha_codec; +}; + +&soc { + /delete-node/sound-9335; +}; + diff --git a/arch/arm/boot/dts/qcom/sdm660-qrd.dts b/arch/arm/boot/dts/qcom/sdm660-qrd.dts index 3284e805a093..4e7cc547e6cd 100644 --- a/arch/arm/boot/dts/qcom/sdm660-qrd.dts +++ b/arch/arm/boot/dts/qcom/sdm660-qrd.dts @@ -86,3 +86,12 @@ qcom,afe-power-off-delay-us = <6>; }; }; + +&slim_aud { + /delete-node/wcd934x_cdc; +}; + +&soc { + /delete-node/sound-tavil; +}; + diff --git a/drivers/android/binder.c b/drivers/android/binder.c index 9e31197f4b6d..2c33b1251afb 100644 --- a/drivers/android/binder.c +++ b/drivers/android/binder.c @@ -466,9 +466,8 @@ struct binder_ref { }; enum binder_deferred_state { - BINDER_DEFERRED_PUT_FILES = 0x01, - BINDER_DEFERRED_FLUSH = 0x02, - BINDER_DEFERRED_RELEASE = 0x04, + BINDER_DEFERRED_FLUSH = 0x01, + BINDER_DEFERRED_RELEASE = 0x02, }; /** @@ -505,8 +504,6 @@ struct binder_priority { * (invariant after initialized) * @tsk task_struct for group_leader of process * (invariant after initialized) - * @files files_struct for process - * (invariant after initialized) * @deferred_work_node: element for binder_deferred_list * (protected by binder_deferred_lock) * @deferred_work: bitmap of deferred work to perform @@ -553,7 +550,6 @@ struct binder_proc { struct list_head waiting_threads; int pid; struct task_struct *tsk; - struct files_struct *files; struct hlist_node deferred_work_node; int deferred_work; bool is_dead; @@ -949,22 +945,34 @@ static void binder_free_thread(struct binder_thread *thread); static void binder_free_proc(struct binder_proc *proc); static void binder_inc_node_tmpref_ilocked(struct binder_node *node); +struct files_struct *binder_get_files_struct(struct binder_proc *proc) +{ + return get_files_struct(proc->tsk); +} + static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) { - struct files_struct *files = proc->files; + struct files_struct *files; unsigned long rlim_cur; unsigned long irqs; + int ret; + files = binder_get_files_struct(proc); if (files == NULL) return -ESRCH; - if (!lock_task_sighand(proc->tsk, &irqs)) - return -EMFILE; + if (!lock_task_sighand(proc->tsk, &irqs)) { + ret = -EMFILE; + goto err; + } rlim_cur = task_rlimit(proc->tsk, RLIMIT_NOFILE); unlock_task_sighand(proc->tsk, &irqs); - return __alloc_fd(files, 0, rlim_cur, flags); + ret = __alloc_fd(files, 0, rlim_cur, flags); +err: + put_files_struct(files); + return ret; } /* @@ -973,8 +981,12 @@ static int task_get_unused_fd_flags(struct binder_proc *proc, int flags) static void task_fd_install( struct binder_proc *proc, unsigned int fd, struct file *file) { - if (proc->files) - __fd_install(proc->files, fd, file); + struct files_struct *files = binder_get_files_struct(proc); + + if (files) { + __fd_install(files, fd, file); + put_files_struct(files); + } } /* @@ -982,18 +994,20 @@ static void task_fd_install( */ static long task_close_fd(struct binder_proc *proc, unsigned int fd) { + struct files_struct *files = binder_get_files_struct(proc); int retval; - if (proc->files == NULL) + if (files == NULL) return -ESRCH; - retval = __close_fd(proc->files, fd); + retval = __close_fd(files, fd); /* can't restart close syscall because file table entry was cleared */ if (unlikely(retval == -ERESTARTSYS || retval == -ERESTARTNOINTR || retval == -ERESTARTNOHAND || retval == -ERESTART_RESTARTBLOCK)) retval = -EINTR; + put_files_struct(files); return retval; } @@ -4811,7 +4825,6 @@ static void binder_vma_close(struct vm_area_struct *vma) (vma->vm_end - vma->vm_start) / SZ_1K, vma->vm_flags, (unsigned long)pgprot_val(vma->vm_page_prot)); binder_alloc_vma_close(&proc->alloc); - binder_defer_work(proc, BINDER_DEFERRED_PUT_FILES); } static int binder_vm_fault(struct vm_area_struct *vma, struct vm_fault *vmf) @@ -4853,10 +4866,8 @@ static int binder_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_private_data = proc; ret = binder_alloc_mmap_handler(&proc->alloc, vma); - if (ret) - return ret; - proc->files = get_files_struct(current); - return 0; + + return ret; err_bad_arg: pr_err("binder_mmap: %d %lx-%lx %s failed %d\n", @@ -5035,8 +5046,6 @@ static void binder_deferred_release(struct binder_proc *proc) struct rb_node *n; int threads, nodes, incoming_refs, outgoing_refs, active_transactions; - BUG_ON(proc->files); - mutex_lock(&binder_procs_lock); hlist_del(&proc->proc_node); mutex_unlock(&binder_procs_lock); @@ -5118,8 +5127,6 @@ static void binder_deferred_release(struct binder_proc *proc) static void binder_deferred_func(struct work_struct *work) { struct binder_proc *proc; - struct files_struct *files; - int defer; do { @@ -5136,21 +5143,11 @@ static void binder_deferred_func(struct work_struct *work) } mutex_unlock(&binder_deferred_lock); - files = NULL; - if (defer & BINDER_DEFERRED_PUT_FILES) { - files = proc->files; - if (files) - proc->files = NULL; - } - if (defer & BINDER_DEFERRED_FLUSH) binder_deferred_flush(proc); if (defer & BINDER_DEFERRED_RELEASE) binder_deferred_release(proc); /* frees proc */ - - if (files) - put_files_struct(files); } while (proc); } static DECLARE_WORK(binder_deferred_work, binder_deferred_func); diff --git a/drivers/clk/msm/mdss/mdss-dp-pll-8998-util.c b/drivers/clk/msm/mdss/mdss-dp-pll-8998-util.c index 0bd7e6413a6b..2d40fdeabcae 100644 --- a/drivers/clk/msm/mdss/mdss-dp-pll-8998-util.c +++ b/drivers/clk/msm/mdss/mdss-dp-pll-8998-util.c @@ -1,4 +1,4 @@ -/* Copyright (c) 2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -128,10 +128,10 @@ int vco_divided_clk_set_div(struct div_clk *clk, int div) auxclk_div = MDSS_PLL_REG_R(dp_res->phy_base, DP_PHY_VCO_DIV); auxclk_div &= ~0x03; /* bits 0 to 1 */ - auxclk_div |= 1; /* Default divider */ - if (div == 4) auxclk_div |= 2; + else + auxclk_div |= 1; /* Default divider */ MDSS_PLL_REG_W(dp_res->phy_base, DP_PHY_VCO_DIV, auxclk_div); diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c index 0f77e35ef287..35ba396e1cd1 100644 --- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c +++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c @@ -2799,7 +2799,6 @@ static int _sde_hdmi_parse_dt_modes(struct device_node *np, u32 v_front_porch, v_pulse_width, v_back_porch; bool h_active_high, v_active_high; u32 flags = 0; - root_node = of_get_child_by_name(np, "qcom,customize-modes"); if (!root_node) { root_node = of_parse_phandle(np, "qcom,customize-modes", 0); @@ -2887,10 +2886,10 @@ static int _sde_hdmi_parse_dt_modes(struct device_node *np, v_active_high = of_property_read_bool(node, "qcom,mode-v-active-high"); - rc = of_property_read_u32(node, "qcom,mode-refersh-rate", + rc = of_property_read_u32(node, "qcom,mode-refresh-rate", &mode->vrefresh); if (rc) { - SDE_ERROR("failed to read refersh-rate, rc=%d\n", rc); + SDE_ERROR("failed to read refresh-rate, rc=%d\n", rc); goto fail; } diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c index 9cbee5243e6d..f5f125c3f71c 100644 --- a/drivers/gpu/drm/msm/sde/sde_plane.c +++ b/drivers/gpu/drm/msm/sde/sde_plane.c @@ -1808,8 +1808,8 @@ static void _sde_plane_install_properties(struct drm_plane *plane, char feature_name[256]; struct sde_phy_plane *pp; uint32_t features = 0xFFFFFFFF, nformats = 64; - u32 maxlinewidth = -1, maxupscale = -1, maxdwnscale = -1; - u32 maxhdeciexp = -1, maxvdeciexp = -1; + u32 maxlinewidth = 0, maxupscale = 0, maxdwnscale = 0; + u32 maxhdeciexp = 0, maxvdeciexp = 0; if (!plane || !psde) { SDE_ERROR("invalid plane\n"); diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c index 862d832823f7..fc7799722026 100644 --- a/drivers/gpu/msm/adreno_dispatch.c +++ b/drivers/gpu/msm/adreno_dispatch.c @@ -677,7 +677,7 @@ static int sendcmd(struct adreno_device *adreno_dev, * then set up the timer. If this misses, then preemption is indeed a * thing and the timer will be set up in due time */ - if (!adreno_in_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE)) { + if (adreno_in_preempt_state(adreno_dev, ADRENO_PREEMPT_NONE)) { if (drawqueue_is_current(dispatch_q)) mod_timer(&dispatcher->timer, dispatch_q->expires); } diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c index 37d92428f02c..592257a332d1 100644 --- a/drivers/gpu/msm/kgsl_debugfs.c +++ b/drivers/gpu/msm/kgsl_debugfs.c @@ -299,6 +299,7 @@ static int print_sparse_mem_entry(int id, void *ptr, void *data) if (!(m->flags & KGSL_MEMFLAGS_SPARSE_VIRT)) return 0; + spin_lock(&entry->bind_lock); node = rb_first(&entry->bind_tree); while (node != NULL) { @@ -309,6 +310,7 @@ static int print_sparse_mem_entry(int id, void *ptr, void *data) obj->v_off, obj->size, obj->p_off); node = rb_next(node); } + spin_unlock(&entry->bind_lock); seq_putc(s, '\n'); diff --git a/drivers/media/i2c/adv7481.c b/drivers/media/i2c/adv7481.c index 74d7b9584827..b6b89a9eefe2 100644 --- a/drivers/media/i2c/adv7481.c +++ b/drivers/media/i2c/adv7481.c @@ -1005,6 +1005,7 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) { struct adv7481_state *state = to_state(sd); int *ret_val = arg; + uint8_t status = 0; long ret = 0; int param = 0; @@ -1039,6 +1040,22 @@ static long adv7481_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg) case VIDIOC_HDMI_RX_CEC_S_ENABLE: ret = adv7481_cec_powerup(state, arg); break; + case VIDIOC_CVBS_G_FIELD_STATUS: + /* Select SDP read-only Map 1 */ + adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + SDP_RW_MAP_REG, 0x02); + status = adv7481_rd_byte(&state->i2c_client, + state->i2c_sdp_addr, SDP_RO_MAP_1_FIELD_ADDR); + adv7481_wr_byte(&state->i2c_client, state->i2c_sdp_addr, + SDP_RW_MAP_REG, 0x00); + if (ret_val) { + *ret_val = ADV_REG_GETFIELD(status, + SDP_RO_MAP_1_EVEN_FIELD); + } else { + pr_err("%s: NULL pointer provided\n", __func__); + ret = -EINVAL; + } + break; default: pr_err("Not a typewriter! Command: 0x%x", cmd); ret = -ENOTTY; diff --git a/drivers/media/i2c/adv7481_reg.h b/drivers/media/i2c/adv7481_reg.h index 60b1301abbe6..96f0a5df10c0 100644 --- a/drivers/media/i2c/adv7481_reg.h +++ b/drivers/media/i2c/adv7481_reg.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -411,6 +411,11 @@ #define SDP_RO_MAIN_IN_LOCK_BMSK 0x0001 #define SDP_RO_MAIN_IN_LOCK_SHFT 0 +/* SDP R/O Map 1 Registers */ +#define SDP_RO_MAP_1_FIELD_ADDR 0x45 +#define SDP_RO_MAP_1_EVEN_FIELD_BMSK 0x10 +#define SDP_RO_MAP_1_EVEN_FIELD_SHFT 4 + /* * CSI Map Registers diff --git a/drivers/media/platform/msm/ais/isp/msm_isp.h b/drivers/media/platform/msm/ais/isp/msm_isp.h index 86974eeb4a32..d4c6eba78b78 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp.h +++ b/drivers/media/platform/msm/ais/isp/msm_isp.h @@ -164,6 +164,8 @@ struct msm_vfe_irq_ops { void (*config_irq)(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1, enum msm_isp_irq_operation); + void (*process_sof_irq)(struct vfe_device *vfe_dev, + uint32_t irq_status0, uint32_t irq_status1); void (*process_eof_irq)(struct vfe_device *vfe_dev, uint32_t irq_status0); }; @@ -411,6 +413,12 @@ struct msm_vfe_frame_request_queue { #define MSM_VFE_REQUESTQ_SIZE 8 +struct msm_vfe_fields_info { + bool even_field; + struct timeval sof_ts; + struct timeval field_ts; +}; + struct msm_vfe_axi_stream { uint32_t frame_id; enum msm_vfe_axi_state state; @@ -457,6 +465,11 @@ struct msm_vfe_axi_stream { enum msm_stream_memory_input_t memory_input; struct msm_isp_sw_framskip sw_skip; uint8_t sw_ping_pong_bit; + + bool interlaced; + struct msm_vfe_fields_info field_info[2]; + uint32_t field_index; + uint32_t field_type; }; struct msm_vfe_axi_composite_info { @@ -798,6 +811,12 @@ struct vfe_device { /* before halt irq info */ uint32_t recovery_irq0_mask; uint32_t recovery_irq1_mask; + + /* interlaced field info */ + void *ba_inst_hdl; + struct task_struct *field_thread_id; + wait_queue_head_t field_waitqueue; + bool wakeupflag; }; struct vfe_parent_device { diff --git a/drivers/media/platform/msm/ais/isp/msm_isp47.c b/drivers/media/platform/msm/ais/isp/msm_isp47.c index 04e879fc3bcf..9da7dee59064 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp47.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp47.c @@ -662,6 +662,37 @@ void msm_vfe47_process_epoch_irq(struct vfe_device *vfe_dev, } } +static void msm_isp47_process_sof_irq(struct vfe_device *vfe_dev, + uint32_t irq_status0, uint32_t irq_status1) +{ + int i, axi_src_idx[4], src_count = 0; + struct msm_vfe_axi_stream *pstream_info; + struct msm_vfe_axi_shared_data *axi_data = &vfe_dev->axi_data; + + if (irq_status0 & BIT(0)) + axi_src_idx[src_count++] = CAMIF_RAW; + if (irq_status1 & BIT(29)) + axi_src_idx[src_count++] = RDI_INTF_0; + if (irq_status1 & BIT(30)) + axi_src_idx[src_count++] = RDI_INTF_1; + if (irq_status1 & BIT(31)) + axi_src_idx[src_count++] = RDI_INTF_2; + + if (src_count == 0) + return; + + for (i = 0; i < src_count; i++) { + pstream_info = &axi_data->stream_info[axi_src_idx[i]]; + + if (pstream_info->interlaced) { + vfe_dev->wakeupflag = true; + wake_up_interruptible(&vfe_dev->field_waitqueue); + /* currently we support only 1 interlaced instance */ + break; + } + } +} + void msm_isp47_process_eof_irq(struct vfe_device *vfe_dev, uint32_t irq_status0) { @@ -2718,6 +2749,7 @@ struct msm_vfe_hardware_info vfe47_hw_info = { .process_stats_irq = msm_isp_process_stats_irq, .process_epoch_irq = msm_vfe47_process_epoch_irq, .config_irq = msm_vfe47_config_irq, + .process_sof_irq = msm_isp47_process_sof_irq, .process_eof_irq = msm_isp47_process_eof_irq, }, .axi_ops = { diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c index a85ee30769c4..9c06ee3b2687 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp_axi_util.c @@ -2042,6 +2042,12 @@ static int msm_isp_process_done_buf(struct vfe_device *vfe_dev, buf_event.u.buf_done.buf_idx = buf->buf_idx; buf_event.u.buf_done.output_format = stream_info->runtime_output_format; + + if (stream_info->interlaced) + buf_event.u.buf_done.field_type = stream_info->field_type; + else + buf_event.u.buf_done.field_type = 0; + if (vfe_dev->fetch_engine_info.is_busy && SRC_TO_INTF(stream_info->stream_src) == VFE_PIX_0) { vfe_dev->fetch_engine_info.is_busy = 0; @@ -3132,6 +3138,7 @@ static int msm_isp_stop_axi_stream(struct vfe_device *vfe_dev, } } + stream_info->interlaced = false; vfe_dev->reg_update_requested &= ~(BIT(SRC_TO_INTF(stream_info->stream_src))); } @@ -3544,13 +3551,18 @@ int msm_isp_axi_output_cfg(struct vfe_device *vfe_dev, void *arg) INIT_LIST_HEAD(&pstream_info->request_q); pstream_info->frame_based = - pCmd->output_path_cfg[axi_src_idx].frame_based; + pCmd->output_path_cfg[axi_src_idx].frame_based & BIT(0); + pstream_info->interlaced = + (pCmd->output_path_cfg[axi_src_idx].frame_based + & BIT(INTERLACE_OFFSET)) ? true : false; /* send buffers to user through vfe dev node */ pstream_info->buf_divert = 1; pstream_info->output_format = pCmd->output_path_cfg[axi_src_idx].format; + pstream_info->field_index = 0; + msm_isp_axi_get_num_planes( pCmd->output_path_cfg[axi_src_idx].format, pstream_info); diff --git a/drivers/media/platform/msm/ais/isp/msm_isp_util.c b/drivers/media/platform/msm/ais/isp/msm_isp_util.c index 9e5317eb2920..2401ff645057 100644 --- a/drivers/media/platform/msm/ais/isp/msm_isp_util.c +++ b/drivers/media/platform/msm/ais/isp/msm_isp_util.c @@ -14,6 +14,8 @@ #include <linux/io.h> #include <media/v4l2-subdev.h> #include <linux/ratelimit.h> +#include <linux/kthread.h> +#include <linux/sched.h> #include "msm.h" #include "msm_isp_util.h" @@ -23,6 +25,7 @@ #include "cam_smmu_api.h" #define CREATE_TRACE_POINTS #include "trace/events/msm_cam.h" +#include "media/msm_ba.h" #define MAX_ISP_V4l2_EVENTS 100 #define MAX_ISP_REG_LIST 100 @@ -1974,6 +1977,166 @@ void msm_isp_reset_burst_count_and_frame_drop( msm_isp_reset_framedrop(vfe_dev, stream_info); } +static void msm_isp_field_type_read_thread(void *data) +{ + int ret = 0; + uint8_t i, j = 0; + bool even_field = 0; + uint64_t timestamp_us[4]; + struct msm_isp_timestamp ts; + struct msm_vfe_axi_stream *stream_info = NULL; + struct vfe_device *vfe_dev = (struct vfe_device *)data; + + pr_debug("Enter field_type_read_thread\n"); + + vfe_dev->ba_inst_hdl = msm_ba_open(NULL); + if (vfe_dev->ba_inst_hdl == NULL) { + pr_err("%s: ba open failed\n", __func__); + return; + } + + while (!kthread_should_stop()) { + ret = 0; + wait_event_interruptible(vfe_dev->field_waitqueue, + vfe_dev->wakeupflag == true); + if (kthread_should_stop()) { + pr_debug("%s: field thread has stopped\n", __func__); + goto bs_close; + } + + for (i = 0; i < VFE_AXI_SRC_MAX; i++) { + if (vfe_dev->axi_data.stream_info[i].interlaced) + break; + } + if (i == VFE_AXI_SRC_MAX) { + vfe_dev->wakeupflag = false; + continue; + } + + stream_info = &vfe_dev->axi_data.stream_info[i]; + j = stream_info->field_index; + + /* Detect field status from bridge chip */ + ret = msm_ba_private_ioctl(vfe_dev->ba_inst_hdl, + VIDIOC_CVBS_G_FIELD_STATUS, &even_field); + if (ret) { + pr_err("%s: get field status failed: %d\n", + __func__, ret); + } else { + msm_isp_get_timestamp(&ts, vfe_dev); + stream_info->field_info[j%2].even_field = even_field; + stream_info->field_info[j%2].field_ts.tv_sec = + ts.buf_time.tv_sec; + stream_info->field_info[j%2].field_ts.tv_usec = + ts.buf_time.tv_usec; + } + + stream_info->field_index++; + + /* once 2 fields info getting done, do the verification */ + if (stream_info->field_index%2 == 0) { + timestamp_us[0] = + stream_info->field_info[0].sof_ts.tv_sec + * 1000 * 1000 + + stream_info->field_info[0].sof_ts.tv_usec; + timestamp_us[1] = + stream_info->field_info[0].field_ts.tv_sec + * 1000 * 1000 + + stream_info->field_info[0].field_ts.tv_usec; + timestamp_us[2] = + stream_info->field_info[1].sof_ts.tv_sec + * 1000 * 1000 + + stream_info->field_info[1].sof_ts.tv_usec; + timestamp_us[3] = + stream_info->field_info[1].field_ts.tv_sec + * 1000 * 1000 + + stream_info->field_info[1].field_ts.tv_usec; + + /* + * Expected timing: + * field 0 SOF -> field 0 type read -> + * field 1 SOF -> field 1 type read + */ + if ((timestamp_us[0] < timestamp_us[1]) && + (timestamp_us[2] < timestamp_us[3]) && + (timestamp_us[1] < timestamp_us[2]) && + (stream_info->field_info[0].even_field != + stream_info->field_info[1].even_field)) { + /* + * Field type: + * 0 - unknown + * 1 - odd first + * 2 - even first + */ + stream_info->field_type = + stream_info->field_info[0].even_field ? + 2 : 1; + } else { + stream_info->field_type = 0; + pr_err("Field: %llu %llu %llu %llu %d %d\n", + timestamp_us[0], timestamp_us[1], + timestamp_us[2], timestamp_us[3], + stream_info->field_info[0].even_field, + stream_info->field_info[1].even_field); + } + } + + vfe_dev->wakeupflag = false; + } + +bs_close: + ret = msm_ba_close(vfe_dev->ba_inst_hdl); + if (ret) + pr_err("%s: msm ba close failed\n", __func__); + vfe_dev->ba_inst_hdl = NULL; +} + +static int msm_isp_init_field_type_kthread(struct vfe_device *vfe_dev) +{ + init_waitqueue_head(&vfe_dev->field_waitqueue); + + ISP_DBG("%s: Queue initialized\n", __func__); + vfe_dev->field_thread_id = kthread_run( + (void *)msm_isp_field_type_read_thread, + (void *)vfe_dev, "field_type_kthread"); + if (IS_ERR(vfe_dev->field_thread_id)) { + pr_err("%s: Unable to run the thread\n", __func__); + return -ENOMEM; + } + + return 0; +} + +static void msm_isp_field_timestamp(struct vfe_device *vfe_dev, + uint32_t irq_status0, uint32_t irq_status1, + struct timeval *timestamp) +{ + uint8_t i, j = 0; + struct msm_vfe_axi_stream *stream_info = NULL; + + for (i = 0; i < VFE_AXI_SRC_MAX; i++) { + if (vfe_dev->axi_data.stream_info[i].interlaced) + break; + } + + if (i == VFE_AXI_SRC_MAX) + return; + + stream_info = &vfe_dev->axi_data.stream_info[i]; + + /* SOF timestamp */ + if (((i == CAMIF_RAW) && (irq_status0 & BIT(0))) + || ((i == RDI_INTF_0) && (irq_status1 & BIT(29))) + || ((i == RDI_INTF_1) && (irq_status1 & BIT(30))) + || ((i == RDI_INTF_2) && (irq_status1 & BIT(31)))) { + j = stream_info->field_index; + stream_info->field_info[j%2].sof_ts.tv_sec = + timestamp->tv_sec; + stream_info->field_info[j%2].sof_ts.tv_usec = + timestamp->tv_usec; + } +} + static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev, uint32_t irq_status0, uint32_t irq_status1, uint32_t ping_pong_status) @@ -1999,6 +2162,10 @@ static void msm_isp_enqueue_tasklet_cmd(struct vfe_device *vfe_dev, MSM_VFE_TASKLETQ_SIZE; list_add_tail(&queue_cmd->list, &vfe_dev->tasklet_q); spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags); + + msm_isp_field_timestamp(vfe_dev, irq_status0, irq_status1, + &queue_cmd->ts.buf_time); + tasklet_schedule(&vfe_dev->vfe_tasklet); } @@ -2121,6 +2288,7 @@ void msm_isp_do_tasklet(unsigned long data) spin_unlock_irqrestore(&vfe_dev->tasklet_lock, flags); ISP_DBG("%s: vfe_id %d status0: 0x%x status1: 0x%x\n", __func__, vfe_dev->pdev->id, irq_status0, irq_status1); + if (vfe_dev->is_split) { spin_lock(&dump_tasklet_lock); tasklet_data.arr[tasklet_data.first]. @@ -2139,6 +2307,8 @@ void msm_isp_do_tasklet(unsigned long data) (tasklet_data.first + 1) % MAX_ISP_PING_PONG_DUMP_SIZE; spin_unlock(&dump_tasklet_lock); } + irq_ops->process_sof_irq(vfe_dev, + irq_status0, irq_status1); irq_ops->process_reset_irq(vfe_dev, irq_status0, irq_status1); irq_ops->process_halt_irq(vfe_dev, @@ -2291,8 +2461,17 @@ int msm_isp_open_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) cam_smmu_reg_client_page_fault_handler( vfe_dev->buf_mgr->iommu_hdl, msm_vfe_iommu_fault_handler, vfe_dev); + + /* to detect interlaced frame type through ba driver */ + rc = msm_isp_init_field_type_kthread(vfe_dev); + if (rc) { + pr_err("%s: init field thread failed\n", __func__); + return rc; + } + mutex_unlock(&vfe_dev->core_mutex); mutex_unlock(&vfe_dev->realtime_mutex); + return 0; } @@ -2361,6 +2540,9 @@ int msm_isp_close_node(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh) } vfe_dev->is_split = 0; + vfe_dev->wakeupflag = true; + kthread_stop(vfe_dev->field_thread_id); + mutex_unlock(&vfe_dev->core_mutex); mutex_unlock(&vfe_dev->realtime_mutex); return 0; diff --git a/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c index 40806d5a164f..f11c2652728a 100644 --- a/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c +++ b/drivers/media/platform/msm/ais/sensor/actuator/msm_actuator.c @@ -98,6 +98,11 @@ static void msm_actuator_parse_i2c_params(struct msm_actuator_ctrl_t *a_ctrl, return; } + if (a_ctrl->i2c_reg_tbl == NULL) { + pr_err("failed. i2c reg tabl is NULL"); + return; + } + size = a_ctrl->reg_tbl_size; write_arr = a_ctrl->reg_tbl; i2c_tbl = a_ctrl->i2c_reg_tbl; @@ -1290,9 +1295,11 @@ static int32_t msm_actuator_set_param(struct msm_actuator_ctrl_t *a_ctrl, if (copy_from_user(&a_ctrl->region_params, (void __user *)set_info->af_tuning_params.region_params, - a_ctrl->region_size * sizeof(struct region_params_t))) + a_ctrl->region_size * sizeof(struct region_params_t))) { + a_ctrl->total_steps = 0; + pr_err("Error copying region_params\n"); return -EFAULT; - + } if (a_ctrl->act_device_type == MSM_CAMERA_PLATFORM_DEVICE) { cci_client = a_ctrl->i2c_client.cci_client; cci_client->sid = diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h index 21fab0590b55..34cac9daea89 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_buf_mgr.h @@ -1,4 +1,4 @@ -/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. +/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -98,6 +98,8 @@ struct msm_isp_buffer { struct timeval *tv; /* Indicates whether buffer is used as ping ot pong buffer */ uint32_t pingpong_bit; + /* Indicates buffer is reconfig due to drop frame */ + uint32_t is_drop_reconfig; /*Native buffer*/ struct list_head list; diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c index 22eb86f4f875..23e27e1179d1 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.c @@ -453,11 +453,69 @@ static long msm_isp_v4l2_fops_ioctl(struct file *file, unsigned int cmd, return video_usercopy(file, cmd, arg, msm_isp_subdev_do_ioctl); } +static void isp_vma_open(struct vm_area_struct *vma) +{ + pr_debug("%s: open called\n", __func__); +} + +static void isp_vma_close(struct vm_area_struct *vma) +{ + pr_debug("%s: close called\n", __func__); +} + +static int isp_vma_fault(struct vm_area_struct *vma, struct vm_fault *vmf) +{ + struct page *page; + struct vfe_device *vfe_dev = vma->vm_private_data; + struct isp_proc *isp_page = NULL; + + isp_page = vfe_dev->isp_page; + + pr_debug("%s: vfeid:%d u_virt_addr:0x%lx k_virt_addr:%pK\n", + __func__, vfe_dev->pdev->id, vma->vm_start, + (void *)isp_page); + if (isp_page != NULL) { + page = virt_to_page(isp_page); + get_page(page); + vmf->page = page; + isp_page->kernel_sofid = + vfe_dev->axi_data.src_info[VFE_PIX_0].frame_id; + isp_page->vfeid = vfe_dev->pdev->id; + } + return 0; +} + +static const struct vm_operations_struct isp_vm_ops = { + .open = isp_vma_open, + .close = isp_vma_close, + .fault = isp_vma_fault, +}; + +static int msm_isp_v4l2_fops_mmap(struct file *filep, + struct vm_area_struct *vma) +{ + int ret = -EINVAL; + struct video_device *vdev = video_devdata(filep); + struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev); + struct vfe_device *vfe_dev = v4l2_get_subdevdata(sd); + + vma->vm_ops = &isp_vm_ops; + vma->vm_flags |= + (unsigned long)(VM_DONTEXPAND | VM_DONTDUMP); + vma->vm_private_data = vfe_dev; + isp_vma_open(vma); + ret = 0; + pr_debug("%s: isp mmap is called vm_start: 0x%lx\n", + __func__, vma->vm_start); + return ret; +} + static struct v4l2_file_operations msm_isp_v4l2_fops = { #ifdef CONFIG_COMPAT .compat_ioctl32 = msm_isp_v4l2_fops_ioctl, #endif - .unlocked_ioctl = msm_isp_v4l2_fops_ioctl + .unlocked_ioctl = msm_isp_v4l2_fops_ioctl, + .mmap = msm_isp_v4l2_fops_mmap }; static int vfe_set_common_data(struct platform_device *pdev) @@ -671,6 +729,8 @@ int vfe_hw_probe(struct platform_device *pdev) msm_isp_v4l2_fops.compat_ioctl32 = msm_isp_v4l2_fops_ioctl; #endif + msm_isp_v4l2_fops.mmap = msm_isp_v4l2_fops_mmap; + vfe_dev->subdev.sd.devnode->fops = &msm_isp_v4l2_fops; vfe_dev->buf_mgr = &vfe_buf_mgr; @@ -687,6 +747,14 @@ int vfe_hw_probe(struct platform_device *pdev) msm_isp_enable_debugfs(vfe_dev, msm_isp_bw_request_history); vfe_dev->buf_mgr->init_done = 1; vfe_dev->vfe_open_cnt = 0; + /*Allocate a page in kernel and map it to camera user process*/ + vfe_dev->isp_page = (struct isp_proc *)get_zeroed_page(GFP_KERNEL); + if (vfe_dev->isp_page == NULL) { + pr_err("%s: no enough memory\n", __func__); + rc = -ENOMEM; + goto probe_fail3; + } + vfe_dev->isp_page->vfeid = vfe_dev->pdev->id; return rc; probe_fail3: diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h index b2d152bf4ef0..d336e1ef1bd7 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h @@ -759,6 +759,11 @@ struct msm_vfe_common_subdev { struct msm_vfe_common_dev_data *common_data; }; +struct isp_proc { + uint32_t kernel_sofid; + uint32_t vfeid; +}; + struct vfe_device { /* Driver private data */ struct platform_device *pdev; @@ -842,6 +847,7 @@ struct vfe_device { uint32_t recovery_irq1_mask; /* total bandwidth per vfe */ uint64_t total_bandwidth; + struct isp_proc *isp_page; }; struct vfe_parent_device { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c index 70950a88fc66..812027f3e539 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c @@ -788,7 +788,7 @@ long msm_vfe47_reset_hardware(struct vfe_device *vfe_dev, msm_camera_io_w(0xFFFFFEFF, vfe_dev->vfe_base + 0x68); msm_camera_io_w(0x1, vfe_dev->vfe_base + 0x58); vfe_dev->hw_info->vfe_ops.axi_ops. - reload_wm(vfe_dev, vfe_dev->vfe_base, 0x0031FFFF); + reload_wm(vfe_dev, vfe_dev->vfe_base, 0x0011FFFF); } if (blocking_call) { diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c index 5bcb3034b82a..15f8061b9919 100644 --- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c +++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c @@ -719,13 +719,7 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, sof_info->stream_get_buf_fail_mask = 0; axi_data = &vfe_dev->axi_data; - /* report that registers are not updated and return empty buffer for - * controllable outputs - */ - if (!vfe_dev->reg_updated) { - sof_info->regs_not_updated = - vfe_dev->reg_update_requested; - } + for (i = 0; i < RDI_INTF_0; i++) { stream_info = msm_isp_get_stream_common_data(vfe_dev, i); @@ -747,6 +741,12 @@ void msm_isp_check_for_output_error(struct vfe_device *vfe_dev, if (stream_info->controllable_output && !vfe_dev->reg_updated) { if (stream_info->undelivered_request_cnt) { + /*report that registers are not updated + * and return empty buffer for controllable + * outputs + */ + sof_info->regs_not_updated = + !vfe_dev->reg_updated; pr_err("Drop frame no reg update\n"); if (msm_isp_drop_frame(vfe_dev, stream_info, ts, sof_info)) { @@ -933,6 +933,8 @@ void msm_isp_increment_frame_id(struct vfe_device *vfe_dev, } if (frame_src == VFE_PIX_0) { + vfe_dev->isp_page->kernel_sofid = + vfe_dev->axi_data.src_info[frame_src].frame_id; if (!src_info->frame_id && !src_info->reg_update_frame_id && ((src_info->frame_id - @@ -1646,23 +1648,30 @@ static void msm_isp_reload_ping_pong_offset( } static int msm_isp_update_deliver_count(struct vfe_device *vfe_dev, - struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_bit) + struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_bit, + struct msm_isp_buffer *done_buf) { int rc = 0; if (!stream_info->controllable_output) goto done; - if (!stream_info->undelivered_request_cnt) { + if (!stream_info->undelivered_request_cnt || + (done_buf == NULL)) { pr_err_ratelimited("%s:%d error undelivered_request_cnt 0\n", __func__, __LINE__); rc = -EINVAL; goto done; } else { + if ((done_buf->is_drop_reconfig == 1) && + (stream_info->sw_ping_pong_bit == -1)) { + goto done; + } /*After wm reload, we get bufdone for ping buffer*/ if (stream_info->sw_ping_pong_bit == -1) stream_info->sw_ping_pong_bit = 0; - stream_info->undelivered_request_cnt--; + if (done_buf->is_drop_reconfig != 1) + stream_info->undelivered_request_cnt--; if (pingpong_bit != stream_info->sw_ping_pong_bit) { pr_err("%s:%d ping pong bit actual %d sw %d\n", __func__, __LINE__, pingpong_bit, @@ -1908,7 +1917,8 @@ int msm_isp_cfg_offline_ping_pong_address(struct vfe_device *vfe_dev, } static int msm_isp_cfg_ping_pong_address( - struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status) + struct msm_vfe_axi_stream *stream_info, uint32_t pingpong_status, + struct msm_isp_buffer *buf) { int i; int j; @@ -1917,7 +1927,6 @@ static int msm_isp_cfg_ping_pong_address( uint32_t buffer_size_byte = 0; int32_t word_per_line = 0; dma_addr_t paddr; - struct msm_isp_buffer *buf = NULL; /* Isolate pingpong_bit from pingpong_status */ @@ -1928,10 +1937,11 @@ static int msm_isp_cfg_ping_pong_address( if (stream_info->buf[!pingpong_bit]) { pr_err("stream %x buffer already set for pingpong %d\n", stream_info->stream_src, !pingpong_bit); - return 0; + return 1; } - buf = msm_isp_get_stream_buffer(vfe_dev, stream_info); + if (buf == NULL) + buf = msm_isp_get_stream_buffer(vfe_dev, stream_info); if (!buf) { msm_isp_cfg_stream_scratch(stream_info, pingpong_status); @@ -2165,6 +2175,7 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, struct msm_isp_bufq *bufq = NULL; uint32_t pingpong_bit; int vfe_idx; + int rc = -1; if (!vfe_dev || !stream_info || !ts || !sof_info) { pr_err("%s %d vfe_dev %pK stream_info %pK ts %pK op_info %pK\n", @@ -2181,17 +2192,42 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, pingpong_bit = (~(pingpong_status >> stream_info->wm[vfe_idx][0]) & 0x1); done_buf = stream_info->buf[pingpong_bit]; - if (done_buf) { - bufq = vfe_dev->buf_mgr->ops->get_bufq(vfe_dev->buf_mgr, - done_buf->bufq_handle); - if (!bufq) { - spin_unlock_irqrestore(&stream_info->lock, flags); - pr_err("%s: Invalid bufq buf_handle %x\n", - __func__, done_buf->bufq_handle); - return -EINVAL; + if (done_buf && + (stream_info->composite_irq[MSM_ISP_COMP_IRQ_EPOCH] == 0)) { + if ((stream_info->sw_ping_pong_bit != -1) && + !vfe_dev->reg_updated) { + rc = msm_isp_cfg_ping_pong_address( + stream_info, ~pingpong_status, done_buf); + if (rc < 0) { + ISP_DBG("%s: Error configuring ping_pong\n", + __func__); + bufq = vfe_dev->buf_mgr->ops->get_bufq( + vfe_dev->buf_mgr, + done_buf->bufq_handle); + if (!bufq) { + spin_unlock_irqrestore( + &stream_info->lock, + flags); + pr_err("%s: Invalid bufq buf_handle %x\n", + __func__, + done_buf->bufq_handle); + return -EINVAL; + } + sof_info->reg_update_fail_mask_ext |= + (bufq->bufq_handle & 0xFF); + } + } + /*Avoid Drop Frame and re-issue pingpong cfg*/ + /*this notify is per ping and pong buffer*/ + done_buf->is_drop_reconfig = 1; + stream_info->current_framedrop_period = 1; + /*Avoid Multiple request frames for single SOF*/ + vfe_dev->axi_data.src_info[VFE_PIX_0].accept_frame = false; + + if (stream_info->current_framedrop_period != + stream_info->requested_framedrop_period) { + msm_isp_cfg_framedrop_reg(stream_info); } - sof_info->reg_update_fail_mask_ext |= - (bufq->bufq_handle & 0xFF); } spin_unlock_irqrestore(&stream_info->lock, flags); @@ -2201,6 +2237,8 @@ int msm_isp_drop_frame(struct vfe_device *vfe_dev, /* no buf done come */ msm_isp_process_axi_irq_stream(vfe_dev, stream_info, pingpong_status, ts); + if (done_buf) + done_buf->is_drop_reconfig = 0; } return 0; } @@ -2505,7 +2543,7 @@ static int msm_isp_init_stream_ping_pong_reg( /* Set address for both PING & PO NG register */ rc = msm_isp_cfg_ping_pong_address( - stream_info, VFE_PING_FLAG); + stream_info, VFE_PING_FLAG, NULL); /* No buffer available on start is not error */ if (rc == -ENOMEM && stream_info->stream_type != BURST_STREAM) return 0; @@ -2517,7 +2555,7 @@ static int msm_isp_init_stream_ping_pong_reg( if (stream_info->stream_type != BURST_STREAM || stream_info->runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address( - stream_info, VFE_PONG_FLAG); + stream_info, VFE_PONG_FLAG, NULL); /* No buffer available on start is not error */ if (rc == -ENOMEM) return 0; @@ -3516,7 +3554,7 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, if (stream_info->undelivered_request_cnt == 1) { rc = msm_isp_cfg_ping_pong_address(stream_info, - VFE_PING_FLAG); + VFE_PING_FLAG, NULL); if (rc) { spin_unlock_irqrestore(&stream_info->lock, flags); stream_info->undelivered_request_cnt--; @@ -3549,10 +3587,10 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, * now. */ rc = msm_isp_cfg_ping_pong_address(stream_info, - VFE_PONG_FLAG); + VFE_PONG_FLAG, NULL); } else { rc = msm_isp_cfg_ping_pong_address( - stream_info, pingpong_status); + stream_info, pingpong_status, NULL); } if (rc) { stream_info->undelivered_request_cnt--; @@ -3574,6 +3612,9 @@ static int msm_isp_request_frame(struct vfe_device *vfe_dev, if (0 == rc) msm_isp_reset_framedrop(vfe_dev, stream_info); + /*Avoid Multiple request frames for single SOF*/ + vfe_dev->axi_data.src_info[frame_src].accept_frame = false; + spin_unlock_irqrestore(&stream_info->lock, flags); return rc; @@ -4057,6 +4098,10 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, done_buf = stream_info->buf[pingpong_bit]; if (vfe_dev->buf_mgr->frameId_mismatch_recovery == 1) { + if (done_buf) { + if (done_buf->is_drop_reconfig == 1) + done_buf->is_drop_reconfig = 0; + } pr_err_ratelimited("%s: Mismatch Recovery in progress, drop frame!\n", __func__); spin_unlock_irqrestore(&stream_info->lock, flags); @@ -4076,14 +4121,26 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, stream_info->frame_id++; stream_info->buf[pingpong_bit] = NULL; + if (stream_info->controllable_output && + (done_buf != NULL) && + (stream_info->sw_ping_pong_bit == -1) && + (done_buf->is_drop_reconfig == 1)) { + /*When wm reloaded and corresponding reg_update fail + * then buffer is reconfig as PING buffer. so, avoid + * NULL assignment to PING buffer and eventually + * next AXI_DONE or buf_done can be successful + */ + stream_info->buf[pingpong_bit] = done_buf; + } + if (stream_info->stream_type == CONTINUOUS_STREAM || stream_info->runtime_num_burst_capture > 1) { rc = msm_isp_cfg_ping_pong_address( - stream_info, pingpong_status); + stream_info, pingpong_status, NULL); if (rc < 0) ISP_DBG("%s: Error configuring ping_pong\n", __func__); - } else if (done_buf) { + } else if (done_buf && (done_buf->is_drop_reconfig != 1)) { msm_isp_cfg_stream_scratch(stream_info, pingpong_status); } @@ -4107,8 +4164,10 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, } rc = msm_isp_update_deliver_count(vfe_dev, stream_info, - pingpong_bit); + pingpong_bit, done_buf); if (rc) { + if (done_buf->is_drop_reconfig == 1) + done_buf->is_drop_reconfig = 0; spin_unlock_irqrestore(&stream_info->lock, flags); pr_err_ratelimited("%s:VFE%d get done buf fail\n", __func__, vfe_dev->pdev->id); @@ -4117,17 +4176,28 @@ void msm_isp_process_axi_irq_stream(struct vfe_device *vfe_dev, return; } - spin_unlock_irqrestore(&stream_info->lock, flags); if ((done_buf->frame_id != frame_id) && vfe_dev->axi_data.enable_frameid_recovery) { + if (done_buf->is_drop_reconfig == 1) + done_buf->is_drop_reconfig = 0; + spin_unlock_irqrestore(&stream_info->lock, flags); msm_isp_handle_done_buf_frame_id_mismatch(vfe_dev, stream_info, done_buf, time_stamp, frame_id); return; } - msm_isp_process_done_buf(vfe_dev, stream_info, + if (done_buf->is_drop_reconfig == 1) { + /*When ping/pong buf is already reconfigured + * then dont issue buf-done for current buffer + */ + done_buf->is_drop_reconfig = 0; + spin_unlock_irqrestore(&stream_info->lock, flags); + } else { + spin_unlock_irqrestore(&stream_info->lock, flags); + msm_isp_process_done_buf(vfe_dev, stream_info, done_buf, time_stamp, frame_id); + } } void msm_isp_process_axi_irq(struct vfe_device *vfe_dev, diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/include/msm_csid_3_5_1_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csid/include/msm_csid_3_5_1_hwreg.h new file mode 100644 index 000000000000..13e560dc207d --- /dev/null +++ b/drivers/media/platform/msm/camera_v2/sensor/csid/include/msm_csid_3_5_1_hwreg.h @@ -0,0 +1,64 @@ +/* Copyright (c) 2015, The Linux Foundation. All rights reserved. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 and + * only version 2 as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +#ifndef MSM_CSID_3_5_1_HWREG_H +#define MSM_CSID_3_5_1_HWREG_H + +#include <sensor/csid/msm_csid.h> + +static uint8_t csid_lane_assign_v3_5_1[PHY_LANE_MAX] = {0, 4, 1, 2, 3}; + +static struct csid_reg_parms_t csid_v3_5_1 = { + /* MIPI CSID registers */ + 0x0, + 0x4, + 0x8, + 0x10, + 0x14, + 0x18, + 0x1C, + 0x20, + 0x24, + 0x64, + 0x68, + 0x6C, + 0x70, + 0x74, + 0x78, + 0x7C, + 0x80, + 0x88, + 0x8C, + 0x90, + 0x94, + 0x98, + 0x9C, + 0xA0, + 0xA8, + 0xAC, + 0xB4, + 0xB8, + 0xBC, + 11, + 0x7FFF, + 0x4, + 17, + 0x30050001, + 0xC, + 0x84, + 0xA4, + 0x7f010800, + 20, + 17, + 16, +}; +#endif diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c index 7ae071176ef4..9473fb0dc44e 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c @@ -27,6 +27,7 @@ #include "include/msm_csid_3_4_1_hwreg.h" #include "include/msm_csid_3_4_2_hwreg.h" #include "include/msm_csid_3_6_0_hwreg.h" +#include "include/msm_csid_3_5_1_hwreg.h" #include "cam_hw_ops.h" #define V4L2_IDENT_CSID 50002 @@ -44,6 +45,7 @@ #define CSID_VERSION_V36 0x30060000 #define CSID_VERSION_V37 0x30070000 #define CSID_VERSION_V35 0x30050000 +#define CSID_VERSION_V35_1 0x30050001 #define CSID_VERSION_V40 0x40000000 #define CSID_VERSION_V50 0x50000000 #define MSM_CSID_DRV_NAME "msm_csid" @@ -1186,6 +1188,12 @@ static int csid_probe(struct platform_device *pdev) csid_lane_assign_v3_5; new_csid_dev->hw_dts_version = CSID_VERSION_V35; } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node, + "qcom,csid-v3.5.1")) { + new_csid_dev->ctrl_reg->csid_reg = csid_v3_5_1; + new_csid_dev->ctrl_reg->csid_lane_assign = + csid_lane_assign_v3_5_1; + new_csid_dev->hw_dts_version = CSID_VERSION_V35_1; + } else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node, "qcom,csid-v5.0")) { new_csid_dev->ctrl_reg->csid_reg = csid_v3_5; new_csid_dev->ctrl_reg->csid_lane_assign = diff --git a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c index 8d091320cbca..a8d7c1f8b489 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c +++ b/drivers/media/platform/msm/camera_v2/sensor/csiphy/msm_csiphy.c @@ -437,6 +437,11 @@ static int msm_csiphy_2phase_lane_config( csiphybase = csiphy_dev->base; lane_mask = csiphy_params->lane_mask & 0x1f; + + lane_enable = msm_camera_io_r(csiphybase + + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_3ph_cmn_ctrl5.addr); + for (i = 0; i < MAX_DPHY_DATA_LN; i++) { if (mask == 0x2) { if (lane_mask & mask) @@ -474,7 +479,11 @@ static int msm_csiphy_2phase_lane_config( clk_lane = 0; } - if (csiphy_params->combo_mode == 1) { + /* In combo mode setting the 4th lane + * as clk_lane for 1 lane sensor, checking + * the lane_mask == 0x18 for one lane sensor + */ + if ((csiphy_params->combo_mode == 1) && (lane_mask == 0x18)) { val |= 0xA; if (mask == csiphy_dev->ctrl_reg-> csiphy_reg.combo_clk_mask) { @@ -520,6 +529,12 @@ static int msm_csiphy_2phase_lane_config( mipi_csiphy_2ph_lnn_cfg4.data, csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. mipi_csiphy_2ph_lnn_cfg4.addr + offset); + if (lane_mask == 0x18) + msm_camera_io_w(0x80, + csiphybase + + csiphy_dev->ctrl_reg->csiphy_3ph_reg. + mipi_csiphy_2ph_lnn_cfg1.addr + offset); + } else { msm_camera_io_w(csiphy_dev->ctrl_reg->csiphy_3ph_reg. mipi_csiphy_2ph_lnn_cfg1.data, @@ -540,8 +555,8 @@ static int msm_csiphy_2phase_lane_config( csiphy_dev->ctrl_reg->csiphy_3ph_reg. mipi_csiphy_2ph_lnn_cfg5.addr + offset); } - if (clk_lane == 1 && - csiphy_dev->hw_version == CSIPHY_VERSION_V342) { + if (clk_lane == 1 && lane_mask != 0x18 && + (csiphy_dev->hw_version == CSIPHY_VERSION_V342)) { msm_camera_io_w(0x1f, csiphybase + csiphy_dev->ctrl_reg->csiphy_3ph_reg. diff --git a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c index 167ed5492088..3f180735dd95 100644 --- a/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c +++ b/drivers/media/platform/msm/camera_v2/sensor/msm_sensor_driver.c @@ -1428,8 +1428,8 @@ static int32_t msm_sensor_driver_i2c_probe(struct i2c_client *client, rc); goto FREE_S_CTRL; } - return rc; } + return rc; FREE_S_CTRL: kfree(s_ctrl); return rc; diff --git a/drivers/media/platform/msm/vidc/msm_vdec.c b/drivers/media/platform/msm/vidc/msm_vdec.c index c80f535d95e1..5959f61c677c 100644 --- a/drivers/media/platform/msm/vidc/msm_vdec.c +++ b/drivers/media/platform/msm/vidc/msm_vdec.c @@ -1957,6 +1957,8 @@ const struct vb2_ops *msm_vdec_get_vb2q_ops(void) int msm_vdec_inst_init(struct msm_vidc_inst *inst) { int rc = 0; + struct msm_vidc_format *fmt = NULL; + if (!inst) { dprintk(VIDC_ERR, "Invalid input = %pK\n", inst); return -EINVAL; @@ -1964,12 +1966,34 @@ int msm_vdec_inst_init(struct msm_vidc_inst *inst) inst->prop.height[CAPTURE_PORT] = DEFAULT_HEIGHT; inst->prop.width[CAPTURE_PORT] = DEFAULT_WIDTH; inst->prop.num_planes[CAPTURE_PORT] = 2; - inst->fmts[CAPTURE_PORT] = vdec_formats[0]; + + /* By default, initialize CAPTURE port to NV12 format */ + fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats, + ARRAY_SIZE(vdec_formats), V4L2_PIX_FMT_NV12, + CAPTURE_PORT); + if (!fmt || fmt->type != CAPTURE_PORT) { + dprintk(VIDC_ERR, + "vdec_formats corrupted\n"); + return -EINVAL; + } + memcpy(&inst->fmts[fmt->type], fmt, + sizeof(struct msm_vidc_format)); inst->prop.height[OUTPUT_PORT] = DEFAULT_HEIGHT; inst->prop.width[OUTPUT_PORT] = DEFAULT_WIDTH; inst->prop.num_planes[OUTPUT_PORT] = 1; - inst->fmts[OUTPUT_PORT] = vdec_formats[2]; + + /* By default, initialize OUTPUT port to H264 decoder */ + fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats, + ARRAY_SIZE(vdec_formats), V4L2_PIX_FMT_H264, + OUTPUT_PORT); + if (!fmt || fmt->type != OUTPUT_PORT) { + dprintk(VIDC_ERR, + "vdec_formats corrupted\n"); + return -EINVAL; + } + memcpy(&inst->fmts[fmt->type], fmt, + sizeof(struct msm_vidc_format)); inst->capability.height.min = MIN_SUPPORTED_HEIGHT; inst->capability.height.max = DEFAULT_HEIGHT; diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c index ec6695a670b0..ebdafd66e590 100644 --- a/drivers/media/platform/msm/vidc/msm_venc.c +++ b/drivers/media/platform/msm/vidc/msm_venc.c @@ -4096,6 +4096,8 @@ const struct v4l2_ctrl_ops *msm_venc_get_ctrl_ops(void) int msm_venc_inst_init(struct msm_vidc_inst *inst) { int rc = 0; + struct msm_vidc_format *fmt = NULL; + if (!inst) { dprintk(VIDC_ERR, "Invalid input = %pK\n", inst); return -EINVAL; @@ -4103,12 +4105,34 @@ int msm_venc_inst_init(struct msm_vidc_inst *inst) inst->prop.height[CAPTURE_PORT] = DEFAULT_HEIGHT; inst->prop.width[CAPTURE_PORT] = DEFAULT_WIDTH; inst->prop.num_planes[CAPTURE_PORT] = 1; - inst->fmts[CAPTURE_PORT] = venc_formats[4]; + + /* By default, initialize CAPTURE port to H264 encoder */ + fmt = msm_comm_get_pixel_fmt_fourcc(venc_formats, + ARRAY_SIZE(venc_formats), V4L2_PIX_FMT_H264, + CAPTURE_PORT); + if (!fmt || fmt->type != CAPTURE_PORT) { + dprintk(VIDC_ERR, + "venc_formats corrupted\n"); + return -EINVAL; + } + memcpy(&inst->fmts[fmt->type], fmt, + sizeof(struct msm_vidc_format)); inst->prop.height[OUTPUT_PORT] = DEFAULT_HEIGHT; inst->prop.width[OUTPUT_PORT] = DEFAULT_WIDTH; inst->prop.num_planes[OUTPUT_PORT] = 1; - inst->fmts[OUTPUT_PORT] = venc_formats[0]; + + /* By default, initialize OUTPUT port to NV12 format */ + fmt = msm_comm_get_pixel_fmt_fourcc(venc_formats, + ARRAY_SIZE(venc_formats), V4L2_PIX_FMT_NV12, + OUTPUT_PORT); + if (!fmt || fmt->type != OUTPUT_PORT) { + dprintk(VIDC_ERR, + "venc_formats corrupted\n"); + return -EINVAL; + } + memcpy(&inst->fmts[fmt->type], fmt, + sizeof(struct msm_vidc_format)); inst->capability.height.min = MIN_SUPPORTED_HEIGHT; inst->capability.height.max = DEFAULT_HEIGHT; diff --git a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c index e602650c4cb5..ebe9ab763a68 100644 --- a/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c +++ b/drivers/misc/qcom/qdsp6v2/audio_hwacc_effects.c @@ -161,7 +161,6 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: Read buffer Allocation failed rc = %d\n", __func__, rc); rc = -ENOMEM; - mutex_unlock(&effects->lock); goto readbuf_fail; } atomic_set(&effects->out_count, effects->config.output.num_buf); @@ -176,7 +175,6 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, if (rc < 0) { pr_err("%s: pcm read block config failed\n", __func__); rc = -EINVAL; - mutex_unlock(&effects->lock); goto cfg_fail; } pr_debug("%s: dec: sample_rate: %d, num_channels: %d, bit_width: %d\n", @@ -191,7 +189,6 @@ static int audio_effects_shared_ioctl(struct file *file, unsigned cmd, pr_err("%s: pcm write format block config failed\n", __func__); rc = -EINVAL; - mutex_unlock(&effects->lock); goto cfg_fail; } @@ -325,6 +322,7 @@ ioctl_fail: readbuf_fail: q6asm_audio_client_buf_free_contiguous(IN, effects->ac); + mutex_unlock(&effects->lock); return rc; cfg_fail: q6asm_audio_client_buf_free_contiguous(IN, @@ -332,6 +330,7 @@ cfg_fail: q6asm_audio_client_buf_free_contiguous(OUT, effects->ac); effects->buf_alloc = 0; + mutex_unlock(&effects->lock); return rc; } diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c index c01f59955797..aa20ebbefe94 100644 --- a/drivers/net/wireless/ath/ath10k/htc.c +++ b/drivers/net/wireless/ath/ath10k/htc.c @@ -86,7 +86,8 @@ static void ath10k_htc_prepare_tx_skb(struct ath10k_htc_ep *ep, hdr->eid = ep->eid; hdr->len = __cpu_to_le16(skb->len - sizeof(*hdr)); hdr->flags = 0; - hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE; + if (ep->tx_credit_flow_enabled) + hdr->flags |= ATH10K_HTC_FLAG_NEED_CREDIT_UPDATE; spin_lock_bh(&ep->htc->tx_lock); hdr->seq_no = ep->seq_no++; diff --git a/drivers/net/wireless/cnss2/pci.c b/drivers/net/wireless/cnss2/pci.c index 8d34d74477eb..9bf4c7e11c66 100644 --- a/drivers/net/wireless/cnss2/pci.c +++ b/drivers/net/wireless/cnss2/pci.c @@ -129,9 +129,10 @@ int cnss_suspend_pci_link(struct cnss_pci_data *pci_priv) pci_disable_device(pci_priv->pci_dev); - ret = pci_set_power_state(pci_priv->pci_dev, PCI_D3hot); - if (ret) - cnss_pr_err("Failed to set D3Hot, err = %d\n", ret); + if (pci_priv->pci_dev->device != QCA6174_DEVICE_ID) { + if (pci_set_power_state(pci_priv->pci_dev, PCI_D3hot)) + cnss_pr_err("Failed to set D3Hot, err = %d\n", ret); + } ret = cnss_set_pci_link(pci_priv, PCI_LINK_DOWN); if (ret) diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c index 491dda6ff7e8..b1a57d8853e8 100644 --- a/drivers/power/supply/qcom/qpnp-fg-gen3.c +++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c @@ -2733,6 +2733,49 @@ static bool is_profile_load_required(struct fg_chip *chip) return true; } +static void fg_update_batt_profile(struct fg_chip *chip) +{ + int rc, offset; + u8 val; + + rc = fg_sram_read(chip, PROFILE_INTEGRITY_WORD, + SW_CONFIG_OFFSET, &val, 1, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in reading SW_CONFIG_OFFSET, rc=%d\n", rc); + return; + } + + /* + * If the RCONN had not been updated, no need to update battery + * profile. Else, update the battery profile so that the profile + * modified by bootloader or HLOS matches with the profile read + * from device tree. + */ + + if (!(val & RCONN_CONFIG_BIT)) + return; + + rc = fg_sram_read(chip, ESR_RSLOW_CHG_WORD, + ESR_RSLOW_CHG_OFFSET, &val, 1, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in reading ESR_RSLOW_CHG_OFFSET, rc=%d\n", rc); + return; + } + offset = (ESR_RSLOW_CHG_WORD - PROFILE_LOAD_WORD) * 4 + + ESR_RSLOW_CHG_OFFSET; + chip->batt_profile[offset] = val; + + rc = fg_sram_read(chip, ESR_RSLOW_DISCHG_WORD, + ESR_RSLOW_DISCHG_OFFSET, &val, 1, FG_IMA_DEFAULT); + if (rc < 0) { + pr_err("Error in reading ESR_RSLOW_DISCHG_OFFSET, rc=%d\n", rc); + return; + } + offset = (ESR_RSLOW_DISCHG_WORD - PROFILE_LOAD_WORD) * 4 + + ESR_RSLOW_DISCHG_OFFSET; + chip->batt_profile[offset] = val; +} + static void clear_battery_profile(struct fg_chip *chip) { u8 val = 0; @@ -2816,6 +2859,8 @@ static void profile_load_work(struct work_struct *work) if (!chip->profile_available) goto out; + fg_update_batt_profile(chip); + if (!is_profile_load_required(chip)) goto done; @@ -2877,6 +2922,10 @@ done: rc); } + rc = fg_rconn_config(chip); + if (rc < 0) + pr_err("Error in configuring Rconn, rc=%d\n", rc); + batt_psy_initialized(chip); fg_notify_charger(chip); chip->profile_loaded = true; @@ -4076,12 +4125,6 @@ static int fg_hw_init(struct fg_chip *chip) return rc; } - rc = fg_rconn_config(chip); - if (rc < 0) { - pr_err("Error in configuring Rconn, rc=%d\n", rc); - return rc; - } - fg_encode(chip->sp, FG_SRAM_ESR_TIGHT_FILTER, chip->dt.esr_tight_flt_upct, buf); rc = fg_sram_write(chip, chip->sp[FG_SRAM_ESR_TIGHT_FILTER].addr_word, diff --git a/drivers/soc/qcom/qdsp6v2/msm_audio_ion_vm.c b/drivers/soc/qcom/qdsp6v2/msm_audio_ion_vm.c index a3aa8823d8ce..afc40461e8e8 100644 --- a/drivers/soc/qcom/qdsp6v2/msm_audio_ion_vm.c +++ b/drivers/soc/qcom/qdsp6v2/msm_audio_ion_vm.c @@ -22,7 +22,6 @@ #include <linux/msm_audio_ion.h> #include <linux/habmm.h> #include "../../../staging/android/ion/ion_priv.h" -#include "../../../staging/android/ion/ion_hvenv_driver.h" #define MSM_AUDIO_ION_PROBED (1 << 0) @@ -628,7 +627,7 @@ struct ion_client *msm_audio_ion_client_create(const char *name) { struct ion_client *pclient = NULL; - pclient = hvenv_ion_client_create(name); + pclient = msm_ion_client_create(name); return pclient; } diff --git a/drivers/soc/qcom/service-locator.c b/drivers/soc/qcom/service-locator.c index f19db5fe99b3..52355699e4f3 100644 --- a/drivers/soc/qcom/service-locator.c +++ b/drivers/soc/qcom/service-locator.c @@ -149,11 +149,10 @@ static void service_locator_recv_msg(struct work_struct *work) do { pr_debug("Notified about a Receive event\n"); - ret = qmi_recv_msg(service_locator.clnt_handle); - if (ret < 0) - pr_err("Error receiving message rc:%d. Retrying...\n", - ret); - } while (ret == 0); + } while ((ret = qmi_recv_msg(service_locator.clnt_handle)) == 0); + + if (ret != -ENOMSG) + pr_err("Error receiving message rc:%d\n", ret); } @@ -190,7 +189,7 @@ static int servreg_loc_send_msg(struct msg_desc *req_desc, */ rc = qmi_send_req_wait(service_locator.clnt_handle, req_desc, req, sizeof(*req), resp_desc, resp, sizeof(*resp), - msecs_to_jiffies(QMI_SERVREG_LOC_SERVER_TIMEOUT)); + QMI_SERVREG_LOC_SERVER_TIMEOUT); if (rc < 0) { pr_err("QMI send req failed for client %s, ret - %d\n", pd->client_name, rc); diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index c08a524f3dab..5644051b4010 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -4294,6 +4294,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, enum usb_device_speed oldspeed = udev->speed; const char *speed; int devnum = udev->devnum; + char *error_event[] = { + "USB_DEVICE_ERROR=Device_No_Response", NULL }; /* root hub ports have a slightly longer reset period * (from USB 2.0 spec, section 7.1.7.5) @@ -4467,6 +4469,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, if (r != -ENODEV) dev_err(&udev->dev, "device descriptor read/64, error %d\n", r); + kobject_uevent_env(&udev->parent->dev.kobj, + KOBJ_CHANGE, error_event); retval = -EMSGSIZE; continue; } @@ -4519,6 +4523,8 @@ hub_port_init(struct usb_hub *hub, struct usb_device *udev, int port1, dev_err(&udev->dev, "device descriptor read/8, error %d\n", retval); + kobject_uevent_env(&udev->parent->dev.kobj, + KOBJ_CHANGE, error_event); if (retval >= 0) retval = -EMSGSIZE; } else { diff --git a/drivers/video/fbdev/msm/mdss_dp_util.c b/drivers/video/fbdev/msm/mdss_dp_util.c index 037741df4382..5cb141b1d5e7 100644 --- a/drivers/video/fbdev/msm/mdss_dp_util.c +++ b/drivers/video/fbdev/msm/mdss_dp_util.c @@ -1233,6 +1233,7 @@ static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io, /* Config header and parity byte 1 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_STREAM_0); + value &= 0x0000ffff; new_value = 0x02; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_1_BIT) @@ -1243,7 +1244,8 @@ static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io, /* Config header and parity byte 2 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_STREAM_1); - new_value = value; + value &= 0xffff0000; + new_value = 0x00; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_2_BIT) | (parity_byte << PARITY_BYTE_2_BIT)); @@ -1253,6 +1255,7 @@ static void mdss_dp_audio_setup_audio_stream_sdp(struct dss_io_data *ctrl_io, /* Config header and parity byte 3 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_STREAM_1); + value &= 0x0000ffff; new_value = num_of_channels - 1; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_3_BIT) @@ -1271,6 +1274,7 @@ static void mdss_dp_audio_setup_audio_timestamp_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 1 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_TIMESTAMP_0); + value &= 0x0000ffff; new_value = 0x1; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_1_BIT) @@ -1281,6 +1285,7 @@ static void mdss_dp_audio_setup_audio_timestamp_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 2 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_TIMESTAMP_1); + value &= 0xffff0000; new_value = 0x17; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_2_BIT) @@ -1291,6 +1296,7 @@ static void mdss_dp_audio_setup_audio_timestamp_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 3 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_TIMESTAMP_1); + value &= 0x0000ffff; new_value = (0x0 | (0x11 << 2)); parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_3_BIT) @@ -1308,6 +1314,7 @@ static void mdss_dp_audio_setup_audio_infoframe_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 1 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_INFOFRAME_0); + value &= 0x0000ffff; new_value = 0x84; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_1_BIT) @@ -1318,6 +1325,7 @@ static void mdss_dp_audio_setup_audio_infoframe_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 2 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_INFOFRAME_1); + value &= 0xffff0000; new_value = 0x1b; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_2_BIT) @@ -1328,6 +1336,7 @@ static void mdss_dp_audio_setup_audio_infoframe_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 3 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_INFOFRAME_1); + value &= 0x0000ffff; new_value = (0x0 | (0x11 << 2)); parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_3_BIT) @@ -1349,6 +1358,7 @@ static void mdss_dp_audio_setup_copy_management_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 1 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_COPYMANAGEMENT_0); + value &= 0x0000ffff; new_value = 0x05; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_1_BIT) @@ -1361,6 +1371,7 @@ static void mdss_dp_audio_setup_copy_management_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 2 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_COPYMANAGEMENT_1); + value &= 0xffff0000; new_value = 0x0F; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_2_BIT) @@ -1373,6 +1384,7 @@ static void mdss_dp_audio_setup_copy_management_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 3 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_COPYMANAGEMENT_1); + value &= 0x0000ffff; new_value = 0x0; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_3_BIT) @@ -1398,6 +1410,7 @@ static void mdss_dp_audio_setup_isrc_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 1 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_ISRC_0); + value &= 0x0000ffff; new_value = 0x06; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_1_BIT) @@ -1408,6 +1421,7 @@ static void mdss_dp_audio_setup_isrc_sdp(struct dss_io_data *ctrl_io) /* Config header and parity byte 2 */ value = readl_relaxed(ctrl_io->base + MMSS_DP_AUDIO_ISRC_1); + value &= 0xffff0000; new_value = 0x0F; parity_byte = mdss_dp_calculate_parity_byte(new_value); value |= ((new_value << HEADER_BYTE_2_BIT) diff --git a/drivers/video/fbdev/msm/mdss_mdp_util.c b/drivers/video/fbdev/msm/mdss_mdp_util.c index 1ae3d0ba4ec6..6015ed20fe56 100644 --- a/drivers/video/fbdev/msm/mdss_mdp_util.c +++ b/drivers/video/fbdev/msm/mdss_mdp_util.c @@ -524,11 +524,12 @@ int mdss_mdp_get_plane_sizes(struct mdss_mdp_format_params *fmt, u32 w, u32 h, if (ps == NULL) return -EINVAL; + memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes)); + if ((w > MAX_IMG_WIDTH) || (h > MAX_IMG_HEIGHT)) return -ERANGE; bpp = fmt->bpp; - memset(ps, 0, sizeof(struct mdss_mdp_plane_sizes)); if (mdss_mdp_is_ubwc_format(fmt)) { rc = mdss_mdp_get_ubwc_plane_size(fmt, w, h, ps); diff --git a/drivers/video/msm/ba/msm_ba.c b/drivers/video/msm/ba/msm_ba.c index 8d1459088b80..0fc251f026b1 100644 --- a/drivers/video/msm/ba/msm_ba.c +++ b/drivers/video/msm/ba/msm_ba.c @@ -555,6 +555,24 @@ long msm_ba_private_ioctl(void *instance, int cmd, void *arg) } } break; + case VIDIOC_CVBS_G_FIELD_STATUS: { + dprintk(BA_DBG, "VIDIOC_CVBS_G_FIELD_STATUS"); + sd = inst->sd; + if (!sd) { + dprintk(BA_ERR, "No sd registered"); + return -EINVAL; + } + if (s_ioctl) { + rc = v4l2_subdev_call(sd, core, ioctl, cmd, s_ioctl); + if (rc) + dprintk(BA_ERR, "%s failed: %ld on cmd: 0x%x", + __func__, rc, cmd); + } else { + dprintk(BA_ERR, "%s: NULL argument provided", __func__); + rc = -EINVAL; + } + } + break; default: dprintk(BA_WARN, "Not a typewriter! Command: 0x%x", cmd); rc = -ENOTTY; diff --git a/include/media/msm_ba.h b/include/media/msm_ba.h index d630e441590f..e13509585e5a 100644 --- a/include/media/msm_ba.h +++ b/include/media/msm_ba.h @@ -18,6 +18,9 @@ #include <media/v4l2-device.h> #include <linux/poll.h> +/* Control ID to fetch register Values */ +#define VIDIOC_CVBS_G_FIELD_STATUS _IOR('V', BASE_VIDIOC_PRIVATE + 5, int) + enum msm_ba_ip { BA_IP_CVBS_0 = 0, BA_IP_CVBS_1, diff --git a/include/uapi/media/ais/msm_ais_isp.h b/include/uapi/media/ais/msm_ais_isp.h index 7c9daafc404d..e093e84ed3f8 100644 --- a/include/uapi/media/ais/msm_ais_isp.h +++ b/include/uapi/media/ais/msm_ais_isp.h @@ -23,6 +23,9 @@ #define ISP_STATS_STREAM_BIT 0x80000000 +#define INTERLACE_SUPPORT +#define INTERLACE_OFFSET (1) + struct msm_vfe_cfg_cmd_list; enum ISP_START_PIXEL_PATTERN { @@ -733,6 +736,7 @@ struct msm_isp_buf_event { uint32_t handle; uint32_t output_format; int8_t buf_idx; + uint8_t field_type; }; struct msm_isp_fetch_eng_event { uint32_t session_id; diff --git a/security/pfe/pfk_ice.c b/security/pfe/pfk_ice.c index facecedc3827..2bf18b74bfd5 100644 --- a/security/pfe/pfk_ice.c +++ b/security/pfe/pfk_ice.c @@ -68,25 +68,34 @@ int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt, char *storage_type) { struct scm_desc desc = {0}; - int ret; + int ret, ret1; char *tzbuf_key = (char *)ice_key; char *tzbuf_salt = (char *)ice_salt; + char *s_type = storage_type; uint32_t smc_id = 0; u32 tzbuflen_key = sizeof(ice_key); u32 tzbuflen_salt = sizeof(ice_salt); - if (index < MIN_ICE_KEY_INDEX || index > MAX_ICE_KEY_INDEX) + if (index < MIN_ICE_KEY_INDEX || index > MAX_ICE_KEY_INDEX) { + pr_err("%s Invalid index %d\n", __func__, index); return -EINVAL; + } - if (!key || !salt) + if (!key || !salt) { + pr_err("%s Invalid key/salt\n", __func__); return -EINVAL; + } - if (!tzbuf_key || !tzbuf_salt) + if (!tzbuf_key || !tzbuf_salt) { + pr_err("%s No Memory\n", __func__); return -ENOMEM; + } - if (storage_type == NULL) + if (s_type == NULL) { + pr_err("%s Invalid storage\n", __func__); return -EINVAL; + } memset(tzbuf_key, 0, tzbuflen_key); memset(tzbuf_salt, 0, tzbuflen_salt); @@ -98,7 +107,6 @@ int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt, dmac_flush_range(tzbuf_salt, tzbuf_salt + tzbuflen_salt); smc_id = TZ_ES_SET_ICE_KEY_ID; - pr_debug(" %s , smc_id = 0x%x\n", __func__, smc_id); desc.arginfo = TZ_ES_SET_ICE_KEY_PARAM_ID; desc.args[0] = index; @@ -107,27 +115,36 @@ int qti_pfk_ice_set_key(uint32_t index, uint8_t *key, uint8_t *salt, desc.args[3] = virt_to_phys(tzbuf_salt); desc.args[4] = tzbuflen_salt; - ret = qcom_ice_setup_ice_hw((const char *)storage_type, true); + ret = qcom_ice_setup_ice_hw((const char *)s_type, true); if (ret) { - pr_err("%s: could not enable clocks: 0x%x\n", __func__, ret); - return ret; + pr_err("%s: could not enable clocks: %d\n", __func__, ret); + goto out; } ret = scm_call2(smc_id, &desc); - ret = qcom_ice_setup_ice_hw((const char *)storage_type, false); - pr_debug(" %s , ret = %d\n", __func__, ret); - if (ret) { - pr_err("%s: Error: 0x%x\n", __func__, ret); + if (ret) { + pr_err("%s: Set key Error: %d\n", __func__, ret); + if (ret == -EBUSY) { + if (qcom_ice_setup_ice_hw((const char *)s_type, false)) + pr_err("%s: disable clock failed\n", __func__); + goto out; + } + /*Try to invalidate the key to keep ICE in proper state*/ smc_id = TZ_ES_INVALIDATE_ICE_KEY_ID; desc.arginfo = TZ_ES_INVALIDATE_ICE_KEY_PARAM_ID; desc.args[0] = index; - scm_call2(smc_id, &desc); + ret1 = scm_call2(smc_id, &desc); + if (ret1) + pr_err("%s:Invalidate key Error: %d\n", __func__, + ret1); } + ret = qcom_ice_setup_ice_hw((const char *)s_type, false); +out: return ret; } @@ -139,14 +156,17 @@ int qti_pfk_ice_invalidate_key(uint32_t index, char *storage_type) uint32_t smc_id = 0; - if (index < MIN_ICE_KEY_INDEX || index > MAX_ICE_KEY_INDEX) + if (index < MIN_ICE_KEY_INDEX || index > MAX_ICE_KEY_INDEX) { + pr_err("%s Invalid index %d\n", __func__, index); return -EINVAL; + } - if (storage_type == NULL) + if (storage_type == NULL) { + pr_err("%s Invalid storage\n", __func__); return -EINVAL; + } smc_id = TZ_ES_INVALIDATE_ICE_KEY_ID; - pr_debug(" %s , smc_id = 0x%x\n", __func__, smc_id); desc.arginfo = TZ_ES_INVALIDATE_ICE_KEY_PARAM_ID; desc.args[0] = index; @@ -160,12 +180,13 @@ int qti_pfk_ice_invalidate_key(uint32_t index, char *storage_type) ret = scm_call2(smc_id, &desc); - ret = qcom_ice_setup_ice_hw((const char *)storage_type, false); - - pr_debug(" %s , ret = %d\n", __func__, ret); - if (ret) + if (ret) { pr_err("%s: Error: 0x%x\n", __func__, ret); + if (qcom_ice_setup_ice_hw((const char *)storage_type, false)) + pr_err("%s: could not disable clocks\n", __func__); + } else { + ret = qcom_ice_setup_ice_hw((const char *)storage_type, false); + } return ret; - } |
