qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
- qcom,mdss-dsi-reset-sequence = <1 200>, <0 200>, <1 200>;
+ qcom,mdss-dsi-reset-sequence = <1 400>, <0 400>, <1 400>;
qcom,mdss-dsi-tx-eot-append;
qcom,mdss-dsi-post-init-delay = <1>;
};
};
};
- aliases {
- mhi_rmnet0 = &mhi_rmnet_0;
- mhi_rmnet1 = &mhi_rmnet_1;
- mhi_uci0 = &mhi_uci;
- mhi0 = &mhi;
- };
-
gpio-leds {
compatible = "gpio-leds";
gpio = <&tlmm 125 0>;
};
- mhi_rmnet_0: qcom,mhi-rmnet@0 {
- compatible = "qcom,mhi-rmnet";
- cell-index = <0>;
- qcom,mhi = <&mhi>;
- qcom,mhi-rx-channel = <101>;
- qcom,mhi-tx-channel = <100>;
- qcom,mhi-mru = <0x4000>;
- status = "okay";
- };
-
- mhi_rmnet_1: qcom,mhi-rmnet@1 {
- compatible = "qcom,mhi-rmnet";
- cell-index = <1>;
- qcom,mhi = <&mhi>;
- qcom,mhi-rx-channel = <47>;
- qcom,mhi-tx-channel = <46>;
- qcom,mhi-mru = <0x4000>;
- qcom,interface-name = "mhi_swip";
- status = "okay";
- };
-
- mhi_uci: qcom,mhi-uci {
- compatible = "qcom,mhi-uci";
- qcom,mhi-uci-channels = <0 0xffff>,
- <1 0x1000>,
- <2 0xffff>,
- <3 0xffff>,
- <10 0xffff>,
- <11 0x1000>,
- <14 0xffff>,
- <15 0x1000>,
- <16 0xffff>,
- <17 0x1000>,
- <18 0xffff>,
- <19 0x1000>,
- <22 0xffff>,
- <23 0x1000>,
- <24 0xffff>,
- <25 0x1000>,
- <32 0xffff>,
- <33 0x1000>;
- qcom,mhi-uci-ctrlchan = <18>;
- qcom,mhi = <&mhi>;
- status = "okay";
- };
-
qcom,diagfwd-usb {
compatible = "qcom,diagfwd-usb";
status = "okay";
/delete-property/ qcom,l1ss-supported;
};
-&mdm3 {
- pinctrl-names = "mdm_active", "mdm_suspend";
- pinctrl-0 = <&ap2mdm_active &mdm2ap_active>;
- pinctrl-1 = <&ap2mdm_sleep &mdm2ap_sleep>;
- interrupt-map = <0 &tlmm 108 0x3
- 1 &tlmm 106 0x3
- 2 &tlmm 112 0x3>;
- qcom,mdm2ap-errfatal-gpio = <&tlmm 108 0x00>;
- qcom,ap2mdm-errfatal-gpio = <&tlmm 109 0x00>;
- qcom,mdm2ap-status-gpio = <&tlmm 106 0x00>;
- qcom,ap2mdm-status-gpio = <&tlmm 107 0x00>;
- qcom,ap2mdm-soft-reset-gpio = <&pm8994_mpps 2 0x00>;
- qcom,ap2mdm-vddmin-gpio = <&tlmm 111 0x00>;
- qcom,mdm2ap-vddmin-gpio = <&tlmm 112 0x00>;
- qcom,mdm-auto-boot;
- qcom,ignore-ssr-failure;
- qcom,mdm-link-info = "0302_02.01.00";
- qcom,mdm-statusline-not-a-powersource;
- qcom,mdm-userspace-handle-shutdown;
- qcom,pil-force-shutdown;
- qcom,shutdown-timeout-ms = <30000>;
- qcom,reset-time-ms = <16203>;
- status = "okay";
-};
-
-&mhi {
- qcom,mhi-address-window = <0x0 0x80000000 0x1 0xffffffff>;
- qcom,pci-dev_id = <0x0302>;
- qcom,pci-domain = <2>;
- qcom,pci-bus = <1>;
- qcom,pci-slot = <0>;
- esoc-names = "mdm";
- esoc-0 = <&mdm3>;
- qcom,msm-bus,name = "mhi";
- qcom,msm-bus,num-cases = <2>;
- qcom,msm-bus,num-paths = <1>;
- qcom,msm-bus,vectors-KBps =
- <100 512 0 0>,
- <100 512 1200000000 650000000>;
- mhi-chan-cfg-0 = <0x0 0x80 0x2 0x92>;
- mhi-chan-cfg-1 = <0x1 0x80 0x2 0xa2>;
- mhi-chan-cfg-2 = <0x2 0x80 0x1 0x91>;
- mhi-chan-cfg-3 = <0x3 0x80 0x1 0xa1>;
- mhi-chan-cfg-4 = <0x4 0x80 0x2 0x92>;
- mhi-chan-cfg-5 = <0x5 0x80 0x2 0xa2>;
- mhi-chan-cfg-6 = <0x6 0xa 0x2 0x92>;
- mhi-chan-cfg-7 = <0x7 0xa 0x2 0xa2>;
- mhi-chan-cfg-10 = <0xa 0x80 0x1 0x92>;
- mhi-chan-cfg-11 = <0xb 0x80 0x1 0xa2>;
- mhi-chan-cfg-14 = <0xe 0x40 0x1 0x92>;
- mhi-chan-cfg-15 = <0xf 0x40 0x1 0xa2>;
- mhi-chan-cfg-16 = <0x10 0x40 0x1 0x92>;
- mhi-chan-cfg-17 = <0x11 0x40 0x1 0xa2>;
- mhi-chan-cfg-18 = <0x12 0x40 0x1 0x92>;
- mhi-chan-cfg-19 = <0x13 0x40 0x1 0xa2>;
- mhi-chan-cfg-20 = <0x14 0xa 0x2 0x92>;
- mhi-chan-cfg-21 = <0x15 0xa 0x2 0xa2>;
- mhi-chan-cfg-22 = <0x16 0x40 0x2 0x92>;
- mhi-chan-cfg-23 = <0x17 0x40 0x2 0xa2>;
- mhi-chan-cfg-24 = <0x18 0xa 0x1 0x91>;
- mhi-chan-cfg-25 = <0x19 0xa 0x1 0xa1>;
- mhi-chan-cfg-32 = <0x20 0x80 0x2 0x92>;
- mhi-chan-cfg-33 = <0x21 0x80 0x2 0xa2>;
- mhi-chan-cfg-34 = <0x22 0x80 0x2 0x92>;
- mhi-chan-cfg-35 = <0x23 0x80 0x2 0xa2>;
- mhi-chan-cfg-46 = <0x2e 0x80 0x2 0x412>;
- mhi-chan-cfg-47 = <0x2f 0x80 0x3 0x422>;
- mhi-chan-cfg-100 = <0x64 0x80 0x4 0x652>;
- mhi-chan-cfg-101 = <0x65 0x80 0x5 0x762>;
- mhi-event-rings = <6>;
- mhi-event-cfg-0 = <0x80 0x0 0x1 0 1 0x11>;
- mhi-event-cfg-1 = <0x80 0x1 0x1 0 1 0x11>;
- mhi-event-cfg-2 = <0x80 0x2 0x5 0 2 0x11>;
- mhi-event-cfg-3 = <0x100 0x3 0x1 47 1 0x48>;
- mhi-event-cfg-4 = <0x100 0x4 0x1 100 1 0x69>;
- mhi-event-cfg-5 = <0x100 0x5 0x1 101 1 0x68>;
- status = "okay";
-};
-
&pm8994_gpios {
gpio@c700 { /* GPIO 8 - WLAN_EN */
qcom,mode = <1>; /* Digital output*/
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
qcom,panel-roi-alignment = <2 2 4 2 1080 2>;
};
+&dsi_lgd_incell_sw49106_fhd_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
+
&pm660l_pwm_4 {
qcom,dtest-line = <2>; /* DTEST2 */
qcom,dtest-output = <2>; /* OUTPUT PWM */
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
#include "dsi-panel-truly-1080p-video.dtsi"
#include "dsi-panel-rm67195-amoled-fhd-cmd.dtsi"
#include "dsi-panel-sharp-split-link-wuxga-video.dtsi"
+#include "dsi-panel-lgd-incell-sw49106-fhd-video.dtsi"
&soc {
dsi_panel_pwr_supply: dsi_panel_pwr_supply {
qcom,mdss-dsi-pan-enable-dynamic-fps;
qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
};
+
+&dsi_lgd_incell_sw49106_fhd_video {
+ qcom,mdss-dsi-panel-timings-phy-v2 = [24 1f 08 09 05 03 04 a0
+ 24 1f 08 09 05 03 04 a0
+ 24 1f 08 09 05 03 04 a0
+ 24 1f 08 09 05 03 04 a0
+ 24 1b 08 09 05 03 04 a0];
+ qcom,mdss-dsi-t-clk-post = <0x0d>;
+ qcom,mdss-dsi-t-clk-pre = <0x30>;
+};
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, 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
&dsi_rm67195_amoled_fhd_cmd {
qcom,panel-supply-entries = <&dsi_panel_pwr_supply_labibb_amoled>;
};
+
+&dsi_lgd_incell_sw49106_fhd_video {
+ qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+ qcom,mdss-dsi-bl-min-level = <1>;
+ qcom,mdss-dsi-bl-max-level = <4095>;
+ qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+};
qcom,msm-id = <246 0x0>;
};
+&ion {
+ /delete-node/ qcom,ion-heap@25;
+
+ system_heap: qcom,ion-heap@25 {
+ reg = <25>;
+ qcom,ion-heap-type = "SYSTEM";
+ };
+
+ audio_heap: qcom,ion-heap@28 {
+ reg = <28>;
+ memory-region = <&ion_audio>;
+ qcom,ion-heap-type = "CARVEOUT";
+ };
+};
+
&reserved_memory {
pmem_shared: pmem_shared_region@1154ca000 {
reg = <0x1 0x154ca000 0x0 0x154ca000>;
label = "pmem_shared_mem";
};
- ion_system: ion_system_region@12a994000 {
- reg = <0x1 0x2a994000 0x0 0x154ca000>;
- label = "ion_system_mem";
+ ion_audio: ion_audio_region {
+ reg = <0 0xf0000000 0 0x00400000>;
+ label = "ion_audio_mem";
};
};
CONFIG_IOMMU_IO_PGTABLE_FAST=y
CONFIG_ARM_SMMU=y
CONFIG_IOMMU_DEBUG=y
-CONFIG_IOMMU_TESTS=y
CONFIG_MSM_PASR=y
CONFIG_MSM_SMEM=y
CONFIG_QPNP_HAPTIC=y
CONFIG_ARM_SMMU=y
CONFIG_IOMMU_DEBUG=y
CONFIG_IOMMU_DEBUG_TRACKING=y
-CONFIG_IOMMU_TESTS=y
CONFIG_MSM_PASR=y
CONFIG_MSM_SMEM=y
CONFIG_QPNP_HAPTIC=y
/* Qualcomm Crypto Engine driver.
*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, 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
struct sps_iovec *iovec = sps_bam_pipe->iovec +
sps_bam_pipe->iovec_count;
+ if (!sg_src)
+ return -ENOENT;
+
while (nbytes > 0) {
len = min(nbytes, sg_dma_len(sg_src));
nbytes -= len;
#include <asm/dma-iommu.h>
#include "iommu-debug.h"
-#if defined(CONFIG_IOMMU_DEBUG_TRACKING) || defined(CONFIG_IOMMU_TESTS)
+#if defined(CONFIG_IOMMU_TESTS)
static const char *iommu_debug_attr_to_string(enum iommu_attr attr)
{
k_ioctl = *ptr;
switch (k_ioctl.id) {
case MSM_CAMERA_BUF_MNGR_IOCTL_ID_GET_BUF_BY_IDX: {
+ struct msm_buf_mngr_info buf_info, *tmp = NULL;
if (k_ioctl.size != sizeof(struct msm_buf_mngr_info))
return -EINVAL;
if (!k_ioctl.ioctl_ptr)
return -EINVAL;
-#ifndef CONFIG_COMPAT
- {
- struct msm_buf_mngr_info buf_info, *tmp = NULL;
-
+ if (!is_compat_task()) {
MSM_CAM_GET_IOCTL_ARG_PTR(&tmp,
&k_ioctl.ioctl_ptr, sizeof(tmp));
if (copy_from_user(&buf_info, tmp,
}
k_ioctl.ioctl_ptr = (uintptr_t)&buf_info;
}
-#endif
+
argp = &k_ioctl;
rc = msm_cam_buf_mgr_ops(cmd, argp);
}
vma = find_vma(current->mm, address);
if (!vma || !vma->vm_file) {
pr_err("cannot find vma\n");
+ rc = -EBADF;
goto err;
}
fd = iterate_fd(current->files, 0, match_file, vma->vm_file);
if (fd == 0) {
pr_err("iterate_fd failed\n");
+ rc = -EBADF;
goto err;
}
page_offset = offset/PAGE_SIZE;
dmabuf = dma_buf_get(fd - 1);
+ if (IS_ERR_OR_NULL(dmabuf)) {
+ pr_err("dma_buf_get failed fd %d ret %pK\n", fd, dmabuf);
+ rc = -EBADF;
+ goto err;
+ }
attach = dma_buf_attach(dmabuf, hab_driver.dev);
if (IS_ERR_OR_NULL(attach)) {
pr_err("dma_buf_attach failed\n");
+ rc = -EBADF;
goto err;
}
if (IS_ERR_OR_NULL(sg_table)) {
pr_err("dma_buf_map_attachment failed\n");
+ rc = -EBADF;
goto err;
}
int i, j, rc = 0;
dmabuf = dma_buf_get(fd);
- if (IS_ERR(dmabuf))
- return PTR_ERR(dmabuf);
+ if (IS_ERR_OR_NULL(dmabuf)) {
+ pr_err("dma_buf_get failed fd %d ret %pK\n", fd, dmabuf);
+ rc = -EBADF;
+ goto err;
+ }
attach = dma_buf_attach(dmabuf, hab_driver.dev);
if (IS_ERR_OR_NULL(attach)) {
pr_err("dma_buf_attach failed\n");
+ rc = -EBADF;
goto err;
}
if (IS_ERR_OR_NULL(sg_table)) {
pr_err("dma_buf_map_attachment failed\n");
+ rc = -EBADF;
goto err;
}
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, 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
/* Wait for ch connect state before sending any command */
wait_queue_head_t ch_connect_wait;
+ /* Wait for ch local and remote disconnect before channel free */
+ wait_queue_head_t ch_free_wait;
+
/*
* Glink channel configuration. This has to be the last
* member of the strucuture as it has variable size
mutex_lock(&ch->mutex);
ch->channel_state = event;
if (event == GLINK_CONNECTED) {
- dev_dbg(wpriv->dev, "%s: glink channel: %s connected\n",
+ dev_info(wpriv->dev, "%s: glink channel: %s connected\n",
__func__, ch->ch_cfg.name);
for (i = 0; i < ch->ch_cfg.no_of_intents; i++) {
ch->ch_cfg.name);
wake_up(&ch->ch_connect_wait);
- mutex_unlock(&ch->mutex);
} else if (event == GLINK_LOCAL_DISCONNECTED) {
/*
* Don't use dev_dbg here as dev may not be valid if channel
* closed from driver close.
*/
- pr_debug("%s: channel: %s disconnected locally\n",
+ pr_info("%s: channel: %s disconnected locally\n",
__func__, ch->ch_cfg.name);
mutex_unlock(&ch->mutex);
-
- if (ch->free_mem) {
- kfree(ch);
- ch = NULL;
- }
+ ch->free_mem = true;
+ wake_up(&ch->ch_free_wait);
+ return;
} else if (event == GLINK_REMOTE_DISCONNECTED) {
- dev_dbg(wpriv->dev, "%s: remote channel: %s disconnected remotely\n",
+ pr_info("%s: remote channel: %s disconnected remotely\n",
__func__, ch->ch_cfg.name);
- mutex_unlock(&ch->mutex);
/*
* If remote disconnect happens, local side also has
* to close the channel as per glink design in a
* separate work_queue.
*/
- queue_work(wpriv->work_queue, &ch->lcl_ch_cls_wrk);
+ if (wpriv && wpriv->work_queue != NULL)
+ queue_work(wpriv->work_queue, &ch->lcl_ch_cls_wrk);
}
+ mutex_unlock(&ch->mutex);
}
/*
mutex_lock(&wpriv->glink_mutex);
if (ch->handle) {
ret = glink_close(ch->handle);
+ ch->handle = NULL;
if (IS_ERR_VALUE(ret)) {
dev_err(wpriv->dev, "%s: glink_close is failed, ret = %d\n",
__func__, ret);
} else {
- ch->handle = NULL;
dev_dbg(wpriv->dev, "%s: ch %s is closed\n", __func__,
ch->ch_cfg.name);
}
ch->handle = NULL;
ret = -EINVAL;
}
+ ch->free_mem = false;
} else {
dev_err(wpriv->dev, "%s: ch %s is already opened\n", __func__,
ch->ch_cfg.name);
err_open:
for (j = 0; j < i; j++)
- if (wpriv->ch[i])
+ if (wpriv->ch[j])
wdsp_glink_close_ch(wpriv->ch[j]);
done:
goto err_ch_mem;
}
ch[i]->channel_state = GLINK_LOCAL_DISCONNECTED;
+ ch[i]->free_mem = true;
memcpy(&ch[i]->ch_cfg, payload, ch_cfg_size);
payload += ch_cfg_size;
INIT_WORK(&ch[i]->lcl_ch_open_wrk, wdsp_glink_lcl_ch_open_wrk);
INIT_WORK(&ch[i]->lcl_ch_cls_wrk, wdsp_glink_lcl_ch_cls_wrk);
init_waitqueue_head(&ch[i]->ch_connect_wait);
+ init_waitqueue_head(&ch[i]->ch_free_wait);
}
INIT_WORK(&wpriv->ch_open_cls_wrk, wdsp_glink_ch_open_cls_wrk);
goto done;
}
+ dev_info(wpriv->dev, "%s: closing wdsp_glink driver\n", __func__);
if (wpriv->glink_state.handle)
glink_unregister_link_state_cb(wpriv->glink_state.handle);
flush_workqueue(wpriv->work_queue);
- destroy_workqueue(wpriv->work_queue);
-
/*
- * Clean up glink channel memory in channel state
- * callback only if close channels are called from here.
+ * Wait for channel local and remote disconnect state notifications
+ * before freeing channel memory.
*/
- if (wpriv->ch) {
- for (i = 0; i < wpriv->no_of_channels; i++) {
- if (wpriv->ch[i]) {
- wpriv->ch[i]->free_mem = true;
- /*
- * Channel handle NULL means channel is already
- * closed. Free the channel memory here itself.
- */
- if (!wpriv->ch[i]->handle) {
- kfree(wpriv->ch[i]);
- wpriv->ch[i] = NULL;
- } else {
- wdsp_glink_close_ch(wpriv->ch[i]);
- }
+ for (i = 0; i < wpriv->no_of_channels; i++) {
+ if (wpriv->ch && wpriv->ch[i]) {
+ /*
+ * Only close glink channel from here if REMOTE has
+ * not already disconnected it
+ */
+ wdsp_glink_close_ch(wpriv->ch[i]);
+
+ ret = wait_event_timeout(wpriv->ch[i]->ch_free_wait,
+ (wpriv->ch[i]->free_mem == true),
+ msecs_to_jiffies(TIMEOUT_MS));
+ if (!ret) {
+ pr_err("%s: glink ch %s failed to notify states properly %d\n",
+ __func__, wpriv->ch[i]->ch_cfg.name,
+ wpriv->ch[i]->channel_state);
+ ret = -EINVAL;
+ goto done;
}
}
+ }
- kfree(wpriv->ch);
- wpriv->ch = NULL;
+ flush_workqueue(wpriv->work_queue);
+ destroy_workqueue(wpriv->work_queue);
+ wpriv->work_queue = NULL;
+
+ for (i = 0; i < wpriv->no_of_channels; i++) {
+ if (wpriv->ch && wpriv->ch[i]) {
+ kfree(wpriv->ch[i]);
+ wpriv->ch[i] = NULL;
+ }
}
+ kfree(wpriv->ch);
+ wpriv->ch = NULL;
mutex_destroy(&wpriv->glink_mutex);
mutex_destroy(&wpriv->rsp_mutex);
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
if (!dev->group_id)
return 0;
- if (master->gr_sid == dev_num)
+ if (master->gr_sid != dev_num)
return 0;
if (master->remove_from_group && master->remove_from_group(master))
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, 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
(swrm->state == SWR_MSTR_UP)) {
dev_dbg(swrm->dev, "%s: SWR master is already UP: %d\n",
__func__, swrm->state);
+ list_for_each_entry(swr_dev, &mstr->devices, dev_list)
+ swr_reset_device(swr_dev);
} else {
pm_runtime_mark_last_busy(&pdev->dev);
mutex_unlock(&swrm->reslock);
{
u32 h_total, hpw, hfp, hbp;
u32 v_total, vpw, vfp, vbp;
+ int dsi_pixel_clock_divider = 0x00;
if (!pdata || !cfg) {
pr_err("%s: invalid input\n", __func__);
v_total, cfg->v_active, cfg->v_front_porch,
cfg->v_pulse_width, cfg->v_back_porch);
+ /* 0x16: dsi pclk divider control.
+ * bit2: 1 = manual dsi pclk divider control; 0 = automatic dsi
+ * pclk divider generation.
+ * bit3-7: the signal sets the dsi pclk divider setting when bit2
+ * is enable.
+ *
+ * If bit2=0 means automatically select dsi pclk divider, so
+ * other bits(divider factor) has no impact.
+ *
+ * If bit2=1, the divider factor should be related to lane num below
+ * 4lanes : divide by 3; 3lanes : divide by 4; 2lanes : divide by 6
+ * So the value of 0x16 can be set as follow:
+ * 4 lanes : 0x1C(00011 100)
+ * 3 lanes : 0x24(00100 100)
+ * 2 lanes : 0x34(00110 100)
+ *
+ * Here, use automatic dsi pclk divider generation, so set 0x00
+ * to cec 0x16 register for all lanes numbers.
+ */
+ adv7533_write(pdata, I2C_ADDR_CEC_DSI, 0x16, dsi_pixel_clock_divider);
/* h_width */
adv7533_write(pdata, I2C_ADDR_CEC_DSI, 0x28, ((h_total & 0xFF0) >> 4));
/*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, 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
enum {
WSA881X_DEV_DOWN,
WSA881X_DEV_UP,
+ WSA881X_DEV_READY,
};
/*
int version;
struct mutex bg_lock;
struct mutex res_lock;
+ struct mutex temp_lock;
struct snd_info_entry *entry;
struct snd_info_entry *version_entry;
int state;
.read = codec_debug_read,
};
+static void wsa881x_regcache_sync(struct wsa881x_priv *wsa881x)
+{
+ mutex_lock(&wsa881x->res_lock);
+ if (wsa881x->state != WSA881X_DEV_READY) {
+ regcache_mark_dirty(wsa881x->regmap);
+ regcache_sync(wsa881x->regmap);
+ wsa881x->state = WSA881X_DEV_READY;
+ }
+ mutex_unlock(&wsa881x->res_lock);
+}
+
static const struct reg_sequence wsa881x_pre_pmu_pa[] = {
{WSA881X_SPKR_DRV_GAIN, 0x41, 0},
{WSA881X_SPKR_MISC_CTL1, 0x01, 0},
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
+ mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, ENABLE);
+ mutex_unlock(&wsa881x->temp_lock);
wsa881x_boost_ctrl(codec, ENABLE);
break;
case SND_SOC_DAPM_POST_PMD:
wsa881x->swr_slave->dev_num,
false);
wsa881x_boost_ctrl(codec, DISABLE);
+ mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, DISABLE);
+ mutex_unlock(&wsa881x->temp_lock);
break;
}
return 0;
return -EINVAL;
}
}
- mutex_lock(&wsa881x->res_lock);
- if (!wsa881x->clk_cnt) {
- regcache_mark_dirty(wsa881x->regmap);
- regcache_sync(wsa881x->regmap);
- }
- mutex_unlock(&wsa881x->res_lock);
-
+ wsa881x_regcache_sync(wsa881x);
+ mutex_lock(&wsa881x->temp_lock);
wsa881x_resource_acquire(codec, ENABLE);
snd_soc_update_bits(codec, WSA881X_TADC_VALUE_CTL, 0x01, 0x00);
wsa_temp_reg->d2_lsb = snd_soc_read(codec, WSA881X_OTP_REG_4);
wsa881x_resource_acquire(codec, DISABLE);
+ mutex_unlock(&wsa881x->temp_lock);
return 0;
}
dev = wsa881x->swr_slave;
wsa881x->codec = codec;
mutex_init(&wsa881x->bg_lock);
- mutex_init(&wsa881x->res_lock);
wsa881x_init(codec);
snprintf(wsa881x->tz_pdata.name, sizeof(wsa881x->tz_pdata.name),
"%s.%x", "wsatz", (u8)dev->addr);
if (wsa881x->tz_pdata.tz_dev)
wsa881x_deinit_thermal(wsa881x->tz_pdata.tz_dev);
mutex_destroy(&wsa881x->bg_lock);
- mutex_destroy(&wsa881x->res_lock);
return 0;
}
if (wsa881x->wsa_rst_np)
pin_state_current = msm_cdc_pinctrl_get_state(
wsa881x->wsa_rst_np);
+ mutex_init(&wsa881x->res_lock);
+ mutex_init(&wsa881x->temp_lock);
wsa881x_gpio_ctrl(wsa881x, true);
wsa881x->state = WSA881X_DEV_UP;
return -EINVAL;
}
debugfs_remove_recursive(debugfs_wsa881x_dent);
+ mutex_destroy(&wsa881x->res_lock);
+ mutex_destroy(&wsa881x->temp_lock);
snd_soc_unregister_codec(&pdev->dev);
if (wsa881x->pd_gpio)
gpio_free(wsa881x->pd_gpio);
dev_err(&pdev->dev, "%s: wsa881x is NULL\n", __func__);
return -EINVAL;
}
+ if (wsa881x->state == WSA881X_DEV_READY) {
+ dev_dbg(&pdev->dev, "%s: device already active\n", __func__);
+ return 0;
+ }
+
wsa881x->bg_cnt = 0;
wsa881x->clk_cnt = 0;
while (swr_get_logical_dev_num(pdev, pdev->addr, &devnum) && retry--) {
usleep_range(1000, 1100);
}
pdev->dev_num = devnum;
- regcache_mark_dirty(wsa881x->regmap);
- regcache_sync(wsa881x->regmap);
+ wsa881x_regcache_sync(wsa881x);
return 0;
}