Merge changes Ibe1b5c65,Ic16b4028,Ia1f664a3 into msm-3.4
* changes:
defconfig: 8974: Enable DLOAD mode for 8974
msm: restart: Add support for download mode on 8974
defconfig: 8974: Configure panic timeout for 8974
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
index 6db1150..82e76fc 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi-panel.txt
@@ -14,6 +14,16 @@
- qcom,mdss-pan-bpp: Specifies the panel bits per pixel. Default value is 24(rgb888).
18 = for rgb666
16 = for rgb565
+- qcom,panel-phy-regulatorSettings: An array of length 8 that specifies the PHY
+ regulator settings for the panel.
+- qcom,panel-phy-timingSettings: An array of length 12 that specifies the PHY
+ timing settings for the panel.
+- qcom,panel-phy-strengthCtrl: An array of length 2 that specifies the PHY
+ strengthCtrl settings for the panel.
+- qcom,panel-phy-bistCtrl: An array of length 6 that specifies the PHY
+ BIST ctrl settings for the panel.
+- qcom,panel-phy-laneConfig: An array of length 45 that specifies the PHY
+ lane configuration settings for the panel.
- qcom,mdss-panel-on-cmds: An array of variable length that lists the init commands
of the panel. Each command will have the format specified
as below:
@@ -42,9 +52,16 @@
Optional properties:
- label: A string used as a descriptive name of the panel
+- qcom,enable-gpio: Specifies the panel lcd/display enable gpio.
+- qcom,rst-gpio: Specifies the panel reset gpio.
- qcom,mdss-pan-porch-values: An array of size 6 that specifies the panel blanking values.
- qcom,mdss-pan-underflow-clr: Specifies the controller settings for the panel underflow clear
settings. Default value is 0xff.
+- qcom,mdss-pan-bl-ctrl: A string that specifies the implementation of backlight
+ control for this panel.
+ "bl_ctrl_pwm" = Backlight controlled by PWM gpio.
+ "bl_ctrl_wled" = Backlight controlled by WLED.
+ "bl_ctrl_dcs_cmds" = Backlight controlled by DCS commands.
- qcom,mdss-pan-bl-levels: Specifies the backlight levels supported by the panel.
Default range is 1 to 255.
diff --git a/Documentation/devicetree/bindings/usb/msm-hsusb.txt b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
index ed84219..62258ca 100644
--- a/Documentation/devicetree/bindings/usb/msm-hsusb.txt
+++ b/Documentation/devicetree/bindings/usb/msm-hsusb.txt
@@ -60,7 +60,9 @@
- reg : pairs of physical base addresses and region sizes
of all the memory mapped BAM devices present
- reg-names : Register region name(s) referenced in reg above
- SSUSB BAM expects "ssusb" and "hsusb" for HSSUB BAM
+ SSUSB BAM expects "ssusb" and "hsusb" for HSSUB BAM.
+ Specify "qscratch_ram1_reg" to provide QSCRATCH's RAM1
+ register to control USB3 private memory for uses as BAM FIFOs.
- interrupts: IRQ lines for BAM devices
- interrupt-names: BAM interrupt name(s) referenced in interrupts above
SSUSB BAM expects "ssusb" and "hsusb" for HSSUB BAM
@@ -98,8 +100,9 @@
qcom,usbbam@f9304000 {
compatible = "qcom,usb-bam-msm";
reg = <0xf9304000 0x5000>,
- <0xf9a44000 0x11000>;
- reg-names = "ssusb", "hsusb";
+ <0xf9a44000 0x11000>,
+ <0xf92f880c 0x4>;
+ reg-names = "ssusb", "hsusb", "qscratch_ram1_reg";
interrupts = <0 132 0 0 135 0>;
interrupt-names = "ssusb", "hsusb";
qcom,usb-active-bam = <0>;
@@ -138,7 +141,7 @@
qcom,pipe3 {
label = "usb-to-peri-qdss-hsusb";
qcom,usb-bam-type = <1>;
- qcom,usb-bam-mem-type = <2>;
+ qcom,usb-bam-mem-type = <1>;
qcom,src-bam-physical-address = <0>;
qcom,src-bam-pipe-index = <0>;
qcom,dst-bam-physical-address = <0>;
@@ -152,14 +155,14 @@
qcom,pipe4 {
label = "peri-to-usb-qdss-hsusb";
qcom,usb-bam-type = <1>;
- qcom,usb-bam-mem-type = <2>;
+ qcom,usb-bam-mem-type = <1>;
qcom,src-bam-physical-address = <0xfc37c000>;
qcom,src-bam-pipe-index = <0>;
qcom,dst-bam-physical-address = <0xf9a44000>;
qcom,dst-bam-pipe-index = <2>;
- qcom,data-fifo-offset = <0>;
- qcom,data-fifo-size = <0x4000>;
- qcom,descriptor-fifo-offset = <0>;
- qcom,descriptor-fifo-size = <0x1400>;
+ qcom,data-fifo-offset = <0xf4000>;
+ qcom,data-fifo-size = <0x1000>;
+ qcom,descriptor-fifo-offset = <0xf5000>;
+ qcom,descriptor-fifo-size = <0x400>;
};
};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index d92d2f6..415122b 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -815,8 +815,9 @@
qcom,usbbam@f9304000 {
compatible = "qcom,usb-bam-msm";
reg = <0xf9304000 0x5000>,
- <0xf9a44000 0x11000>;
- reg-names = "ssusb", "hsusb";
+ <0xf9a44000 0x11000>,
+ <0xf92f880c 0x4>;
+ reg-names = "ssusb", "hsusb", "qscratch_ram1_reg";
interrupts = <0 132 0 0 135 0>;
interrupt-names = "ssusb", "hsusb";
qcom,usb-active-bam = <0>;
@@ -855,7 +856,7 @@
qcom,pipe3 {
label = "usb-to-peri-qdss-hsusb";
qcom,usb-bam-type = <1>;
- qcom,usb-bam-mem-type = <2>;
+ qcom,usb-bam-mem-type = <1>;
qcom,src-bam-physical-address = <0>;
qcom,src-bam-pipe-index = <0>;
qcom,dst-bam-physical-address = <0>;
@@ -869,15 +870,15 @@
qcom,pipe4 {
label = "peri-to-usb-qdss-hsusb";
qcom,usb-bam-type = <1>;
- qcom,usb-bam-mem-type = <2>;
+ qcom,usb-bam-mem-type = <1>;
qcom,src-bam-physical-address = <0xfc37c000>;
qcom,src-bam-pipe-index = <0>;
qcom,dst-bam-physical-address = <0xf9a44000>;
qcom,dst-bam-pipe-index = <2>;
- qcom,data-fifo-offset = <0>;
- qcom,data-fifo-size = <0x4000>;
- qcom,descriptor-fifo-offset = <0>;
- qcom,descriptor-fifo-size = <0x1400>;
+ qcom,data-fifo-offset = <0xf4000>;
+ qcom,data-fifo-size = <0x1000>;
+ qcom,descriptor-fifo-offset = <0xf5000>;
+ qcom,descriptor-fifo-size = <0x400>;
};
};
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 6366376..1097907 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -142,6 +142,7 @@
.l2_freq_tbl_size = sizeof(l2_freq_tbl),
.bus_scale = &bus_scale_data,
.qfprom_phys_base = 0x00700000,
+ .stby_khz = 384000,
};
static int __init acpuclk_8960ab_probe(struct platform_device *pdev)
diff --git a/arch/arm/mach-msm/board-8064-display.c b/arch/arm/mach-msm/board-8064-display.c
index 5780ca1..d7568ab 100644
--- a/arch/arm/mach-msm/board-8064-display.c
+++ b/arch/arm/mach-msm/board-8064-display.c
@@ -62,6 +62,7 @@
#define MIPI_VIDEO_TOSHIBA_WSVGA_PANEL_NAME "mipi_video_toshiba_wsvga"
#define MIPI_VIDEO_CHIMEI_WXGA_PANEL_NAME "mipi_video_chimei_wxga"
#define HDMI_PANEL_NAME "hdmi_msm"
+#define MHL_PANEL_NAME "hdmi_msm,mhl_8334"
#define TVOUT_PANEL_NAME "tvout_msm"
#define LVDS_PIXEL_MAP_PATTERN_1 1
@@ -73,11 +74,18 @@
static unsigned char hdmi_is_primary;
#endif
+static unsigned char mhl_display_enabled;
+
unsigned char apq8064_hdmi_as_primary_selected(void)
{
return hdmi_is_primary;
}
+unsigned char apq8064_mhl_display_enabled(void)
+{
+ return mhl_display_enabled;
+}
+
static void set_mdp_clocks_for_wuxga(void);
static int msm_fb_detect_panel(const char *name)
@@ -1067,7 +1075,15 @@
PANEL_NAME_MAX_LEN);
pr_debug("msm_fb_pdata.ext_panel_name %s\n",
msm_fb_pdata.ext_panel_name);
+
+ if (!strncmp((char *)msm_fb_pdata.ext_panel_name,
+ MHL_PANEL_NAME, strnlen(MHL_PANEL_NAME,
+ PANEL_NAME_MAX_LEN))) {
+ pr_debug("MHL is external display by boot parameter\n");
+ mhl_display_enabled = 1;
+ }
}
msm_fb_pdata.ext_resolution = resolution;
+ hdmi_msm_data.is_mhl_enabled = mhl_display_enabled;
}
diff --git a/arch/arm/mach-msm/board-8064.h b/arch/arm/mach-msm/board-8064.h
index 2258b8d..50885ad 100644
--- a/arch/arm/mach-msm/board-8064.h
+++ b/arch/arm/mach-msm/board-8064.h
@@ -84,6 +84,7 @@
#define APQ_8064_GSBI5_QUP_I2C_BUS_ID 5
unsigned char apq8064_hdmi_as_primary_selected(void);
+unsigned char apq8064_mhl_display_enabled(void);
void apq8064_init_fb(void);
void apq8064_allocate_fb_region(void);
void apq8064_mdp_writeback(struct memtype_reserve *reserve_table);
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index e9a034e..6add371 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2761,21 +2761,17 @@
msm_kgsl_3d0.dev.platform_data;
uint32_t soc_platform_version = socinfo_get_version();
- if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
- kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
- kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
- }
if (cpu_is_msm8960ab()) {
kgsl_3d0_pdata->chipid = ADRENO_CHIPID(3, 2, 1, 0);
- } else {
-
+ } else if (SOCINFO_VERSION_MAJOR(soc_platform_version) == 1) {
+ kgsl_3d0_pdata->pwrlevel[0].gpu_freq = 320000000;
+ kgsl_3d0_pdata->pwrlevel[1].gpu_freq = 266667000;
+ } else if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3) {
/* 8960v3 GPU registers returns 5 for patch release
* but it should be 6, so dummy up the chipid here
* based the platform type
*/
-
- if (SOCINFO_VERSION_MAJOR(soc_platform_version) >= 3)
- kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
+ kgsl_3d0_pdata->chipid = ADRENO_CHIPID(2, 2, 0, 6);
}
}
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index b67d982..e00f150 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -63,6 +63,13 @@
#define PMEM_KERNEL_EBI1_SIZE 0x3A000
#define MSM_PMEM_AUDIO_SIZE 0x1F4000
+#define SNDDEV_CAP_NONE 0x0
+#define SNDDEV_CAP_RX 0x1 /* RX direction */
+#define SNDDEV_CAP_TX 0x2 /* TX direction */
+#define SNDDEV_CAP_VOICE 0x4 /* Support voice call */
+#define SNDDEV_CAP_FM 0x10 /* Support FM radio */
+#define SNDDEV_CAP_TTY 0x20 /* Support TTY */
+
#if defined(CONFIG_GPIO_SX150X)
enum {
SX150X_CORE,
@@ -494,7 +501,6 @@
SND(FM_ANALOG_STEREO_HEADSET_CODEC, 36),
};
#undef SND
-
static struct msm_snd_endpoints msm_device_snd_endpoints = {
.endpoints = snd_endpoints_list,
.num = sizeof(snd_endpoints_list) / sizeof(struct snd_endpoint)
@@ -508,6 +514,55 @@
},
};
+#define CAD(desc, num, cap) { .name = #desc, .id = num, .capability = cap, }
+static struct cad_endpoint cad_endpoints_list[] = {
+ CAD(NONE, 0, SNDDEV_CAP_NONE),
+ CAD(HANDSET_SPKR, 1, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(HANDSET_MIC, 2, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_MIC, 3, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_SPKR_MONO, 4, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_SPKR_STEREO, 5, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_MIC, 6, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_MONO, 7, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_STEREO, 8, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(BT_SCO_MIC, 9, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(BT_SCO_SPKR, 10, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(BT_A2DP_SPKR, 11, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(TTY_HEADSET_MIC, 12, (SNDDEV_CAP_TX | \
+ SNDDEV_CAP_VOICE | SNDDEV_CAP_TTY)),
+ CAD(TTY_HEADSET_SPKR, 13, (SNDDEV_CAP_RX | \
+ SNDDEV_CAP_VOICE | SNDDEV_CAP_TTY)),
+ CAD(HEADSET_STEREO_PLUS_SPKR_MONO_RX, 19, (SNDDEV_CAP_TX | \
+ SNDDEV_CAP_VOICE)),
+ CAD(LP_FM_HEADSET_SPKR_STEREO_RX, 25, (SNDDEV_CAP_TX | SNDDEV_CAP_FM)),
+ CAD(I2S_RX, 26, (SNDDEV_CAP_RX)),
+ CAD(SPEAKER_PHONE_MIC_ENDFIRE, 45, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HANDSET_MIC_ENDFIRE, 46, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(I2S_TX, 48, (SNDDEV_CAP_TX)),
+ CAD(LP_FM_HEADSET_SPKR_STEREO_PLUS_HEADSET_SPKR_STEREO_RX, 57, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_HEADSET_SPKR_STEREO, 65, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_SPEAKER_PHONE_MONO, 67, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_BT_A2DP_SPKR, 69, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(MAX, 80, SNDDEV_CAP_NONE),
+};
+#undef CAD
+static struct msm_cad_endpoints msm_device_cad_endpoints = {
+ .endpoints = cad_endpoints_list,
+ .num = sizeof(cad_endpoints_list) / sizeof(struct cad_endpoint)
+};
+
+static struct platform_device msm_device_cad = {
+ .name = "msm_cad",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_device_cad_endpoints
+ },
+};
+
#define DEC0_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
@@ -814,6 +869,7 @@
&android_pmem_audio_device,
&msm_device_nand,
&msm_device_snd,
+ &msm_device_cad,
&msm_device_adspdec,
&asoc_msm_pcm,
&asoc_msm_dai0,
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index 7556931..1da9ede 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -75,6 +75,13 @@
#define I2C_PIN_CTL 0x15
#define I2C_NORMAL 0x40
+#define SNDDEV_CAP_NONE 0x0
+#define SNDDEV_CAP_RX 0x1 /* RX direction */
+#define SNDDEV_CAP_TX 0x2 /* TX direction */
+#define SNDDEV_CAP_VOICE 0x4 /* Support voice call */
+#define SNDDEV_CAP_FM 0x10 /* Support FM radio */
+#define SNDDEV_CAP_TTY 0x20 /* Support TTY */
+
static struct platform_device msm_wlan_ar6000_pm_device = {
.name = "wlan_ar6000_pm_dev",
.id = -1,
@@ -454,6 +461,56 @@
},
};
+#define CAD(desc, num, cap) { .name = #desc, .id = num, .capability = cap, }
+static struct cad_endpoint cad_endpoints_list[] = {
+ CAD(NONE, 0, SNDDEV_CAP_NONE),
+ CAD(HANDSET_SPKR, 1, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(HANDSET_MIC, 2, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_MIC, 3, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_SPKR_MONO, 4, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(HEADSET_SPKR_STEREO, 5, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_MIC, 6, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_MONO, 7, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(SPEAKER_PHONE_STEREO, 8, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(BT_SCO_MIC, 9, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(BT_SCO_SPKR, 10, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(BT_A2DP_SPKR, 11, (SNDDEV_CAP_RX | SNDDEV_CAP_VOICE)),
+ CAD(TTY_HEADSET_MIC, 12, (SNDDEV_CAP_TX | \
+ SNDDEV_CAP_VOICE | SNDDEV_CAP_TTY)),
+ CAD(TTY_HEADSET_SPKR, 13, (SNDDEV_CAP_RX | \
+ SNDDEV_CAP_VOICE | SNDDEV_CAP_TTY)),
+ CAD(HEADSET_STEREO_PLUS_SPKR_MONO_RX, 19, (SNDDEV_CAP_TX | \
+ SNDDEV_CAP_VOICE)),
+ CAD(LP_FM_HEADSET_SPKR_STEREO_RX, 25, (SNDDEV_CAP_TX | SNDDEV_CAP_FM)),
+ CAD(I2S_RX, 26, (SNDDEV_CAP_RX)),
+ CAD(SPEAKER_PHONE_MIC_ENDFIRE, 45, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(HANDSET_MIC_ENDFIRE, 46, (SNDDEV_CAP_TX | SNDDEV_CAP_VOICE)),
+ CAD(I2S_TX, 48, (SNDDEV_CAP_TX)),
+ CAD(LP_FM_HEADSET_SPKR_STEREO_PLUS_HEADSET_SPKR_STEREO_RX, 57, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_HEADSET_SPKR_STEREO, 65, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_SPEAKER_PHONE_MONO, 67, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(FM_DIGITAL_BT_A2DP_SPKR, 69, \
+ (SNDDEV_CAP_FM | SNDDEV_CAP_RX)),
+ CAD(MAX, 80, SNDDEV_CAP_NONE),
+};
+#undef CAD
+
+static struct msm_cad_endpoints msm_device_cad_endpoints = {
+ .endpoints = cad_endpoints_list,
+ .num = sizeof(cad_endpoints_list) / sizeof(struct cad_endpoint)
+};
+
+static struct platform_device msm_device_cad = {
+ .name = "msm_cad",
+ .id = -1,
+ .dev = {
+ .platform_data = &msm_device_cad_endpoints
+ },
+};
+
#define DEC0_FORMAT ((1<<MSM_ADSP_CODEC_MP3)| \
(1<<MSM_ADSP_CODEC_AAC)|(1<<MSM_ADSP_CODEC_WMA)| \
(1<<MSM_ADSP_CODEC_WMAPRO)|(1<<MSM_ADSP_CODEC_AMRWB)| \
@@ -702,6 +759,7 @@
&msm_batt_device,
&msm_device_adspdec,
&msm_device_snd,
+ &msm_device_cad,
&asoc_msm_pcm,
&asoc_msm_dai0,
&asoc_msm_dai1,
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 41bc229..dc05dcf 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -122,6 +122,10 @@
#define USB_HSIC_CMD_RCGR 0x0440
#define USB_HSIC_IO_CAL_CMD_RCGR 0x0458
#define USB_HS_SYSTEM_CMD_RCGR 0x0490
+#define SYS_NOC_USB3_AXI_CBCR 0x0108
+#define USB30_SLEEP_CBCR 0x03CC
+#define USB2A_PHY_SLEEP_CBCR 0x04AC
+#define USB2B_PHY_SLEEP_CBCR 0x04B4
#define SDCC1_APPS_CMD_RCGR 0x04D0
#define SDCC2_APPS_CMD_RCGR 0x0510
#define SDCC3_APPS_CMD_RCGR 0x0550
@@ -2198,6 +2202,51 @@
},
};
+struct branch_clk gcc_sys_noc_usb3_axi_clk = {
+ .cbcr_reg = SYS_NOC_USB3_AXI_CBCR,
+ .parent = &usb30_master_clk_src.c,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_sys_noc_usb3_axi_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_sys_noc_usb3_axi_clk.c),
+ },
+};
+
+struct branch_clk gcc_usb30_sleep_clk = {
+ .cbcr_reg = USB30_SLEEP_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_usb30_sleep_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb30_sleep_clk.c),
+ },
+};
+
+struct branch_clk gcc_usb2a_phy_sleep_clk = {
+ .cbcr_reg = USB2A_PHY_SLEEP_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_usb2a_phy_sleep_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb2a_phy_sleep_clk.c),
+ },
+};
+
+struct branch_clk gcc_usb2b_phy_sleep_clk = {
+ .cbcr_reg = USB2B_PHY_SLEEP_CBCR,
+ .has_sibling = 1,
+ .base = &virt_bases[GCC_BASE],
+ .c = {
+ .dbg_name = "gcc_usb2b_phy_sleep_clk",
+ .ops = &clk_ops_branch,
+ CLK_INIT(gcc_usb2b_phy_sleep_clk.c),
+ },
+};
+
static struct branch_clk gcc_usb_hs_ahb_clk = {
.cbcr_reg = USB_HS_AHB_CBCR,
.has_sibling = 1,
@@ -4552,6 +4601,10 @@
{&gcc_blsp1_qup1_i2c_apps_clk.c, GCC_BASE, 0x008b},
{&gcc_blsp2_uart6_apps_clk.c, GCC_BASE, 0x00c3},
{&gcc_sdcc2_ahb_clk.c, GCC_BASE, 0x0071},
+ {&gcc_usb30_sleep_clk.c, GCC_BASE, 0x0051},
+ {&gcc_usb2a_phy_sleep_clk.c, GCC_BASE, 0x0063},
+ {&gcc_usb2b_phy_sleep_clk.c, GCC_BASE, 0x0064},
+ {&gcc_sys_noc_usb3_axi_clk.c, GCC_BASE, 0x0001},
{&gcc_ocmem_noc_cfg_ahb_clk.c, GCC_BASE, 0x0029},
{&gcc_ce1_clk.c, GCC_BASE, 0x0138},
{&gcc_lpass_q6_axi_clk.c, GCC_BASE, 0x0160},
@@ -4648,7 +4701,7 @@
{&q6ss_ahb_lfabif_clk.c, LPASS_BASE, 0x001e},
{&q6ss_ahbm_clk.c, LPASS_BASE, 0x001d},
{&audio_core_ixfabric_clk.c, LPASS_BASE, 0x0059},
- {&mss_bus_q6_clk.c, MSS_BASE, 0x003c},
+ {&mss_bus_q6_clk.c, MSS_BASE, 0x003b},
{&mss_xo_q6_clk.c, MSS_BASE, 0x0007},
{&l2_m_clk, APCS_BASE, 0x0081},
@@ -4684,18 +4737,15 @@
clk->sample_ticks = 0x10000;
clk->multiplier = 1;
- writel_relaxed(0, MSS_REG_BASE(MSS_DEBUG_CLK_CTL_REG));
- writel_relaxed(0, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
- writel_relaxed(0, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL_REG));
- writel_relaxed(0, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
-
switch (measure_mux[i].base) {
case GCC_BASE:
+ writel_relaxed(0, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
clk_sel = measure_mux[i].debug_mux;
break;
case MMSS_BASE:
+ writel_relaxed(0, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL_REG));
clk_sel = 0x02C;
regval = BVAL(11, 0, measure_mux[i].debug_mux);
writel_relaxed(regval, MMSS_REG_BASE(MMSS_DEBUG_CLK_CTL_REG));
@@ -4706,6 +4756,7 @@
break;
case LPASS_BASE:
+ writel_relaxed(0, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
clk_sel = 0x161;
regval = BVAL(11, 0, measure_mux[i].debug_mux);
writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
@@ -4716,6 +4767,7 @@
break;
case MSS_BASE:
+ writel_relaxed(0, MSS_REG_BASE(MSS_DEBUG_CLK_CTL_REG));
clk_sel = 0x32;
regval = BVAL(5, 0, measure_mux[i].debug_mux);
writel_relaxed(regval, MSS_REG_BASE(MSS_DEBUG_CLK_CTL_REG));
@@ -4985,8 +5037,14 @@
CLK_LOOKUP("iface_clk", gcc_tsif_ahb_clk.c, ""),
CLK_LOOKUP("ref_clk", gcc_tsif_ref_clk.c, ""),
+ CLK_LOOKUP("mem_clk", gcc_usb30_master_clk.c, "usb_bam"),
+ CLK_LOOKUP("mem_iface_clk", gcc_sys_noc_usb3_axi_clk.c, "usb_bam"),
CLK_LOOKUP("core_clk", gcc_usb30_master_clk.c, "msm_dwc3"),
CLK_LOOKUP("utmi_clk", gcc_usb30_mock_utmi_clk.c, "msm_dwc3"),
+ CLK_LOOKUP("iface_clk", gcc_sys_noc_usb3_axi_clk.c, "msm_dwc3"),
+ CLK_LOOKUP("sleep_clk", gcc_usb30_sleep_clk.c, "msm_dwc3"),
+ CLK_LOOKUP("sleep_a_clk", gcc_usb2a_phy_sleep_clk.c, "msm_dwc3"),
+ CLK_LOOKUP("sleep_b_clk", gcc_usb2b_phy_sleep_clk.c, "msm_dwc3"),
CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c, "msm_otg"),
CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c, "msm_otg"),
CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c, "msm_hsic_host"),
diff --git a/arch/arm/mach-msm/clock-local2.c b/arch/arm/mach-msm/clock-local2.c
index d5ee35b..42b36f6 100644
--- a/arch/arm/mach-msm/clock-local2.c
+++ b/arch/arm/mach-msm/clock-local2.c
@@ -110,20 +110,26 @@
void set_rate_hid(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
u32 cfg_regval;
+ unsigned long flags;
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
cfg_regval &= ~(CFG_RCGR_DIV_MASK | CFG_RCGR_SRC_SEL_MASK);
cfg_regval |= nf->div_src_val;
writel_relaxed(cfg_regval, CFG_RCGR_REG(rcg));
rcg_update_config(rcg);
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
/* RCG set rate function for clocks with MND & Half Integer Dividers. */
void set_rate_mnd(struct rcg_clk *rcg, struct clk_freq_tbl *nf)
{
u32 cfg_regval;
+ unsigned long flags;
+ spin_lock_irqsave(&local_clock_reg_lock, flags);
+ cfg_regval = readl_relaxed(CFG_RCGR_REG(rcg));
writel_relaxed(nf->m_val, M_REG(rcg));
writel_relaxed(nf->n_val, N_REG(rcg));
writel_relaxed(nf->d_val, D_REG(rcg));
@@ -139,6 +145,7 @@
writel_relaxed(cfg_regval, CFG_RCGR_REG(rcg));
rcg_update_config(rcg);
+ spin_unlock_irqrestore(&local_clock_reg_lock, flags);
}
static int rcg_clk_enable(struct clk *c)
@@ -157,7 +164,6 @@
struct clk_freq_tbl *cf, *nf;
struct rcg_clk *rcg = to_rcg_clk(c);
int rc = 0;
- unsigned long flags;
for (nf = rcg->freq_tbl; nf->freq_hz != FREQ_END
&& nf->freq_hz != rate; nf++)
@@ -178,13 +184,9 @@
BUG_ON(!rcg->set_rate);
- spin_lock_irqsave(&local_clock_reg_lock, flags);
-
/* Perform clock-specific frequency switch operations. */
rcg->set_rate(rcg, nf);
- spin_unlock_irqrestore(&local_clock_reg_lock, flags);
-
/* Release source requirements of the old freq. */
if (rcg->c.count)
clk_disable(cf->src_clk);
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index c6a0441..3b262bc 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -2848,26 +2848,6 @@
struct msm_iommu_domain_name apq8064_iommu_ctx_names[] = {
/* Camera */
{
- .name = "vpe_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
.name = "ijpeg_src",
.domain = CAMERA_DOMAIN,
},
diff --git a/arch/arm/mach-msm/devices-8930.c b/arch/arm/mach-msm/devices-8930.c
index eac2140..a257a9c 100644
--- a/arch/arm/mach-msm/devices-8930.c
+++ b/arch/arm/mach-msm/devices-8930.c
@@ -853,26 +853,6 @@
struct msm_iommu_domain_name msm8930_iommu_ctx_names[] = {
/* Camera */
{
- .name = "vpe_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
.name = "ijpeg_src",
.domain = CAMERA_DOMAIN,
},
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index d121c3e..377ecae 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -4061,26 +4061,6 @@
struct msm_iommu_domain_name msm8960_iommu_ctx_names[] = {
/* Camera */
{
- .name = "vpe_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
.name = "ijpeg_src",
.domain = CAMERA_DOMAIN,
},
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 5295cbc..e7d652b 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1263,8 +1263,8 @@
},
{
.name = "dma_chnl",
- .start = DMOV_SDC3_CHAN,
- .end = DMOV_SDC3_CHAN,
+ .start = DMOV_NAND_CHAN,
+ .end = DMOV_NAND_CHAN,
.flags = IORESOURCE_DMA,
},
{
diff --git a/arch/arm/mach-msm/devices-msm7x30.c b/arch/arm/mach-msm/devices-msm7x30.c
index a6473c6..45486f4 100644
--- a/arch/arm/mach-msm/devices-msm7x30.c
+++ b/arch/arm/mach-msm/devices-msm7x30.c
@@ -1329,7 +1329,7 @@
static struct kgsl_device_platform_data kgsl_2d0_pdata = {
.pwrlevel = {
{
- .gpu_freq = 192000000,
+ .gpu_freq = 0,
.bus_freq = 192000000,
},
},
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 9f31a18..57d7f08 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -3003,26 +3003,6 @@
struct msm_iommu_domain_name msm8660_iommu_ctx_names[] = {
/* Camera */
{
- .name = "vpe_src",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vpe_dst",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_imgwr",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
- .name = "vfe_misc",
- .domain = CAMERA_DOMAIN,
- },
- /* Camera */
- {
.name = "ijpeg_src",
.domain = CAMERA_DOMAIN,
},
diff --git a/arch/arm/mach-msm/include/mach/board.h b/arch/arm/mach-msm/include/mach/board.h
index 1060a9d..d8f8480 100644
--- a/arch/arm/mach-msm/include/mach/board.h
+++ b/arch/arm/mach-msm/include/mach/board.h
@@ -296,6 +296,17 @@
unsigned num;
};
+struct cad_endpoint {
+ int id;
+ const char *name;
+ uint32_t capability;
+};
+
+struct msm_cad_endpoints {
+ struct cad_endpoint *endpoints;
+ unsigned num;
+};
+
#define MSM_MAX_DEC_CNT 14
/* 7k target ADSP information */
/* Bit 23:0, for codec identification like mp3, wav etc *
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index f7ba507..d80cc02 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -97,6 +97,7 @@
const int cpu_is_krait(void);
const int cpu_is_krait_v1(void);
const int cpu_is_krait_v2(void);
+const int cpu_is_krait_v3(void);
static inline int cpu_is_msm7x01(void)
{
diff --git a/arch/arm/mach-msm/include/mach/sps.h b/arch/arm/mach-msm/include/mach/sps.h
index edc4b39..000ffe4 100644
--- a/arch/arm/mach-msm/include/mach/sps.h
+++ b/arch/arm/mach-msm/include/mach/sps.h
@@ -75,6 +75,8 @@
#define SPS_BAM_OPT_BAMDMA (1UL << 2)
/* BAM IRQ is registered for apps wakeup */
#define SPS_BAM_OPT_IRQ_WAKEUP (1UL << 3)
+/* Ignore external block pipe reset */
+#define SPS_BAM_NO_EXT_P_RST (1UL << 4)
/* BAM device management flags */
diff --git a/arch/arm/mach-msm/mdm2.c b/arch/arm/mach-msm/mdm2.c
index 2073856..43c85bb 100644
--- a/arch/arm/mach-msm/mdm2.c
+++ b/arch/arm/mach-msm/mdm2.c
@@ -108,6 +108,8 @@
int soft_reset_direction =
mdm_drv->pdata->soft_reset_inverted ? 1 : 0;
+ mdm_peripheral_disconnect(mdm_drv);
+
/* Wait for the modem to complete its power down actions. */
for (i = 20; i > 0; i--) {
if (gpio_get_value(mdm_drv->mdm2ap_status_gpio) == 0)
@@ -127,7 +129,6 @@
*/
msleep(4000);
}
- mdm_peripheral_disconnect(mdm_drv);
}
static void mdm_do_first_power_on(struct mdm_modem_drv *mdm_drv)
diff --git a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
index 9ba9f7b1..70bb406 100644
--- a/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
+++ b/arch/arm/mach-msm/msm_bus/msm_bus_board_8960.c
@@ -21,7 +21,7 @@
#include <mach/rpm.h>
#include "msm_bus_core.h"
-#define NMASTERS 45
+#define NMASTERS 55
#define NSLAVES 75
#define NFAB_8960 5
diff --git a/arch/arm/mach-msm/msm_watchdog_v2.c b/arch/arm/mach-msm/msm_watchdog_v2.c
index ea408f7..af903f8 100644
--- a/arch/arm/mach-msm/msm_watchdog_v2.c
+++ b/arch/arm/mach-msm/msm_watchdog_v2.c
@@ -19,6 +19,8 @@
#include <linux/jiffies.h>
#include <linux/sched.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/percpu.h>
#include <linux/of.h>
#include <linux/cpu.h>
#include <linux/platform_device.h>
@@ -54,6 +56,8 @@
cpumask_t alive_mask;
struct work_struct init_dogwork_struct;
struct delayed_work dogwork_struct;
+ bool irq_ppi;
+ struct msm_watchdog_data __percpu **wdog_cpu_dd;
struct notifier_block panic_blk;
};
@@ -199,7 +203,7 @@
ping_other_cpus(wdog_dd);
pet_watchdog(wdog_dd);
if (enable)
- schedule_delayed_work(&wdog_dd->dogwork_struct,
+ schedule_delayed_work_on(0, &wdog_dd->dogwork_struct,
delay_time);
}
@@ -218,6 +222,8 @@
/* In case we got suspended mid-exit */
__raw_writel(0, wdog_dd->base + WDT0_EN);
}
+ if (wdog_dd->irq_ppi)
+ free_percpu(wdog_dd->wdog_cpu_dd);
printk(KERN_INFO "MSM Watchdog Exit - Deactivated\n");
kzfree(wdog_dd);
return 0;
@@ -242,6 +248,13 @@
return IRQ_HANDLED;
}
+static irqreturn_t wdog_ppi_bark(int irq, void *dev_id)
+{
+ struct msm_watchdog_data *wdog_dd =
+ *(struct msm_watchdog_data **)(dev_id);
+ return wdog_bark_handler(irq, wdog_dd);
+}
+
static void configure_bark_dump(struct msm_watchdog_data *wdog_dd)
{
int ret;
@@ -287,6 +300,32 @@
init_dogwork_struct);
unsigned long delay_time;
u64 timeout;
+ int ret;
+
+ if (wdog_dd->irq_ppi) {
+ wdog_dd->wdog_cpu_dd = alloc_percpu(struct msm_watchdog_data *);
+ if (!wdog_dd->wdog_cpu_dd) {
+ dev_err(wdog_dd->dev, "fail to allocate cpu data\n");
+ return;
+ }
+ *__this_cpu_ptr(wdog_dd->wdog_cpu_dd) = wdog_dd;
+ ret = request_percpu_irq(wdog_dd->bark_irq, wdog_ppi_bark,
+ "apps_wdog_bark",
+ wdog_dd->wdog_cpu_dd);
+ if (ret) {
+ dev_err(wdog_dd->dev, "failed to request bark irq\n");
+ free_percpu(wdog_dd->wdog_cpu_dd);
+ return;
+ }
+ } else {
+ ret = devm_request_irq(wdog_dd->dev, wdog_dd->bark_irq,
+ wdog_bark_handler, IRQF_TRIGGER_RISING,
+ "apps_wdog_bark", wdog_dd);
+ if (ret) {
+ dev_err(wdog_dd->dev, "failed to request bark irq\n");
+ return;
+ }
+ }
delay_time = msecs_to_jiffies(wdog_dd->pet_time);
wdog_dd->min_slack_ticks = UINT_MAX;
wdog_dd->min_slack_ns = ULLONG_MAX;
@@ -298,12 +337,14 @@
wdog_dd->panic_blk.notifier_call = panic_wdog_handler;
atomic_notifier_chain_register(&panic_notifier_list,
&wdog_dd->panic_blk);
- schedule_delayed_work(&wdog_dd->dogwork_struct, delay_time);
+ schedule_delayed_work_on(0, &wdog_dd->dogwork_struct, delay_time);
__raw_writel(1, wdog_dd->base + WDT0_EN);
__raw_writel(1, wdog_dd->base + WDT0_RST);
wdog_dd->last_pet = sched_clock();
printk(KERN_INFO "MSM Watchdog Initialized\n");
+ if (wdog_dd->irq_ppi)
+ enable_percpu_irq(wdog_dd->bark_irq, 0);
return;
}
@@ -377,6 +418,7 @@
__func__);
return -ENXIO;
}
+ pdata->irq_ppi = irq_is_per_cpu(pdata->bark_irq);
dump_pdata(pdata);
return 0;
}
@@ -396,13 +438,6 @@
goto err;
wdog_dd->dev = &pdev->dev;
platform_set_drvdata(pdev, wdog_dd);
- ret = devm_request_irq(&pdev->dev, wdog_dd->bark_irq, wdog_bark_handler,
- IRQF_TRIGGER_RISING, "apps_wdog_bark", wdog_dd);
- if (ret) {
- dev_err(&pdev->dev, "failed to request bark irq\n");
- ret = -ENXIO;
- goto err;
- }
cpumask_clear(&wdog_dd->alive_mask);
INIT_WORK(&wdog_dd->init_dogwork_struct, init_watchdog_work);
INIT_DELAYED_WORK(&wdog_dd->dogwork_struct, pet_watchdog_work);
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 39fbba8..8e0113c 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -830,3 +830,17 @@
return 0;
};
}
+
+const int cpu_is_krait_v3(void)
+{
+ switch (read_cpuid_id()) {
+ case 0x512F04D0:
+ case 0x511F06F0:
+ case 0x511F06F1:
+ case 0x510F05D0:
+ return 1;
+
+ default:
+ return 0;
+ };
+}
diff --git a/drivers/bluetooth/hci_ath.c b/drivers/bluetooth/hci_ath.c
index cfcacff..50b3362 100644
--- a/drivers/bluetooth/hci_ath.c
+++ b/drivers/bluetooth/hci_ath.c
@@ -93,7 +93,7 @@
static void hostwake_interrupt(unsigned long data)
{
- printk(KERN_INFO " wakeup host\n");
+ BT_INFO(" wakeup host\n");
}
static void modify_timer_task(void)
@@ -109,7 +109,7 @@
{
int status = 0;
if (test_bit(BT_TXEXPIRED, &flags)) {
- printk(KERN_INFO "wakeup device\n");
+ BT_INFO("wakeup device\n");
gpio_set_value(bsi->ext_wake, 0);
msleep(20);
gpio_set_value(bsi->ext_wake, 1);
@@ -138,12 +138,114 @@
hci_uart_tx_wakeup(hu);
}
+static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id)
+{
+ /* schedule a tasklet to handle the change in the host wake line */
+ tasklet_schedule(&hostwake_task);
+ return IRQ_HANDLED;
+}
+
+static int ath_bluesleep_gpio_config(int on)
+{
+ int ret = 0;
+
+ BT_INFO("%s config: %d", __func__, on);
+ if (!on) {
+ if (disable_irq_wake(bsi->host_wake_irq))
+ BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n");
+ goto free_host_wake_irq;
+ }
+
+ ret = gpio_request(bsi->host_wake, "bt_host_wake");
+ if (ret < 0) {
+ BT_ERR("failed to request gpio pin %d, error %d\n",
+ bsi->host_wake, ret);
+ goto gpio_config_failed;
+ }
+
+ /* configure host_wake as input */
+ ret = gpio_direction_input(bsi->host_wake);
+ if (ret < 0) {
+ BT_ERR("failed to config GPIO %d as input pin, err %d\n",
+ bsi->host_wake, ret);
+ goto gpio_host_wake;
+ }
+
+ ret = gpio_request(bsi->ext_wake, "bt_ext_wake");
+ if (ret < 0) {
+ BT_ERR("failed to request gpio pin %d, error %d\n",
+ bsi->ext_wake, ret);
+ goto gpio_host_wake;
+ }
+
+ ret = gpio_direction_output(bsi->ext_wake, 1);
+ if (ret < 0) {
+ BT_ERR("failed to config GPIO %d as output pin, err %d\n",
+ bsi->ext_wake, ret);
+ goto gpio_ext_wake;
+ }
+
+ gpio_set_value(bsi->ext_wake, 1);
+
+ /* Initialize spinlock. */
+ spin_lock_init(&rw_lock);
+
+ /* Initialize timer */
+ init_timer(&tx_timer);
+ tx_timer.function = bluesleep_tx_timer_expire;
+ tx_timer.data = 0;
+
+ /* initialize host wake tasklet */
+ tasklet_init(&hostwake_task, hostwake_interrupt, 0);
+
+ if (bsi->irq_polarity == POLARITY_LOW) {
+ ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
+ IRQF_DISABLED | IRQF_TRIGGER_FALLING,
+ "bluetooth hostwake", NULL);
+ } else {
+ ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
+ IRQF_DISABLED | IRQF_TRIGGER_RISING,
+ "bluetooth hostwake", NULL);
+ }
+ if (ret < 0) {
+ BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ");
+ goto delete_timer;
+ }
+
+ ret = enable_irq_wake(bsi->host_wake_irq);
+ if (ret < 0) {
+ BT_ERR("Couldn't enable BT_HOST_WAKE as wakeup interrupt");
+ goto free_host_wake_irq;
+ }
+
+ return 0;
+
+free_host_wake_irq:
+ free_irq(bsi->host_wake_irq, NULL);
+delete_timer:
+ del_timer(&tx_timer);
+gpio_ext_wake:
+ gpio_free(bsi->ext_wake);
+gpio_host_wake:
+ gpio_free(bsi->host_wake);
+gpio_config_failed:
+ return ret;
+}
+
/* Initialize protocol */
static int ath_open(struct hci_uart *hu)
{
struct ath_struct *ath;
- BT_DBG("hu %p", hu);
+ BT_DBG("hu %p, bsi %p", hu, bsi);
+
+ if (!bsi)
+ return -EIO;
+
+ if (ath_bluesleep_gpio_config(1) < 0) {
+ BT_ERR("HCIATH3K GPIO Config failed");
+ return -EIO;
+ }
ath = kzalloc(sizeof(*ath), GFP_ATOMIC);
if (!ath)
@@ -190,6 +292,9 @@
hu->priv = NULL;
kfree(ath);
+ if (bsi)
+ ath_bluesleep_gpio_config(0);
+
return 0;
}
@@ -200,6 +305,8 @@
{
struct ath_struct *ath = hu->priv;
+ BT_DBG("");
+
if (bt_cb(skb)->pkt_type == HCI_SCODATA_PKT) {
kfree_skb(skb);
return 0;
@@ -243,6 +350,8 @@
struct ath_struct *ath = hu->priv;
unsigned int type;
+ BT_DBG("");
+
if (hci_recv_stream_fragment(hu->hdev, data, count) < 0)
BT_ERR("Frame Reassembly Failed");
@@ -260,7 +369,7 @@
if (type == HCI_EVENT_PKT) {
clear_bit(BT_SLEEPCMD, &flags);
- printk(KERN_INFO "cur_sleep:%d\n", ath->cur_sleep);
+ BT_INFO("cur_sleep:%d\n", ath->cur_sleep);
if (ath->cur_sleep == 1)
set_bit(BT_SLEEPENABLE, &flags);
else
@@ -276,19 +385,11 @@
{
if (!test_bit(BT_SLEEPENABLE, &flags))
return;
- BT_DBG("Tx timer expired");
- printk(KERN_INFO "Tx timer expired\n");
+ BT_INFO("Tx timer expired\n");
set_bit(BT_TXEXPIRED, &flags);
}
-static irqreturn_t bluesleep_hostwake_isr(int irq, void *dev_id)
-{
- /* schedule a tasklet to handle the change in the host wake line */
- tasklet_schedule(&hostwake_task);
- return IRQ_HANDLED;
-}
-
static struct hci_uart_proto athp = {
.id = HCI_UART_ATH3K,
.open = ath_open,
@@ -304,6 +405,8 @@
int ret;
struct resource *res;
+ BT_DBG("");
+
bsi = kzalloc(sizeof(struct bluesleep_info), GFP_KERNEL);
if (!bsi) {
ret = -ENOMEM;
@@ -319,107 +422,35 @@
}
bsi->host_wake = res->start;
- ret = gpio_request(bsi->host_wake, "bt_host_wake");
- if (ret)
- goto free_bsi;
-
- /* configure host_wake as input */
- ret = gpio_direction_input(bsi->host_wake);
- if (ret < 0) {
- pr_err("%s: gpio_direction_input failed for GPIO %d, error %d\n",
- __func__, bsi->host_wake, ret);
- gpio_free(bsi->host_wake);
- goto free_bsi;
- }
-
res = platform_get_resource_byname(pdev, IORESOURCE_IO,
"gpio_ext_wake");
if (!res) {
BT_ERR("couldn't find ext_wake gpio\n");
ret = -ENODEV;
- goto free_bt_host_wake;
+ goto free_bsi;
}
bsi->ext_wake = res->start;
- ret = gpio_request(bsi->ext_wake, "bt_ext_wake");
- if (ret)
- goto free_bt_host_wake;
-
- /* configure ext_wake as output mode*/
- ret = gpio_direction_output(bsi->ext_wake, 1);
- if (ret < 0) {
- pr_err("%s: gpio_direction_output failed for GPIO %d, error %d\n",
- __func__, bsi->ext_wake, ret);
- gpio_free(bsi->ext_wake);
- goto free_bt_host_wake;
- }
- gpio_set_value(bsi->ext_wake, 1);
-
bsi->host_wake_irq = platform_get_irq_byname(pdev, "host_wake");
if (bsi->host_wake_irq < 0) {
BT_ERR("couldn't find host_wake irq\n");
ret = -ENODEV;
- goto free_bt_ext_wake;
+ goto free_bsi;
}
bsi->irq_polarity = POLARITY_LOW; /* low edge (falling edge) */
- /* Initialize spinlock. */
- spin_lock_init(&rw_lock);
-
- /* Initialize timer */
- init_timer(&tx_timer);
- tx_timer.function = bluesleep_tx_timer_expire;
- tx_timer.data = 0;
-
- /* initialize host wake tasklet */
- tasklet_init(&hostwake_task, hostwake_interrupt, 0);
-
- if (bsi->irq_polarity == POLARITY_LOW) {
- ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
- IRQF_DISABLED | IRQF_TRIGGER_FALLING,
- "bluetooth hostwake", NULL);
- } else {
- ret = request_irq(bsi->host_wake_irq, bluesleep_hostwake_isr,
- IRQF_DISABLED | IRQF_TRIGGER_RISING,
- "bluetooth hostwake", NULL);
- }
- if (ret < 0) {
- BT_ERR("Couldn't acquire BT_HOST_WAKE IRQ");
- goto free_bt_timer;
- }
-
- ret = enable_irq_wake(bsi->host_wake_irq);
- if (ret < 0) {
- BT_ERR("Couldn't enable BT_HOST_WAKE as wakeup interrupt");
- free_irq(bsi->host_wake_irq, NULL);
- goto free_bt_timer;
- }
-
return 0;
-free_bt_timer:
- del_timer(&tx_timer);
-free_bt_ext_wake:
- gpio_free(bsi->ext_wake);
-free_bt_host_wake:
- gpio_free(bsi->host_wake);
free_bsi:
kfree(bsi);
+ bsi = NULL;
failed:
return ret;
}
static int bluesleep_remove(struct platform_device *pdev)
{
- /* assert bt wake */
- gpio_set_value(bsi->ext_wake, 0);
- if (disable_irq_wake(bsi->host_wake_irq))
- BT_ERR("Couldn't disable hostwake IRQ wakeup mode\n");
- free_irq(bsi->host_wake_irq, NULL);
- del_timer_sync(&tx_timer);
- gpio_free(bsi->host_wake);
- gpio_free(bsi->ext_wake);
kfree(bsi);
return 0;
}
diff --git a/drivers/bluetooth/hci_ibs.c b/drivers/bluetooth/hci_ibs.c
index fb084f5..6253605 100644
--- a/drivers/bluetooth/hci_ibs.c
+++ b/drivers/bluetooth/hci_ibs.c
@@ -112,6 +112,13 @@
unsigned long rx_vote; /* clock must be on for RX */
struct timer_list tx_idle_timer;
struct timer_list wake_retrans_timer;
+ struct workqueue_struct *workqueue;
+ struct work_struct ws_awake_rx;
+ struct work_struct ws_awake_device;
+ struct work_struct ws_rx_vote_off;
+ struct work_struct ws_tx_vote_off;
+ void *ibs_hu; /* keeps the hci_uart pointer for reference */
+
/* debug */
unsigned long ibs_sent_wacks;
unsigned long ibs_sent_slps;
@@ -242,12 +249,90 @@
return err;
}
+static void ibs_wq_awake_device(struct work_struct *work)
+{
+ struct ibs_struct *ibs = container_of(work, struct ibs_struct,
+ ws_awake_device);
+ struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+
+ BT_DBG(" %p ", hu);
+
+ /* Vote for serial clock */
+ ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
+
+ spin_lock(&ibs->hci_ibs_lock);
+
+ /* send wake indication to device */
+ if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0)
+ BT_ERR("cannot send WAKE to device");
+
+ ibs->ibs_sent_wakes++; /* debug */
+
+ /* start retransmit timer */
+ mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);
+
+ spin_unlock(&ibs->hci_ibs_lock);
+}
+
+static void ibs_wq_awake_rx(struct work_struct *work)
+{
+ struct ibs_struct *ibs = container_of(work, struct ibs_struct,
+ ws_awake_rx);
+ struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+
+ BT_DBG(" %p ", hu);
+
+ ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
+
+ spin_lock(&ibs->hci_ibs_lock);
+ ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
+ /* Always acknowledge device wake up,
+ * sending IBS message doesn't count as TX ON
+ */
+ if (send_hci_ibs_cmd(HCI_IBS_WAKE_ACK, hu) < 0)
+ BT_ERR("cannot acknowledge device wake up");
+
+ ibs->ibs_sent_wacks++; /* debug */
+
+ spin_unlock(&ibs->hci_ibs_lock);
+ /* actually send the packets */
+ hci_uart_tx_wakeup(hu);
+
+}
+
+static void ibs_wq_serial_rx_clock_vote_off(struct work_struct *work)
+{
+ struct ibs_struct *ibs = container_of(work, struct ibs_struct,
+ ws_rx_vote_off);
+ struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+
+ BT_DBG(" %p ", hu);
+
+ ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu);
+
+}
+
+static void ibs_wq_serial_tx_clock_vote_off(struct work_struct *work)
+{
+ struct ibs_struct *ibs = container_of(work, struct ibs_struct,
+ ws_tx_vote_off);
+ struct hci_uart *hu = (struct hci_uart *)ibs->ibs_hu;
+
+ BT_DBG(" %p ", hu);
+
+ hci_uart_tx_wakeup(hu); /* run HCI tx handling unlocked */
+
+ /* now that message queued to tty driver, vote for tty clocks off */
+ /* It is up to the tty driver to pend the clocks off until tx done. */
+ ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
+
+}
+
static void hci_ibs_tx_idle_timeout(unsigned long arg)
{
struct hci_uart *hu = (struct hci_uart *) arg;
struct ibs_struct *ibs = hu->priv;
unsigned long flags;
- unsigned long vote_tx_sleep = 0;
BT_DBG("hu %p idle timeout in %lu state", hu, ibs->tx_ibs_state);
@@ -267,22 +352,11 @@
}
ibs->tx_ibs_state = HCI_IBS_TX_ASLEEP;
ibs->ibs_sent_slps++; /* debug */
- vote_tx_sleep = 1;
break;
}
- spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+ queue_work(ibs->workqueue, &ibs->ws_tx_vote_off);
- hci_uart_tx_wakeup(hu); /* run HCI tx handling unlocked */
-
- if (!vote_tx_sleep)
- return;
- /* now that message queued to tty driver, vote for tty clocks off */
- /* It is up to the tty driver to pend the clocks off until tx done. */
-
- spin_lock_irqsave_nested(&ibs->hci_ibs_lock,
- flags, SINGLE_DEPTH_NESTING);
- ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_OFF, hu);
out:
spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
}
@@ -336,6 +410,19 @@
skb_queue_head_init(&ibs->txq);
skb_queue_head_init(&ibs->tx_wait_q);
spin_lock_init(&ibs->hci_ibs_lock);
+ ibs->workqueue = create_singlethread_workqueue("ibs_wq");
+ if (!ibs->workqueue) {
+ BT_ERR("IBS Workqueue not initialized properly");
+ kfree(ibs);
+ return -ENOMEM;
+ }
+
+ INIT_WORK(&ibs->ws_awake_rx, ibs_wq_awake_rx);
+ INIT_WORK(&ibs->ws_awake_device, ibs_wq_awake_device);
+ INIT_WORK(&ibs->ws_rx_vote_off, ibs_wq_serial_rx_clock_vote_off);
+ INIT_WORK(&ibs->ws_tx_vote_off, ibs_wq_serial_tx_clock_vote_off);
+
+ ibs->ibs_hu = (void *)hu;
/* Assume we start with both sides asleep -- extra wakes OK */
ibs->tx_ibs_state = HCI_IBS_TX_ASLEEP;
@@ -432,6 +519,8 @@
skb_queue_purge(&ibs->txq);
del_timer(&ibs->tx_idle_timer);
del_timer(&ibs->wake_retrans_timer);
+ destroy_workqueue(ibs->workqueue);
+ ibs->ibs_hu = NULL;
kfree_skb(ibs->rx_skb);
@@ -463,9 +552,10 @@
/* Make sure clock is on - we may have turned clock off since
* receiving the wake up indicator
*/
- ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_ON, hu);
- ibs->rx_ibs_state = HCI_IBS_RX_AWAKE;
- /* deliberate fall-through */
+ /* awake rx clock */
+ queue_work(ibs->workqueue, &ibs->ws_awake_rx);
+ spin_unlock_irqrestore(&ibs->hci_ibs_lock, flags);
+ return;
case HCI_IBS_RX_AWAKE:
/* Always acknowledge device wake up,
* sending IBS message doesn't count as TX ON.
@@ -510,7 +600,8 @@
case HCI_IBS_RX_AWAKE:
/* update state */
ibs->rx_ibs_state = HCI_IBS_RX_ASLEEP;
- ibs_msm_serial_clock_vote(HCI_IBS_RX_VOTE_CLOCK_OFF, hu);
+ /* vote off rx clock under workqueue */
+ queue_work(ibs->workqueue, &ibs->ws_rx_vote_off);
break;
case HCI_IBS_RX_ASLEEP:
/* deliberate fall-through */
@@ -595,20 +686,12 @@
case HCI_IBS_TX_ASLEEP:
BT_DBG("device asleep, waking up and queueing packet");
- ibs_msm_serial_clock_vote(HCI_IBS_TX_VOTE_CLOCK_ON, hu);
/* save packet for later */
skb_queue_tail(&ibs->tx_wait_q, skb);
- /* awake device */
- if (send_hci_ibs_cmd(HCI_IBS_WAKE_IND, hu) < 0) {
- BT_ERR("cannot send WAKE to device");
- break;
- }
- ibs->ibs_sent_wakes++; /* debug */
-
- /* start retransmit timer */
- mod_timer(&ibs->wake_retrans_timer, jiffies + wake_retrans);
ibs->tx_ibs_state = HCI_IBS_TX_WAKING;
+ /* schedule a work queue to wake up device */
+ queue_work(ibs->workqueue, &ibs->ws_awake_device);
break;
case HCI_IBS_TX_WAKING:
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 0febaf3..69783f4 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -272,6 +272,7 @@
unsigned char *buf_in_smux;
int in_busy_smux;
int diag_smux_enabled;
+ int smux_connected;
/* HSIC variables */
unsigned char *buf_in_hsic;
int hsic_ch;
diff --git a/drivers/char/diag/diagfwd_hsic.c b/drivers/char/diag/diagfwd_hsic.c
index fedcf03..81c6afa 100644
--- a/drivers/char/diag/diagfwd_hsic.c
+++ b/drivers/char/diag/diagfwd_hsic.c
@@ -296,7 +296,7 @@
usb_diag_free_req(driver->mdm_ch);
}
- if (driver->logging_mode != MEMORY_DEVICE_MODE) {
+ if (driver->logging_mode == USB_MODE) {
if (driver->hsic_device_enabled) {
driver->in_busy_hsic_write_on_device = 1;
driver->in_busy_hsic_read_on_device = 1;
@@ -307,6 +307,7 @@
} else if (driver->diag_smux_enabled) {
driver->in_busy_smux = 1;
driver->lcid = LCID_INVALID;
+ driver->smux_connected = 0;
/* Turn off communication over usb mdm and smux */
msm_smux_close(LCID_VALID);
}
@@ -440,7 +441,8 @@
int ret;
if (driver->diag_smux_enabled) {
if (driver->lcid && driver->usb_buf_mdm_out &&
- (driver->read_len_mdm > 0)) {
+ (driver->read_len_mdm > 0) &&
+ driver->smux_connected) {
ret = msm_smux_write(driver->lcid, NULL,
driver->usb_buf_mdm_out, driver->read_len_mdm);
if (ret)
diff --git a/drivers/char/diag/diagfwd_smux.c b/drivers/char/diag/diagfwd_smux.c
index 8bbc67e..ae90686 100644
--- a/drivers/char/diag/diagfwd_smux.c
+++ b/drivers/char/diag/diagfwd_smux.c
@@ -26,13 +26,17 @@
switch (event_type) {
case SMUX_CONNECTED:
- pr_debug("diag: SMUX_CONNECTED received\n");
+ pr_info("diag: SMUX_CONNECTED received\n");
+ driver->smux_connected = 1;
driver->in_busy_smux = 0;
/* read data from USB MDM channel & Initiate first write */
queue_work(driver->diag_bridge_wq,
&(driver->diag_read_mdm_work));
break;
case SMUX_DISCONNECTED:
+ driver->smux_connected = 0;
+ driver->lcid = LCID_INVALID;
+ msm_smux_close(LCID_VALID);
pr_info("diag: SMUX_DISCONNECTED received\n");
break;
case SMUX_WRITE_DONE:
@@ -112,6 +116,7 @@
pr_info("diag: open SMUX ch, r = %d\n", ret);
} else {
pr_err("diag: failed to open SMUX ch, r = %d\n", ret);
+ return ret;
}
}
/* Poll USB channel to check for data*/
@@ -146,8 +151,20 @@
return ret;
}
+static int diagfwd_smux_remove(struct platform_device *pdev)
+{
+ driver->lcid = LCID_INVALID;
+ driver->smux_connected = 0;
+ driver->diag_smux_enabled = 0;
+ driver->in_busy_smux = 1;
+ kfree(driver->buf_in_smux);
+ driver->buf_in_smux = NULL;
+ return 0;
+}
+
struct platform_driver msm_diagfwd_smux_driver = {
.probe = diagfwd_smux_probe,
+ .remove = diagfwd_smux_remove,
.driver = {
.name = "SMUX_DIAG",
.owner = THIS_MODULE,
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index e805c7f..46d3e5d 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -1516,6 +1516,12 @@
static int etm_count;
struct coresight_desc *desc;
+ /* Fail probe for Krait pass3 until supported */
+ if (cpu_is_krait_v3()) {
+ dev_info(dev, "ETM: failing probe for Krait pass3\n");
+ return -EINVAL;
+ }
+
if (pdev->dev.of_node) {
pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
if (IS_ERR(pdata))
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index b4ae6ef..19dd6dc 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -179,7 +179,7 @@
"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
512, 0, 2, SZ_256K },
/* A3XX doesn't use the pix_shader_start */
- { ADRENO_REV_A320, 3, 2, 0, ANY_ID,
+ { ADRENO_REV_A320, 3, 2, ANY_ID, ANY_ID,
"a300_pm4.fw", "a300_pfp.fw", &adreno_a3xx_gpudev,
512, 0, 2, SZ_512K },
{ ADRENO_REV_A330, 3, 3, 0, 0,
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 880fe92..8c45475 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -465,16 +465,17 @@
&pwr->power_flags)) {
trace_kgsl_clk(device, state);
/* High latency clock maintenance. */
- if ((pwr->pwrlevels[0].gpu_freq > 0) &&
- (device->state != KGSL_STATE_NAP)) {
+ if (device->state != KGSL_STATE_NAP) {
for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
if (pwr->grp_clks[i])
clk_prepare(pwr->grp_clks[i]);
- clk_set_rate(pwr->grp_clks[0],
- pwr->pwrlevels[pwr->active_pwrlevel].
+
+ if (pwr->pwrlevels[0].gpu_freq > 0)
+ clk_set_rate(pwr->grp_clks[0],
+ pwr->pwrlevels
+ [pwr->active_pwrlevel].
gpu_freq);
}
-
/* as last step, enable grp_clk
this is to let GPU interrupt to come */
for (i = KGSL_MAX_CLKS - 1; i > 0; i--)
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index c6d568c..0d15f75 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -939,7 +939,6 @@
server_q_idx = msm_find_free_queue();
if (server_q_idx < 0)
return server_q_idx;
-
rc = msm_server_begin_session(pcam, server_q_idx);
if (rc < 0) {
pr_err("%s error starting server session ", __func__);
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 5b618f8..577648f 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -31,6 +31,7 @@
#include <media/videobuf2-msm-mem.h>
#include <media/msm_isp.h>
#include <mach/camera.h>
+#include <mach/iommu.h>
#include <media/msm_isp.h>
#include <linux/ion.h>
#include <linux/iommu.h>
@@ -315,6 +316,10 @@
uint32_t ping_imem_cbcr;
uint32_t pong_imem_y;
uint32_t pong_imem_cbcr;
+
+ /*IOMMU domain for this session*/
+ int domain_num;
+ struct iommu_domain *domain;
};
struct msm_isp_buf_info {
@@ -417,6 +422,8 @@
struct msm_cam_media_controller *p_mctl;
struct msm_mem_map_info mem_map;
int dev_num;
+ int domain_num;
+ struct iommu_domain *domain;
};
struct msm_cam_subdev_info {
@@ -576,6 +583,10 @@
* dispatch the irq to the corresponding subdev. */
struct v4l2_subdev *subdev_table[MSM_CAM_HW_MAX];
struct msm_cam_server_irqmap_entry hw_irqmap[CAMERA_SS_IRQ_MAX];
+
+ /*IOMMU domain (Page table)*/
+ int domain_num;
+ struct iommu_domain *domain;
};
enum msm_cam_buf_lookup_type {
@@ -623,9 +634,9 @@
struct msm_free_buf *free_buf);
/*Memory(PMEM) functions*/
int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
- struct ion_client *client);
+ struct ion_client *client, int domain_num);
int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg,
- struct ion_client *client);
+ struct ion_client *client, int domain_num);
int msm_pmem_region_get_phy_addr(struct hlist_head *ptype,
struct msm_mem_map_info *mem_map, int32_t *phyaddr);
uint8_t msm_pmem_region_lookup(struct hlist_head *ptype,
@@ -647,7 +658,7 @@
struct msm_vfe_cfg_cmd *cfgcmd, void *data);
int msm_vpe_subdev_init(struct v4l2_subdev *sd);
int msm_gemini_subdev_init(struct v4l2_subdev *gemini_sd);
-void msm_vpe_subdev_release(void);
+void msm_vpe_subdev_release(struct v4l2_subdev *sd);
void msm_gemini_subdev_release(struct v4l2_subdev *gemini_sd);
int msm_mctl_is_pp_msg_type(struct msm_cam_media_controller *p_mctl,
int msg_type);
@@ -695,9 +706,9 @@
int msm_mctl_buf_return_buf(struct msm_cam_media_controller *pmctl,
int image_mode, struct msm_frame_buffer *buf);
int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
- struct ion_client *client);
+ struct ion_client *client, int domain_num);
int msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
- struct ion_client *client);
+ struct ion_client *client, int domain_num);
int msm_mctl_pp_mctl_divert_done(struct msm_cam_media_controller *p_mctl,
void __user *arg);
void msm_release_ion_client(struct kref *ref);
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index a0cbed5..953f042 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -130,7 +130,8 @@
rc = videobuf2_pmem_contig_user_get(mem, &offset,
buf_type,
pcam_inst->buf_offset[buf_idx][i].addr_offset,
- pcam_inst->path, pmctl->client);
+ pcam_inst->path, pmctl->client,
+ pmctl->domain_num);
else
rc = videobuf2_pmem_contig_mmap_get(mem, &offset,
buf_type, pcam_inst->path);
@@ -265,7 +266,8 @@
}
for (i = 0; i < vb->num_planes; i++) {
mem = vb2_plane_cookie(vb, i);
- videobuf2_pmem_contig_user_put(mem, pmctl->client);
+ videobuf2_pmem_contig_user_put(mem, pmctl->client,
+ pmctl->domain_num);
}
buf->state = MSM_BUFFER_STATE_UNUSED;
}
@@ -856,21 +858,21 @@
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
/* Unmap using ION APIs */
static void __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
int i = 0;
for (i = 0; i < meta_frame->frame.num_planes; i++) {
D("%s Plane %d handle %p", __func__, i,
meta_frame->map[i].handle);
ion_unmap_iommu(client, meta_frame->map[i].handle,
- CAMERA_DOMAIN, GEN_POOL);
+ domain_num, 0);
ion_free(client, meta_frame->map[i].handle);
}
}
/* Map using ION APIs */
static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
unsigned long paddr = 0;
unsigned long len = 0;
@@ -886,7 +888,7 @@
for (j = i-1; j >= 0; j--) {
ion_unmap_iommu(client,
meta_frame->map[j].handle,
- CAMERA_DOMAIN, GEN_POOL);
+ domain_num, 0);
ion_free(client, meta_frame->map[j].handle);
}
return -EACCES;
@@ -895,7 +897,7 @@
meta_frame->frame.mp[i].fd, i,
meta_frame->map[i].handle);
if (ion_map_iommu(client, meta_frame->map[i].handle,
- CAMERA_DOMAIN, GEN_POOL, SZ_4K,
+ domain_num, 0, SZ_4K,
0, &paddr, &len, UNCACHED, 0) < 0) {
pr_err("%s: cannot map address plane %d", __func__, i);
ion_free(client, meta_frame->map[i].handle);
@@ -904,7 +906,7 @@
if (meta_frame->map[j].handle) {
ion_unmap_iommu(client,
meta_frame->map[j].handle,
- CAMERA_DOMAIN, GEN_POOL);
+ domain_num, 0);
ion_free(client,
meta_frame->map[j].handle);
}
@@ -925,7 +927,7 @@
if (meta_frame->map[j].handle) {
ion_unmap_iommu(client,
meta_frame->map[j].handle,
- CAMERA_DOMAIN, GEN_POOL);
+ domain_num, 0);
ion_free(client,
meta_frame->map[j].handle);
}
@@ -952,7 +954,7 @@
#else
/* Unmap using PMEM APIs */
static int __msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
int i = 0, rc = 0;
@@ -965,7 +967,7 @@
/* Map using PMEM APIs */
static int __msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
unsigned long kvstart = 0;
unsigned long paddr = 0;
@@ -1024,7 +1026,7 @@
#endif
int msm_mctl_map_user_frame(struct msm_cam_meta_frame *meta_frame,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
if ((NULL == meta_frame) || (NULL == client)) {
@@ -1035,16 +1037,16 @@
memset(&meta_frame->map[0], 0,
sizeof(struct msm_cam_buf_map_info) * VIDEO_MAX_PLANES);
- return __msm_mctl_map_user_frame(meta_frame, client);
+ return __msm_mctl_map_user_frame(meta_frame, client, domain_num);
}
int msm_mctl_unmap_user_frame(struct msm_cam_meta_frame *meta_frame,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
if ((NULL == meta_frame) || (NULL == client)) {
pr_err("%s Invalid input ", __func__);
return -EINVAL;
}
- __msm_mctl_unmap_user_frame(meta_frame, client);
+ __msm_mctl_unmap_user_frame(meta_frame, client, domain_num);
return 0;
}
diff --git a/drivers/media/video/msm/msm_mem.c b/drivers/media/video/msm/msm_mem.c
index e2e9d1b..5136d9d 100644
--- a/drivers/media/video/msm/msm_mem.c
+++ b/drivers/media/video/msm/msm_mem.c
@@ -116,7 +116,7 @@
}
static int msm_pmem_table_add(struct hlist_head *ptype,
- struct msm_pmem_info *info, struct ion_client *client)
+ struct msm_pmem_info *info, struct ion_client *client, int domain_num)
{
unsigned long paddr;
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -135,7 +135,7 @@
region->handle = ion_import_dma_buf(client, info->fd);
if (IS_ERR_OR_NULL(region->handle))
goto out1;
- if (ion_map_iommu(client, region->handle, CAMERA_DOMAIN, GEN_POOL,
+ if (ion_map_iommu(client, region->handle, domain_num, 0,
SZ_4K, 0, &paddr, &len, UNCACHED, 0) < 0)
goto out2;
#elif CONFIG_ANDROID_PMEM
@@ -180,7 +180,7 @@
return 0;
out3:
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- ion_unmap_iommu(client, region->handle, CAMERA_DOMAIN, GEN_POOL);
+ ion_unmap_iommu(client, region->handle, domain_num, 0);
#endif
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
out2:
@@ -195,7 +195,8 @@
}
static int __msm_register_pmem(struct hlist_head *ptype,
- struct msm_pmem_info *pinfo, struct ion_client *client)
+ struct msm_pmem_info *pinfo, struct ion_client *client,
+ int domain_num)
{
int rc = 0;
@@ -211,7 +212,7 @@
case MSM_PMEM_BAYER_GRID:
case MSM_PMEM_BAYER_FOCUS:
case MSM_PMEM_BAYER_HIST:
- rc = msm_pmem_table_add(ptype, pinfo, client);
+ rc = msm_pmem_table_add(ptype, pinfo, client, domain_num);
break;
default:
@@ -223,7 +224,8 @@
}
static int __msm_pmem_table_del(struct hlist_head *ptype,
- struct msm_pmem_info *pinfo, struct ion_client *client)
+ struct msm_pmem_info *pinfo, struct ion_client *client,
+ int domain_num)
{
int rc = 0;
struct msm_pmem_region *region;
@@ -250,7 +252,7 @@
hlist_del(node);
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
ion_unmap_iommu(client, region->handle,
- CAMERA_DOMAIN, GEN_POOL);
+ domain_num, 0);
ion_free(client, region->handle);
#else
put_pmem_file(region->file);
@@ -394,7 +396,8 @@
}
int msm_register_pmem(struct hlist_head *ptype, void __user *arg,
- struct ion_client *client)
+ struct ion_client *client,
+ int domain_num)
{
struct msm_pmem_info info;
@@ -403,12 +406,12 @@
return -EFAULT;
}
- return __msm_register_pmem(ptype, &info, client);
+ return __msm_register_pmem(ptype, &info, client, domain_num);
}
//EXPORT_SYMBOL(msm_register_pmem);
int msm_pmem_table_del(struct hlist_head *ptype, void __user *arg,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
struct msm_pmem_info info;
@@ -417,6 +420,6 @@
return -EFAULT;
}
- return __msm_pmem_table_del(ptype, &info, client);
+ return __msm_pmem_table_del(ptype, &info, client, domain_num);
}
//EXPORT_SYMBOL(msm_pmem_table_del);
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 9fa9734..ede0f7a 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -36,8 +36,8 @@
#define D(fmt, args...) do {} while (0)
#endif
-static int vpe_enable(uint32_t);
-static int vpe_disable(void);
+static int vpe_enable(uint32_t, struct msm_cam_media_controller *);
+static int vpe_disable(struct msm_cam_media_controller *);
static int vpe_update_scaler(struct msm_pp_crop *pcrop);
struct vpe_ctrl_type *vpe_ctrl;
static atomic_t vpe_init_done = ATOMIC_INIT(0);
@@ -520,7 +520,7 @@
{"vpe_pclk", -1},
};
-int vpe_enable(uint32_t clk_rate)
+int vpe_enable(uint32_t clk_rate, struct msm_cam_media_controller *mctl)
{
int rc = 0;
unsigned long flags = 0;
@@ -549,8 +549,27 @@
if (rc < 0)
goto vpe_clk_failed;
+#ifdef CONFIG_MSM_IOMMU
+ rc = iommu_attach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+ if (rc < 0) {
+ pr_err("%s: Device attach failed\n", __func__);
+ goto src_attach_failed;
+ }
+ rc = iommu_attach_device(mctl->domain, vpe_ctrl->iommu_ctx_dst);
+ if (rc < 0) {
+ pr_err("%s: Device attach failed\n", __func__);
+ goto dst_attach_failed;
+ }
+#endif
return rc;
+#ifdef CONFIG_MSM_IOMMU
+dst_attach_failed:
+ iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+src_attach_failed:
+#endif
+ msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
+ vpe_ctrl->vpe_clk, ARRAY_SIZE(vpe_clk_info), 0);
vpe_clk_failed:
if (vpe_ctrl->fs_vpe)
regulator_disable(vpe_ctrl->fs_vpe);
@@ -560,7 +579,7 @@
return rc;
}
-int vpe_disable(void)
+int vpe_disable(struct msm_cam_media_controller *mctl)
{
int rc = 0;
unsigned long flags = 0;
@@ -572,7 +591,10 @@
return rc;
}
spin_unlock_irqrestore(&vpe_ctrl->lock, flags);
-
+#ifdef CONFIG_MSM_IOMMU
+ iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_dst);
+ iommu_detach_device(mctl->domain, vpe_ctrl->iommu_ctx_src);
+#endif
disable_irq(vpe_ctrl->vpeirq->start);
tasklet_kill(&vpe_tasklet);
msm_cam_clk_enable(&vpe_ctrl->pdev->dev, vpe_clk_info,
@@ -655,23 +677,25 @@
return rc; /* this rc should have error code. */
}
-void msm_vpe_subdev_release(void)
+void msm_vpe_subdev_release(struct v4l2_subdev *sd)
{
+ struct msm_cam_media_controller *mctl;
+ mctl = v4l2_get_subdev_hostdata(sd);
if (!atomic_read(&vpe_init_done)) {
/* no VPE object created */
pr_err("%s: no VPE object to release", __func__);
return;
}
-
vpe_reset();
- vpe_disable();
+ vpe_disable(mctl);
iounmap(vpe_ctrl->vpebase);
vpe_ctrl->vpebase = NULL;
atomic_set(&vpe_init_done, 0);
}
EXPORT_SYMBOL(msm_vpe_subdev_release);
-static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd)
+static int msm_vpe_process_vpe_cmd(struct msm_vpe_cfg_cmd *vpe_cmd,
+ struct msm_cam_media_controller *mctl)
{
int rc = 0;
@@ -802,7 +826,7 @@
D("%s Mapping Source frame ", __func__);
zoom->src_frame.frame = zoom->pp_frame_cmd.src_frame;
rc = msm_mctl_map_user_frame(&zoom->src_frame,
- zoom->p_mctl->client);
+ zoom->p_mctl->client, mctl->domain_num);
if (rc < 0) {
pr_err("%s Error mapping source buffer rc = %d",
__func__, rc);
@@ -813,12 +837,12 @@
D("%s Mapping Destination frame ", __func__);
zoom->dest_frame.frame = zoom->pp_frame_cmd.dest_frame;
rc = msm_mctl_map_user_frame(&zoom->dest_frame,
- zoom->p_mctl->client);
+ zoom->p_mctl->client, mctl->domain_num);
if (rc < 0) {
pr_err("%s Error mapping dest buffer rc = %d",
__func__, rc);
msm_mctl_unmap_user_frame(&zoom->src_frame,
- zoom->p_mctl->client);
+ zoom->p_mctl->client, mctl->domain_num);
kfree(zoom);
break;
}
@@ -843,13 +867,13 @@
return -EFAULT;
}
turbo_mode = (int)clk_rate.rate;
- rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE) :
- vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE);
+ rc = turbo_mode ? vpe_enable(VPE_TURBO_MODE_CLOCK_RATE, mctl) :
+ vpe_enable(VPE_NORMAL_MODE_CLOCK_RATE, mctl);
break;
}
case VPE_CMD_DISABLE:
- rc = vpe_disable();
+ rc = vpe_disable(mctl);
break;
default:
@@ -864,7 +888,8 @@
{
struct msm_vpe_cfg_cmd *vpe_cmd;
int rc = 0;
-
+ struct msm_cam_media_controller *mctl;
+ mctl = v4l2_get_subdev_hostdata(sd);
switch (cmd) {
case VIDIOC_MSM_VPE_INIT: {
msm_vpe_subdev_init(sd);
@@ -872,12 +897,12 @@
}
case VIDIOC_MSM_VPE_RELEASE:
- msm_vpe_subdev_release();
+ msm_vpe_subdev_release(sd);
break;
case MSM_CAM_V4L2_IOCTL_CFG_VPE: {
vpe_cmd = (struct msm_vpe_cfg_cmd *)arg;
- rc = msm_vpe_process_vpe_cmd(vpe_cmd);
+ rc = msm_vpe_process_vpe_cmd(vpe_cmd, mctl);
if (rc < 0) {
pr_err("%s Error processing VPE cmd %d ",
__func__, vpe_cmd->cmd_type);
@@ -903,9 +928,9 @@
D("%s Unmapping source and destination buffers ",
__func__);
msm_mctl_unmap_user_frame(&pp_frame_info->src_frame,
- pp_frame_info->p_mctl->client);
+ pp_frame_info->p_mctl->client, mctl->domain_num);
msm_mctl_unmap_user_frame(&pp_frame_info->dest_frame,
- pp_frame_info->p_mctl->client);
+ pp_frame_info->p_mctl->client, mctl->domain_num);
pp_event_info.event = MCTL_PP_EVENT_CMD_ACK;
pp_event_info.ack.cmd = pp_frame_info->user_cmd;
@@ -973,7 +998,8 @@
{
struct vpe_ctrl_type *vpe_ctrl = v4l2_get_subdevdata(sd);
struct msm_mctl_pp_frame_info *frame_info = vpe_ctrl->pp_frame_info;
-
+ struct msm_cam_media_controller *mctl;
+ mctl = v4l2_get_subdev_hostdata(sd);
if (atomic_read(&vpe_ctrl->active) == 0) {
pr_err("%s already closed\n", __func__);
return -EINVAL;
@@ -983,9 +1009,9 @@
if (frame_info) {
D("%s Unmap the pending item from the queue ", __func__);
msm_mctl_unmap_user_frame(&frame_info->src_frame,
- frame_info->p_mctl->client);
+ frame_info->p_mctl->client, mctl->domain_num);
msm_mctl_unmap_user_frame(&frame_info->dest_frame,
- frame_info->p_mctl->client);
+ frame_info->p_mctl->client, mctl->domain_num);
}
/* Drain the payload queue. */
msm_queue_drain(&vpe_ctrl->eventData_q, list_eventdata);
@@ -1066,6 +1092,19 @@
disable_irq(vpe_ctrl->vpeirq->start);
+#ifdef CONFIG_MSM_IOMMU
+ /*get device context for IOMMU*/
+ vpe_ctrl->iommu_ctx_src = msm_iommu_get_ctx("vpe_src"); /*re-confirm*/
+ vpe_ctrl->iommu_ctx_dst = msm_iommu_get_ctx("vpe_dst"); /*re-confirm*/
+ if (!vpe_ctrl->iommu_ctx_src || !vpe_ctrl->iommu_ctx_dst) {
+ release_mem_region(vpe_ctrl->vpemem->start,
+ resource_size(vpe_ctrl->vpemem));
+ pr_err("%s: No iommu fw context found\n", __func__);
+ rc = -ENODEV;
+ goto vpe_no_resource;
+ }
+#endif
+
atomic_set(&vpe_ctrl->active, 0);
vpe_ctrl->pdev = pdev;
sd_info.sdev_type = VPE_DEV;
diff --git a/drivers/media/video/msm/msm_vpe.h b/drivers/media/video/msm/msm_vpe.h
index 6516ea1..aad2380 100644
--- a/drivers/media/video/msm/msm_vpe.h
+++ b/drivers/media/video/msm/msm_vpe.h
@@ -121,6 +121,8 @@
struct msm_mctl_pp_frame_info *pp_frame_info;
atomic_t active;
struct msm_device_queue eventData_q; /*V4L2 Event Payload Queue*/
+ struct device *iommu_ctx_src;
+ struct device *iommu_ctx_dst;
};
/*
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index f8c102f..b8a6217 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -160,6 +160,16 @@
g_server_dev.interface_map_table[i].mctl_handle = 0;
}
+struct iommu_domain *msm_cam_server_get_domain()
+{
+ return g_server_dev.domain;
+}
+
+int msm_cam_server_get_domain_num()
+{
+ return g_server_dev.domain_num;
+}
+
uint32_t msm_cam_server_get_mctl_handle(void)
{
uint32_t i;
@@ -1056,7 +1066,7 @@
{
int rc = 0;
rc = msm_iommu_map_contig_buffer(
- (unsigned long)IMEM_Y_PING_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+ (unsigned long)IMEM_Y_PING_OFFSET, mctl->domain_num, 0,
((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
SZ_4K, IOMMU_WRITE | IOMMU_READ,
(unsigned long *)&mctl->ping_imem_y);
@@ -1068,7 +1078,7 @@
mctl->ping_imem_cbcr = 0;
}
msm_iommu_map_contig_buffer(
- (unsigned long)IMEM_Y_PONG_OFFSET, CAMERA_DOMAIN, GEN_POOL,
+ (unsigned long)IMEM_Y_PONG_OFFSET, mctl->domain_num, 0,
((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)),
SZ_4K, IOMMU_WRITE | IOMMU_READ,
(unsigned long *)&mctl->pong_imem_y);
@@ -1085,10 +1095,10 @@
static void unmap_imem_addresses(struct msm_cam_media_controller *mctl)
{
msm_iommu_unmap_contig_buffer(mctl->ping_imem_y,
- CAMERA_DOMAIN, GEN_POOL,
+ mctl->domain_num, 0,
((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
msm_iommu_unmap_contig_buffer(mctl->pong_imem_y,
- CAMERA_DOMAIN, GEN_POOL,
+ mctl->domain_num, 0,
((IMEM_Y_SIZE + IMEM_CBCR_SIZE + 4095) & (~4095)));
mctl->ping_imem_y = 0;
mctl->ping_imem_cbcr = 0;
@@ -1471,6 +1481,10 @@
pr_err("%s: invalid mctl controller", __func__);
goto error;
}
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ pmctl->domain = msm_cam_server_get_domain();
+ pmctl->domain_num = msm_cam_server_get_domain_num();
+#endif
rc = map_imem_addresses(pmctl);
if (rc < 0) {
pr_err("%sFailed to map imem addresses %d\n", __func__, rc);
@@ -2215,6 +2229,23 @@
return err;
}
+#ifdef CONFIG_MSM_IOMMU
+static int camera_register_domain(void)
+{
+ struct msm_iova_partition camera_fw_partition = {
+ .start = SZ_128K,
+ .size = SZ_2G - SZ_128K,
+ };
+ struct msm_iova_layout camera_fw_layout = {
+ .partitions = &camera_fw_partition,
+ .npartitions = 1,
+ .client_name = "camera_isp",
+ .domain_flags = 0,
+ };
+
+ return msm_register_domain(&camera_fw_layout);
+}
+#endif
static int msm_setup_server_dev(struct platform_device *pdev)
{
@@ -2291,6 +2322,21 @@
g_server_dev.interface_map_table[i].interface = 0x01 << i;
g_server_dev.interface_map_table[i].mctl_handle = 0;
}
+#ifdef CONFIG_MSM_IOMMU
+ g_server_dev.domain_num = camera_register_domain();
+ if (g_server_dev.domain_num < 0) {
+ pr_err("%s: could not register domain\n", __func__);
+ rc = -ENODEV;
+ return rc;
+ }
+ g_server_dev.domain =
+ msm_get_iommu_domain(g_server_dev.domain_num);
+ if (!g_server_dev.domain) {
+ pr_err("%s: cannot find domain\n", __func__);
+ rc = -ENODEV;
+ return rc;
+ }
+#endif
return rc;
}
@@ -2348,6 +2394,11 @@
return rc;
}
+#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
+ pmctl->domain = msm_cam_server_get_domain();
+ pmctl->domain_num = msm_cam_server_get_domain_num();
+#endif
+
D("%s: call mctl_open\n", __func__);
rc = pmctl->mctl_open(pmctl, MSM_APPS_ID_V4L2);
@@ -2620,6 +2671,7 @@
pr_err("%s: cannot find mctl\n", __func__);
return -ENODEV;
}
+
INIT_HLIST_HEAD(&config_cam->p_mctl->stats_info.pmem_stats_list);
spin_lock_init(&config_cam->p_mctl->stats_info.pmem_stats_spinlock);
@@ -2733,13 +2785,15 @@
case MSM_CAM_IOCTL_REGISTER_PMEM:
return msm_register_pmem(
&config_cam->p_mctl->stats_info.pmem_stats_list,
- (void __user *)arg, config_cam->p_mctl->client);
+ (void __user *)arg, config_cam->p_mctl->client,
+ config_cam->p_mctl->domain_num);
break;
case MSM_CAM_IOCTL_UNREGISTER_PMEM:
return msm_pmem_table_del(
&config_cam->p_mctl->stats_info.pmem_stats_list,
- (void __user *)arg, config_cam->p_mctl->client);
+ (void __user *)arg, config_cam->p_mctl->client,
+ config_cam->p_mctl->domain_num);
break;
case VIDIOC_SUBSCRIBE_EVENT:
diff --git a/drivers/media/video/msm/server/msm_cam_server.h b/drivers/media/video/msm/server/msm_cam_server.h
index 42900f3..d38bb98 100644
--- a/drivers/media/video/msm/server/msm_cam_server.h
+++ b/drivers/media/video/msm/server/msm_cam_server.h
@@ -20,6 +20,8 @@
#include "msm.h"
uint32_t msm_cam_server_get_mctl_handle(void);
+struct iommu_domain *msm_cam_server_get_domain(void);
+int msm_cam_server_get_domain_num(void);
struct msm_cam_media_controller *msm_cam_server_get_mctl(uint32_t handle);
void msm_cam_server_free_mctl(uint32_t handle);
/* Server session control APIs */
diff --git a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
index 0bd7b94..2179282 100644
--- a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.c
@@ -401,7 +401,7 @@
stats_buf = &bufq->bufs[i];
rc = vfe31_ctrl->stats_ops.enqueue_buf(
vfe31_ctrl->stats_ops.stats_ctrl,
- &(stats_buf->info), NULL);
+ &(stats_buf->info), NULL, -1);
if (rc < 0) {
pr_err("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
@@ -412,7 +412,7 @@
}
static unsigned long vfe31_stats_unregbuf(
- struct msm_stats_reqbuf *req_buf)
+ struct msm_stats_reqbuf *req_buf, int domain_num)
{
int i = 0, rc = 0;
@@ -420,7 +420,7 @@
rc = vfe31_ctrl->stats_ops.buf_unprepare(
vfe31_ctrl->stats_ops.stats_ctrl,
req_buf->stats_type, i,
- vfe31_ctrl->stats_ops.client);
+ vfe31_ctrl->stats_ops.client, domain_num);
if (rc < 0) {
pr_err("%s: unreg stats buf (type = %d) err = %d",
__func__, req_buf->stats_type, rc);
@@ -3296,7 +3296,7 @@
}
static long vfe_stats_bufq_sub_ioctl(struct msm_vfe_cfg_cmd *cmd,
- void *ion_client)
+ void *ion_client, int domain_num)
{
long rc = 0;
switch (cmd->cmd_type) {
@@ -3344,7 +3344,7 @@
}
rc = vfe31_ctrl->stats_ops.enqueue_buf(&vfe31_ctrl->stats_ctrl,
(struct msm_stats_buf_info *)cmd->value,
- vfe31_ctrl->stats_ops.client);
+ vfe31_ctrl->stats_ops.client, domain_num);
break;
case VFE_CMD_STATS_FLUSH_BUFQ: {
struct msm_stats_flush_bufq *flush_req = NULL;
@@ -3376,7 +3376,7 @@
rc = -EINVAL ;
goto end;
}
- rc = vfe31_stats_unregbuf(req_buf);
+ rc = vfe31_stats_unregbuf(req_buf, domain_num);
}
break;
default:
@@ -3630,7 +3630,8 @@
case VFE_CMD_STATS_FLUSH_BUFQ:
case VFE_CMD_STATS_UNREGBUF:
/* for easy porting put in one envelope */
- rc = vfe_stats_bufq_sub_ioctl(cmd, vfe_params->data);
+ rc = vfe_stats_bufq_sub_ioctl(cmd, vfe_params->data,
+ pmctl->domain_num);
return rc;
default:
if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
@@ -4003,10 +4004,25 @@
vfe31_ctrl->vfe_camif_clk,
ARRAY_SIZE(vfe_camif_clk_info), 1);
if (rc < 0)
- goto vfe_clk_enable_failed;
+ goto vfe_camif_clk_enable_failed;
msm_vfe_camif_pad_reg_reset();
}
+#ifdef CONFIG_MSM_IOMMU
+ rc = iommu_attach_device(mctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+ if (rc < 0) {
+ rc = -ENODEV;
+ pr_err("%s: Device attach failed\n", __func__);
+ goto device_imgwr_attach_failed;
+ }
+ rc = iommu_attach_device(mctl->domain, vfe31_ctrl->iommu_ctx_misc);
+ if (rc < 0) {
+ rc = -ENODEV;
+ pr_err("%s: Device attach failed\n", __func__);
+ goto device_misc_attach_failed;
+ }
+#endif
+
msm_camio_bus_scale_cfg(
mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
msm_camio_bus_scale_cfg(
@@ -4017,6 +4033,19 @@
return rc;
+#ifdef CONFIG_MSM_IOMMU
+device_misc_attach_failed:
+ iommu_detach_device(mctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+device_imgwr_attach_failed:
+#endif
+ if (!mctl->sdata->csi_if)
+ msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
+ vfe_camif_clk_info,
+ vfe31_ctrl->vfe_camif_clk,
+ ARRAY_SIZE(vfe_camif_clk_info), 0);
+vfe_camif_clk_enable_failed:
+ msm_cam_clk_enable(&vfe31_ctrl->pdev->dev, vfe_clk_info,
+ vfe31_ctrl->vfe_clk, ARRAY_SIZE(vfe_clk_info), 0);
vfe_clk_enable_failed:
regulator_disable(vfe31_ctrl->fs_vfe);
vfe_fs_failed:
@@ -4025,7 +4054,6 @@
camif_remap_failed:
iounmap(vfe31_ctrl->vfebase);
vfe_remap_failed:
- disable_irq(vfe31_ctrl->vfeirq->start);
mctl_failed:
return rc;
}
@@ -4037,6 +4065,11 @@
disable_irq(vfe31_ctrl->vfeirq->start);
tasklet_kill(&vfe31_tasklet);
+#ifdef CONFIG_MSM_IOMMU
+ iommu_detach_device(pmctl->domain, vfe31_ctrl->iommu_ctx_misc);
+ iommu_detach_device(pmctl->domain, vfe31_ctrl->iommu_ctx_imgwr);
+#endif
+
if (!pmctl->sdata->csi_if)
msm_cam_clk_enable(&vfe31_ctrl->pdev->dev,
vfe_camif_clk_info,
@@ -4140,6 +4173,25 @@
disable_irq(vfe31_ctrl->vfeirq->start);
+#ifdef CONFIG_MSM_IOMMU
+ /*get device context for IOMMU*/
+ vfe31_ctrl->iommu_ctx_imgwr =
+ msm_iommu_get_ctx("vfe_imgwr"); /*re-confirm*/
+ vfe31_ctrl->iommu_ctx_misc =
+ msm_iommu_get_ctx("vfe_misc"); /*re-confirm*/
+ if (!vfe31_ctrl->iommu_ctx_imgwr || !vfe31_ctrl->iommu_ctx_misc) {
+ if (vfe31_ctrl->camifmem) {
+ release_mem_region(vfe31_ctrl->camifmem->start,
+ resource_size(vfe31_ctrl->camifmem));
+ }
+ release_mem_region(vfe31_ctrl->vfemem->start,
+ resource_size(vfe31_ctrl->vfemem));
+ pr_err("%s: No iommu fw context found\n", __func__);
+ rc = -ENODEV;
+ goto vfe31_no_resource;
+ }
+#endif
+
vfe31_ctrl->pdev = pdev;
vfe31_ctrl->fs_vfe = regulator_get(&vfe31_ctrl->pdev->dev, "vdd");
if (IS_ERR(vfe31_ctrl->fs_vfe)) {
diff --git a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
index 60db8e5..97ecd6e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
+++ b/drivers/media/video/msm/vfe/msm_vfe31_v4l2.h
@@ -928,6 +928,8 @@
uint32_t snapshot_frame_cnt;
struct msm_stats_bufq_ctrl stats_ctrl;
struct msm_stats_ops stats_ops;
+ struct device *iommu_ctx_imgwr;
+ struct device *iommu_ctx_misc;
};
enum VFE31_STATS_NUM {
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index 84a36b9..908f3fb 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -995,7 +995,7 @@
stats_buf = &bufq->bufs[i];
rc = vfe32_ctrl->stats_ops.enqueue_buf(
vfe32_ctrl->stats_ops.stats_ctrl,
- &(stats_buf->info), NULL);
+ &(stats_buf->info), NULL, -1);
if (rc < 0) {
pr_err("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
@@ -1008,7 +1008,7 @@
static unsigned long vfe32_stats_unregbuf(
struct vfe32_ctrl_type *vfe32_ctrl,
- struct msm_stats_reqbuf *req_buf)
+ struct msm_stats_reqbuf *req_buf, int domain_num)
{
int i = 0, rc = 0;
@@ -1016,7 +1016,7 @@
rc = vfe32_ctrl->stats_ops.buf_unprepare(
vfe32_ctrl->stats_ops.stats_ctrl,
req_buf->stats_type, i,
- vfe32_ctrl->stats_ops.client);
+ vfe32_ctrl->stats_ops.client, domain_num);
if (rc < 0) {
pr_err("%s: unreg stats buf (type = %d) err = %d",
__func__, req_buf->stats_type, rc);
@@ -4910,7 +4910,7 @@
static long vfe_stats_bufq_sub_ioctl(
struct vfe32_ctrl_type *vfe_ctrl,
- struct msm_vfe_cfg_cmd *cmd, void *ion_client)
+ struct msm_vfe_cfg_cmd *cmd, void *ion_client, int domain_num)
{
long rc = 0;
switch (cmd->cmd_type) {
@@ -4959,7 +4959,7 @@
rc = vfe_ctrl->stats_ops.enqueue_buf(
&vfe_ctrl->stats_ctrl,
(struct msm_stats_buf_info *)cmd->value,
- vfe_ctrl->stats_ops.client);
+ vfe_ctrl->stats_ops.client, domain_num);
break;
case VFE_CMD_STATS_FLUSH_BUFQ:
{
@@ -4993,7 +4993,7 @@
rc = -EINVAL ;
goto end;
}
- rc = vfe32_stats_unregbuf(vfe_ctrl, req_buf);
+ rc = vfe32_stats_unregbuf(vfe_ctrl, req_buf, domain_num);
}
break;
default:
@@ -5048,7 +5048,7 @@
case VFE_CMD_STATS_UNREGBUF:
/* for easy porting put in one envelope */
rc = vfe_stats_bufq_sub_ioctl(vfe32_ctrl,
- cmd, vfe_params->data);
+ cmd, vfe_params->data, pmctl->domain_num);
return rc;
default:
if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
@@ -5273,6 +5273,21 @@
if (rc < 0)
goto clk_enable_failed;
+#ifdef CONFIG_MSM_IOMMU
+ rc = iommu_attach_device(mctl->domain, axi_ctrl->iommu_ctx_imgwr);
+ if (rc < 0) {
+ pr_err("%s: imgwr attach failed rc = %d\n", __func__, rc);
+ rc = -ENODEV;
+ goto device_imgwr_attach_failed;
+ }
+ rc = iommu_attach_device(mctl->domain, axi_ctrl->iommu_ctx_misc);
+ if (rc < 0) {
+ pr_err("%s: misc attach failed rc = %d\n", __func__, rc);
+ rc = -ENODEV;
+ goto device_misc_attach_failed;
+ }
+#endif
+
msm_camio_bus_scale_cfg(
mctl->sdata->pdata->cam_bus_scale_table, S_INIT);
msm_camio_bus_scale_cfg(
@@ -5293,6 +5308,13 @@
return rc;
+#ifdef CONFIG_MSM_IOMMU
+device_misc_attach_failed:
+ iommu_detach_device(mctl->domain, axi_ctrl->iommu_ctx_imgwr);
+device_imgwr_attach_failed:
+#endif
+ msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe32_clk_info,
+ axi_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
clk_enable_failed:
if (axi_ctrl->fs_vfe)
regulator_disable(axi_ctrl->fs_vfe);
@@ -5300,7 +5322,6 @@
iounmap(axi_ctrl->share_ctrl->vfebase);
axi_ctrl->share_ctrl->vfebase = NULL;
remap_failed:
- disable_irq(axi_ctrl->vfeirq->start);
mctl_failed:
return rc;
}
@@ -5344,6 +5365,10 @@
return;
disable_irq(axi_ctrl->vfeirq->start);
tasklet_kill(&axi_ctrl->vfe32_tasklet);
+#ifdef CONFIG_MSM_IOMMU
+ iommu_detach_device(pmctl->domain, axi_ctrl->iommu_ctx_misc);
+ iommu_detach_device(pmctl->domain, axi_ctrl->iommu_ctx_imgwr);
+#endif
msm_cam_clk_enable(&axi_ctrl->pdev->dev, vfe32_clk_info,
axi_ctrl->vfe_clk, ARRAY_SIZE(vfe32_clk_info), 0);
if (axi_ctrl->fs_vfe)
@@ -6396,6 +6421,21 @@
goto vfe32_no_resource;
}
+#ifdef CONFIG_MSM_IOMMU
+ /*get device context for IOMMU*/
+ axi_ctrl->iommu_ctx_imgwr =
+ msm_iommu_get_ctx("vfe_imgwr"); /*re-confirm*/
+ axi_ctrl->iommu_ctx_misc =
+ msm_iommu_get_ctx("vfe_misc"); /*re-confirm*/
+ if (!axi_ctrl->iommu_ctx_imgwr || !axi_ctrl->iommu_ctx_misc) {
+ release_mem_region(axi_ctrl->vfemem->start,
+ resource_size(axi_ctrl->vfemem));
+ pr_err("%s: No iommu fw context found\n", __func__);
+ rc = -ENODEV;
+ goto vfe32_no_resource;
+ }
+#endif
+
tasklet_init(&axi_ctrl->vfe32_tasklet,
axi32_do_tasklet, (unsigned long)axi_ctrl);
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.h b/drivers/media/video/msm/vfe/msm_vfe32.h
index 81df0d5..985493e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.h
+++ b/drivers/media/video/msm/vfe/msm_vfe32.h
@@ -1006,6 +1006,8 @@
struct clk *vfe_clk[3];
struct tasklet_struct vfe32_tasklet;
struct vfe_share_ctrl_t *share_ctrl;
+ struct device *iommu_ctx_imgwr;
+ struct device *iommu_ctx_misc;
};
struct vfe32_ctrl_type {
diff --git a/drivers/media/video/msm/vfe/msm_vfe40.c b/drivers/media/video/msm/vfe/msm_vfe40.c
index 1aee087..875e034 100644
--- a/drivers/media/video/msm/vfe/msm_vfe40.c
+++ b/drivers/media/video/msm/vfe/msm_vfe40.c
@@ -415,7 +415,7 @@
stats_buf = &bufq->bufs[i];
rc = vfe40_ctrl->stats_ops.enqueue_buf(
vfe40_ctrl->stats_ops.stats_ctrl,
- &(stats_buf->info), NULL);
+ &(stats_buf->info), NULL, -1);
if (rc < 0) {
pr_err("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
@@ -3308,7 +3308,7 @@
static long vfe_stats_bufq_sub_ioctl(
struct vfe40_ctrl_type *vfe_ctrl,
- struct msm_vfe_cfg_cmd *cmd, void *ion_client)
+ struct msm_vfe_cfg_cmd *cmd, void *ion_client, int domain_num)
{
long rc = 0;
switch (cmd->cmd_type) {
@@ -3357,7 +3357,7 @@
rc = vfe_ctrl->stats_ops.enqueue_buf(
&vfe_ctrl->stats_ctrl,
(struct msm_stats_buf_info *)cmd->value,
- vfe_ctrl->stats_ops.client);
+ vfe_ctrl->stats_ops.client, domain_num);
break;
case VFE_CMD_STATS_FLUSH_BUFQ:
{
@@ -3419,7 +3419,7 @@
case VFE_CMD_STATS_FLUSH_BUFQ:
/* for easy porting put in one envelope */
rc = vfe_stats_bufq_sub_ioctl(vfe40_ctrl,
- cmd, vfe_params->data);
+ cmd, vfe_params->data, pmctl->domain_num);
return rc;
default:
if (cmd->cmd_type != CMD_CONFIG_PING_ADDR &&
diff --git a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
index 460eb07..75d9293 100644
--- a/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
+++ b/drivers/media/video/msm/vfe/msm_vfe7x27a_v4l2.c
@@ -395,7 +395,7 @@
stats_buf = &bufq->bufs[i];
rc = vfe2x_ctrl->stats_ops.enqueue_buf(
vfe2x_ctrl->stats_ops.stats_ctrl,
- &(stats_buf->info), NULL);
+ &(stats_buf->info), NULL, -1);
if (rc < 0) {
pr_err("%s: dq stats buf (type = %d) err = %d",
__func__, stats_type, rc);
@@ -414,7 +414,7 @@
rc = vfe2x_ctrl->stats_ops.buf_unprepare(
vfe2x_ctrl->stats_ops.stats_ctrl,
req_buf->stats_type, i,
- vfe2x_ctrl->stats_ops.client);
+ vfe2x_ctrl->stats_ops.client, -1);
if (rc < 0) {
pr_err("%s: unreg stats buf (type = %d) err = %d",
__func__, req_buf->stats_type, rc);
@@ -473,7 +473,7 @@
stats_buf->state == MSM_STATS_BUFFER_STATE_PREPARED) {
rc = vfe2x_ctrl->stats_ops.enqueue_buf(
&vfe2x_ctrl->stats_ctrl,
- info, vfe2x_ctrl->stats_ops.client);
+ info, vfe2x_ctrl->stats_ops.client, -1);
if (rc < 0) {
pr_err("%s: enqueue_buf (type = %d), index : %d, err = %d",
__func__, info->type, info->buf_idx, rc);
@@ -555,7 +555,7 @@
rc = vfe2x_ctrl->stats_ops.enqueue_buf(
&vfe2x_ctrl->stats_ctrl,
(struct msm_stats_buf_info *)cmd->value,
- vfe2x_ctrl->stats_ops.client);
+ vfe2x_ctrl->stats_ops.client, -1);
}
break;
case VFE_CMD_STATS_FLUSH_BUFQ: {
@@ -2352,7 +2352,7 @@
return 0;
}
-void msm_vpe_subdev_release(void)
+void msm_vpe_subdev_release(struct v4l2_subdev *sd)
{
return;
}
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
index 5fbcdb1..5820d76 100644
--- a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
+++ b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.c
@@ -182,7 +182,8 @@
#endif
static int msm_stats_buf_prepare(struct msm_stats_bufq_ctrl *stats_ctrl,
- struct msm_stats_buf_info *info, struct ion_client *client)
+ struct msm_stats_buf_info *info, struct ion_client *client,
+ int domain_num)
{
unsigned long paddr;
#ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
@@ -219,7 +220,7 @@
goto out1;
}
if (ion_map_iommu(client, stats_buf->handle,
- CAMERA_DOMAIN, GEN_POOL, SZ_4K,
+ domain_num, 0, SZ_4K,
0, &paddr, &len, UNCACHED, 0) < 0) {
rc = -EINVAL;
pr_err("%s: cannot map address", __func__);
@@ -257,7 +258,7 @@
return 0;
out3:
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- ion_unmap_iommu(client, stats_buf->handle, CAMERA_DOMAIN, GEN_POOL);
+ ion_unmap_iommu(client, stats_buf->handle, domain_num, 0);
#endif
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
out2:
@@ -270,7 +271,7 @@
}
static int msm_stats_buf_unprepare(struct msm_stats_bufq_ctrl *stats_ctrl,
enum msm_stats_enum_type stats_type, int buf_idx,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
int rc = 0;
struct msm_stats_bufq *bufq = NULL;
@@ -292,7 +293,7 @@
}
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
ion_unmap_iommu(client, stats_buf->handle,
- CAMERA_DOMAIN, GEN_POOL);
+ domain_num, 0);
ion_free(client, stats_buf->handle);
#else
put_pmem_file(stats_buf->file);
@@ -472,12 +473,13 @@
return rc;
}
static int msm_stats_enqueue_buf(struct msm_stats_bufq_ctrl *stats_ctrl,
- struct msm_stats_buf_info *info, struct ion_client *client)
+ struct msm_stats_buf_info *info, struct ion_client *client,
+ int domain_num)
{
int rc = 0;
D("%s: stats type : %d, idx : %d\n", __func__,
info->type, info->buf_idx);
- rc = msm_stats_buf_prepare(stats_ctrl, info, client);
+ rc = msm_stats_buf_prepare(stats_ctrl, info, client, domain_num);
if (rc < 0) {
pr_err("%s: buf_prepare failed, rc = %d", __func__, rc);
return -EINVAL;
diff --git a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
index 18fd425..bf3e70e 100644
--- a/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
+++ b/drivers/media/video/msm/vfe/msm_vfe_stats_buf.h
@@ -55,8 +55,8 @@
struct msm_stats_bufq_ctrl *stats_ctrl;
struct ion_client *client;
int (*enqueue_buf) (struct msm_stats_bufq_ctrl *stats_ctrl,
- struct msm_stats_buf_info *info,
- struct ion_client *client);
+ struct msm_stats_buf_info *info,
+ struct ion_client *client, int domain_num);
int (*qbuf) (struct msm_stats_bufq_ctrl *stats_ctrl,
enum msm_stats_enum_type stats_type,
int buf_idx);
@@ -69,10 +69,10 @@
int (*buf_unprepare) (struct msm_stats_bufq_ctrl *stats_ctrl,
enum msm_stats_enum_type stats_type,
int buf_idx,
- struct ion_client *client);
+ struct ion_client *client, int domain_num);
int (*buf_prepare) (struct msm_stats_bufq_ctrl *stats_ctrl,
- struct msm_stats_buf_info *info,
- struct ion_client *client);
+ struct msm_stats_buf_info *info,
+ struct ion_client *client, int domain_num);
int (*reqbuf) (struct msm_stats_bufq_ctrl *stats_ctrl,
struct msm_stats_reqbuf *reqbuf,
struct ion_client *client);
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index d48240a..16fb14d 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -81,12 +81,11 @@
goto fail_device_address;
}
- mem->kvaddr += offset;
mem->mem_type = client->mem_type;
mem->smem_priv = hndl;
- mem->device_addr = iova + offset;
+ mem->device_addr = iova;
mem->size = buffer_size;
- pr_debug("Buffer device address: 0x%lx, size: %d\n",
+ pr_err("NOTE: Buffer device address: 0x%lx, size: %d\n",
mem->device_addr, mem->size);
return rc;
fail_device_address:
@@ -145,8 +144,8 @@
goto fail_device_address;
}
mem->device_addr = iova;
- pr_debug("device_address = 0x%lx, kvaddr = 0x%p\n",
- mem->device_addr, mem->kvaddr);
+ pr_err("NOTE: device_address = 0x%lx, kvaddr = 0x%p, size = %d\n",
+ mem->device_addr, mem->kvaddr, size);
mem->size = size;
return rc;
fail_device_address:
diff --git a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
index bab7642..4e810dc 100644
--- a/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
+++ b/drivers/media/video/msm_vidc/msm_v4l2_vidc.c
@@ -165,6 +165,7 @@
int buff_off;
int size;
u32 uvaddr;
+ u32 device_addr;
struct msm_smem *handle;
};
@@ -230,6 +231,28 @@
return ret;
}
+struct buffer_info *get_same_fd_buffer(struct list_head *list,
+ int fd)
+{
+ struct buffer_info *temp;
+ struct buffer_info *ret = NULL;
+ if (!list || fd < 0) {
+ pr_err("%s Invalid input\n", __func__);
+ goto err_invalid_input;
+ }
+ if (!list_empty(list)) {
+ list_for_each_entry(temp, list, list) {
+ if (temp && temp->fd == fd) {
+ pr_err("Found same fd buffer\n");
+ ret = temp;
+ break;
+ }
+ }
+ }
+err_invalid_input:
+ return ret;
+}
+
static int msm_v4l2_open(struct file *filp)
{
int rc = 0;
@@ -362,8 +385,9 @@
rc = msm_vidc_release_buf(&v4l2_inst->vidc_inst,
&buffer_info);
list_del(&bi->list);
- msm_smem_free(v4l2_inst->mem_client,
- bi->handle);
+ if (bi->handle)
+ msm_smem_free(v4l2_inst->mem_client,
+ bi->handle);
kfree(bi);
}
}
@@ -374,8 +398,9 @@
int msm_v4l2_prepare_buf(struct file *file, void *fh,
struct v4l2_buffer *b)
{
- struct msm_smem *handle;
+ struct msm_smem *handle = NULL;
struct buffer_info *binfo;
+ struct buffer_info *temp;
struct msm_vidc_inst *vidc_inst;
struct msm_v4l2_vid_inst *v4l2_inst;
int i, rc = 0;
@@ -402,28 +427,43 @@
rc = -ENOMEM;
goto exit;
}
- handle = msm_smem_user_to_kernel(v4l2_inst->mem_client,
+ temp = get_same_fd_buffer(&v4l2_inst->registered_bufs,
+ b->m.planes[i].reserved[0]);
+ if (temp) {
+ binfo->type = b->type;
+ binfo->fd = b->m.planes[i].reserved[0];
+ binfo->buff_off = b->m.planes[i].reserved[1];
+ binfo->size = b->m.planes[i].length;
+ binfo->uvaddr = b->m.planes[i].m.userptr;
+ binfo->device_addr =
+ temp->handle->device_addr + binfo->buff_off;
+ binfo->handle = NULL;
+ } else {
+ handle = msm_smem_user_to_kernel(v4l2_inst->mem_client,
b->m.planes[i].reserved[0],
b->m.planes[i].reserved[1],
vidc_inst->core->resources.io_map[NS_MAP].domain,
0);
- if (!handle) {
- pr_err("Failed to get device buffer address\n");
- kfree(binfo);
- goto exit;
+ if (!handle) {
+ pr_err("Failed to get device buffer address\n");
+ kfree(binfo);
+ goto exit;
+ }
+ binfo->type = b->type;
+ binfo->fd = b->m.planes[i].reserved[0];
+ binfo->buff_off = b->m.planes[i].reserved[1];
+ binfo->size = b->m.planes[i].length;
+ binfo->uvaddr = b->m.planes[i].m.userptr;
+ binfo->device_addr =
+ handle->device_addr + binfo->buff_off;
+ binfo->handle = handle;
+ pr_debug("Registering buffer: %d, %d, %d\n",
+ b->m.planes[i].reserved[0],
+ b->m.planes[i].reserved[1],
+ b->m.planes[i].length);
}
- binfo->type = b->type;
- binfo->fd = b->m.planes[i].reserved[0];
- binfo->buff_off = b->m.planes[i].reserved[1];
- binfo->size = b->m.planes[i].length;
- binfo->uvaddr = b->m.planes[i].m.userptr;
- binfo->handle = handle;
- pr_debug("Registering buffer: %d, %d, %d\n",
- b->m.planes[i].reserved[0],
- b->m.planes[i].reserved[1],
- b->m.planes[i].length);
list_add_tail(&binfo->list, &v4l2_inst->registered_bufs);
- b->m.planes[i].m.userptr = handle->device_addr;
+ b->m.planes[i].m.userptr = binfo->device_addr;
}
rc = msm_vidc_prepare_buf(&v4l2_inst->vidc_inst, b);
exit:
@@ -453,14 +493,16 @@
rc = -EINVAL;
goto err_invalid_buff;
}
- b->m.planes[i].m.userptr = binfo->handle->device_addr;
- pr_debug("Queueing device address = %ld\n",
- binfo->handle->device_addr);
- rc = msm_smem_clean_invalidate(v4l2_inst->mem_client,
- binfo->handle);
- if (rc) {
- pr_err("Failed to clean caches: %d\n", rc);
- goto err_invalid_buff;
+ b->m.planes[i].m.userptr = binfo->device_addr;
+ pr_debug("Queueing device address = 0x%x\n",
+ binfo->device_addr);
+ if (binfo->handle) {
+ rc = msm_smem_clean_invalidate(v4l2_inst->mem_client,
+ binfo->handle);
+ if (rc) {
+ pr_err("Failed to clean caches: %d\n", rc);
+ goto err_invalid_buff;
+ }
}
}
rc = msm_vidc_qbuf(&v4l2_inst->vidc_inst, b);
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index ffa873f..7f83625 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -469,8 +469,8 @@
return -EINVAL;
}
if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
- inst->prop.width = f->fmt.pix_mp.width;
- inst->prop.height = f->fmt.pix_mp.height;
+ struct hal_frame_size frame_sz;
+
fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
CAPTURE_PORT);
@@ -480,6 +480,21 @@
rc = -EINVAL;
goto err_invalid_fmt;
}
+
+ inst->prop.width = f->fmt.pix_mp.width;
+ inst->prop.height = f->fmt.pix_mp.height;
+
+ frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
+ frame_sz.width = inst->prop.width;
+ frame_sz.height = inst->prop.height;
+ pr_debug("width = %d, height = %d\n",
+ frame_sz.width, frame_sz.height);
+ rc = vidc_hal_session_set_property((void *)inst->session,
+ HAL_PARAM_FRAME_SIZE, &frame_sz);
+ if (rc) {
+ pr_err("Failed to set hal property for framesize\n");
+ goto err_invalid_fmt;
+ }
} else if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
fmt = msm_comm_get_pixel_fmt_fourcc(vdec_formats,
ARRAY_SIZE(vdec_formats), f->fmt.pix_mp.pixelformat,
@@ -570,7 +585,6 @@
{
int i, rc = 0;
struct msm_vidc_inst *inst;
- struct hal_frame_size frame_sz;
unsigned long flags;
if (!q || !q->drv_priv) {
pr_err("Invalid input, q = %p\n", q);
@@ -595,27 +609,42 @@
pr_err("Failed to open instance\n");
break;
}
- frame_sz.buffer_type = HAL_BUFFER_OUTPUT;
- frame_sz.width = inst->prop.width;
- frame_sz.height = inst->prop.height;
- pr_debug("width = %d, height = %d\n",
- frame_sz.width, frame_sz.height);
- rc = vidc_hal_session_set_property((void *)inst->session,
- HAL_PARAM_FRAME_SIZE, &frame_sz);
- if (rc) {
- pr_err("Failed to set hal property for framesize\n");
- break;
- }
+
rc = msm_comm_try_get_bufreqs(inst);
if (rc) {
pr_err("Failed to get buffer requirements: %d\n", rc);
break;
}
*num_planes = 1;
+
spin_lock_irqsave(&inst->lock, flags);
- *num_buffers = inst->buff_req.buffer[1].buffer_count_actual;
+ if (*num_buffers && *num_buffers >
+ inst->buff_req.buffer[HAL_BUFFER_OUTPUT].
+ buffer_count_actual) {
+ struct hal_buffer_count_actual new_buf_count;
+ enum hal_property property_id =
+ HAL_PARAM_BUFFER_COUNT_ACTUAL;
+
+ new_buf_count.buffer_type = HAL_BUFFER_OUTPUT;
+ new_buf_count.buffer_count_actual = *num_buffers;
+ rc = vidc_hal_session_set_property(inst->session,
+ property_id, &new_buf_count);
+
+ spin_unlock_irqrestore(&inst->lock, flags);
+ if (!rc && msm_comm_try_get_bufreqs(inst)) {
+ /* We are allowed to reject clients' request for
+ * more buffers and suggest our own bufreq */
+ pr_warn("Unable to increase the number of output buffers to %d\n",
+ *num_buffers);
+ }
+ spin_lock_irqsave(&inst->lock, flags);
+ }
+ *num_buffers = inst->buff_req.buffer[HAL_BUFFER_OUTPUT].
+ buffer_count_actual;
spin_unlock_irqrestore(&inst->lock, flags);
- pr_debug("size = %d, alignment = %d\n",
+
+ pr_debug("count = %d, size = %d, alignment = %d\n",
+ inst->buff_req.buffer[1].buffer_count_actual,
inst->buff_req.buffer[1].buffer_size,
inst->buff_req.buffer[1].buffer_alignment);
for (i = 0; i < *num_planes; i++) {
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index d69ed53..0d62ccc 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -430,6 +430,7 @@
struct msm_vidc_cb_cmd_done *response = data;
struct msm_vidc_inst *inst;
unsigned long flags;
+ int i;
if (!response || !response->data) {
pr_err("Failed to get valid response for prop info\n");
return;
@@ -439,6 +440,12 @@
memcpy(&inst->buff_req, response->data,
sizeof(struct buffer_requirements));
spin_unlock_irqrestore(&inst->lock, flags);
+ for (i = 0; i < 8; i++) {
+ pr_err("NOTE: buffer type: %d, count : %d, size: %d\n",
+ inst->buff_req.buffer[i].buffer_type,
+ inst->buff_req.buffer[i].buffer_count_actual,
+ inst->buff_req.buffer[i].buffer_size);
+ }
signal_session_msg_receipt(cmd, inst);
}
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index 9f2ead4..ba053f2 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -320,7 +320,7 @@
}
dprintk(1, "%s: irq=0x%08x\n", __func__, irq);
- if (!(irq & (VP_PIC_DONE || VP_MODE_CHANGE))) {
+ if (!(irq & (VP_PIC_DONE | VP_MODE_CHANGE))) {
writel_relaxed(irq, VCAP_VP_INT_CLEAR);
pr_err("VP IRQ shows some error\n");
return IRQ_HANDLED;
@@ -789,7 +789,7 @@
top_field = 1;
#endif
vp_act->vp_state = VP_FRAME2;
- writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
+ writel_relaxed(0x01100001, VCAP_VP_INTERRUPT_ENABLE);
#ifdef TOP_FIELD_FIX
writel_iowmb(0x00000000 | vp_act->top_field << 0, VCAP_VP_CTRL);
writel_iowmb(0x00010000 | vp_act->top_field << 0, VCAP_VP_CTRL);
@@ -836,7 +836,7 @@
#endif
/* Config VP & Enable Interrupt */
- writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
+ writel_relaxed(0x01100001, VCAP_VP_INTERRUPT_ENABLE);
#ifdef TOP_FIELD_FIX
writel_iowmb(0x00000000 | vp_act->top_field << 0, VCAP_VP_CTRL);
writel_iowmb(0x00010000 | vp_act->top_field << 0, VCAP_VP_CTRL);
diff --git a/drivers/media/video/videobuf2-msm-mem.c b/drivers/media/video/videobuf2-msm-mem.c
index 740d183..c1a392e2 100644
--- a/drivers/media/video/videobuf2-msm-mem.c
+++ b/drivers/media/video/videobuf2-msm-mem.c
@@ -62,7 +62,7 @@
goto alloc_failed;
}
rc = ion_map_iommu(mem->client, mem->ion_handle,
- CAMERA_DOMAIN, GEN_POOL, SZ_4K, 0,
+ -1, 0, SZ_4K, 0,
(unsigned long *)&phyaddr,
(unsigned long *)&len, UNCACHED, 0);
if (rc < 0) {
@@ -87,7 +87,7 @@
{
int32_t rc = 0;
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
- ion_unmap_iommu(mem->client, mem->ion_handle, CAMERA_DOMAIN, GEN_POOL);
+ ion_unmap_iommu(mem->client, mem->ion_handle, -1, 0);
ion_free(mem->client, mem->ion_handle);
ion_client_destroy(mem->client);
#else
@@ -174,7 +174,8 @@
struct videobuf2_msm_offset *offset,
enum videobuf2_buffer_type buffer_type,
uint32_t addr_offset, int path,
- struct ion_client *client)
+ struct ion_client *client,
+ int domain_num)
{
unsigned long len;
int rc = 0;
@@ -190,7 +191,7 @@
pr_err("%s ION import failed\n", __func__);
return PTR_ERR(mem->ion_handle);
}
- rc = ion_map_iommu(client, mem->ion_handle, CAMERA_DOMAIN, GEN_POOL,
+ rc = ion_map_iommu(client, mem->ion_handle, domain_num, 0,
SZ_4K, 0, (unsigned long *)&mem->phyaddr, &len, UNCACHED, 0);
if (rc < 0)
ion_free(client, mem->ion_handle);
@@ -220,12 +221,12 @@
EXPORT_SYMBOL_GPL(videobuf2_pmem_contig_user_get);
void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem,
- struct ion_client *client)
+ struct ion_client *client, int domain_num)
{
if (mem->is_userptr) {
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
ion_unmap_iommu(client, mem->ion_handle,
- CAMERA_DOMAIN, GEN_POOL);
+ domain_num, 0);
ion_free(client, mem->ion_handle);
#elif CONFIG_ANDROID_PMEM
put_pmem_file(mem->file);
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 71c68ac..b4cf435 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -535,7 +535,6 @@
unsigned int ch_cnt)
{
u16 grph = 0;
- u32 sph[SLIM_MAX_RX_PORTS] = {0};
int i = 0 , idx = 0;
int ret = 0;
struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
@@ -549,10 +548,9 @@
ret = -EINVAL;
goto err;
}
- sph[i] = rx[idx].sph;
grph = rx[idx].grph;
- pr_debug("%s: ch_num[%d] %d, idx %d, sph[%d] %x, grph %x\n",
- __func__, i, ch_num[i], idx, i, sph[i], grph);
+ pr_debug("%s: ch_num[%d] %d, idx %d, grph %x\n",
+ __func__, i, ch_num[i], idx, grph);
}
/* slim_control_ch (REMOVE) */
@@ -561,12 +559,6 @@
pr_err("%s: slim_control_ch failed ret[%d]\n", __func__, ret);
goto err;
}
- /* slim_disconnect_port */
- ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
- if (ret < 0) {
- pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
- __func__, ret);
- }
for (i = 0; i < ch_cnt; i++) {
idx = (ch_num[i] - BASE_CH_NUM - sh_ch.rx_port_start_offset);
rx[idx].grph = 0;
@@ -580,7 +572,6 @@
unsigned int ch_cnt)
{
u16 grph = 0;
- u32 sph[SLIM_MAX_TX_PORTS] = {0};
int ret = 0;
int i = 0 , idx = 0;
struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
@@ -594,15 +585,8 @@
ret = -EINVAL;
goto err;
}
- sph[i] = tx[idx].sph;
grph = tx[idx].grph;
}
- /* slim_disconnect_port */
- ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
- if (ret < 0) {
- pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
- __func__, ret);
- }
/* slim_control_ch (REMOVE) */
ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
if (ret < 0) {
@@ -633,3 +617,48 @@
return ret;
}
EXPORT_SYMBOL_GPL(wcd9xxx_get_slave_port);
+
+int wcd9xxx_disconnect_port(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
+ unsigned int ch_cnt, unsigned int rx_tx)
+{
+ u32 sph[SLIM_MAX_TX_PORTS] = {0};
+ int i = 0 , idx = 0;
+ int ret = 0;
+ struct wcd9xxx_slim_sch_rx *rx = sh_ch.rx;
+ struct wcd9xxx_slim_sch_tx *tx = sh_ch.tx;
+
+ pr_debug("%s: ch_cnt[%d], rx_tx flag = %d\n", __func__, ch_cnt, rx_tx);
+ for (i = 0; i < ch_cnt; i++) {
+ /* rx_tx will be 1 for rx, 0 for tx */
+ if (rx_tx) {
+ idx = (ch_num[i] - BASE_CH_NUM -
+ sh_ch.rx_port_start_offset);
+ if (idx < 0) {
+ pr_err("%s: Invalid index found for RX = %d\n",
+ __func__, idx);
+ ret = -EINVAL;
+ goto err;
+ }
+ sph[i] = rx[idx].sph;
+ } else {
+ idx = (ch_num[i] - BASE_CH_NUM);
+ if (idx < 0) {
+ pr_err("%s:Invalid index found for TX = %d\n",
+ __func__, idx);
+ ret = -EINVAL;
+ goto err;
+ }
+ sph[i] = tx[idx].sph;
+ }
+ }
+
+ /* slim_disconnect_port */
+ ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
+ if (ret < 0) {
+ pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+ __func__, ret);
+ }
+err:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(wcd9xxx_disconnect_port);
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c
index 590aa58..d82c353 100644
--- a/drivers/mmc/core/mmc_ops.c
+++ b/drivers/mmc/core/mmc_ops.c
@@ -409,7 +409,6 @@
if (index == EXT_CSD_BKOPS_START)
return 0;
- mmc_delay(1);
/* Must check status to be sure of no errors */
do {
err = mmc_send_status(card, &status);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index b8db530..cd97701 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -3358,6 +3358,9 @@
{
struct device *dev = mmc_dev(host->mmc);
+ pr_info("%s: PM: sdcc_suspended=%d, pending_resume=%d, sdcc_suspending=%d\n",
+ mmc_hostname(host->mmc), host->sdcc_suspended,
+ host->pending_resume, host->sdcc_suspending);
pr_info("%s: RPM: runtime_status=%d, usage_count=%d,"
" is_suspended=%d, disable_depth=%d, runtime_error=%d,"
" request_pending=%d, request=%d\n",
@@ -3379,8 +3382,7 @@
if (mmc->card && mmc_card_sdio(mmc->card))
goto out;
- if (host->sdcc_suspended && host->pending_resume &&
- !pm_runtime_suspended(dev)) {
+ if (host->sdcc_suspended && host->pending_resume) {
host->pending_resume = false;
pm_runtime_get_noresume(dev);
rc = msmsdcc_runtime_resume(dev);
@@ -3401,8 +3403,8 @@
skip_get_sync:
if (rc < 0) {
- pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
- __func__, rc);
+ WARN(1, "%s: %s: failed with error %d\n", mmc_hostname(mmc),
+ __func__, rc);
msmsdcc_print_rpm_info(host);
return rc;
}
@@ -3428,15 +3430,9 @@
rc = pm_runtime_put_sync(mmc->parent);
- /*
- * Ignore -EAGAIN as that is not fatal, it means that
- * either runtime usage count is non-zero or the runtime
- * pm itself is disabled or not in proper state to process
- * idle notification.
- */
- if (rc < 0 && (rc != -EAGAIN)) {
- pr_info("%s: %s: failed with error %d", mmc_hostname(mmc),
- __func__, rc);
+ if (rc < 0) {
+ WARN(1, "%s: %s: failed with error %d\n", mmc_hostname(mmc),
+ __func__, rc);
msmsdcc_print_rpm_info(host);
return rc;
}
@@ -6324,6 +6320,7 @@
wake_unlock(&host->sdio_suspend_wlock);
}
+ host->pending_resume = false;
pr_debug("%s: %s: end\n", mmc_hostname(mmc), __func__);
return 0;
}
@@ -6396,7 +6393,13 @@
if (mmc->card && mmc_card_sdio(mmc->card))
rc = msmsdcc_runtime_resume(dev);
- else
+ /*
+ * As runtime PM is enabled before calling the device's platform resume
+ * callback, we use the pm_runtime_suspended API to know if SDCC is
+ * really runtime suspended or not and set the pending_resume flag only
+ * if its not runtime suspended.
+ */
+ else if (!pm_runtime_suspended(dev))
host->pending_resume = true;
if (host->plat->status_irq) {
diff --git a/drivers/platform/msm/sps/bam.c b/drivers/platform/msm/sps/bam.c
index 2873a5f..7924578 100644
--- a/drivers/platform/msm/sps/bam.c
+++ b/drivers/platform/msm/sps/bam.c
@@ -643,10 +643,10 @@
*/
int bam_init(void *base, u32 ee,
u16 summing_threshold,
- u32 irq_mask, u32 *version, u32 *num_pipes)
+ u32 irq_mask, u32 *version,
+ u32 *num_pipes, u32 p_rst)
{
- /* disable bit#11 because of HW bug */
- u32 cfg_bits = 0xffffffff & ~(1 << 11);
+ u32 cfg_bits;
u32 ver = 0;
SPS_DBG2("sps:%s:bam=0x%x(va).ee=%d.", __func__, (u32) base, ee);
@@ -667,6 +667,11 @@
"use default 4.\n", (u32) base);
}
+ if (p_rst)
+ cfg_bits = 0xffffffff & ~(3 << 11);
+ else
+ cfg_bits = 0xffffffff & ~(1 << 11);
+
bam_write_reg_field(base, CTRL, BAM_SW_RST, 1);
/* No delay needed */
bam_write_reg_field(base, CTRL, BAM_SW_RST, 0);
diff --git a/drivers/platform/msm/sps/bam.h b/drivers/platform/msm/sps/bam.h
index 3521ffa..c183fcd 100644
--- a/drivers/platform/msm/sps/bam.h
+++ b/drivers/platform/msm/sps/bam.h
@@ -102,13 +102,16 @@
*
* @num_pipes - return number of pipes
*
+ * @p_rst - ignore external block pipe reset
+ *
* @return 0 on success, negative value on error
*
*/
int bam_init(void *base,
u32 ee,
u16 summing_threshold,
- u32 irq_mask, u32 *version, u32 *num_pipes);
+ u32 irq_mask, u32 *version,
+ u32 *num_pipes, u32 p_rst);
/**
* Initialize BAM device security execution environment
diff --git a/drivers/platform/msm/sps/sps_bam.c b/drivers/platform/msm/sps/sps_bam.c
index de7fb75..e3be11d 100644
--- a/drivers/platform/msm/sps/sps_bam.c
+++ b/drivers/platform/msm/sps/sps_bam.c
@@ -254,7 +254,8 @@
dev->props.ee,
(u16) dev->props.summing_threshold,
irq_mask,
- &dev->version, &num_pipes);
+ &dev->version, &num_pipes,
+ dev->props.options & SPS_BAM_NO_EXT_P_RST);
else
/* No, so just verify that it is enabled */
rc = bam_check(dev->base, &dev->version, &num_pipes);
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index f6b50a0..a347984 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/interrupt.h>
#include <linux/platform_device.h>
+#include <linux/clk.h>
#include <linux/io.h>
#include <linux/stat.h>
#include <linux/module.h>
@@ -54,11 +55,14 @@
static struct usb_bam_connect_info usb_bam_connections[CONNECTIONS_NUM];
static struct usb_bam_pipe_connect ***msm_usb_bam_connections_info;
static struct usb_bam_pipe_connect *bam_connection_arr;
+void __iomem *qscratch_ram1_reg;
+struct clk *mem_clk;
+struct clk *mem_iface_clk;
static int connect_pipe(u8 conn_idx, enum usb_bam_pipe_dir pipe_dir,
u32 *usb_pipe_idx)
{
- int ret;
+ int ret, ram1_value;
struct sps_pipe **pipe = &sps_pipes[conn_idx][pipe_dir];
struct sps_connect *connection =
&sps_connections[conn_idx][pipe_dir];
@@ -77,13 +81,13 @@
ret = sps_get_config(*pipe, connection);
if (ret) {
pr_err("%s: tx get config failed %d\n", __func__, ret);
- goto get_config_failed;
+ goto free_sps_endpoint;
}
ret = sps_phy2h(pipe_connection->src_phy_addr, &(connection->source));
if (ret) {
pr_err("%s: sps_phy2h failed (src BAM) %d\n", __func__, ret);
- goto get_config_failed;
+ goto free_sps_endpoint;
}
connection->src_pipe_index = pipe_connection->src_pipe_index;
@@ -91,7 +95,7 @@
&(connection->destination));
if (ret) {
pr_err("%s: sps_phy2h failed (dst BAM) %d\n", __func__, ret);
- goto get_config_failed;
+ goto free_sps_endpoint;
}
connection->dest_pipe_index = pipe_connection->dst_pipe_index;
@@ -113,7 +117,7 @@
if (ret) {
pr_err("%s: data fifo setup failure %d\n", __func__,
ret);
- goto fifo_setup_error;
+ goto free_sps_endpoint;
}
ret = sps_setup_bam2bam_fifo(
@@ -123,11 +127,33 @@
if (ret) {
pr_err("%s: desc. fifo setup failure %d\n", __func__,
ret);
- goto fifo_setup_error;
+ goto free_sps_endpoint;
}
} else if (pipe_connection->mem_type == USB_PRIVATE_MEM) {
pr_debug("%s: USB BAM using private memory\n", __func__);
- /* BAM is using dedicated USB private memory, map it */
+
+ if (IS_ERR(mem_clk) || IS_ERR(mem_iface_clk)) {
+ pr_err("%s: Failed to enable USB mem_clk\n", __func__);
+ ret = IS_ERR(mem_clk);
+ goto free_sps_endpoint;
+ }
+
+ clk_prepare_enable(mem_clk);
+ clk_prepare_enable(mem_iface_clk);
+
+ /*
+ * Enable USB PRIVATE RAM to be used for BAM FIFOs
+ * HSUSB: Only RAM13 is used for BAM FIFOs
+ * SSUSB: RAM11, 12, 13 are used for BAM FIFOs
+ */
+ if (pdata->usb_active_bam == HSUSB_BAM)
+ ram1_value = 0x4;
+ else
+ ram1_value = 0x7;
+
+ pr_debug("Writing 0x%x to QSCRATCH_RAM1\n", ram1_value);
+ writel_relaxed(ram1_value, qscratch_ram1_reg);
+
data_mem_buf[conn_idx][pipe_dir].phys_base =
pipe_connection->data_fifo_base_offset +
pdata->usb_base_address;
@@ -187,8 +213,7 @@
error:
sps_disconnect(*pipe);
-fifo_setup_error:
-get_config_failed:
+free_sps_endpoint:
sps_free_endpoint(*pipe);
return ret;
}
@@ -215,6 +240,13 @@
connection->data.base, connection->data.phys_base);
dma_free_coherent(&usb_bam_pdev->dev, connection->desc.size,
connection->desc.base, connection->desc.phys_base);
+ } else if (pipe_connection->mem_type == USB_PRIVATE_MEM) {
+ pr_debug("Freeing USB private memory used by BAM PIPE\n");
+ writel_relaxed(0x0, qscratch_ram1_reg);
+ iounmap(connection->data.base);
+ iounmap(connection->desc.base);
+ clk_disable_unprepare(mem_clk);
+ clk_disable_unprepare(mem_iface_clk);
}
connection->options &= ~SPS_O_AUTO_ENABLE;
@@ -597,7 +629,9 @@
void *usb_virt_addr;
struct msm_usb_bam_platform_data *pdata =
usb_bam_pdev->dev.platform_data;
- struct resource *res;
+ struct usb_bam_pipe_connect *pipe_connection =
+ &msm_usb_bam_connections_info[pdata->usb_active_bam][0][0];
+ struct resource *res, *ram_resource;
int irq;
res = platform_get_resource_byname(usb_bam_pdev, IORESOURCE_MEM,
@@ -614,11 +648,35 @@
return irq;
}
- usb_virt_addr = ioremap(res->start, resource_size(res));
+ usb_virt_addr = devm_ioremap(&usb_bam_pdev->dev, res->start,
+ resource_size(res));
if (!usb_virt_addr) {
pr_err("%s: ioremap failed\n", __func__);
return -ENOMEM;
}
+
+ /* Check if USB3 pipe memory needs to be enabled */
+ if (pipe_connection->mem_type == USB_PRIVATE_MEM) {
+ pr_debug("%s: Enabling USB private memory for: %s\n", __func__,
+ bam_enable_strings[pdata->usb_active_bam]);
+
+ ram_resource = platform_get_resource_byname(usb_bam_pdev,
+ IORESOURCE_MEM, "qscratch_ram1_reg");
+ if (!res) {
+ dev_err(&usb_bam_pdev->dev, "Unable to get qscratch\n");
+ ret = -ENODEV;
+ goto free_bam_regs;
+ }
+
+ qscratch_ram1_reg = devm_ioremap(&usb_bam_pdev->dev,
+ ram_resource->start,
+ resource_size(ram_resource));
+ if (!qscratch_ram1_reg) {
+ pr_err("%s: ioremap failed for qscratch\n", __func__);
+ ret = -ENOMEM;
+ goto free_bam_regs;
+ }
+ }
usb_props.phys_addr = res->start;
usb_props.virt_addr = usb_virt_addr;
usb_props.virt_size = resource_size(res);
@@ -630,10 +688,18 @@
ret = sps_register_bam_device(&usb_props, &h_usb);
if (ret < 0) {
pr_err("%s: register bam error %d\n", __func__, ret);
- return -EFAULT;
+ ret = -EFAULT;
+ goto free_qscratch_reg;
}
return 0;
+
+free_qscratch_reg:
+ iounmap(qscratch_ram1_reg);
+free_bam_regs:
+ iounmap(usb_virt_addr);
+
+ return ret;
}
static ssize_t
@@ -698,6 +764,14 @@
usb_bam_wake_work);
}
+ mem_clk = devm_clk_get(&pdev->dev, "mem_clk");
+ if (IS_ERR(mem_clk))
+ dev_dbg(&pdev->dev, "failed to get mem_clock\n");
+
+ mem_iface_clk = devm_clk_get(&pdev->dev, "mem_iface_clk");
+ if (IS_ERR(mem_iface_clk))
+ dev_dbg(&pdev->dev, "failed to get mem_iface_clock\n");
+
if (pdev->dev.of_node) {
dev_dbg(&pdev->dev, "device tree enabled\n");
pdata = usb_bam_dt_to_pdata(pdev);
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index 0e836c7..44fdbc1 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -56,7 +56,7 @@
};
enum qpnp_regulator_type {
- QPNP_REGULATOR_TYPE_HF_BUCK = 0x03,
+ QPNP_REGULATOR_TYPE_BUCK = 0x03,
QPNP_REGULATOR_TYPE_LDO = 0x04,
QPNP_REGULATOR_TYPE_VS = 0x05,
QPNP_REGULATOR_TYPE_BOOST = 0x1B,
@@ -87,6 +87,7 @@
};
enum qpnp_common_regulator_registers {
+ QPNP_COMMON_REG_DIG_MAJOR_REV = 0x01,
QPNP_COMMON_REG_TYPE = 0x04,
QPNP_COMMON_REG_SUBTYPE = 0x05,
QPNP_COMMON_REG_VOLTAGE_RANGE = 0x40,
@@ -106,7 +107,7 @@
};
enum qpnp_boost_registers {
- QPNP_BOOST_REG_CURRENT_LIMIT = 0x40,
+ QPNP_BOOST_REG_CURRENT_LIMIT = 0x4A,
};
/* Used for indexing into ctrl_reg. These are offets from 0x40 */
@@ -117,10 +118,6 @@
QPNP_COMMON_IDX_ENABLE = 6,
};
-enum qpnp_boost_control_register_index {
- QPNP_BOOST_IDX_CURRENT_LIMIT = 0,
-};
-
/* Common regulator control register layout */
#define QPNP_COMMON_ENABLE_MASK 0x80
#define QPNP_COMMON_ENABLE 0x80
@@ -190,6 +187,8 @@
enum qpnp_regulator_type type;
enum qpnp_regulator_subtype subtype;
enum qpnp_regulator_logical_type logical_type;
+ u32 revision_min;
+ u32 revision_max;
struct regulator_ops *ops;
struct qpnp_voltage_set_points *set_points;
int hpm_min_load;
@@ -213,11 +212,13 @@
u8 ctrl_reg[8];
};
-#define QPNP_VREG_MAP(_type, _subtype, _logical_type, _ops_val, \
- _set_points_val, _hpm_min_load) \
+#define QPNP_VREG_MAP(_type, _subtype, _dig_major_min, _dig_major_max, \
+ _logical_type, _ops_val, _set_points_val, _hpm_min_load) \
{ \
.type = QPNP_REGULATOR_TYPE_##_type, \
.subtype = QPNP_REGULATOR_SUBTYPE_##_subtype, \
+ .revision_min = _dig_major_min, \
+ .revision_max = _dig_major_max, \
.logical_type = QPNP_REGULATOR_LOGICAL_TYPE_##_logical_type, \
.ops = &qpnp_##_ops_val##_ops, \
.set_points = &_set_points_val##_set_points, \
@@ -262,6 +263,10 @@
VOLTAGE_RANGE(2, 750000, 775000, 1537500, 12500),
};
+static struct qpnp_voltage_range nldo3_ranges[] = {
+ VOLTAGE_RANGE(0, 375000, 375000, 1537500, 12500),
+};
+
static struct qpnp_voltage_range smps_ranges[] = {
VOLTAGE_RANGE(0, 375000, 375000, 1562500, 12500),
VOLTAGE_RANGE(1, 1550000, 1575000, 3125000, 25000),
@@ -281,6 +286,8 @@
= SET_POINTS(nldo1_ranges);
static struct qpnp_voltage_set_points nldo2_set_points
= SET_POINTS(nldo2_ranges);
+static struct qpnp_voltage_set_points nldo3_set_points
+ = SET_POINTS(nldo3_ranges);
static struct qpnp_voltage_set_points smps_set_points = SET_POINTS(smps_ranges);
static struct qpnp_voltage_set_points ftsmps_set_points
= SET_POINTS(ftsmps_ranges);
@@ -292,6 +299,7 @@
&pldo_set_points,
&nldo1_set_points,
&nldo2_set_points,
+ &nldo3_set_points,
&smps_set_points,
&ftsmps_set_points,
&boost_set_points,
@@ -959,24 +967,30 @@
.enable_time = qpnp_regulator_common_enable_time,
};
+/* Maximum possible digital major revision value */
+#define INF 0xFF
+
static const struct qpnp_regulator_mapping supported_regulators[] = {
- QPNP_VREG_MAP(HF_BUCK, GP_CTL, SMPS, smps, smps, 100000),
- QPNP_VREG_MAP(LDO, N300, LDO, ldo, nldo1, 10000),
- QPNP_VREG_MAP(LDO, N600, LDO, ldo, nldo2, 10000),
- QPNP_VREG_MAP(LDO, N1200, LDO, ldo, nldo2, 10000),
- QPNP_VREG_MAP(LDO, P50, LDO, ldo, pldo, 5000),
- QPNP_VREG_MAP(LDO, P150, LDO, ldo, pldo, 10000),
- QPNP_VREG_MAP(LDO, P300, LDO, ldo, pldo, 10000),
- QPNP_VREG_MAP(LDO, P600, LDO, ldo, pldo, 10000),
- QPNP_VREG_MAP(LDO, P1200, LDO, ldo, pldo, 10000),
- QPNP_VREG_MAP(VS, LV100, VS, vs, none, 0),
- QPNP_VREG_MAP(VS, LV300, VS, vs, none, 0),
- QPNP_VREG_MAP(VS, MV300, VS, vs, none, 0),
- QPNP_VREG_MAP(VS, MV500, VS, vs, none, 0),
- QPNP_VREG_MAP(VS, HDMI, VS, vs, none, 0),
- QPNP_VREG_MAP(VS, OTG, VS, vs, none, 0),
- QPNP_VREG_MAP(BOOST, 5V_BOOST, BOOST, boost, boost, 0),
- QPNP_VREG_MAP(FTS, FTS_CTL, FTSMPS, ftsmps, ftsmps, 100000),
+ /* type subtype dig_min dig_max ltype ops setpoints hpm_min */
+ QPNP_VREG_MAP(BUCK, GP_CTL, 0, INF, SMPS, smps, smps, 100000),
+ QPNP_VREG_MAP(LDO, N300, 0, INF, LDO, ldo, nldo1, 10000),
+ QPNP_VREG_MAP(LDO, N600, 0, 0, LDO, ldo, nldo2, 10000),
+ QPNP_VREG_MAP(LDO, N1200, 0, 0, LDO, ldo, nldo2, 10000),
+ QPNP_VREG_MAP(LDO, N600, 1, INF, LDO, ldo, nldo3, 10000),
+ QPNP_VREG_MAP(LDO, N1200, 1, INF, LDO, ldo, nldo3, 10000),
+ QPNP_VREG_MAP(LDO, P50, 0, INF, LDO, ldo, pldo, 5000),
+ QPNP_VREG_MAP(LDO, P150, 0, INF, LDO, ldo, pldo, 10000),
+ QPNP_VREG_MAP(LDO, P300, 0, INF, LDO, ldo, pldo, 10000),
+ QPNP_VREG_MAP(LDO, P600, 0, INF, LDO, ldo, pldo, 10000),
+ QPNP_VREG_MAP(LDO, P1200, 0, INF, LDO, ldo, pldo, 10000),
+ QPNP_VREG_MAP(VS, LV100, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(VS, LV300, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(VS, MV300, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(VS, MV500, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(VS, HDMI, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(VS, OTG, 0, INF, VS, vs, none, 0),
+ QPNP_VREG_MAP(BOOST, 5V_BOOST, 0, INF, BOOST, boost, boost, 0),
+ QPNP_VREG_MAP(FTS, FTS_CTL, 0, INF, FTSMPS, ftsmps, ftsmps, 100000),
};
static int qpnp_regulator_match(struct qpnp_regulator *vreg)
@@ -984,29 +998,39 @@
const struct qpnp_regulator_mapping *mapping;
struct device_node *node = vreg->spmi_dev->dev.of_node;
int rc, i;
- u8 raw_type[2], type, subtype;
- u32 type_reg[2];
+ u32 type_reg[2], dig_major_rev;
+ u8 version[QPNP_COMMON_REG_SUBTYPE - QPNP_COMMON_REG_DIG_MAJOR_REV + 1];
+ u8 type, subtype;
- rc = of_property_read_u32_array(node, "qcom,force-type",
- type_reg, 2);
+ rc = qpnp_vreg_read(vreg, QPNP_COMMON_REG_DIG_MAJOR_REV, version,
+ ARRAY_SIZE(version));
+ if (rc) {
+ vreg_err(vreg, "could not read version registers, rc=%d\n", rc);
+ return rc;
+ }
+ dig_major_rev = version[QPNP_COMMON_REG_DIG_MAJOR_REV
+ - QPNP_COMMON_REG_DIG_MAJOR_REV];
+ type = version[QPNP_COMMON_REG_TYPE
+ - QPNP_COMMON_REG_DIG_MAJOR_REV];
+ subtype = version[QPNP_COMMON_REG_SUBTYPE
+ - QPNP_COMMON_REG_DIG_MAJOR_REV];
+
+ /*
+ * Override type and subtype register values if qcom,force-type is
+ * present in the device tree node.
+ */
+ rc = of_property_read_u32_array(node, "qcom,force-type", type_reg, 2);
if (!rc) {
type = type_reg[0];
subtype = type_reg[1];
- } else {
- rc = qpnp_vreg_read(vreg, QPNP_COMMON_REG_TYPE, raw_type, 2);
- if (rc) {
- vreg_err(vreg,
- "could not read type register, rc=%d\n", rc);
- return rc;
- }
- type = raw_type[0];
- subtype = raw_type[1];
}
rc = -ENODEV;
for (i = 0; i < ARRAY_SIZE(supported_regulators); i++) {
mapping = &supported_regulators[i];
- if (mapping->type == type && mapping->subtype == subtype) {
+ if (mapping->type == type && mapping->subtype == subtype
+ && mapping->revision_min <= dig_major_rev
+ && mapping->revision_max >= dig_major_rev) {
vreg->logical_type = mapping->logical_type;
vreg->set_points = mapping->set_points;
vreg->hpm_min_load = mapping->hpm_min_load;
@@ -1096,10 +1120,14 @@
if (type == QPNP_REGULATOR_LOGICAL_TYPE_BOOST
&& pdata->boost_current_limit
!= QPNP_BOOST_CURRENT_LIMIT_HW_DEFAULT) {
- ctrl_reg[QPNP_BOOST_IDX_CURRENT_LIMIT] &=
- ~QPNP_BOOST_CURRENT_LIMIT_MASK;
- ctrl_reg[QPNP_BOOST_IDX_CURRENT_LIMIT] |=
- pdata->boost_current_limit & QPNP_BOOST_CURRENT_LIMIT_MASK;
+ reg = pdata->boost_current_limit;
+ mask = QPNP_BOOST_CURRENT_LIMIT_MASK;
+ rc = qpnp_vreg_masked_read_write(vreg,
+ QPNP_BOOST_REG_CURRENT_LIMIT, reg, mask);
+ if (rc) {
+ vreg_err(vreg, "spmi write failed, rc=%d\n", rc);
+ return rc;
+ }
}
/* Write back any control register values that were modified. */
diff --git a/drivers/usb/gadget/f_adb.c b/drivers/usb/gadget/f_adb.c
index b997a3f..9778673 100644
--- a/drivers/usb/gadget/f_adb.c
+++ b/drivers/usb/gadget/f_adb.c
@@ -48,7 +48,6 @@
atomic_t read_excl;
atomic_t write_excl;
atomic_t open_excl;
- struct delayed_work adb_release_w;
struct list_head tx_idle;
@@ -410,11 +409,6 @@
return r;
}
-static void adb_release_work(struct work_struct *w)
-{
- adb_closed_callback();
-}
-
static int adb_open(struct inode *ip, struct file *fp)
{
pr_info("adb_open\n");
@@ -429,8 +423,7 @@
/* clear the error latch */
atomic_set(&_adb_dev->error, 0);
- if (!cancel_delayed_work_sync(&_adb_dev->adb_release_w))
- adb_ready_callback();
+ adb_ready_callback();
return 0;
}
@@ -439,16 +432,7 @@
{
pr_info("adb_release\n");
- /*
- * When USB cable is plugged out, adb reader is unblocked and
- * -EIO is returned to user space. adb daemon reopen the port
- * which would disable and enable USB configuration unnecessarily.
- *
- * Delay notifying the adb close event to android by 1 sec. If
- * ADB daemon opens the port with in 1 sec, USB configuration
- * re-enable does not happen.
- */
- schedule_delayed_work(&_adb_dev->adb_release_w, msecs_to_jiffies(1000));
+ adb_closed_callback();
adb_unlock(&_adb_dev->open_excl);
return 0;
@@ -624,7 +608,6 @@
atomic_set(&dev->read_excl, 0);
atomic_set(&dev->write_excl, 0);
- INIT_DELAYED_WORK(&dev->adb_release_w, adb_release_work);
INIT_LIST_HEAD(&dev->tx_idle);
_adb_dev = dev;
diff --git a/drivers/usb/host/ehci-msm-hsic.c b/drivers/usb/host/ehci-msm-hsic.c
index eebda9e..7af0afd 100644
--- a/drivers/usb/host/ehci-msm-hsic.c
+++ b/drivers/usb/host/ehci-msm-hsic.c
@@ -354,21 +354,33 @@
static int ulpi_read(struct msm_hsic_hcd *mehci, u32 reg)
{
struct usb_hcd *hcd = hsic_to_hcd(mehci);
- unsigned long timeout;
+ int cnt = 0;
/* initiate read operation */
writel_relaxed(ULPI_RUN | ULPI_READ | ULPI_ADDR(reg),
USB_ULPI_VIEWPORT);
/* wait for completion */
- timeout = jiffies + usecs_to_jiffies(ULPI_IO_TIMEOUT_USEC);
- while (readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN) {
- if (time_after(jiffies, timeout)) {
- dev_err(mehci->dev, "ulpi_read: timeout %08x\n",
- readl_relaxed(USB_ULPI_VIEWPORT));
- return -ETIMEDOUT;
- }
+ while (cnt < ULPI_IO_TIMEOUT_USEC) {
+ if (!(readl_relaxed(USB_ULPI_VIEWPORT) & ULPI_RUN))
+ break;
udelay(1);
+ cnt++;
+ }
+
+ if (cnt >= ULPI_IO_TIMEOUT_USEC) {
+ dev_err(mehci->dev, "ulpi_read: timeout ULPI_VIEWPORT: %08x\n",
+ readl_relaxed(USB_ULPI_VIEWPORT));
+ dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
+ readl_relaxed(USB_PORTSC),
+ readl_relaxed(USB_USBCMD),
+ readl_relaxed(USB_FRINDEX));
+
+ /*frame counter increments afte 125us*/
+ udelay(130);
+ dev_err(mehci->dev, "ulpi_read: FRINDEX: %08x\n",
+ readl_relaxed(USB_FRINDEX));
+ return -ETIMEDOUT;
}
return ULPI_DATA_READ(readl_relaxed(USB_ULPI_VIEWPORT));
@@ -393,7 +405,17 @@
}
if (cnt >= ULPI_IO_TIMEOUT_USEC) {
- dev_err(mehci->dev, "ulpi_write: timeout\n");
+ dev_err(mehci->dev, "ulpi_write: timeout ULPI_VIEWPORT: %08x\n",
+ readl_relaxed(USB_ULPI_VIEWPORT));
+ dev_err(mehci->dev, "PORTSC: %08x USBCMD: %08x FRINDEX: %08x\n",
+ readl_relaxed(USB_PORTSC),
+ readl_relaxed(USB_USBCMD),
+ readl_relaxed(USB_FRINDEX));
+
+ /*frame counter increments afte 125us*/
+ udelay(130);
+ dev_err(mehci->dev, "ulpi_write: FRINDEX: %08x\n",
+ readl_relaxed(USB_FRINDEX));
return -ETIMEDOUT;
}
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 0976fc6..c6ffaf2 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1418,7 +1418,7 @@
video_format, video_format_2string(video_format),
supported ? "Supported" : "Not-Supported");
if (supported) {
- if (mhl_is_connected()) {
+ if (mhl_is_enabled()) {
const struct hdmi_disp_mode_timing_type *mhl_timing =
hdmi_mhl_get_supported_mode(video_format);
boolean mhl_supported = mhl_timing != NULL;
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 26e5687..a5e72fe 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -4448,6 +4448,11 @@
return 0;
}
+bool mhl_is_enabled(void)
+{
+ return hdmi_msm_state->is_mhl_enabled;
+}
+
static int __devinit hdmi_msm_probe(struct platform_device *pdev)
{
int rc;
@@ -4620,6 +4625,12 @@
if (switch_dev_register(&external_common_state->sdev) < 0)
DEV_ERR("Hdmi switch registration failed\n");
+ /* Set the default video resolution for MHL-enabled display */
+ if (hdmi_msm_state->is_mhl_enabled) {
+ DEV_DBG("MHL Enabled. Restricting default video resolution\n");
+ external_common_state->video_resolution =
+ HDMI_VFRMT_1920x1080p30_16_9;
+ }
return 0;
error:
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 6325fd9..6f78305 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -338,7 +338,7 @@
if (pipe->pipe_used) {
cnt++;
real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
- if (real_pipe->pipe_used) {
+ if (real_pipe && real_pipe->pipe_used) {
/* pipe not unset */
mdp4_overlay_vsync_commit(pipe);
}
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 517f103..cac6962 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -214,7 +214,7 @@
if (pipe->pipe_used) {
cnt++;
real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
- if (real_pipe->pipe_used) {
+ if (real_pipe && real_pipe->pipe_used) {
/* pipe not unset */
mdp4_overlay_vsync_commit(pipe);
}
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index 972e2ea..00f44d4 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -199,7 +199,7 @@
if (pipe->pipe_used) {
cnt++;
real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
- if (real_pipe->pipe_used) {
+ if (real_pipe && real_pipe->pipe_used) {
/* pipe not unset */
mdp4_overlay_vsync_commit(pipe);
}
@@ -796,8 +796,6 @@
vctrl->vsync_time = ktime_get();
schedule_work(&vctrl->vsync_work);
- pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
-
spin_lock(&vctrl->spin_lock);
if (vctrl->wait_vsync_cnt) {
complete_all(&vctrl->vsync_comp);
@@ -823,6 +821,7 @@
vctrl = &vsync_ctrl_db[cndx];
pipe = vctrl->base_pipe;
+ pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
spin_lock(&vctrl->spin_lock);
if (vctrl->blt_change) {
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 54452b0..08c3815 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -218,7 +218,7 @@
if (pipe->pipe_used) {
cnt++;
real_pipe = mdp4_overlay_ndx2pipe(pipe->pipe_ndx);
- if (real_pipe->pipe_used) {
+ if (real_pipe && real_pipe->pipe_used) {
/* pipe not unset */
mdp4_overlay_vsync_commit(pipe);
}
diff --git a/drivers/video/msm/mdss/mdss_dsi.c b/drivers/video/msm/mdss/mdss_dsi.c
index f012e2e..8c61be9 100644
--- a/drivers/video/msm/mdss/mdss_dsi.c
+++ b/drivers/video/msm/mdss/mdss_dsi.c
@@ -119,7 +119,12 @@
return ret;
}
+ mdss_dsi_panel_reset(1);
+
} else {
+
+ mdss_dsi_panel_reset(0);
+
ret = regulator_disable(dsi_drv.vdd_vreg);
if (ret) {
pr_err("%s: Failed to disable regulator.\n", __func__);
@@ -180,7 +185,7 @@
}
spin_lock_bh(&dsi_clk_lock);
- mdss_dsi_clk_disable();
+ mdss_dsi_clk_disable(pdata);
/* disable dsi engine */
MIPI_OUTP(mdss_dsi_base + 0x0004, 0);
@@ -212,15 +217,18 @@
pinfo = &pdata->panel_info;
- cont_splash_clk_ctrl(0);
+ MIPI_OUTP(mdss_dsi_base + 0x118, 1);
+ MIPI_OUTP(mdss_dsi_base + 0x118, 0);
+
+ mdss_dsi_phy_sw_reset(pdata);
+ mdss_dsi_phy_enable(pdata, 1);
+ mdss_dsi_phy_init(pdata);
+
mdss_dsi_prepare_clocks();
spin_lock_bh(&dsi_clk_lock);
- MIPI_OUTP(mdss_dsi_base + 0x118, 1);
- MIPI_OUTP(mdss_dsi_base + 0x118, 0);
-
- mdss_dsi_clk_enable();
+ mdss_dsi_clk_enable(pdata);
spin_unlock_bh(&dsi_clk_lock);
clk_rate = pdata->panel_info.clk_rate;
@@ -496,6 +504,7 @@
pdata->dsi_base = mdss_dsi_base;
pdata->mmss_cc_base = mmss_cc_base;
+ pdata->set_backlight = panel_data->bl_ctrl;
/*
* register in mdp driver
diff --git a/drivers/video/msm/mdss/mdss_dsi.h b/drivers/video/msm/mdss/mdss_dsi.h
index 0af4371..6acb8d5 100644
--- a/drivers/video/msm/mdss/mdss_dsi.h
+++ b/drivers/video/msm/mdss/mdss_dsi.h
@@ -76,6 +76,12 @@
DSI_CMD_MODE_MDP,
};
+enum dsi_panel_bl_ctrl {
+ BL_PWM,
+ BL_WLED,
+ BL_DCS_CMD,
+};
+
#define DSI_NON_BURST_SYNCH_PULSE 0
#define DSI_NON_BURST_SYNCH_EVENT 1
#define DSI_BURST_MODE 2
@@ -241,6 +247,7 @@
struct mdss_panel_info panel_info;
int (*on) (struct mdss_panel_data *pdata);
int (*off) (struct mdss_panel_data *pdata);
+ void (*bl_ctrl) (u32 bl_level);
};
struct mdss_dsi_drv_pdata {
@@ -279,8 +286,8 @@
void mdss_dsi_cmd_mdp_start(void);
void mdss_dsi_cmd_bta_sw_trigger(struct mdss_panel_data *pdata);
void mdss_dsi_ack_err_status(unsigned char *dsi_base);
-void mdss_dsi_clk_enable(void);
-void mdss_dsi_clk_disable(void);
+void mdss_dsi_clk_enable(struct mdss_panel_data *pdata);
+void mdss_dsi_clk_disable(struct mdss_panel_data *pdata);
void mdss_dsi_controller_cfg(int enable,
struct mdss_panel_data *pdata);
void mdss_dsi_sw_reset(struct mdss_panel_data *pdata);
@@ -294,6 +301,10 @@
void mdss_dsi_clk_deinit(struct device *dev);
void mdss_dsi_prepare_clocks(void);
void mdss_dsi_unprepare_clocks(void);
-void cont_splash_clk_ctrl(int enable);
unsigned char *mdss_dsi_get_base_adr(void);
+void mdss_dsi_panel_reset(int enable);
+void mdss_dsi_phy_enable(struct mdss_panel_data *pdata, int on);
+void mdss_dsi_phy_init(struct mdss_panel_data *pdata);
+void mdss_dsi_phy_sw_reset(struct mdss_panel_data *pdata);
+
#endif /* MDSS_DSI_H */
diff --git a/drivers/video/msm/mdss/mdss_dsi_panel.c b/drivers/video/msm/mdss/mdss_dsi_panel.c
index bfb7fae..e4b1867 100644
--- a/drivers/video/msm/mdss/mdss_dsi_panel.c
+++ b/drivers/video/msm/mdss/mdss_dsi_panel.c
@@ -13,7 +13,12 @@
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/qpnp/pin.h>
+#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/leds.h>
#include "mdss_dsi.h"
@@ -28,6 +33,68 @@
static int num_of_off_cmds;
static char *on_cmds, *off_cmds;
+static char bl_ctrl;
+DEFINE_LED_TRIGGER(bl_led_trigger);
+
+static struct mdss_dsi_phy_ctrl phy_params;
+
+static int rst_gpio;
+static int disp_en;
+
+struct qpnp_pin_cfg param = {
+ .mode = QPNP_PIN_MODE_DIG_OUT,
+ .output_type = QPNP_PIN_OUT_BUF_OPEN_DRAIN_NMOS,
+ .invert = QPNP_PIN_INVERT_ENABLE,
+ .pull = QPNP_PIN_MPP_PULL_UP_30KOHM,
+ .vin_sel = QPNP_PIN_VIN3,
+ .out_strength = QPNP_PIN_OUT_STRENGTH_HIGH,
+ .select = QPNP_PIN_SEL_DTEST3,
+ .master_en = QPNP_PIN_MASTER_ENABLE,
+ .aout_ref = QPNP_PIN_AOUT_0V625,
+ .ain_route = QPNP_PIN_AIN_AMUX_CH7,
+ .cs_out = QPNP_PIN_CS_OUT_20MA,
+};
+
+void mdss_dsi_panel_reset(int enable)
+{
+ if (!disp_en)
+ pr_debug("%s:%d, reset line not configured\n",
+ __func__, __LINE__);
+
+ if (!rst_gpio)
+ pr_debug("%s:%d, reset line not configured\n",
+ __func__, __LINE__);
+
+ if (enable) {
+ gpio_set_value(disp_en, 1);
+ gpio_set_value(rst_gpio, 1);
+ usleep(10);
+ gpio_set_value(rst_gpio, 0);
+ usleep(200);
+ gpio_set_value(rst_gpio, 1);
+ } else {
+ gpio_set_value(rst_gpio, 0);
+ gpio_set_value(disp_en, 0);
+ }
+}
+
+static void mdss_dsi_panel_bl_ctrl(u32 bl_level)
+{
+ if (bl_ctrl) {
+ switch (bl_ctrl) {
+ case BL_WLED:
+ led_trigger_event(bl_led_trigger, bl_level);
+ break;
+
+ default:
+ pr_err("%s: Unknown bl_ctrl configuration\n",
+ __func__);
+ break;
+ }
+ } else
+ pr_err("%s:%d, bl_ctrl not configured", __func__, __LINE__);
+}
+
static int mdss_dsi_panel_on(struct mdss_panel_data *pdata)
{
struct mipi_panel_info *mipi;
@@ -37,6 +104,8 @@
pr_debug("%s:%d, debug info (mode) : %d\n", __func__, __LINE__,
mipi->mode);
+ mdss_dsi_panel_reset(1);
+
if (mipi->mode == DSI_VIDEO_MODE) {
mdss_dsi_cmds_tx(pdata, &dsi_panel_tx_buf, dsi_panel_on_cmds,
num_of_on_cmds);
@@ -64,6 +133,8 @@
return -EINVAL;
}
+ mdss_dsi_panel_reset(0);
+
return 0;
}
@@ -75,6 +146,7 @@
int rc, i, len;
int cmd_plen, data_offset;
const char *data;
+ static const char *bl_ctrl_type;
rc = of_property_read_u32_array(np, "qcom,mdss-pan-res", res, 2);
if (rc) {
@@ -85,6 +157,59 @@
panel_data->panel_info.xres = (!rc ? res[0] : 640);
panel_data->panel_info.yres = (!rc ? res[1] : 480);
+ rc = of_property_read_u32_array(np, "qcom,mdss-pan-active-res", res, 2);
+ if (rc == 0) {
+ panel_data->panel_info.lcdc.xres_pad =
+ panel_data->panel_info.xres - res[0];
+ panel_data->panel_info.lcdc.yres_pad =
+ panel_data->panel_info.yres - res[1];
+ }
+
+ disp_en = of_get_named_gpio(np, "qcom,enable-gpio", 0);
+ if (!gpio_is_valid(disp_en)) {
+ pr_err("%s:%d, Disp_en gpio not specified\n",
+ __func__, __LINE__);
+ return -ENODEV;
+ }
+
+ rc = gpio_request(disp_en, "disp_enable");
+ if (rc) {
+ pr_err("request reset gpio failed, rc=%d\n",
+ rc);
+ gpio_free(disp_en);
+ return -ENODEV;
+ }
+ rc = gpio_direction_output(disp_en, 1);
+ if (rc) {
+ pr_err("set_direction for disp_en gpio failed, rc=%d\n",
+ rc);
+ gpio_free(disp_en);
+ return -ENODEV;
+ }
+
+ rst_gpio = of_get_named_gpio(np, "qcom,rst-gpio", 0);
+ if (!gpio_is_valid(rst_gpio)) {
+ pr_err("%s:%d, reset gpio not specified\n",
+ __func__, __LINE__);
+ } else {
+ rc = qpnp_pin_config(rst_gpio, ¶m);
+ if (rc) {
+ pr_err("request reset gpio failed, rc=%d\n",
+ rc);
+ gpio_free(disp_en);
+ return rc;
+ }
+
+ rc = gpio_request(rst_gpio, "disp_rst_n");
+ if (rc) {
+ pr_err("request reset gpio failed, rc=%d\n",
+ rc);
+ gpio_free(rst_gpio);
+ gpio_free(disp_en);
+ return -ENODEV;
+ }
+ }
+
rc = of_property_read_u32(np, "qcom,mdss-pan-bpp", &tmp);
if (rc) {
pr_err("%s:%d, panel bpp not specified\n",
@@ -106,6 +231,14 @@
"qcom,mdss-pan-underflow-clr", &tmp);
panel_data->panel_info.lcdc.underflow_clr = (!rc ? tmp : 0xff);
+ bl_ctrl_type = of_get_property(pdev->dev.of_node,
+ "qcom,mdss-pan-bl-ctrl", NULL);
+ if (!strncmp(bl_ctrl_type, "bl_ctrl_wled", 12)) {
+ led_trigger_register_simple("bkl-trigger", &bl_led_trigger);
+ pr_debug("%s: SUCCESS-> WLED TRIGGER register\n", __func__);
+ bl_ctrl = BL_WLED;
+ }
+
rc = of_property_read_u32_array(np,
"qcom,mdss-pan-bl-levels", res, 2);
panel_data->panel_info.bl_min = (!rc ? res[0] : 0);
@@ -184,6 +317,53 @@
rc = of_property_read_u32(np, "qcom,mdss-pan-dsi-frame-rate", &tmp);
panel_data->panel_info.mipi.frame_rate = (!rc ? tmp : 60);
+ data = of_get_property(np, "qcom,panel-phy-regulatorSettings", &len);
+ if ((!data) || (len != 8)) {
+ pr_err("%s:%d, Unable to read Phy regulator settings",
+ __func__, __LINE__);
+ goto error;
+ }
+ for (i = 0; i < len; i++)
+ phy_params.regulator[i] = data[i];
+
+ data = of_get_property(np, "qcom,panel-phy-timingSettings", &len);
+ if ((!data) || (len != 12)) {
+ pr_err("%s:%d, Unable to read Phy timing settings",
+ __func__, __LINE__);
+ goto error;
+ }
+ for (i = 0; i < len; i++)
+ phy_params.timing[i] = data[i];
+
+ data = of_get_property(np, "qcom,panel-phy-strengthCtrl", &len);
+ if ((!data) || (len != 2)) {
+ pr_err("%s:%d, Unable to read Phy Strength ctrl settings",
+ __func__, __LINE__);
+ goto error;
+ }
+ phy_params.strength[0] = data[0];
+ phy_params.strength[1] = data[1];
+
+ data = of_get_property(np, "qcom,panel-phy-bistCtrl", &len);
+ if ((!data) || (len != 6)) {
+ pr_err("%s:%d, Unable to read Phy Bist Ctrl settings",
+ __func__, __LINE__);
+ goto error;
+ }
+ for (i = 0; i < len; i++)
+ phy_params.bistCtrl[i] = data[i];
+
+ data = of_get_property(np, "qcom,panel-phy-laneConfig", &len);
+ if ((!data) || (len != 45)) {
+ pr_err("%s:%d, Unable to read Phy lane configure settings",
+ __func__, __LINE__);
+ goto error;
+ }
+ for (i = 0; i < len; i++)
+ phy_params.laneCfg[i] = data[i];
+
+ panel_data->panel_info.mipi.dsi_phy_db = &phy_params;
+
data = of_get_property(np, "qcom,panel-on-cmds", &len);
if (!data) {
pr_err("%s:%d, Unable to read ON cmds", __func__, __LINE__);
@@ -288,6 +468,10 @@
kfree(dsi_panel_off_cmds);
kfree(on_cmds);
kfree(off_cmds);
+ if (rst_gpio)
+ gpio_free(rst_gpio);
+ if (disp_en)
+ gpio_free(disp_en);
return -EINVAL;
}
@@ -295,7 +479,7 @@
static int __devinit mdss_dsi_panel_probe(struct platform_device *pdev)
{
int rc = 0;
- struct mdss_panel_common_pdata *vendor_pdata = NULL;
+ static struct mdss_panel_common_pdata vendor_pdata;
static const char *panel_name;
if (pdev->dev.parent == NULL) {
@@ -314,21 +498,15 @@
else
pr_info("%s: Panel Name = %s\n", __func__, panel_name);
- vendor_pdata = devm_kzalloc(&pdev->dev,
- sizeof(*vendor_pdata), GFP_KERNEL);
- if (!vendor_pdata)
- return -ENOMEM;
-
- rc = mdss_panel_parse_dt(pdev, vendor_pdata);
- if (rc) {
- devm_kfree(&pdev->dev, vendor_pdata);
- vendor_pdata = NULL;
+ rc = mdss_panel_parse_dt(pdev, &vendor_pdata);
+ if (rc)
return rc;
- }
- vendor_pdata->on = mdss_dsi_panel_on;
- vendor_pdata->off = mdss_dsi_panel_off;
- rc = dsi_panel_device_register(pdev, vendor_pdata);
+ vendor_pdata.on = mdss_dsi_panel_on;
+ vendor_pdata.off = mdss_dsi_panel_off;
+ vendor_pdata.bl_ctrl = mdss_dsi_panel_bl_ctrl;
+
+ rc = dsi_panel_device_register(pdev, &vendor_pdata);
if (rc)
return rc;
diff --git a/drivers/video/msm/mdss/mdss_panel.h b/drivers/video/msm/mdss/mdss_panel.h
index 91010f4..5d23548 100644
--- a/drivers/video/msm/mdss/mdss_panel.h
+++ b/drivers/video/msm/mdss/mdss_panel.h
@@ -83,6 +83,18 @@
u32 yres_pad;
};
+
+/* DSI PHY configuration */
+struct mdss_dsi_phy_ctrl {
+ uint32_t regulator[8];
+ uint32_t timing[12];
+ uint32_t ctrl[4];
+ uint32_t strength[2];
+ char bistCtrl[6];
+ uint32_t pll[21];
+ char laneCfg[45];
+};
+
struct mipi_panel_info {
char mode; /* video/cmd */
char interleave_mode;
@@ -103,7 +115,7 @@
char t_clk_post; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
char t_clk_pre; /* 0xc0, DSI_CLKOUT_TIMING_CTRL */
char vc; /* virtual channel */
- struct mipi_dsi_phy_ctrl *dsi_phy_db;
+ struct mdss_dsi_phy_ctrl *dsi_phy_db;
/* video mode */
char pulse_mode_hsa_he;
char hfp_power_stop;
diff --git a/drivers/video/msm/mdss/msm_mdss_io_8974.c b/drivers/video/msm/mdss/msm_mdss_io_8974.c
index c766ec7..9d9a366 100644
--- a/drivers/video/msm/mdss/msm_mdss_io_8974.c
+++ b/drivers/video/msm/mdss/msm_mdss_io_8974.c
@@ -12,6 +12,7 @@
*/
#include <linux/clk.h>
#include <linux/interrupt.h>
+#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
@@ -26,8 +27,9 @@
static struct dsi_clk_desc dsi_pclk;
-static struct clk *dsi_byte_div_clk;
+static struct clk *dsi_byte_clk;
static struct clk *dsi_esc_clk;
+static struct clk *dsi_pixel_clk;
int mdss_dsi_clk_on;
@@ -35,16 +37,23 @@
{
struct device *dev = &pdev->dev;
- dsi_byte_div_clk = clk_get(dev, "byte_clk");
- if (IS_ERR(dsi_byte_div_clk)) {
- pr_err("can't find dsi_byte_div_clk\n");
- dsi_byte_div_clk = NULL;
+ dsi_byte_clk = clk_get(dev, "byte_clk");
+ if (IS_ERR(dsi_byte_clk)) {
+ pr_err("can't find dsi_byte_clk\n");
+ dsi_byte_clk = NULL;
+ goto mdss_dsi_clk_err;
+ }
+
+ dsi_pixel_clk = clk_get(dev, "pixel_clk");
+ if (IS_ERR(dsi_pixel_clk)) {
+ pr_err("can't find dsi_pixel_clk\n");
+ dsi_pixel_clk = NULL;
goto mdss_dsi_clk_err;
}
dsi_esc_clk = clk_get(dev, "core_clk");
if (IS_ERR(dsi_esc_clk)) {
- printk(KERN_ERR "can't find dsi_esc_clk\n");
+ pr_err("can't find dsi_esc_clk\n");
dsi_esc_clk = NULL;
goto mdss_dsi_clk_err;
}
@@ -58,10 +67,12 @@
void mdss_dsi_clk_deinit(struct device *dev)
{
- if (dsi_byte_div_clk)
- clk_put(dsi_byte_div_clk);
+ if (dsi_byte_clk)
+ clk_put(dsi_byte_clk);
if (dsi_esc_clk)
clk_put(dsi_esc_clk);
+ if (dsi_pixel_clk)
+ clk_put(dsi_pixel_clk);
}
#define PREF_DIV_RATIO 27
@@ -143,57 +154,145 @@
return 0;
}
-void cont_splash_clk_ctrl(int enable)
-{
- static int cont_splash_clks_enabled;
- if (enable && !cont_splash_clks_enabled) {
- clk_prepare_enable(dsi_byte_div_clk);
- clk_prepare_enable(dsi_esc_clk);
- cont_splash_clks_enabled = 1;
- } else if (!enable && cont_splash_clks_enabled) {
- clk_disable_unprepare(dsi_byte_div_clk);
- clk_disable_unprepare(dsi_esc_clk);
- cont_splash_clks_enabled = 0;
- }
-}
-
void mdss_dsi_prepare_clocks(void)
{
- clk_prepare(dsi_byte_div_clk);
+ clk_prepare(dsi_byte_clk);
clk_prepare(dsi_esc_clk);
+ clk_prepare(dsi_pixel_clk);
}
void mdss_dsi_unprepare_clocks(void)
{
clk_unprepare(dsi_esc_clk);
- clk_unprepare(dsi_byte_div_clk);
+ clk_unprepare(dsi_pixel_clk);
+ clk_unprepare(dsi_byte_clk);
}
-void mdss_dsi_clk_enable(void)
+void mdss_dsi_clk_enable(struct mdss_panel_data *pdata)
{
if (mdss_dsi_clk_on) {
pr_info("%s: mdss_dsi_clks already ON\n", __func__);
return;
}
- if (clk_set_rate(dsi_byte_div_clk, 1) < 0) /* divided by 1 */
- pr_err("%s: dsi_byte_div_clk - clk_set_rate failed\n",
- __func__);
- if (clk_set_rate(dsi_esc_clk, 2) < 0) /* divided by 2 */
+ if (clk_set_rate(dsi_esc_clk, 19200000) < 0)
pr_err("%s: dsi_esc_clk - clk_set_rate failed\n",
__func__);
- clk_enable(dsi_byte_div_clk);
+
+ if (clk_set_rate(dsi_byte_clk, 53000000) < 0)
+ pr_err("%s: dsi_byte_clk - clk_set_rate failed\n",
+ __func__);
+
+ if (clk_set_rate(dsi_pixel_clk, 70000000) < 0)
+ pr_err("%s: dsi_pixel_clk - clk_set_rate failed\n",
+ __func__);
+
clk_enable(dsi_esc_clk);
+ clk_enable(dsi_byte_clk);
+ clk_enable(dsi_pixel_clk);
+
mdss_dsi_clk_on = 1;
}
-void mdss_dsi_clk_disable(void)
+void mdss_dsi_clk_disable(struct mdss_panel_data *pdata)
{
if (mdss_dsi_clk_on == 0) {
pr_info("%s: mdss_dsi_clks already OFF\n", __func__);
return;
}
+
+ clk_disable(dsi_pixel_clk);
+ clk_disable(dsi_byte_clk);
clk_disable(dsi_esc_clk);
- clk_disable(dsi_byte_div_clk);
+
mdss_dsi_clk_on = 0;
}
+
+void mdss_dsi_phy_sw_reset(struct mdss_panel_data *pdata)
+{
+ /* start phy sw reset */
+ MIPI_OUTP((pdata->dsi_base) + 0x12c, 0x0001);
+ wmb();
+ usleep(1);
+ /* end phy sw reset */
+ MIPI_OUTP((pdata->dsi_base) + 0x12c, 0x0000);
+ wmb();
+ usleep(1);
+}
+
+void mdss_dsi_phy_enable(struct mdss_panel_data *pdata, int on)
+{
+ if (on) {
+ MIPI_OUTP((pdata->dsi_base) + 0x0220, 0x006);
+ usleep(10);
+ MIPI_OUTP((pdata->dsi_base) + 0x0268, 0x001);
+ usleep(10);
+ MIPI_OUTP((pdata->dsi_base) + 0x0268, 0x000);
+ usleep(10);
+ MIPI_OUTP((pdata->dsi_base) + 0x0220, 0x007);
+ wmb();
+
+ /* MMSS_DSI_0_PHY_DSIPHY_CTRL_0 */
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x07e);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x06e);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x06c);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x064);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x065);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x075);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x077);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x07f);
+ wmb();
+
+ } else {
+ MIPI_OUTP((pdata->dsi_base) + 0x0220, 0x006);
+ usleep(10);
+ MIPI_OUTP((pdata->dsi_base) + 0x0470, 0x000);
+ wmb();
+ }
+}
+
+void mdss_dsi_phy_init(struct mdss_panel_data *pdata)
+{
+ struct mdss_dsi_phy_ctrl *pd;
+ int i, off, ln, offset;
+
+ pd = (pdata->panel_info.mipi).dsi_phy_db;
+
+ off = 0x0580; /* phy regulator ctrl settings */
+ for (i = 0; i < 8; i++) {
+ MIPI_OUTP((pdata->dsi_base) + off, pd->regulator[i]);
+ wmb();
+ off += 4;
+ }
+
+ off = 0x0440; /* phy timing ctrl 0 - 11 */
+ for (i = 0; i < 12; i++) {
+ MIPI_OUTP((pdata->dsi_base) + off, pd->timing[i]);
+ wmb();
+ off += 4;
+ }
+
+ /* Strength ctrl 0 - 1 */
+ MIPI_OUTP((pdata->dsi_base) + 0x0484, pd->strength[0]);
+ MIPI_OUTP((pdata->dsi_base) + 0x0488, pd->strength[1]);
+ wmb();
+
+ off = 0x04b4; /* phy BIST ctrl 0 - 5 */
+ for (i = 0; i < 6; i++) {
+ MIPI_OUTP((pdata->dsi_base) + off, pd->bistCtrl[i]);
+ wmb();
+ off += 4;
+ }
+
+ /* 4 lanes + clk lane configuration */
+ /* lane config n * (0 - 4) & DataPath setup */
+ for (ln = 0; ln < 5; ln++) {
+ off = 0x0300 + (ln * 0x40);
+ for (i = 0; i < 9; i++) {
+ offset = i + (ln * 9);
+ MIPI_OUTP((pdata->dsi_base) + off, pd->laneCfg[offset]);
+ wmb();
+ off += 4;
+ }
+ }
+}
diff --git a/drivers/video/msm/mhl/mhl_8334.c b/drivers/video/msm/mhl/mhl_8334.c
index 646dd29..4347dc7 100644
--- a/drivers/video/msm/mhl/mhl_8334.c
+++ b/drivers/video/msm/mhl/mhl_8334.c
@@ -224,12 +224,6 @@
return 0;
}
-bool mhl_is_connected(void)
-{
- return true;
-}
-
-
/* USB_HANDSHAKING FUNCTIONS */
int mhl_device_discovery(const char *name, int *result)
@@ -547,6 +541,11 @@
pr_debug("MHL: mhl_msm_state->mhl_data->irq=[%d]\n",
mhl_msm_state->mhl_data->irq);
+ if (!mhl_msm_state->mhl_data->mhl_enabled) {
+ pr_info("MHL Display not enabled\n");
+ return -ENODEV;
+ }
+
/* Init GPIO stuff here */
ret = mhl_sii_gpio_setup(1);
if (ret == -1) {
diff --git a/drivers/video/msm/mhl_api.h b/drivers/video/msm/mhl_api.h
index a4364ea..7fdbaa9 100644
--- a/drivers/video/msm/mhl_api.h
+++ b/drivers/video/msm/mhl_api.h
@@ -15,9 +15,9 @@
#define __MHL_API_H__
#ifdef CONFIG_FB_MSM_HDMI_MHL_8334
-bool mhl_is_connected(void);
+bool mhl_is_enabled(void);
#else
-static bool mhl_is_connected(void)
+static bool mhl_is_enabled(void)
{
return false;
}
diff --git a/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h b/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
index 9619527..0d5d058 100644
--- a/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
+++ b/include/linux/mfd/wcd9xxx/wcd9xxx-slimslave.h
@@ -116,4 +116,6 @@
unsigned int *rx_ch,
unsigned int *tx_ch);
int wcd9xxx_get_slave_port(unsigned int ch_num);
+int wcd9xxx_disconnect_port(struct wcd9xxx *wcd9xxx, unsigned int *ch_num,
+ unsigned int tot_ch, unsigned int rx_tx);
#endif /* __WCD9310_SLIMSLAVE_H_ */
diff --git a/include/linux/usb/msm_hsusb_hw.h b/include/linux/usb/msm_hsusb_hw.h
index 516f764..a040d49 100644
--- a/include/linux/usb/msm_hsusb_hw.h
+++ b/include/linux/usb/msm_hsusb_hw.h
@@ -29,6 +29,7 @@
#define USBCMD_RESET 2
#define USB_USBINTR (MSM_USB_BASE + 0x0148)
+#define USB_FRINDEX (MSM_USB_BASE + 0x014C)
#define PORTSC_PHCD (1 << 23) /* phy suspend mode */
#define PORTSC_PTS_MASK (3 << 30)
diff --git a/include/media/videobuf2-msm-mem.h b/include/media/videobuf2-msm-mem.h
index 84e2bea..5285997 100644
--- a/include/media/videobuf2-msm-mem.h
+++ b/include/media/videobuf2-msm-mem.h
@@ -72,9 +72,10 @@
struct videobuf2_msm_offset *offset,
enum videobuf2_buffer_type,
uint32_t addr_offset, int path,
- struct ion_client *client);
+ struct ion_client *client,
+ int domain_num);
void videobuf2_pmem_contig_user_put(struct videobuf2_contig_pmem *mem,
- struct ion_client *client);
+ struct ion_client *client, int domain_num);
unsigned long videobuf2_to_pmem_contig(struct vb2_buffer *buf,
unsigned int plane_no);
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 4758829..9881640 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -4472,8 +4472,8 @@
pr_err("%s: Slim close tx/rx wait timeout\n",
__func__);
ret = -EINVAL;
- }
- ret = 0;
+ } else
+ ret = 0;
break;
}
return ret;
@@ -4486,7 +4486,7 @@
struct snd_soc_codec *codec = w->codec;
struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
u32 j = 0;
- u32 ret = 0;
+ int ret = 0;
codec->control_data = dev_get_drvdata(codec->dev->parent);
tabla = codec->control_data;
@@ -4543,13 +4543,22 @@
ret = wcd9xxx_close_slim_sch_rx(tabla,
tabla_p->dai[j].ch_num,
tabla_p->dai[j].ch_tot);
- tabla_p->dai[j].rate = 0;
- memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
- tabla_p->dai[j].ch_tot));
- tabla_p->dai[j].ch_tot = 0;
ret = tabla_codec_enable_chmask(tabla_p,
SND_SOC_DAPM_POST_PMD,
j);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot,
+ 1);
+ pr_info("%s: Disconnect RX port ret = %d\n",
+ __func__, ret);
+ }
+ tabla_p->dai[j].rate = 0;
+ memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
+ tabla_p->dai[j].ch_tot));
+ tabla_p->dai[j].ch_tot = 0;
+
if ((tabla != NULL) &&
(tabla->dev != NULL) &&
(tabla->dev->parent != NULL)) {
@@ -4569,7 +4578,7 @@
struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
/* index to the DAI ID, for now hardcoding */
u32 j = 0;
- u32 ret = 0;
+ int ret = 0;
codec->control_data = dev_get_drvdata(codec->dev->parent);
tabla = codec->control_data;
@@ -4626,13 +4635,21 @@
ret = wcd9xxx_close_slim_sch_tx(tabla,
tabla_p->dai[j].ch_num,
tabla_p->dai[j].ch_tot);
+ ret = tabla_codec_enable_chmask(tabla_p,
+ SND_SOC_DAPM_POST_PMD,
+ j);
+ if (ret < 0) {
+ ret = wcd9xxx_disconnect_port(tabla,
+ tabla_p->dai[j].ch_num,
+ tabla_p->dai[j].ch_tot, 0);
+ pr_info("%s: Disconnect TX port, ret = %d\n",
+ __func__, ret);
+ }
+
tabla_p->dai[j].rate = 0;
memset(tabla_p->dai[j].ch_num, 0, (sizeof(u32)*
tabla_p->dai[j].ch_tot));
tabla_p->dai[j].ch_tot = 0;
- ret = tabla_codec_enable_chmask(tabla_p,
- SND_SOC_DAPM_POST_PMD,
- j);
if ((tabla != NULL) &&
(tabla->dev != NULL) &&
(tabla->dev->parent != NULL)) {
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index f5bbf56..7c5bba8 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -627,7 +627,7 @@
#undef S
#define S(X, Y) ((TABLA_MBHC_CAL_PLUG_TYPE_PTR(tabla_cal)->X) = (Y))
S(v_no_mic, 30);
- S(v_hs_max, 1550);
+ S(v_hs_max, 2400);
#undef S
#define S(X, Y) ((TABLA_MBHC_CAL_BTN_DET_PTR(tabla_cal)->X) = (Y))
S(c[0], 62);
@@ -645,24 +645,24 @@
btn_low = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_LOW);
btn_high = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_V_BTN_HIGH);
btn_low[0] = -50;
- btn_high[0] = 10;
- btn_low[1] = 11;
- btn_high[1] = 38;
- btn_low[2] = 39;
- btn_high[2] = 64;
- btn_low[3] = 65;
- btn_high[3] = 91;
- btn_low[4] = 92;
- btn_high[4] = 115;
- btn_low[5] = 116;
- btn_high[5] = 141;
- btn_low[6] = 142;
- btn_high[6] = 163;
- btn_low[7] = 164;
- btn_high[7] = 250;
+ btn_high[0] = 20;
+ btn_low[1] = 21;
+ btn_high[1] = 62;
+ btn_low[2] = 62;
+ btn_high[2] = 104;
+ btn_low[3] = 105;
+ btn_high[3] = 143;
+ btn_low[4] = 144;
+ btn_high[4] = 181;
+ btn_low[5] = 182;
+ btn_high[5] = 218;
+ btn_low[6] = 219;
+ btn_high[6] = 254;
+ btn_low[7] = 255;
+ btn_high[7] = 330;
n_ready = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_READY);
- n_ready[0] = 48;
- n_ready[1] = 38;
+ n_ready[0] = 80;
+ n_ready[1] = 68;
n_cic = tabla_mbhc_cal_btn_det_mp(btn_cfg, TABLA_BTN_DET_N_CIC);
n_cic[0] = 60;
n_cic[1] = 47;
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 1dbd698..42bc979 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -548,7 +548,6 @@
}
prtd = &compr->prtd;
prtd->substream = substream;
- prtd->audio_client->perf_mode = false;
prtd->audio_client = q6asm_audio_client_alloc(
(app_cb)compr_event_handler, compr);
if (!prtd->audio_client) {
@@ -556,7 +555,7 @@
kfree(prtd);
return -ENOMEM;
}
-
+ prtd->audio_client->perf_mode = false;
pr_info("%s: session ID %d\n", __func__, prtd->audio_client->session);
prtd->session_id = prtd->audio_client->session;
diff --git a/sound/soc/msm/msm-multi-ch-pcm-q6.c b/sound/soc/msm/msm-multi-ch-pcm-q6.c
index 2d23b48..a13d4da 100644
--- a/sound/soc/msm/msm-multi-ch-pcm-q6.c
+++ b/sound/soc/msm/msm-multi-ch-pcm-q6.c
@@ -330,7 +330,6 @@
return -ENOMEM;
}
prtd->substream = substream;
- prtd->audio_client->perf_mode = false;
prtd->audio_client = q6asm_audio_client_alloc(
(app_cb)event_handler, prtd);
if (!prtd->audio_client) {
@@ -338,6 +337,7 @@
kfree(prtd);
return -ENOMEM;
}
+ prtd->audio_client->perf_mode = false;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
runtime->hw = msm_pcm_hardware_playback;
ret = q6asm_open_write(prtd->audio_client,
diff --git a/sound/soc/msm/msm-pcm-lpa.c b/sound/soc/msm/msm-pcm-lpa.c
index 116ce3e..ff0fb3b 100644
--- a/sound/soc/msm/msm-pcm-lpa.c
+++ b/sound/soc/msm/msm-pcm-lpa.c
@@ -282,7 +282,6 @@
}
runtime->hw = msm_pcm_hardware;
prtd->substream = substream;
- prtd->audio_client->perf_mode = false;
prtd->audio_client = q6asm_audio_client_alloc(
(app_cb)event_handler, prtd);
if (!prtd->audio_client) {
@@ -290,6 +289,7 @@
kfree(prtd);
return -ENOMEM;
}
+ prtd->audio_client->perf_mode = false;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
ret = q6asm_open_write(prtd->audio_client, FORMAT_LINEAR_PCM);
if (ret < 0) {
diff --git a/sound/soc/msm/msm8960.c b/sound/soc/msm/msm8960.c
index 040bbe0..a1be978 100644
--- a/sound/soc/msm/msm8960.c
+++ b/sound/soc/msm/msm8960.c
@@ -1754,11 +1754,18 @@
return ret;
}
- if (msm8960_configure_headset_mic_gpios()) {
- pr_err("%s Fail to configure headset mic gpios\n", __func__);
+ if (cpu_is_msm8960()) {
+ if (msm8960_configure_headset_mic_gpios()) {
+ pr_err("%s Fail to configure headset mic gpios\n",
+ __func__);
+ msm8960_headset_gpios_configured = 0;
+ } else
+ msm8960_headset_gpios_configured = 1;
+ } else {
msm8960_headset_gpios_configured = 0;
- } else
- msm8960_headset_gpios_configured = 1;
+ pr_debug("%s headset GPIO 23 and 35 not configured msm960ab",
+ __func__);
+ }
mutex_init(&cdc_mclk_mutex);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 4522d15..79016b5 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3231,6 +3231,7 @@
card->instantiated = 0;
mutex_init(&card->mutex);
mutex_init(&card->dpcm_mutex);
+ mutex_init(&card->dapm_power_mutex);
mutex_lock(&client_mutex);
list_add(&card->list, &card_list);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 729142f..5ac643416 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1290,7 +1290,7 @@
/* Do we need to apply any queued changes? */
if (sort[w->id] != cur_sort || w->reg != cur_reg ||
w->dapm != cur_dapm || w->subseq != cur_subseq) {
- if (!list_empty(&pending))
+ if (cur_dapm && !list_empty(&pending))
dapm_seq_run_coalesced(cur_dapm, &pending);
if (cur_dapm && cur_dapm->seq_notifier) {
@@ -1350,7 +1350,7 @@
"Failed to apply widget power: %d\n", ret);
}
- if (!list_empty(&pending))
+ if (cur_dapm && !list_empty(&pending))
dapm_seq_run_coalesced(cur_dapm, &pending);
if (cur_dapm && cur_dapm->seq_notifier) {
@@ -1567,6 +1567,8 @@
trace_snd_soc_dapm_start(card);
+ mutex_lock(&card->dapm_power_mutex);
+
list_for_each_entry(d, &card->dapm_list, list) {
if (d->n_widgets || d->codec == NULL) {
if (d->idle_bias_off)
@@ -1682,6 +1684,8 @@
"DAPM sequencing finished, waiting %dms\n", card->pop_time);
pop_wait(card->pop_time);
+ mutex_unlock(&card->dapm_power_mutex);
+
trace_snd_soc_dapm_done(card);
return 0;
@@ -3092,9 +3096,9 @@
if (stream == NULL)
return 0;
- //mutex_lock(&codec->mutex);
+ mutex_lock(&codec->mutex);
soc_dapm_stream_event(&codec->dapm, stream, event);
- //mutex_unlock(&codec->mutex);
+ mutex_unlock(&codec->mutex);
return 0;
}