summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts8
-rw-r--r--arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts1
-rw-r--r--arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi1
-rw-r--r--arch/arm/boot/dts/qcom/msm8996.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/msm8996pro-auto-adp-lite.dts8
-rw-r--r--arch/arm/boot/dts/qcom/msm8998-qrd-overlay.dts1
-rw-r--r--arch/arm/boot/dts/qcom/sda630-pm660a-qrd-hdk.dts13
-rw-r--r--arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts10
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-pm.dtsi2
-rw-r--r--arch/arm/boot/dts/qcom/sdm660-regulator.dtsi4
-rw-r--r--arch/arm/boot/dts/qcom/sdm660.dtsi12
-rw-r--r--arch/arm/kernel/stacktrace.c1
-rw-r--r--arch/arm64/kernel/stacktrace.c1
-rw-r--r--drivers/base/firmware_class.c3
-rw-r--r--drivers/bluetooth/btfm_slim_wcn3990.c6
-rw-r--r--drivers/cpuidle/lpm-levels.c6
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c111
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h11
-rw-r--r--drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h3
-rw-r--r--drivers/gpu/drm/msm/msm_drv.h10
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.c152
-rw-r--r--drivers/gpu/drm/msm/sde/sde_connector.h24
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.c9
-rw-r--r--drivers/gpu/drm/msm/sde/sde_formats.c263
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog.c171
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog.h16
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_catalog_format.h57
-rw-r--r--drivers/gpu/drm/msm/sde/sde_hw_mdss.h17
-rw-r--r--drivers/gpu/drm/msm/sde/sde_kms.c1
-rw-r--r--drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c31
-rw-r--r--drivers/media/platform/msm/ais/msm.c88
-rw-r--r--drivers/media/platform/msm/ais/msm.h5
-rw-r--r--drivers/media/platform/msm/ais/msm_vb2/msm_vb2.c143
-rw-r--r--drivers/media/platform/msm/ais/msm_vb2/msm_vb2.h1
-rw-r--r--drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c2
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c12
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c8
-rw-r--r--drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c4
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c21
-rw-r--r--drivers/net/wireless/cnss/cnss_pci.c62
-rw-r--r--drivers/perf/arm_pmu.c1
-rw-r--r--drivers/platform/msm/gsi/gsi.c29
-rw-r--r--drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c4
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_client.c17
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c18
-rw-r--r--drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c3
-rw-r--r--drivers/power/reset/msm-poweroff.c17
-rw-r--r--drivers/power/supply/qcom/qpnp-smb2.c27
-rw-r--r--drivers/soc/qcom/glink_smem_native_xprt.c2
-rw-r--r--drivers/soc/qcom/msm_glink_pkt.c31
-rw-r--r--drivers/soc/qcom/wcd-dsp-glink.c58
-rw-r--r--fs/mbcache.c15
-rw-r--r--include/linux/ipc_router.h1
-rw-r--r--include/linux/msm_gsi.h18
-rw-r--r--include/uapi/drm/drm_fourcc.h17
-rw-r--r--include/uapi/drm/msm_drm.h35
-rw-r--r--kernel/events/core.c39
-rw-r--r--kernel/events/hw_breakpoint.c2
-rw-r--r--net/ipc_router/ipc_router_core.c17
59 files changed, 1388 insertions, 264 deletions
diff --git a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts
index fee184663336..9f8d432a3112 100644
--- a/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts
+++ b/arch/arm/boot/dts/qcom/apq8096pro-v1.1-auto-adp-lite.dts
@@ -46,6 +46,14 @@
status = "disabled";
};
};
+
+ qcom,adv7481@70 {
+ status = "disabled";
+ };
+
+ qcom,msm-ba {
+ status = "disabled";
+ };
};
&dsi_adv_7533_2 {
diff --git a/arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts b/arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts
index 022841b5e769..bd29c0307576 100644
--- a/arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts
+++ b/arch/arm/boot/dts/qcom/apq8098-v2.1-mediabox.dts
@@ -90,6 +90,7 @@
&snd_9335 {
qcom,msm-mi2s-master = <1>, <1>, <1>, <0>;
+ qcom,msm-mbhc-hphl-swh = <1>;
};
&wcd_usbc_analog_en1_gpio {
diff --git a/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi b/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi
index da28e56bc2df..e4e488597efd 100644
--- a/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi
+++ b/arch/arm/boot/dts/qcom/msm-arm-smmu-8998.dtsi
@@ -155,6 +155,7 @@
interrupts = <GIC_SPI 329 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 330 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 331 IRQ_TYPE_EDGE_RISING>;
+ qcom,deferred-regulator-disable-delay = <80>;
vdd-supply = <&gdsc_gpu_cx>;
clocks = <&clock_gcc clk_gcc_gpu_cfg_ahb_clk>,
<&clock_gcc clk_gcc_bimc_gfx_clk>,
diff --git a/arch/arm/boot/dts/qcom/msm8996.dtsi b/arch/arm/boot/dts/qcom/msm8996.dtsi
index 7c3f035a841b..80b3437beac6 100644
--- a/arch/arm/boot/dts/qcom/msm8996.dtsi
+++ b/arch/arm/boot/dts/qcom/msm8996.dtsi
@@ -1064,6 +1064,7 @@
qcom,pm-qos-irq-cpu = <0>;
qcom,pm-qos-irq-latency = <70 70>;
+ non-removable;
status = "disabled";
};
@@ -1268,6 +1269,7 @@
qcom,pm-qos-cpu-group-latency-us = <70 70>;
qcom,pm-qos-default-cpu = <0>;
+ non-removable;
status = "disabled";
};
diff --git a/arch/arm/boot/dts/qcom/msm8996pro-auto-adp-lite.dts b/arch/arm/boot/dts/qcom/msm8996pro-auto-adp-lite.dts
index 1cf61486c9e8..48d5cb78611b 100644
--- a/arch/arm/boot/dts/qcom/msm8996pro-auto-adp-lite.dts
+++ b/arch/arm/boot/dts/qcom/msm8996pro-auto-adp-lite.dts
@@ -46,6 +46,14 @@
status = "disabled";
};
};
+
+ qcom,adv7481@70 {
+ status = "disabled";
+ };
+
+ qcom,msm-ba {
+ status = "disabled";
+ };
};
&pil_modem {
diff --git a/arch/arm/boot/dts/qcom/msm8998-qrd-overlay.dts b/arch/arm/boot/dts/qcom/msm8998-qrd-overlay.dts
index 55255261a827..ce1c62d9c2ae 100644
--- a/arch/arm/boot/dts/qcom/msm8998-qrd-overlay.dts
+++ b/arch/arm/boot/dts/qcom/msm8998-qrd-overlay.dts
@@ -17,6 +17,7 @@
#include <dt-bindings/clock/msm-clocks-8998.h>
#include <dt-bindings/interrupt-controller/irq.h>
+#include "msm8998-mdss-panels.dtsi"
#include "msm8998-qrd.dtsi"
/ {
diff --git a/arch/arm/boot/dts/qcom/sda630-pm660a-qrd-hdk.dts b/arch/arm/boot/dts/qcom/sda630-pm660a-qrd-hdk.dts
index 227a8999a745..4c4c758daa29 100644
--- a/arch/arm/boot/dts/qcom/sda630-pm660a-qrd-hdk.dts
+++ b/arch/arm/boot/dts/qcom/sda630-pm660a-qrd-hdk.dts
@@ -60,6 +60,19 @@
/delete-node/ &tasha_hph_en0;
/delete-node/ &tasha_hph_en1;
+&qusb_phy0 {
+ qcom,qusb-phy-init-seq = <0xf8 0x80
+ 0xb3 0x84
+ 0x83 0x88
+ 0xc7 0x8c
+ 0x30 0x08
+ 0x79 0x0c
+ 0x21 0x10
+ 0x14 0x9c
+ 0x9f 0x1c
+ 0x00 0x18>;
+};
+
&tasha_snd {
qcom,model = "sdm660-tasha-skus-snd-card";
qcom,audio-routing =
diff --git a/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts b/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts
index 7fb0c9d03825..604823ff416e 100644
--- a/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts
+++ b/arch/arm/boot/dts/qcom/sda660-pm660a-qrd-hdk.dts
@@ -218,4 +218,14 @@
<0x00188018 0x4>;
reg-names = "qusb_phy_base",
"ref_clk_addr";
+ qcom,qusb-phy-init-seq = <0xf8 0x80
+ 0xb3 0x84
+ 0x83 0x88
+ 0xc7 0x8c
+ 0x30 0x08
+ 0x79 0x0c
+ 0x21 0x10
+ 0x14 0x9c
+ 0x9f 0x1c
+ 0x00 0x18>;
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-pm.dtsi b/arch/arm/boot/dts/qcom/sdm660-pm.dtsi
index 21fab4923331..cdf1e47665fb 100644
--- a/arch/arm/boot/dts/qcom/sdm660-pm.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-pm.dtsi
@@ -39,7 +39,7 @@
qcom,vctl-timeout-us = <500>;
qcom,vctl-port = <0x0>;
qcom,phase-port = <0x1>;
- qcom,saw2-avs-ctl = <0x1010031>;
+ qcom,saw2-avs-ctl = <0x101c031>;
qcom,saw2-avs-limit = <0x4580458>;
qcom,pfm-port = <0x2>;
};
diff --git a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
index 66bea3050586..a4111f6d1b94 100644
--- a/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660-regulator.dtsi
@@ -744,8 +744,8 @@
< (-4000) 4000 7000 19000 (-8000)>;
qcom,cpr-closed-loop-voltage-fuse-adjustment =
- <(-32000) (-30000) (-29000) (-23000)
- (-21000)>;
+ <(-32000) (-30000) (-29000) (-38000)
+ (-36000)>;
qcom,cpr-floor-to-ceiling-max-range =
<32000 32000 32000 40000 44000
diff --git a/arch/arm/boot/dts/qcom/sdm660.dtsi b/arch/arm/boot/dts/qcom/sdm660.dtsi
index b3c2f3c634c6..d1e4cc2b192a 100644
--- a/arch/arm/boot/dts/qcom/sdm660.dtsi
+++ b/arch/arm/boot/dts/qcom/sdm660.dtsi
@@ -1232,9 +1232,17 @@
compatible = "qcom,clk-cpu-osm";
reg = <0x179c0000 0x4000>, <0x17916000 0x1000>,
<0x17816000 0x1000>, <0x179d1000 0x1000>,
- <0x00784130 0x8>;
+ <0x00784130 0x8>, <0x17914800 0x800>;
reg-names = "osm", "pwrcl_pll", "perfcl_pll",
- "apcs_common", "perfcl_efuse";
+ "apcs_common", "perfcl_efuse",
+ "pwrcl_acd";
+
+ qcom,acdtd-val = <0x0000a111 0x0000a111>;
+ qcom,acdcr-val = <0x002c5ffd 0x002c5ffd>;
+ qcom,acdsscr-val = <0x00000901 0x00000901>;
+ qcom,acdextint0-val = <0x2cf9ae8 0x2cf9ae8>;
+ qcom,acdextint1-val = <0x2cf9afe 0x2cf9afe>;
+ qcom,acdautoxfer-val = <0x00000015 0x00000015>;
vdd-pwrcl-supply = <&apc0_pwrcl_vreg>;
vdd-perfcl-supply = <&apc1_perfcl_vreg>;
diff --git a/arch/arm/kernel/stacktrace.c b/arch/arm/kernel/stacktrace.c
index 5964c77c593d..a1898c6092d1 100644
--- a/arch/arm/kernel/stacktrace.c
+++ b/arch/arm/kernel/stacktrace.c
@@ -175,6 +175,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
__save_stack_trace(tsk, trace, 1);
}
+EXPORT_SYMBOL(save_stack_trace_tsk);
void save_stack_trace(struct stack_trace *trace)
{
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index cb3eec8e8e50..1fd1a9a6596f 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -184,6 +184,7 @@ void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
if (trace->nr_entries < trace->max_entries)
trace->entries[trace->nr_entries++] = ULONG_MAX;
}
+EXPORT_SYMBOL(save_stack_trace_tsk);
void save_stack_trace(struct stack_trace *trace)
{
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 68561696f31b..a1696e1d199f 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -311,7 +311,8 @@ static const char * const fw_path[] = {
"/lib/firmware/updates/" UTS_RELEASE,
"/lib/firmware/updates",
"/lib/firmware/" UTS_RELEASE,
- "/lib/firmware"
+ "/lib/firmware",
+ "/lib64/firmware"
};
/*
diff --git a/drivers/bluetooth/btfm_slim_wcn3990.c b/drivers/bluetooth/btfm_slim_wcn3990.c
index 77e2973e023c..0c4e0b3d5c2e 100644
--- a/drivers/bluetooth/btfm_slim_wcn3990.c
+++ b/drivers/bluetooth/btfm_slim_wcn3990.c
@@ -88,12 +88,12 @@ int btfm_slim_chrk_enable_port(struct btfmslim *btfmslim, uint8_t port_num,
BTFMSLIM_DBG("port(%d) enable(%d)", port_num, enable);
if (rxport) {
- if (enable && btfmslim->sample_rate == 48000) {
- /* For A2DP Rx */
+ if (enable) {
+ /* For SCO Rx, A2DP Rx */
reg_val = 0x1;
port_bit = port_num - 0x10;
reg = CHRK_SB_PGD_RX_PORTn_MULTI_CHNL_0(port_bit);
- BTFMSLIM_DBG("writing reg_val (%d) to reg(%x) for A2DP",
+ BTFMSLIM_DBG("writing reg_val (%d) to reg(%x)",
reg_val, reg);
ret = btfm_slim_write(btfmslim, reg, 1, &reg_val, IFD);
if (ret) {
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index b69e59eeeae1..7cd1bbbe1ee8 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -1119,10 +1119,14 @@ static int cluster_configure(struct lpm_cluster *cluster, int idx,
bool from_idle, int predicted)
{
struct lpm_cluster_level *level = &cluster->levels[idx];
+ struct cpumask online_cpus;
int ret, i;
+ cpumask_and(&online_cpus, &cluster->num_children_in_sync,
+ cpu_online_mask);
+
if (!cpumask_equal(&cluster->num_children_in_sync, &cluster->child_cpus)
- || is_IPI_pending(&cluster->num_children_in_sync)) {
+ || is_IPI_pending(&online_cpus)) {
return -EPERM;
}
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
index d0c3deefabd7..2ee75a2c1039 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.c
@@ -1867,6 +1867,106 @@ int sde_hdmi_get_info(struct msm_display_info *info,
return rc;
}
+static void sde_hdmi_panel_set_hdr_infoframe(struct sde_hdmi *display,
+struct drm_msm_ext_panel_hdr_metadata *hdr_meta)
+{
+ u32 packet_payload = 0;
+ u32 packet_header = 0;
+ u32 packet_control = 0;
+ u32 const type_code = 0x87;
+ u32 const version = 0x01;
+ u32 const length = 0x1a;
+ u32 const descriptor_id = 0x00;
+ struct hdmi *hdmi;
+ struct drm_connector *connector;
+
+ if (!display || !hdr_meta) {
+ SDE_ERROR("invalid input\n");
+ return;
+ }
+
+ hdmi = display->ctrl.ctrl;
+ connector = display->ctrl.ctrl->connector;
+
+ if (!hdmi || !connector) {
+ SDE_ERROR("invalid input\n");
+ return;
+ }
+
+ if (!connector->hdr_supported) {
+ SDE_ERROR("Sink does not support HDR\n");
+ return;
+ }
+
+ /* Setup Packet header and payload */
+ packet_header = type_code | (version << 8) | (length << 16);
+ hdmi_write(hdmi, HDMI_GENERIC0_HDR, packet_header);
+
+ packet_payload = (hdr_meta->eotf << 8);
+ if (connector->hdr_metadata_type_one) {
+ packet_payload |= (descriptor_id << 16)
+ | (HDMI_GET_LSB(hdr_meta->display_primaries_x[0])
+ << 24);
+ hdmi_write(hdmi, HDMI_GENERIC0_0, packet_payload);
+ } else {
+ pr_debug("Metadata Type 1 not supported\n");
+ hdmi_write(hdmi, HDMI_GENERIC0_0, packet_payload);
+ goto enable_packet_control;
+ }
+
+ packet_payload =
+ (HDMI_GET_MSB(hdr_meta->display_primaries_x[0]))
+ | (HDMI_GET_LSB(hdr_meta->display_primaries_y[0]) << 8)
+ | (HDMI_GET_MSB(hdr_meta->display_primaries_y[0]) << 16)
+ | (HDMI_GET_LSB(hdr_meta->display_primaries_x[1]) << 24);
+ hdmi_write(hdmi, HDMI_GENERIC0_1, packet_payload);
+
+ packet_payload =
+ (HDMI_GET_MSB(hdr_meta->display_primaries_x[1]))
+ | (HDMI_GET_LSB(hdr_meta->display_primaries_y[1]) << 8)
+ | (HDMI_GET_MSB(hdr_meta->display_primaries_y[1]) << 16)
+ | (HDMI_GET_LSB(hdr_meta->display_primaries_x[2]) << 24);
+ hdmi_write(hdmi, HDMI_GENERIC0_2, packet_payload);
+
+ packet_payload =
+ (HDMI_GET_MSB(hdr_meta->display_primaries_x[2]))
+ | (HDMI_GET_LSB(hdr_meta->display_primaries_y[2]) << 8)
+ | (HDMI_GET_MSB(hdr_meta->display_primaries_y[2]) << 16)
+ | (HDMI_GET_LSB(hdr_meta->white_point_x) << 24);
+ hdmi_write(hdmi, HDMI_GENERIC0_3, packet_payload);
+
+ packet_payload =
+ (HDMI_GET_MSB(hdr_meta->white_point_x))
+ | (HDMI_GET_LSB(hdr_meta->white_point_y) << 8)
+ | (HDMI_GET_MSB(hdr_meta->white_point_y) << 16)
+ | (HDMI_GET_LSB(hdr_meta->max_luminance) << 24);
+ hdmi_write(hdmi, HDMI_GENERIC0_4, packet_payload);
+
+ packet_payload =
+ (HDMI_GET_MSB(hdr_meta->max_luminance))
+ | (HDMI_GET_LSB(hdr_meta->min_luminance) << 8)
+ | (HDMI_GET_MSB(hdr_meta->min_luminance) << 16)
+ | (HDMI_GET_LSB(hdr_meta->max_content_light_level) << 24);
+ hdmi_write(hdmi, HDMI_GENERIC0_5, packet_payload);
+
+ packet_payload =
+ (HDMI_GET_MSB(hdr_meta->max_content_light_level))
+ | (HDMI_GET_LSB(hdr_meta->max_average_light_level) << 8)
+ | (HDMI_GET_MSB(hdr_meta->max_average_light_level) << 16);
+ hdmi_write(hdmi, HDMI_GENERIC0_6, packet_payload);
+
+enable_packet_control:
+ /*
+ * GENERIC0_LINE | GENERIC0_CONT | GENERIC0_SEND
+ * Setup HDMI TX generic packet control
+ * Enable this packet to transmit every frame
+ * Enable HDMI TX engine to transmit Generic packet 1
+ */
+ packet_control = hdmi_read(hdmi, HDMI_GEN_PKT_CTRL);
+ packet_control |= BIT(0) | BIT(1) | BIT(2) | BIT(16);
+ hdmi_write(hdmi, HDMI_GEN_PKT_CTRL, packet_control);
+}
+
int sde_hdmi_set_property(struct drm_connector *connector,
struct drm_connector_state *state,
int property_index,
@@ -2203,6 +2303,17 @@ sde_hdmi_connector_detect(struct drm_connector *connector,
return status;
}
+int sde_hdmi_pre_kickoff(struct drm_connector *connector,
+ void *display,
+ struct msm_display_kickoff_params *params)
+{
+
+ sde_hdmi_panel_set_hdr_infoframe(display,
+ params->hdr_metadata);
+
+ return 0;
+}
+
int sde_hdmi_connector_get_modes(struct drm_connector *connector, void *display)
{
struct sde_hdmi *hdmi_display = (struct sde_hdmi *)display;
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
index 47f440d617a3..6b9bcfec031b 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi.h
@@ -452,6 +452,17 @@ bool sde_hdmi_tx_is_panel_on(struct sde_hdmi *hdmi_ctrl);
int sde_hdmi_start_hdcp(struct drm_connector *connector);
void sde_hdmi_hdcp_off(struct sde_hdmi *hdmi_ctrl);
+
+/*
+ * sde_hdmi_pre_kickoff - program kickoff-time features
+ * @display: Pointer to private display structure
+ * @params: Parameters for kickoff-time programming
+ * Returns: Zero on success
+ */
+int sde_hdmi_pre_kickoff(struct drm_connector *connector,
+ void *display,
+ struct msm_display_kickoff_params *params);
+
#else /*#ifdef CONFIG_DRM_SDE_HDMI*/
static inline u32 sde_hdmi_get_num_of_displays(void)
diff --git a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
index 6b310acee0ff..8b69dd31f637 100644
--- a/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
+++ b/drivers/gpu/drm/msm/hdmi-staging/sde_hdmi_util.h
@@ -94,6 +94,9 @@
/* default hsyncs for 4k@60 for 200ms */
#define HDMI_DEFAULT_TIMEOUT_HSYNC 28571
+#define HDMI_GET_MSB(x)(x >> 8)
+#define HDMI_GET_LSB(x)(x & 0xff)
+
/*
* Bits 1:0 in HDMI_HW_DDC_CTRL that dictate how the HDCP 2.2 RxStatus will be
* read by the hardware
diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
index f85938f8a034..d696f05e0459 100644
--- a/drivers/gpu/drm/msm/msm_drv.h
+++ b/drivers/gpu/drm/msm/msm_drv.h
@@ -143,6 +143,8 @@ enum msm_mdp_crtc_property {
enum msm_mdp_conn_property {
/* blob properties, always put these first */
CONNECTOR_PROP_SDE_INFO,
+ CONNECTOR_PROP_HDR_INFO,
+ CONNECTOR_PROP_HDR_METADATA,
/* # of blob properties */
CONNECTOR_PROP_BLOBCOUNT,
@@ -234,6 +236,14 @@ struct msm_display_info {
};
/**
+ * struct - msm_display_kickoff_params - info for display features at kickoff
+ * @hdr_metadata: HDR metadata info passed from userspace
+ */
+struct msm_display_kickoff_params {
+ struct drm_msm_ext_panel_hdr_metadata *hdr_metadata;
+};
+
+/**
* struct msm_drm_event - defines custom event notification struct
* @base: base object required for event notification by DRM framework.
* @event: event object required for event notification by DRM framework.
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index e08fe210604c..0bb8298c1013 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -17,6 +17,12 @@
#include "sde_connector.h"
#include "sde_backlight.h"
+#define SDE_DEBUG_CONN(c, fmt, ...) SDE_DEBUG("conn%d " fmt,\
+ (c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
+
+#define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\
+ (c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
+
static const struct drm_prop_enum_list e_topology_name[] = {
{SDE_RM_TOPOLOGY_UNKNOWN, "sde_unknown"},
{SDE_RM_TOPOLOGY_SINGLEPIPE, "sde_singlepipe"},
@@ -54,6 +60,36 @@ int sde_connector_get_info(struct drm_connector *connector,
return c_conn->ops.get_info(info, c_conn->display);
}
+int sde_connector_pre_kickoff(struct drm_connector *connector)
+{
+ struct sde_connector *c_conn;
+ struct sde_connector_state *c_state;
+ struct msm_display_kickoff_params params;
+ int rc;
+
+ if (!connector) {
+ SDE_ERROR("invalid argument\n");
+ return -EINVAL;
+ }
+
+ c_conn = to_sde_connector(connector);
+ c_state = to_sde_connector_state(connector->state);
+
+ if (!c_conn->display) {
+ SDE_ERROR("invalid argument\n");
+ return -EINVAL;
+ }
+
+ if (!c_conn->ops.pre_kickoff)
+ return 0;
+
+ params.hdr_metadata = &c_state->hdr_meta;
+
+ rc = c_conn->ops.pre_kickoff(connector, c_conn->display, &params);
+
+ return rc;
+}
+
static void sde_connector_destroy(struct drm_connector *connector)
{
struct sde_connector *c_conn;
@@ -70,7 +106,8 @@ static void sde_connector_destroy(struct drm_connector *connector)
if (c_conn->blob_caps)
drm_property_unreference_blob(c_conn->blob_caps);
-
+ if (c_conn->blob_hdr)
+ drm_property_unreference_blob(c_conn->blob_hdr);
msm_property_destroy(&c_conn->property_info);
drm_connector_unregister(connector);
@@ -204,6 +241,68 @@ sde_connector_atomic_duplicate_state(struct drm_connector *connector)
return &c_state->base;
}
+static int _sde_connector_set_hdr_info(
+ struct sde_connector *c_conn,
+ struct sde_connector_state *c_state,
+ void *usr_ptr)
+{
+ struct drm_connector *connector;
+ struct drm_msm_ext_panel_hdr_metadata *hdr_meta;
+ int i;
+
+ if (!c_conn || !c_state) {
+ SDE_ERROR_CONN(c_conn, "invalid args\n");
+ return -EINVAL;
+ }
+
+ connector = &c_conn->base;
+
+ if (!connector->hdr_supported) {
+ SDE_ERROR_CONN(c_conn, "sink doesn't support HDR\n");
+ return -ENOTSUPP;
+ }
+
+ memset(&c_state->hdr_meta, 0, sizeof(c_state->hdr_meta));
+
+ if (!usr_ptr) {
+ SDE_DEBUG_CONN(c_conn, "hdr metadata cleared\n");
+ return 0;
+ }
+
+ if (copy_from_user(&c_state->hdr_meta,
+ (void __user *)usr_ptr,
+ sizeof(*hdr_meta))) {
+ SDE_ERROR_CONN(c_conn, "failed to copy hdr metadata\n");
+ return -EFAULT;
+ }
+
+ hdr_meta = &c_state->hdr_meta;
+
+ SDE_DEBUG_CONN(c_conn, "hdr_supported %d\n",
+ hdr_meta->hdr_supported);
+ SDE_DEBUG_CONN(c_conn, "eotf %d\n",
+ hdr_meta->eotf);
+ SDE_DEBUG_CONN(c_conn, "white_point_x %d\n",
+ hdr_meta->white_point_x);
+ SDE_DEBUG_CONN(c_conn, "white_point_y %d\n",
+ hdr_meta->white_point_y);
+ SDE_DEBUG_CONN(c_conn, "max_luminance %d\n",
+ hdr_meta->max_luminance);
+ SDE_DEBUG_CONN(c_conn, "max_content_light_level %d\n",
+ hdr_meta->max_content_light_level);
+ SDE_DEBUG_CONN(c_conn, "max_average_light_level %d\n",
+ hdr_meta->max_average_light_level);
+
+ for (i = 0; i < HDR_PRIMARIES_COUNT; i++) {
+ SDE_DEBUG_CONN(c_conn, "display_primaries_x [%d]\n",
+ hdr_meta->display_primaries_x[i]);
+ SDE_DEBUG_CONN(c_conn, "display_primaries_y [%d]\n",
+ hdr_meta->display_primaries_y[i]);
+ }
+
+ return 0;
+}
+
static int sde_connector_atomic_set_property(struct drm_connector *connector,
struct drm_connector_state *state,
struct drm_property *property,
@@ -263,6 +362,12 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
SDE_ERROR("invalid topology_control: 0x%llX\n", val);
}
+ if (idx == CONNECTOR_PROP_HDR_METADATA) {
+ rc = _sde_connector_set_hdr_info(c_conn, c_state, (void *)val);
+ if (rc)
+ SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc);
+ }
+
/* check for custom property handling */
if (!rc && c_conn->ops.set_property) {
rc = c_conn->ops.set_property(connector,
@@ -355,6 +460,32 @@ void sde_connector_complete_commit(struct drm_connector *connector)
sde_fence_signal(&to_sde_connector(connector)->retire_fence, 0);
}
+static void sde_connector_update_hdr_props(struct drm_connector *connector)
+{
+ struct sde_connector *c_conn = to_sde_connector(connector);
+ struct drm_msm_ext_panel_hdr_properties hdr_prop = {};
+
+ hdr_prop.hdr_supported = connector->hdr_supported;
+
+ if (hdr_prop.hdr_supported) {
+ hdr_prop.hdr_eotf =
+ connector->hdr_eotf;
+ hdr_prop.hdr_metadata_type_one =
+ connector->hdr_metadata_type_one;
+ hdr_prop.hdr_max_luminance =
+ connector->hdr_max_luminance;
+ hdr_prop.hdr_avg_luminance =
+ connector->hdr_avg_luminance;
+ hdr_prop.hdr_min_luminance =
+ connector->hdr_min_luminance;
+ }
+ msm_property_set_blob(&c_conn->property_info,
+ &c_conn->blob_hdr,
+ &hdr_prop,
+ sizeof(hdr_prop),
+ CONNECTOR_PROP_HDR_INFO);
+}
+
static enum drm_connector_status
sde_connector_detect(struct drm_connector *connector, bool force)
{
@@ -392,6 +523,7 @@ static const struct drm_connector_funcs sde_connector_ops = {
static int sde_connector_get_modes(struct drm_connector *connector)
{
struct sde_connector *c_conn;
+ int ret = 0;
if (!connector) {
SDE_ERROR("invalid connector\n");
@@ -403,8 +535,11 @@ static int sde_connector_get_modes(struct drm_connector *connector)
SDE_DEBUG("missing get_modes callback\n");
return 0;
}
+ ret = c_conn->ops.get_modes(connector, c_conn->display);
+ if (ret)
+ sde_connector_update_hdr_props(connector);
- return c_conn->ops.get_modes(connector, c_conn->display);
+ return ret;
}
static enum drm_mode_status
@@ -575,6 +710,17 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
kfree(info);
}
+ if (connector_type == DRM_MODE_CONNECTOR_HDMIA) {
+ msm_property_install_blob(&c_conn->property_info,
+ "hdr_properties",
+ DRM_MODE_PROP_IMMUTABLE,
+ CONNECTOR_PROP_HDR_INFO);
+ }
+
+ msm_property_install_volatile_range(&c_conn->property_info,
+ "hdr_metadata", 0x0, 0, ~0, 0,
+ CONNECTOR_PROP_HDR_METADATA);
+
msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
@@ -612,6 +758,8 @@ struct drm_connector *sde_connector_init(struct drm_device *dev,
error_destroy_property:
if (c_conn->blob_caps)
drm_property_unreference_blob(c_conn->blob_caps);
+ if (c_conn->blob_hdr)
+ drm_property_unreference_blob(c_conn->blob_hdr);
msm_property_destroy(&c_conn->property_info);
error_unregister_conn:
drm_connector_unregister(&c_conn->base);
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 3f26ee7d5965..19e2b8a3e41c 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -122,6 +122,19 @@ struct sde_connector_ops {
int (*get_info)(struct msm_display_info *info, void *display);
int (*set_backlight)(void *display, u32 bl_lvl);
+
+
+ /**
+ * pre_kickoff - trigger display to program kickoff-time features
+ * @connector: Pointer to drm connector structure
+ * @display: Pointer to private display structure
+ * @params: Parameter bundle of connector-stored information for
+ * kickoff-time programming into the display
+ * Returns: Zero on success
+ */
+ int (*pre_kickoff)(struct drm_connector *connector,
+ void *display,
+ struct msm_display_kickoff_params *params);
};
/**
@@ -139,6 +152,7 @@ struct sde_connector_ops {
* @property_info: Private structure for generic property handling
* @property_data: Array of private data for generic property handling
* @blob_caps: Pointer to blob structure for 'capabilities' property
+ * @blob_hdr: Pointer to blob structure for 'hdr_properties' property
*/
struct sde_connector {
struct drm_connector base;
@@ -159,6 +173,7 @@ struct sde_connector {
struct msm_property_info property_info;
struct msm_property_data property_data[CONNECTOR_PROP_COUNT];
struct drm_property_blob *blob_caps;
+ struct drm_property_blob *blob_hdr;
};
/**
@@ -206,12 +221,14 @@ struct sde_connector {
* @out_fb: Pointer to output frame buffer, if applicable
* @aspace: Address space for accessing frame buffer objects, if applicable
* @property_values: Local cache of current connector property values
+ * @hdr_meta: HDR metadata info passed from userspace
*/
struct sde_connector_state {
struct drm_connector_state base;
struct drm_framebuffer *out_fb;
struct msm_gem_address_space *aspace;
uint64_t property_values[CONNECTOR_PROP_COUNT];
+ struct drm_msm_ext_panel_hdr_metadata hdr_meta;
};
/**
@@ -303,5 +320,12 @@ void sde_connector_complete_commit(struct drm_connector *connector);
int sde_connector_get_info(struct drm_connector *connector,
struct msm_display_info *info);
+/**
+ * sde_connector_pre_kickoff - trigger kickoff time feature programming
+ * @connector: Pointer to drm connector object
+ * Returns: Zero on success
+ */
+int sde_connector_pre_kickoff(struct drm_connector *connector);
+
#endif /* _SDE_CONNECTOR_H_ */
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 030b192e5df4..fa03fc8f7ac9 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -795,6 +795,7 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
struct sde_encoder_virt *sde_enc;
struct sde_encoder_phys *phys;
unsigned int i;
+ int rc;
if (!drm_enc) {
SDE_ERROR("invalid encoder\n");
@@ -811,6 +812,14 @@ void sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc)
if (phys && phys->ops.prepare_for_kickoff)
phys->ops.prepare_for_kickoff(phys);
}
+
+ if (sde_enc->cur_master && sde_enc->cur_master->connector) {
+ rc = sde_connector_pre_kickoff(sde_enc->cur_master->connector);
+ if (rc)
+ SDE_ERROR_ENC(sde_enc, "kickoff conn%d failed rc %d\n",
+ sde_enc->cur_master->connector->base.id,
+ rc);
+ }
}
void sde_encoder_kickoff(struct drm_encoder *drm_enc)
diff --git a/drivers/gpu/drm/msm/sde/sde_formats.c b/drivers/gpu/drm/msm/sde/sde_formats.c
index a59ec31ba276..49b3d8e96938 100644
--- a/drivers/gpu/drm/msm/sde/sde_formats.c
+++ b/drivers/gpu/drm/msm/sde/sde_formats.c
@@ -11,12 +11,15 @@
*/
#include <uapi/drm/drm_fourcc.h>
+#include <uapi/media/msm_media_info.h>
#include "sde_kms.h"
#include "sde_formats.h"
#define SDE_UBWC_META_MACRO_W_H 16
#define SDE_UBWC_META_BLOCK_SIZE 256
+#define SDE_UBWC_PLANE_SIZE_ALIGNMENT 4096
+
#define SDE_MAX_IMG_WIDTH 0x3FFF
#define SDE_MAX_IMG_HEIGHT 0x3FFF
@@ -42,7 +45,7 @@ bp, flg, fm, np) \
.unpack_count = uc, \
.bpp = bp, \
.fetch_mode = fm, \
- .flag = flg, \
+ .flag = {(flg)}, \
.num_planes = np \
}
@@ -60,7 +63,7 @@ alpha, chroma, count, bp, flg, fm, np) \
.unpack_count = count, \
.bpp = bp, \
.fetch_mode = fm, \
- .flag = flg, \
+ .flag = {(flg)}, \
.num_planes = np \
}
@@ -77,7 +80,24 @@ alpha, chroma, count, bp, flg, fm, np) \
.unpack_count = 2, \
.bpp = 2, \
.fetch_mode = fm, \
- .flag = flg, \
+ .flag = {(flg)}, \
+ .num_planes = np \
+}
+
+#define PSEUDO_YUV_FMT_LOOSE(fmt, a, r, g, b, e0, e1, chroma, flg, fm, np)\
+{ \
+ .base.pixel_format = DRM_FORMAT_ ## fmt, \
+ .fetch_planes = SDE_PLANE_PSEUDO_PLANAR, \
+ .alpha_enable = false, \
+ .element = { (e0), (e1), 0, 0 }, \
+ .bits = { g, b, r, a }, \
+ .chroma_sample = chroma, \
+ .unpack_align_msb = 1, \
+ .unpack_tight = 0, \
+ .unpack_count = 2, \
+ .bpp = 2, \
+ .fetch_mode = fm, \
+ .flag = {(flg)}, \
.num_planes = np \
}
@@ -95,10 +115,20 @@ flg, fm, np) \
.unpack_count = 1, \
.bpp = bp, \
.fetch_mode = fm, \
- .flag = flg, \
+ .flag = {(flg)}, \
.num_planes = np \
}
+/*
+ * struct sde_media_color_map - maps drm format to media format
+ * @format: DRM base pixel format
+ * @color: Media API color related to DRM format
+ */
+struct sde_media_color_map {
+ uint32_t format;
+ uint32_t color;
+};
+
static const struct sde_format sde_format_map[] = {
INTERLEAVED_RGB_FMT(ARGB8888,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
@@ -270,49 +300,49 @@ static const struct sde_format sde_format_map[] = {
INTERLEAVED_RGB_FMT(BGRA1010102,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
+ C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
true, 4, SDE_FORMAT_FLAG_DX,
SDE_FETCH_LINEAR, 1),
INTERLEAVED_RGB_FMT(RGBA1010102,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
+ C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
true, 4, SDE_FORMAT_FLAG_DX,
SDE_FETCH_LINEAR, 1),
INTERLEAVED_RGB_FMT(ABGR2101010,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
+ C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
true, 4, SDE_FORMAT_FLAG_DX,
SDE_FETCH_LINEAR, 1),
INTERLEAVED_RGB_FMT(ARGB2101010,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
+ C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
true, 4, SDE_FORMAT_FLAG_DX,
SDE_FETCH_LINEAR, 1),
INTERLEAVED_RGB_FMT(XRGB2101010,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
+ C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
false, 4, SDE_FORMAT_FLAG_DX,
SDE_FETCH_LINEAR, 1),
INTERLEAVED_RGB_FMT(BGRX1010102,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C1_B_Cb, C0_G_Y, C2_R_Cr, C3_ALPHA, 4,
+ C3_ALPHA, C2_R_Cr, C0_G_Y, C1_B_Cb, 4,
false, 4, SDE_FORMAT_FLAG_DX,
SDE_FETCH_LINEAR, 1),
INTERLEAVED_RGB_FMT(XBGR2101010,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
+ C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
false, 4, SDE_FORMAT_FLAG_DX,
SDE_FETCH_LINEAR, 1),
INTERLEAVED_RGB_FMT(RGBX1010102,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
- C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
+ C3_ALPHA, C1_B_Cb, C0_G_Y, C2_R_Cr, 4,
false, 4, SDE_FORMAT_FLAG_DX,
SDE_FETCH_LINEAR, 1),
@@ -384,31 +414,31 @@ static const struct sde_format sde_format_map[] = {
* the data will be passed by user-space.
*/
static const struct sde_format sde_format_map_ubwc[] = {
- INTERLEAVED_RGB_FMT(RGB565,
+ INTERLEAVED_RGB_FMT(BGR565,
0, COLOR_5BIT, COLOR_6BIT, COLOR_5BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, 0, 3,
false, 2, 0,
SDE_FETCH_UBWC, 2),
- INTERLEAVED_RGB_FMT(RGBA8888,
+ INTERLEAVED_RGB_FMT(ABGR8888,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
true, 4, 0,
SDE_FETCH_UBWC, 2),
- INTERLEAVED_RGB_FMT(RGBX8888,
+ INTERLEAVED_RGB_FMT(XBGR8888,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
false, 4, 0,
SDE_FETCH_UBWC, 2),
- INTERLEAVED_RGB_FMT(RGBA1010102,
+ INTERLEAVED_RGB_FMT(ABGR2101010,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
true, 4, SDE_FORMAT_FLAG_DX,
SDE_FETCH_UBWC, 2),
- INTERLEAVED_RGB_FMT(RGBX1010102,
+ INTERLEAVED_RGB_FMT(XBGR2101010,
COLOR_8BIT, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
C2_R_Cr, C0_G_Y, C1_B_Cb, C3_ALPHA, 4,
true, 4, SDE_FORMAT_FLAG_DX,
@@ -421,6 +451,30 @@ static const struct sde_format sde_format_map_ubwc[] = {
SDE_FETCH_UBWC, 4),
};
+static const struct sde_format sde_format_map_p010[] = {
+ PSEUDO_YUV_FMT_LOOSE(NV12,
+ 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C1_B_Cb, C2_R_Cr,
+ SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX),
+ SDE_FETCH_LINEAR, 2),
+};
+
+static const struct sde_format sde_format_map_p010_ubwc[] = {
+ PSEUDO_YUV_FMT_LOOSE(NV12,
+ 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C1_B_Cb, C2_R_Cr,
+ SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX),
+ SDE_FETCH_UBWC, 4),
+};
+
+static const struct sde_format sde_format_map_tp10_ubwc[] = {
+ PSEUDO_YUV_FMT(NV12,
+ 0, COLOR_8BIT, COLOR_8BIT, COLOR_8BIT,
+ C1_B_Cb, C2_R_Cr,
+ SDE_CHROMA_420, (SDE_FORMAT_FLAG_YUV | SDE_FORMAT_FLAG_DX),
+ SDE_FETCH_UBWC, 4),
+};
+
/* _sde_get_v_h_subsample_rate - Get subsample rates for all formats we support
* Note: Not using the drm_format_*_subsampling since we have formats
*/
@@ -452,6 +506,37 @@ static void _sde_get_v_h_subsample_rate(
}
}
+static int _sde_format_get_media_color_ubwc(const struct sde_format *fmt)
+{
+ static const struct sde_media_color_map sde_media_ubwc_map[] = {
+ {DRM_FORMAT_ABGR8888, COLOR_FMT_RGBA8888_UBWC},
+ {DRM_FORMAT_XBGR8888, COLOR_FMT_RGBA8888_UBWC},
+ {DRM_FORMAT_ABGR2101010, COLOR_FMT_RGBA1010102_UBWC},
+ {DRM_FORMAT_XBGR2101010, COLOR_FMT_RGBA1010102_UBWC},
+ {DRM_FORMAT_BGR565, COLOR_FMT_RGB565_UBWC},
+ };
+ int color_fmt = -1;
+ int i;
+
+ if (fmt->base.pixel_format == DRM_FORMAT_NV12) {
+ if (SDE_FORMAT_IS_DX(fmt)) {
+ if (fmt->unpack_tight)
+ color_fmt = COLOR_FMT_NV12_BPP10_UBWC;
+ else
+ color_fmt = COLOR_FMT_P010_UBWC;
+ } else
+ color_fmt = COLOR_FMT_NV12_UBWC;
+ return color_fmt;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(sde_media_ubwc_map); ++i)
+ if (fmt->base.pixel_format == sde_media_ubwc_map[i].format) {
+ color_fmt = sde_media_ubwc_map[i].color;
+ break;
+ }
+ return color_fmt;
+}
+
static int _sde_format_get_plane_sizes_ubwc(
const struct sde_format *fmt,
const uint32_t width,
@@ -459,6 +544,7 @@ static int _sde_format_get_plane_sizes_ubwc(
struct sde_hw_fmt_layout *layout)
{
int i;
+ int color;
memset(layout, 0, sizeof(struct sde_hw_fmt_layout));
layout->format = fmt;
@@ -466,84 +552,53 @@ static int _sde_format_get_plane_sizes_ubwc(
layout->height = height;
layout->num_planes = fmt->num_planes;
- if (fmt->base.pixel_format == DRM_FORMAT_NV12) {
- uint32_t y_stride_alignment, uv_stride_alignment;
- uint32_t y_height_alignment, uv_height_alignment;
- uint32_t y_tile_width = 32;
- uint32_t y_tile_height = 8;
- uint32_t uv_tile_width = y_tile_width / 2;
- uint32_t uv_tile_height = y_tile_height;
- uint32_t y_bpp_numer = 1, y_bpp_denom = 1;
- uint32_t uv_bpp_numer = 1, uv_bpp_denom = 1;
-
- y_stride_alignment = 128;
- uv_stride_alignment = 64;
- y_height_alignment = 32;
- uv_height_alignment = 32;
- y_bpp_numer = 1;
- uv_bpp_numer = 2;
- y_bpp_denom = 1;
- uv_bpp_denom = 1;
+ color = _sde_format_get_media_color_ubwc(fmt);
+ if (color < 0) {
+ DRM_ERROR("UBWC format not supported for fmt:0x%X\n",
+ fmt->base.pixel_format);
+ return -EINVAL;
+ }
+
+ if (SDE_FORMAT_IS_YUV(layout->format)) {
+ uint32_t y_sclines, uv_sclines;
+ uint32_t y_meta_scanlines = 0;
+ uint32_t uv_meta_scanlines = 0;
layout->num_planes = 4;
- /* Y bitstream stride and plane size */
- layout->plane_pitch[0] = ALIGN(width, y_stride_alignment);
- layout->plane_pitch[0] = (layout->plane_pitch[0] * y_bpp_numer)
- / y_bpp_denom;
- layout->plane_size[0] = ALIGN(layout->plane_pitch[0] *
- ALIGN(height, y_height_alignment), 4096);
-
- /* CbCr bitstream stride and plane size */
- layout->plane_pitch[1] = ALIGN(width / 2, uv_stride_alignment);
- layout->plane_pitch[1] = (layout->plane_pitch[1] * uv_bpp_numer)
- / uv_bpp_denom;
- layout->plane_size[1] = ALIGN(layout->plane_pitch[1] *
- ALIGN(height / 2, uv_height_alignment), 4096);
-
- /* Y meta data stride and plane size */
- layout->plane_pitch[2] = ALIGN(
- DIV_ROUND_UP(width, y_tile_width), 64);
- layout->plane_size[2] = ALIGN(layout->plane_pitch[2] *
- ALIGN(DIV_ROUND_UP(height, y_tile_height), 16), 4096);
-
- /* CbCr meta data stride and plane size */
- layout->plane_pitch[3] = ALIGN(
- DIV_ROUND_UP(width / 2, uv_tile_width), 64);
- layout->plane_size[3] = ALIGN(layout->plane_pitch[3] *
- ALIGN(DIV_ROUND_UP(height / 2, uv_tile_height), 16),
- 4096);
-
- } else if (fmt->base.pixel_format == DRM_FORMAT_ABGR8888 ||
- fmt->base.pixel_format == DRM_FORMAT_XBGR8888 ||
- fmt->base.pixel_format == DRM_FORMAT_BGRA1010102 ||
- fmt->base.pixel_format == DRM_FORMAT_BGRX1010102 ||
- fmt->base.pixel_format == DRM_FORMAT_BGR565) {
-
- uint32_t stride_alignment, aligned_bitstream_width;
-
- if (fmt->base.pixel_format == DRM_FORMAT_BGR565)
- stride_alignment = 128;
- else
- stride_alignment = 64;
- layout->num_planes = 3;
+ layout->plane_pitch[0] = VENUS_Y_STRIDE(color, width);
+ y_sclines = VENUS_Y_SCANLINES(color, height);
+ layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
+ y_sclines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);
+
+ layout->plane_pitch[1] = VENUS_UV_STRIDE(color, width);
+ uv_sclines = VENUS_UV_SCANLINES(color, height);
+ layout->plane_size[1] = MSM_MEDIA_ALIGN(layout->plane_pitch[1] *
+ uv_sclines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);
+
+ layout->plane_pitch[2] = VENUS_Y_META_STRIDE(color, width);
+ y_meta_scanlines = VENUS_Y_META_SCANLINES(color, height);
+ layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
+ y_meta_scanlines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);
+
+ layout->plane_pitch[3] = VENUS_UV_META_STRIDE(color, width);
+ uv_meta_scanlines = VENUS_UV_META_SCANLINES(color, height);
+ layout->plane_size[3] = MSM_MEDIA_ALIGN(layout->plane_pitch[3] *
+ uv_meta_scanlines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);
- /* Nothing in plane[1] */
+ } else {
+ uint32_t rgb_scanlines, rgb_meta_scanlines;
- /* RGB bitstream stride and plane size */
- aligned_bitstream_width = ALIGN(width, stride_alignment);
- layout->plane_pitch[0] = aligned_bitstream_width * fmt->bpp;
- layout->plane_size[0] = ALIGN(fmt->bpp * aligned_bitstream_width
- * ALIGN(height, 16), 4096);
+ layout->num_planes = 3;
- /* RGB meta data stride and plane size */
- layout->plane_pitch[2] = ALIGN(DIV_ROUND_UP(
- aligned_bitstream_width, 16), 64);
- layout->plane_size[2] = ALIGN(layout->plane_pitch[2] *
- ALIGN(DIV_ROUND_UP(height, 4), 16), 4096);
- } else {
- DRM_ERROR("UBWC format not supported for fmt:0x%X\n",
- fmt->base.pixel_format);
- return -EINVAL;
+ layout->plane_pitch[0] = VENUS_RGB_STRIDE(color, width);
+ rgb_scanlines = VENUS_RGB_SCANLINES(color, height);
+ layout->plane_size[0] = MSM_MEDIA_ALIGN(layout->plane_pitch[0] *
+ rgb_scanlines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);
+
+ layout->plane_pitch[2] = VENUS_RGB_META_STRIDE(color, width);
+ rgb_meta_scanlines = VENUS_RGB_META_SCANLINES(color, height);
+ layout->plane_size[2] = MSM_MEDIA_ALIGN(layout->plane_pitch[2] *
+ rgb_meta_scanlines, SDE_UBWC_PLANE_SIZE_ALIGNMENT);
}
for (i = 0; i < SDE_MAX_PLANES; i++)
@@ -574,6 +629,7 @@ static int _sde_format_get_plane_sizes_linear(
} else {
uint32_t v_subsample, h_subsample;
uint32_t chroma_samp;
+ uint32_t bpp = 1;
chroma_samp = fmt->chroma_sample;
_sde_get_v_h_subsample_rate(chroma_samp, &v_subsample,
@@ -584,8 +640,11 @@ static int _sde_format_get_plane_sizes_linear(
return -EINVAL;
}
- layout->plane_pitch[0] = width;
- layout->plane_pitch[1] = width / h_subsample;
+ if ((fmt->base.pixel_format == DRM_FORMAT_NV12) &&
+ (SDE_FORMAT_IS_DX(fmt)))
+ bpp = 2;
+ layout->plane_pitch[0] = width * bpp;
+ layout->plane_pitch[1] = layout->plane_pitch[0] / h_subsample;
layout->plane_size[0] = layout->plane_pitch[0] * height;
layout->plane_size[1] = layout->plane_pitch[1] *
(height / v_subsample);
@@ -874,7 +933,8 @@ int sde_format_check_modified_format(
DRM_ERROR("invalid handle for plane %d\n", i);
return -EINVAL;
}
- bos_total_size += bos[i]->size;
+ if ((i == 0) || (bos[i] != bos[0]))
+ bos_total_size += bos[i]->size;
}
if (bos_total_size < layout.total_size) {
@@ -926,6 +986,23 @@ const struct sde_format *sde_get_sde_format_ext(
map_size = ARRAY_SIZE(sde_format_map_ubwc);
DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED", format);
break;
+ case DRM_FORMAT_MOD_QCOM_DX:
+ map = sde_format_map_p010;
+ map_size = ARRAY_SIZE(sde_format_map_p010);
+ DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_DX", format);
+ break;
+ case (DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_COMPRESSED):
+ map = sde_format_map_p010_ubwc;
+ map_size = ARRAY_SIZE(sde_format_map_p010_ubwc);
+ DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED/DX", format);
+ break;
+ case (DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_COMPRESSED |
+ DRM_FORMAT_MOD_QCOM_TIGHT):
+ map = sde_format_map_tp10_ubwc;
+ map_size = ARRAY_SIZE(sde_format_map_tp10_ubwc);
+ DBG("found fmt 0x%X DRM_FORMAT_MOD_QCOM_COMPRESSED/DX/TIGHT",
+ format);
+ break;
default:
DRM_ERROR("unsupported format modifier %llX\n", mod0);
return NULL;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index 17b678cfca46..4f84e31db5f6 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -405,6 +405,38 @@ static struct sde_prop_type vbif_prop[] = {
/*************************************************************
* static API list
*************************************************************/
+
+/**
+ * _sde_copy_formats - copy formats from src_list to dst_list
+ * @dst_list: pointer to destination list where to copy formats
+ * @dst_list_size: size of destination list
+ * @dst_list_pos: starting position on the list where to copy formats
+ * @src_list: pointer to source list where to copy formats from
+ * @src_list_size: size of source list
+ * Return: number of elements populated
+ */
+static uint32_t _sde_copy_formats(
+ struct sde_format_extended *dst_list,
+ uint32_t dst_list_size,
+ uint32_t dst_list_pos,
+ const struct sde_format_extended *src_list,
+ uint32_t src_list_size)
+{
+ uint32_t cur_pos, i;
+
+ if (!dst_list || !src_list || (dst_list_pos >= (dst_list_size - 1)))
+ return 0;
+
+ for (i = 0, cur_pos = dst_list_pos;
+ (cur_pos < (dst_list_size - 1)) && src_list[i].fourcc_format
+ && (i < src_list_size); ++i, ++cur_pos)
+ dst_list[cur_pos] = src_list[i];
+
+ dst_list[cur_pos].fourcc_format = 0;
+
+ return i;
+}
+
static int _parse_dt_u32_handler(struct device_node *np,
char *prop_name, u32 *offsets, int len, bool mandatory)
{
@@ -658,7 +690,7 @@ static void _sde_sspp_setup_vig(struct sde_mdss_cfg *sde_cfg,
sblk->maxdwnscale = MAX_SSPP_DOWNSCALE;
sspp->id = SSPP_VIG0 + *vig_count;
sspp->clk_ctrl = SDE_CLK_CTRL_VIG0 + *vig_count;
- sblk->format_list = plane_formats_yuv;
+ sspp->type = SSPP_TYPE_VIG;
set_bit(SDE_SSPP_QOS, &sspp->features);
(*vig_count)++;
@@ -728,7 +760,7 @@ static void _sde_sspp_setup_rgb(struct sde_mdss_cfg *sde_cfg,
sblk->maxdwnscale = MAX_SSPP_DOWNSCALE;
sspp->id = SSPP_RGB0 + *rgb_count;
sspp->clk_ctrl = SDE_CLK_CTRL_RGB0 + *rgb_count;
- sblk->format_list = plane_formats;
+ sspp->type = SSPP_TYPE_RGB;
set_bit(SDE_SSPP_QOS, &sspp->features);
(*rgb_count)++;
@@ -768,7 +800,7 @@ static void _sde_sspp_setup_cursor(struct sde_mdss_cfg *sde_cfg,
sblk->maxdwnscale = SSPP_UNITY_SCALE;
sspp->id = SSPP_CURSOR0 + *cursor_count;
sspp->clk_ctrl = SDE_CLK_CTRL_CURSOR0 + *cursor_count;
- sblk->format_list = plane_formats;
+ sspp->type = SSPP_TYPE_CURSOR;
(*cursor_count)++;
snprintf(sspp->name, sizeof(sspp->name), "cursor%d", *cursor_count-1);
}
@@ -781,7 +813,7 @@ static void _sde_sspp_setup_dma(struct sde_mdss_cfg *sde_cfg,
sblk->maxdwnscale = SSPP_UNITY_SCALE;
sspp->id = SSPP_DMA0 + *dma_count;
sspp->clk_ctrl = SDE_CLK_CTRL_DMA0 + *dma_count;
- sblk->format_list = plane_formats;
+ sspp->type = SSPP_TYPE_DMA;
set_bit(SDE_SSPP_QOS, &sspp->features);
(*dma_count)++;
snprintf(sspp->name, sizeof(sspp->name), "dma%d", *dma_count-1);
@@ -1258,7 +1290,6 @@ static int sde_wb_parse_dt(struct device_node *np,
wb->xin_id = PROP_VALUE_ACCESS(prop_value, WB_XIN_ID, i);
wb->vbif_idx = VBIF_NRT;
wb->len = PROP_VALUE_ACCESS(prop_value, WB_LEN, 0);
- wb->format_list = wb2_formats;
if (!prop_exists[WB_LEN])
wb->len = DEFAULT_SDE_HW_BLOCK_LEN;
sblk->maxlinewidth = sde_cfg->max_wb_linewidth;
@@ -1988,9 +2019,124 @@ end:
return rc;
}
-static void sde_hardware_caps(struct sde_mdss_cfg *sde_cfg,
+static int sde_hardware_format_caps(struct sde_mdss_cfg *sde_cfg,
uint32_t hw_rev)
{
+ int i, rc = 0;
+ uint32_t dma_list_size, vig_list_size, wb2_list_size;
+ uint32_t cursor_list_size = 0;
+ struct sde_sspp_sub_blks *sblk;
+ uint32_t index = 0;
+
+ if (IS_SDE_MAJOR_MINOR_SAME((hw_rev), SDE_HW_VER_300)) {
+ cursor_list_size = ARRAY_SIZE(cursor_formats);
+ sde_cfg->cursor_formats = kcalloc(cursor_list_size,
+ sizeof(struct sde_format_extended), GFP_KERNEL);
+ if (!sde_cfg->cursor_formats) {
+ rc = -ENOMEM;
+ goto end;
+ }
+ index = _sde_copy_formats(sde_cfg->cursor_formats,
+ cursor_list_size, 0, cursor_formats,
+ ARRAY_SIZE(cursor_formats));
+ }
+
+ dma_list_size = ARRAY_SIZE(plane_formats);
+ vig_list_size = ARRAY_SIZE(plane_formats_yuv);
+ wb2_list_size = ARRAY_SIZE(wb2_formats);
+
+ dma_list_size += ARRAY_SIZE(rgb_10bit_formats);
+ vig_list_size += ARRAY_SIZE(rgb_10bit_formats)
+ + ARRAY_SIZE(tp10_ubwc_formats)
+ + ARRAY_SIZE(p010_formats);
+ wb2_list_size += ARRAY_SIZE(rgb_10bit_formats)
+ + ARRAY_SIZE(tp10_ubwc_formats);
+
+ sde_cfg->dma_formats = kcalloc(dma_list_size,
+ sizeof(struct sde_format_extended), GFP_KERNEL);
+ if (!sde_cfg->dma_formats) {
+ rc = -ENOMEM;
+ goto end;
+ }
+
+ sde_cfg->vig_formats = kcalloc(vig_list_size,
+ sizeof(struct sde_format_extended), GFP_KERNEL);
+ if (!sde_cfg->vig_formats) {
+ rc = -ENOMEM;
+ goto end;
+ }
+
+ sde_cfg->wb_formats = kcalloc(wb2_list_size,
+ sizeof(struct sde_format_extended), GFP_KERNEL);
+ if (!sde_cfg->wb_formats) {
+ SDE_ERROR("failed to allocate wb format list\n");
+ rc = -ENOMEM;
+ goto end;
+ }
+
+ index = _sde_copy_formats(sde_cfg->dma_formats, dma_list_size,
+ 0, plane_formats, ARRAY_SIZE(plane_formats));
+ index += _sde_copy_formats(sde_cfg->dma_formats, dma_list_size,
+ index, rgb_10bit_formats,
+ ARRAY_SIZE(rgb_10bit_formats));
+
+ index = _sde_copy_formats(sde_cfg->vig_formats, vig_list_size,
+ 0, plane_formats_yuv, ARRAY_SIZE(plane_formats_yuv));
+ index += _sde_copy_formats(sde_cfg->vig_formats, vig_list_size,
+ index, rgb_10bit_formats,
+ ARRAY_SIZE(rgb_10bit_formats));
+ index += _sde_copy_formats(sde_cfg->vig_formats, vig_list_size,
+ index, p010_formats, ARRAY_SIZE(p010_formats));
+
+ index += _sde_copy_formats(sde_cfg->vig_formats, vig_list_size,
+ index, tp10_ubwc_formats,
+ ARRAY_SIZE(tp10_ubwc_formats));
+
+ index = _sde_copy_formats(sde_cfg->wb_formats, wb2_list_size,
+ 0, wb2_formats, ARRAY_SIZE(wb2_formats));
+ index += _sde_copy_formats(sde_cfg->wb_formats, wb2_list_size,
+ index, rgb_10bit_formats,
+ ARRAY_SIZE(rgb_10bit_formats));
+ index += _sde_copy_formats(sde_cfg->wb_formats, wb2_list_size,
+ index, tp10_ubwc_formats,
+ ARRAY_SIZE(tp10_ubwc_formats));
+
+ for (i = 0; i < sde_cfg->sspp_count; ++i) {
+ struct sde_sspp_cfg *sspp = &sde_cfg->sspp[i];
+
+ sblk = (struct sde_sspp_sub_blks *)sspp->sblk;
+ switch (sspp->type) {
+ case SSPP_TYPE_VIG:
+ sblk->format_list = sde_cfg->vig_formats;
+ break;
+ case SSPP_TYPE_CURSOR:
+ if (IS_SDE_MAJOR_MINOR_SAME((hw_rev), SDE_HW_VER_300))
+ sblk->format_list = sde_cfg->cursor_formats;
+ else
+ SDE_ERROR("invalid sspp type %d, xin id %d\n",
+ sspp->type, sspp->xin_id);
+ break;
+ case SSPP_TYPE_DMA:
+ sblk->format_list = sde_cfg->dma_formats;
+ break;
+ default:
+ SDE_ERROR("invalid sspp type %d\n", sspp->type);
+ rc = -EINVAL;
+ goto end;
+ }
+ }
+
+ for (i = 0; i < sde_cfg->wb_count; ++i)
+ sde_cfg->wb[i].format_list = sde_cfg->wb_formats;
+
+end:
+ return rc;
+}
+
+static int sde_hardware_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
+{
+ int rc = 0;
+
switch (hw_rev) {
case SDE_HW_VER_170:
case SDE_HW_VER_171:
@@ -1998,10 +2144,14 @@ static void sde_hardware_caps(struct sde_mdss_cfg *sde_cfg,
/* update msm8996 target here */
break;
case SDE_HW_VER_300:
+ case SDE_HW_VER_301:
case SDE_HW_VER_400:
/* update cobalt and skunk target here */
+ rc = sde_hardware_format_caps(sde_cfg, hw_rev);
break;
}
+
+ return rc;
}
void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
@@ -2040,6 +2190,11 @@ void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
}
}
+ kfree(sde_cfg->dma_formats);
+ kfree(sde_cfg->cursor_formats);
+ kfree(sde_cfg->vig_formats);
+ kfree(sde_cfg->wb_formats);
+
kfree(sde_cfg);
}
@@ -2109,7 +2264,9 @@ struct sde_mdss_cfg *sde_hw_catalog_init(struct drm_device *dev,
if (rc)
SDE_DEBUG("virtual plane is not supported.\n");
- sde_hardware_caps(sde_cfg, hw_rev);
+ rc = sde_hardware_caps(sde_cfg, hw_rev);
+ if (rc)
+ goto end;
return sde_cfg;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index bca221d2a959..01204df48871 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -42,7 +42,8 @@
#define SDE_HW_VER_170 SDE_HW_VER(1, 7, 0) /* 8996 v1.0 */
#define SDE_HW_VER_171 SDE_HW_VER(1, 7, 1) /* 8996 v2.0 */
#define SDE_HW_VER_172 SDE_HW_VER(1, 7, 2) /* 8996 v3.0 */
-#define SDE_HW_VER_300 SDE_HW_VER(3, 0, 0) /* cobalt v1.0 */
+#define SDE_HW_VER_300 SDE_HW_VER(3, 0, 0) /* 8998 v1.0 */
+#define SDE_HW_VER_301 SDE_HW_VER(3, 0, 1) /* 8998 v1.1 */
#define SDE_HW_VER_400 SDE_HW_VER(4, 0, 0) /* msmskunk v1.0 */
#define IS_MSMSKUNK_TARGET(rev) IS_SDE_MAJOR_MINOR_SAME((rev), SDE_HW_VER_400)
@@ -457,7 +458,8 @@ struct sde_ctl_cfg {
* @sblk: SSPP sub-blocks information
* @xin_id: bus client identifier
* @clk_ctrl clock control identifier
- *@name source pipe name
+ * @name source pipe name
+ * @type sspp type identifier
*/
struct sde_sspp_cfg {
SDE_HW_BLK_INFO;
@@ -465,6 +467,7 @@ struct sde_sspp_cfg {
u32 xin_id;
enum sde_clk_ctrl_type clk_ctrl;
char name[SSPP_NAME_SIZE];
+ u32 type;
};
/**
@@ -652,6 +655,10 @@ struct sde_vp_cfg {
* @csc_type csc or csc_10bit support.
* @has_src_split source split feature status
* @has_cdp Client driver prefetch feature status
+ * @dma_formats Supported formats for dma pipe
+ * @cursor_formats Supported formats for cursor pipe
+ * @vig_formats Supported formats for vig pipe
+ * @wb_formats Supported formats for wb
*/
struct sde_mdss_cfg {
u32 hwversion;
@@ -704,6 +711,11 @@ struct sde_mdss_cfg {
u32 vp_count;
struct sde_vp_cfg vp[MAX_BLOCKS];
+
+ struct sde_format_extended *dma_formats;
+ struct sde_format_extended *cursor_formats;
+ struct sde_format_extended *vig_formats;
+ struct sde_format_extended *wb_formats;
};
struct sde_mdss_hw_cfg_handler {
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog_format.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog_format.h
index 296694422653..dbc8981a7f8f 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog_format.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog_format.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -16,17 +16,17 @@ static const struct sde_format_extended plane_formats[] = {
{DRM_FORMAT_ARGB8888, 0},
{DRM_FORMAT_ABGR8888, 0},
{DRM_FORMAT_RGBA8888, 0},
- {DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_BGRA8888, 0},
{DRM_FORMAT_XRGB8888, 0},
{DRM_FORMAT_RGBX8888, 0},
{DRM_FORMAT_BGRX8888, 0},
{DRM_FORMAT_XBGR8888, 0},
- {DRM_FORMAT_RGBX8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_RGB888, 0},
{DRM_FORMAT_BGR888, 0},
{DRM_FORMAT_RGB565, 0},
- {DRM_FORMAT_RGB565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_BGR565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_BGR565, 0},
{DRM_FORMAT_ARGB1555, 0},
{DRM_FORMAT_ABGR1555, 0},
@@ -52,16 +52,16 @@ static const struct sde_format_extended plane_formats_yuv[] = {
{DRM_FORMAT_ABGR8888, 0},
{DRM_FORMAT_RGBA8888, 0},
{DRM_FORMAT_BGRX8888, 0},
- {DRM_FORMAT_RGBA8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_BGRA8888, 0},
{DRM_FORMAT_XRGB8888, 0},
{DRM_FORMAT_XBGR8888, 0},
{DRM_FORMAT_RGBX8888, 0},
- {DRM_FORMAT_RGBX8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_RGB888, 0},
{DRM_FORMAT_BGR888, 0},
{DRM_FORMAT_RGB565, 0},
- {DRM_FORMAT_RGB565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_BGR565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_BGR565, 0},
{DRM_FORMAT_ARGB1555, 0},
{DRM_FORMAT_ABGR1555, 0},
@@ -94,13 +94,33 @@ static const struct sde_format_extended plane_formats_yuv[] = {
{0, 0},
};
+static const struct sde_format_extended cursor_formats[] = {
+ {DRM_FORMAT_ARGB8888, 0},
+ {DRM_FORMAT_ABGR8888, 0},
+ {DRM_FORMAT_RGBA8888, 0},
+ {DRM_FORMAT_BGRA8888, 0},
+ {DRM_FORMAT_XRGB8888, 0},
+ {DRM_FORMAT_ARGB1555, 0},
+ {DRM_FORMAT_ABGR1555, 0},
+ {DRM_FORMAT_RGBA5551, 0},
+ {DRM_FORMAT_BGRA5551, 0},
+ {DRM_FORMAT_ARGB4444, 0},
+ {DRM_FORMAT_ABGR4444, 0},
+ {DRM_FORMAT_RGBA4444, 0},
+ {DRM_FORMAT_BGRA4444, 0},
+ {0, 0},
+};
+
static const struct sde_format_extended wb2_formats[] = {
{DRM_FORMAT_RGB565, 0},
+ {DRM_FORMAT_BGR565, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_RGB888, 0},
{DRM_FORMAT_ARGB8888, 0},
{DRM_FORMAT_RGBA8888, 0},
+ {DRM_FORMAT_ABGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_XRGB8888, 0},
{DRM_FORMAT_RGBX8888, 0},
+ {DRM_FORMAT_XBGR8888, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_ARGB1555, 0},
{DRM_FORMAT_RGBA5551, 0},
{DRM_FORMAT_XRGB1555, 0},
@@ -127,8 +147,31 @@ static const struct sde_format_extended wb2_formats[] = {
{DRM_FORMAT_YUV420, 0},
{DRM_FORMAT_NV12, 0},
+ {DRM_FORMAT_NV12, DRM_FORMAT_MOD_QCOM_COMPRESSED},
{DRM_FORMAT_NV16, 0},
{DRM_FORMAT_YUYV, 0},
{0, 0},
};
+
+static const struct sde_format_extended rgb_10bit_formats[] = {
+ {DRM_FORMAT_BGRA1010102, 0},
+ {DRM_FORMAT_BGRX1010102, 0},
+ {DRM_FORMAT_RGBA1010102, 0},
+ {DRM_FORMAT_RGBX1010102, 0},
+ {DRM_FORMAT_ABGR2101010, 0},
+ {DRM_FORMAT_ABGR2101010, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_XBGR2101010, 0},
+ {DRM_FORMAT_XBGR2101010, DRM_FORMAT_MOD_QCOM_COMPRESSED},
+ {DRM_FORMAT_ARGB2101010, 0},
+ {DRM_FORMAT_XRGB2101010, 0},
+};
+
+static const struct sde_format_extended p010_formats[] = {
+ {DRM_FORMAT_NV12, DRM_FORMAT_MOD_QCOM_DX},
+};
+
+static const struct sde_format_extended tp10_ubwc_formats[] = {
+ {DRM_FORMAT_NV12, DRM_FORMAT_MOD_QCOM_COMPRESSED |
+ DRM_FORMAT_MOD_QCOM_DX | DRM_FORMAT_MOD_QCOM_TIGHT},
+};
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
index dcba248d27b0..7a5e7ad79f0f 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_mdss.h
@@ -41,11 +41,18 @@
#define SDE_MAX_DE_CURVES 3
#endif
-#define SDE_FORMAT_FLAG_YUV (1 << 0)
-#define SDE_FORMAT_FLAG_DX (1 << 1)
+enum sde_format_flags {
+ SDE_FORMAT_FLAG_YUV_BIT,
+ SDE_FORMAT_FLAG_DX_BIT,
+ SDE_FORMAT_FLAG_BIT_MAX,
+};
-#define SDE_FORMAT_IS_YUV(X) ((X)->flag & SDE_FORMAT_FLAG_YUV)
-#define SDE_FORMAT_IS_DX(X) ((X)->flag & SDE_FORMAT_FLAG_DX)
+#define SDE_FORMAT_FLAG_YUV BIT(SDE_FORMAT_FLAG_YUV_BIT)
+#define SDE_FORMAT_FLAG_DX BIT(SDE_FORMAT_FLAG_DX_BIT)
+#define SDE_FORMAT_IS_YUV(X) \
+ (test_bit(SDE_FORMAT_FLAG_YUV_BIT, (X)->flag))
+#define SDE_FORMAT_IS_DX(X) \
+ (test_bit(SDE_FORMAT_FLAG_DX_BIT, (X)->flag))
#define SDE_FORMAT_IS_LINEAR(X) ((X)->fetch_mode == SDE_FETCH_LINEAR)
#define SDE_FORMAT_IS_UBWC(X) ((X)->fetch_mode == SDE_FETCH_UBWC)
@@ -357,7 +364,7 @@ struct sde_format {
u8 alpha_enable;
u8 num_planes;
enum sde_fetch_type fetch_mode;
- u32 flag;
+ DECLARE_BITMAP(flag, SDE_FORMAT_FLAG_BIT_MAX);
u16 tile_width;
u16 tile_height;
};
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index a240ed08da89..031493aa42b8 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -602,6 +602,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
.get_info = sde_hdmi_get_info,
.set_property = sde_hdmi_set_property,
.get_property = sde_hdmi_get_property,
+ .pre_kickoff = sde_hdmi_pre_kickoff,
};
struct msm_display_info info = {0};
struct drm_encoder *encoder;
diff --git a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
index daa35845fc0a..93c9c3c373b8 100644
--- a/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
+++ b/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_core.c
@@ -1495,7 +1495,7 @@ static int synaptics_rmi4_irq_enable(struct synaptics_rmi4_data *rmi4_data,
return retval;
}
-static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler,
+static int synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler,
struct synaptics_rmi4_fn_desc *fd,
unsigned int intr_count)
{
@@ -1503,6 +1503,12 @@ static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler,
unsigned char intr_offset;
fhandler->intr_reg_num = (intr_count + 7) / 8;
+ if (fhandler->intr_reg_num >= MAX_INTR_REGISTERS) {
+ fhandler->intr_reg_num = 0;
+ fhandler->num_of_data_sources = 0;
+ fhandler->intr_mask = 0;
+ return -EINVAL;
+ }
if (fhandler->intr_reg_num != 0)
fhandler->intr_reg_num -= 1;
@@ -1515,7 +1521,7 @@ static void synaptics_rmi4_set_intr_mask(struct synaptics_rmi4_fn *fhandler,
ii++)
fhandler->intr_mask |= 1 << ii;
- return;
+ return 0;
}
static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data,
@@ -1523,12 +1529,17 @@ static int synaptics_rmi4_f01_init(struct synaptics_rmi4_data *rmi4_data,
struct synaptics_rmi4_fn_desc *fd,
unsigned int intr_count)
{
+ int retval;
+
fhandler->fn_number = fd->fn_number;
fhandler->num_of_data_sources = fd->intr_src_count;
fhandler->data = NULL;
fhandler->extra = NULL;
- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
+
rmi4_data->f01_query_base_addr = fd->query_base_addr;
rmi4_data->f01_ctrl_base_addr = fd->ctrl_base_addr;
@@ -1653,7 +1664,9 @@ static int synaptics_rmi4_f11_init(struct synaptics_rmi4_data *rmi4_data,
if (retval < 0)
return retval;
- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
abs_data_size = query[5] & MASK_2BIT;
abs_data_blk_size = 3 + (2 * (abs_data_size == 0 ? 1 : 0));
@@ -1934,7 +1947,9 @@ static int synaptics_rmi4_f12_init(struct synaptics_rmi4_data *rmi4_data,
if (retval < 0)
goto free_function_handler_mem;
- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
/* Allocate memory for finger data storage space */
fhandler->data_size = num_of_fingers * size_of_2d_data;
@@ -2092,7 +2107,9 @@ static int synaptics_rmi4_f1a_init(struct synaptics_rmi4_data *rmi4_data,
fhandler->fn_number = fd->fn_number;
fhandler->num_of_data_sources = fd->intr_src_count;
- synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ retval = synaptics_rmi4_set_intr_mask(fhandler, fd, intr_count);
+ if (retval < 0)
+ return retval;
retval = synaptics_rmi4_f1a_alloc_mem(rmi4_data, fhandler);
if (retval < 0)
@@ -2491,6 +2508,8 @@ flash_prog_mode:
dev_dbg(rmi4_data->pdev->dev.parent,
"%s: Number of interrupt registers = %d\n",
__func__, rmi4_data->num_of_intr_regs);
+ if (rmi4_data->num_of_intr_regs >= MAX_INTR_REGISTERS)
+ return -EINVAL;
retval = synaptics_rmi4_reg_read(rmi4_data,
rmi4_data->f01_query_base_addr,
diff --git a/drivers/media/platform/msm/ais/msm.c b/drivers/media/platform/msm/ais/msm.c
index 3e2c13b9cbbe..3c2e28eaa4f9 100644
--- a/drivers/media/platform/msm/ais/msm.c
+++ b/drivers/media/platform/msm/ais/msm.c
@@ -283,22 +283,47 @@ void msm_delete_stream(unsigned int session_id, unsigned int stream_id)
struct msm_session *session = NULL;
struct msm_stream *stream = NULL;
unsigned long flags;
+ int try_count = 0;
session = msm_queue_find(msm_session_q, struct msm_session,
list, __msm_queue_find_session, &session_id);
+
if (!session)
return;
- stream = msm_queue_find(&session->stream_q, struct msm_stream,
- list, __msm_queue_find_stream, &stream_id);
- if (!stream)
- return;
- spin_lock_irqsave(&(session->stream_q.lock), flags);
- list_del_init(&stream->list);
- session->stream_q.len--;
- kfree(stream);
- stream = NULL;
- spin_unlock_irqrestore(&(session->stream_q.lock), flags);
+ while (1) {
+
+ if (try_count > 5) {
+ pr_err("%s : not able to delete stream %d\n",
+ __func__, __LINE__);
+ break;
+ }
+
+ write_lock(&session->stream_rwlock);
+ try_count++;
+ stream = msm_queue_find(&session->stream_q, struct msm_stream,
+ list, __msm_queue_find_stream, &stream_id);
+
+ if (!stream) {
+ write_unlock(&session->stream_rwlock);
+ return;
+ }
+
+ if (msm_vb2_get_stream_state(stream) != 1) {
+ write_unlock(&session->stream_rwlock);
+ continue;
+ }
+
+ spin_lock_irqsave(&(session->stream_q.lock), flags);
+ list_del_init(&stream->list);
+ session->stream_q.len--;
+ kfree(stream);
+ stream = NULL;
+ spin_unlock_irqrestore(&(session->stream_q.lock), flags);
+ write_unlock(&session->stream_rwlock);
+ break;
+ }
+
}
EXPORT_SYMBOL(msm_delete_stream);
@@ -446,6 +471,7 @@ int msm_create_session(unsigned int session_id, struct video_device *vdev)
mutex_init(&session->lock);
mutex_init(&session->lock_q);
mutex_init(&session->close_lock);
+ rwlock_init(&session->stream_rwlock);
return 0;
}
EXPORT_SYMBOL(msm_create_session);
@@ -1040,17 +1066,25 @@ static struct v4l2_file_operations msm_fops = {
#endif
};
-struct msm_stream *msm_get_stream(unsigned int session_id,
- unsigned int stream_id)
+struct msm_session *msm_get_session(unsigned int session_id)
{
struct msm_session *session;
- struct msm_stream *stream;
session = msm_queue_find(msm_session_q, struct msm_session,
list, __msm_queue_find_session, &session_id);
if (!session)
return ERR_PTR(-EINVAL);
+ return session;
+}
+EXPORT_SYMBOL(msm_get_session);
+
+
+struct msm_stream *msm_get_stream(struct msm_session *session,
+ unsigned int stream_id)
+{
+ struct msm_stream *stream;
+
stream = msm_queue_find(&session->stream_q, struct msm_stream,
list, __msm_queue_find_stream, &stream_id);
@@ -1108,6 +1142,34 @@ struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q)
}
EXPORT_SYMBOL(msm_get_stream_from_vb2q);
+struct msm_session *msm_get_session_from_vb2q(struct vb2_queue *q)
+{
+ struct msm_session *session;
+ struct msm_stream *stream;
+ unsigned long flags1;
+ unsigned long flags2;
+
+ spin_lock_irqsave(&msm_session_q->lock, flags1);
+ list_for_each_entry(session, &(msm_session_q->list), list) {
+ spin_lock_irqsave(&(session->stream_q.lock), flags2);
+ list_for_each_entry(
+ stream, &(session->stream_q.list), list) {
+ if (stream->vb2_q == q) {
+ spin_unlock_irqrestore
+ (&(session->stream_q.lock), flags2);
+ spin_unlock_irqrestore
+ (&msm_session_q->lock, flags1);
+ return session;
+ }
+ }
+ spin_unlock_irqrestore(&(session->stream_q.lock), flags2);
+ }
+ spin_unlock_irqrestore(&msm_session_q->lock, flags1);
+ return NULL;
+}
+EXPORT_SYMBOL(msm_get_session_from_vb2q);
+
+
#ifdef CONFIG_COMPAT
long msm_copy_camera_private_ioctl_args(unsigned long arg,
struct msm_camera_private_ioctl_arg *k_ioctl,
diff --git a/drivers/media/platform/msm/ais/msm.h b/drivers/media/platform/msm/ais/msm.h
index d8b2d5871fc2..5d456310c301 100644
--- a/drivers/media/platform/msm/ais/msm.h
+++ b/drivers/media/platform/msm/ais/msm.h
@@ -114,6 +114,7 @@ struct msm_session {
struct mutex lock;
struct mutex lock_q;
struct mutex close_lock;
+ rwlock_t stream_rwlock;
};
static inline bool msm_is_daemon_present(void)
@@ -131,11 +132,13 @@ int msm_create_stream(unsigned int session_id,
void msm_delete_stream(unsigned int session_id, unsigned int stream_id);
int msm_create_command_ack_q(unsigned int session_id, unsigned int stream_id);
void msm_delete_command_ack_q(unsigned int session_id, unsigned int stream_id);
-struct msm_stream *msm_get_stream(unsigned int session_id,
+struct msm_session *msm_get_session(unsigned int session_id);
+struct msm_stream *msm_get_stream(struct msm_session *session,
unsigned int stream_id);
struct vb2_queue *msm_get_stream_vb2q(unsigned int session_id,
unsigned int stream_id);
struct msm_stream *msm_get_stream_from_vb2q(struct vb2_queue *q);
+struct msm_session *msm_get_session_from_vb2q(struct vb2_queue *q);
struct msm_session *msm_session_find(unsigned int session_id);
#ifdef CONFIG_COMPAT
long msm_copy_camera_private_ioctl_args(unsigned long arg,
diff --git a/drivers/media/platform/msm/ais/msm_vb2/msm_vb2.c b/drivers/media/platform/msm/ais/msm_vb2/msm_vb2.c
index 2c1c0a34389a..36aa3f62fbec 100644
--- a/drivers/media/platform/msm/ais/msm_vb2/msm_vb2.c
+++ b/drivers/media/platform/msm/ais/msm_vb2/msm_vb2.c
@@ -44,17 +44,25 @@ static int msm_vb2_queue_setup(struct vb2_queue *q,
static int msm_vb2_buf_init(struct vb2_buffer *vb)
{
struct msm_stream *stream;
+ struct msm_session *session;
struct msm_vb2_buffer *msm_vb2_buf;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
+ session = msm_get_session_from_vb2q(vb->vb2_queue);
+ if (IS_ERR_OR_NULL(session))
+ return -EINVAL;
+
+ read_lock(&session->stream_rwlock);
+
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
if (!stream) {
pr_err("%s: Couldn't find stream\n", __func__);
+ read_unlock(&session->stream_rwlock);
return -EINVAL;
}
msm_vb2_buf = container_of(vbuf, struct msm_vb2_buffer, vb2_v4l2_buf);
msm_vb2_buf->in_freeq = 0;
-
+ read_unlock(&session->stream_rwlock);
return 0;
}
@@ -62,6 +70,7 @@ static void msm_vb2_buf_queue(struct vb2_buffer *vb)
{
struct msm_vb2_buffer *msm_vb2;
struct msm_stream *stream;
+ struct msm_session *session;
unsigned long flags;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
@@ -71,21 +80,30 @@ static void msm_vb2_buf_queue(struct vb2_buffer *vb)
return;
}
+ session = msm_get_session_from_vb2q(vb->vb2_queue);
+ if (IS_ERR_OR_NULL(session))
+ return;
+
+ read_lock(&session->stream_rwlock);
+
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
if (!stream) {
pr_err("%s:%d] NULL stream", __func__, __LINE__);
+ read_unlock(&session->stream_rwlock);
return;
}
spin_lock_irqsave(&stream->stream_lock, flags);
list_add_tail(&msm_vb2->list, &stream->queued_list);
spin_unlock_irqrestore(&stream->stream_lock, flags);
+ read_unlock(&session->stream_rwlock);
}
static void msm_vb2_buf_finish(struct vb2_buffer *vb)
{
struct msm_vb2_buffer *msm_vb2;
struct msm_stream *stream;
+ struct msm_session *session;
unsigned long flags;
struct msm_vb2_buffer *msm_vb2_entry, *temp;
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
@@ -96,9 +114,16 @@ static void msm_vb2_buf_finish(struct vb2_buffer *vb)
return;
}
+ session = msm_get_session_from_vb2q(vb->vb2_queue);
+ if (IS_ERR_OR_NULL(session))
+ return;
+
+ read_lock(&session->stream_rwlock);
+
stream = msm_get_stream_from_vb2q(vb->vb2_queue);
if (!stream) {
pr_err("%s:%d] NULL stream", __func__, __LINE__);
+ read_unlock(&session->stream_rwlock);
return;
}
@@ -111,18 +136,27 @@ static void msm_vb2_buf_finish(struct vb2_buffer *vb)
}
}
spin_unlock_irqrestore(&stream->stream_lock, flags);
+ read_unlock(&session->stream_rwlock);
}
static void msm_vb2_stop_stream(struct vb2_queue *q)
{
struct msm_vb2_buffer *msm_vb2, *temp;
struct msm_stream *stream;
+ struct msm_session *session;
unsigned long flags;
struct vb2_v4l2_buffer *vb2_v4l2_buf;
+ session = msm_get_session_from_vb2q(q);
+ if (IS_ERR_OR_NULL(session))
+ return;
+
+ read_lock(&session->stream_rwlock);
+
stream = msm_get_stream_from_vb2q(q);
if (!stream) {
pr_err_ratelimited("%s:%d] NULL stream", __func__, __LINE__);
+ read_unlock(&session->stream_rwlock);
return;
}
@@ -142,8 +176,28 @@ static void msm_vb2_stop_stream(struct vb2_queue *q)
msm_vb2->in_freeq = 0;
}
spin_unlock_irqrestore(&stream->stream_lock, flags);
+ read_unlock(&session->stream_rwlock);
}
+int msm_vb2_get_stream_state(struct msm_stream *stream)
+{
+ struct msm_vb2_buffer *msm_vb2, *temp;
+ unsigned long flags;
+ int rc = 1;
+
+ spin_lock_irqsave(&stream->stream_lock, flags);
+ list_for_each_entry_safe(msm_vb2, temp, &(stream->queued_list), list) {
+ if (msm_vb2->in_freeq != 0) {
+ rc = 0;
+ break;
+ }
+ }
+ spin_unlock_irqrestore(&stream->stream_lock, flags);
+ return rc;
+}
+EXPORT_SYMBOL(msm_vb2_get_stream_state);
+
+
static struct vb2_ops msm_vb2_get_q_op = {
.queue_setup = msm_vb2_queue_setup,
.buf_init = msm_vb2_buf_init,
@@ -199,13 +253,22 @@ static struct vb2_v4l2_buffer *msm_vb2_get_buf(int session_id,
{
struct msm_stream *stream;
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
+ struct msm_session *session;
struct msm_vb2_buffer *msm_vb2 = NULL;
unsigned long flags;
- stream = msm_get_stream(session_id, stream_id);
- if (IS_ERR_OR_NULL(stream))
+ session = msm_get_session(session_id);
+ if (IS_ERR_OR_NULL(session))
return NULL;
+ read_lock(&session->stream_rwlock);
+
+ stream = msm_get_stream(session, stream_id);
+ if (IS_ERR_OR_NULL(stream)) {
+ read_unlock(&session->stream_rwlock);
+ return NULL;
+ }
+
spin_lock_irqsave(&stream->stream_lock, flags);
if (!stream->vb2_q) {
@@ -228,6 +291,7 @@ static struct vb2_v4l2_buffer *msm_vb2_get_buf(int session_id,
vb2_v4l2_buf = NULL;
end:
spin_unlock_irqrestore(&stream->stream_lock, flags);
+ read_unlock(&session->stream_rwlock);
return vb2_v4l2_buf;
}
@@ -236,12 +300,22 @@ static struct vb2_v4l2_buffer *msm_vb2_get_buf_by_idx(int session_id,
{
struct msm_stream *stream;
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
+ struct msm_session *session;
struct msm_vb2_buffer *msm_vb2 = NULL;
unsigned long flags;
- stream = msm_get_stream(session_id, stream_id);
- if (IS_ERR_OR_NULL(stream))
+ session = msm_get_session(session_id);
+ if (IS_ERR_OR_NULL(session))
+ return NULL;
+
+ read_lock(&session->stream_rwlock);
+
+ stream = msm_get_stream(session, stream_id);
+
+ if (IS_ERR_OR_NULL(stream)) {
+ read_unlock(&session->stream_rwlock);
return NULL;
+ }
spin_lock_irqsave(&stream->stream_lock, flags);
@@ -263,6 +337,7 @@ static struct vb2_v4l2_buffer *msm_vb2_get_buf_by_idx(int session_id,
vb2_v4l2_buf = NULL;
end:
spin_unlock_irqrestore(&stream->stream_lock, flags);
+ read_unlock(&session->stream_rwlock);
return vb2_v4l2_buf;
}
@@ -270,15 +345,24 @@ static int msm_vb2_put_buf(struct vb2_v4l2_buffer *vb, int session_id,
unsigned int stream_id)
{
struct msm_stream *stream;
+ struct msm_session *session;
struct msm_vb2_buffer *msm_vb2;
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
int rc = 0;
unsigned long flags;
- stream = msm_get_stream(session_id, stream_id);
- if (IS_ERR_OR_NULL(stream))
+ session = msm_get_session(session_id);
+ if (IS_ERR_OR_NULL(session))
return -EINVAL;
+ read_lock(&session->stream_rwlock);
+
+ stream = msm_get_stream(session, stream_id);
+ if (IS_ERR_OR_NULL(stream)) {
+ read_unlock(&session->stream_rwlock);
+ return -EINVAL;
+ }
+
spin_lock_irqsave(&stream->stream_lock, flags);
if (vb) {
list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
@@ -306,6 +390,7 @@ static int msm_vb2_put_buf(struct vb2_v4l2_buffer *vb, int session_id,
rc = -EINVAL;
}
spin_unlock_irqrestore(&stream->stream_lock, flags);
+ read_unlock(&session->stream_rwlock);
return rc;
}
@@ -317,11 +402,21 @@ static int msm_vb2_buf_done(struct vb2_v4l2_buffer *vb, int session_id,
struct msm_vb2_buffer *msm_vb2;
struct msm_stream *stream;
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
+ struct msm_session *session;
int rc = 0;
- stream = msm_get_stream(session_id, stream_id);
- if (IS_ERR_OR_NULL(stream))
+ session = msm_get_session(session_id);
+ if (IS_ERR_OR_NULL(session))
return -EINVAL;
+
+ read_lock(&session->stream_rwlock);
+
+ stream = msm_get_stream(session, stream_id);
+ if (IS_ERR_OR_NULL(stream)) {
+ read_unlock(&session->stream_rwlock);
+ return -EINVAL;
+ }
+
spin_lock_irqsave(&stream->stream_lock, flags);
if (vb) {
list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
@@ -353,6 +448,7 @@ static int msm_vb2_buf_done(struct vb2_v4l2_buffer *vb, int session_id,
rc = -EINVAL;
}
spin_unlock_irqrestore(&stream->stream_lock, flags);
+ read_unlock(&session->stream_rwlock);
return rc;
}
@@ -361,14 +457,23 @@ long msm_vb2_return_buf_by_idx(int session_id, unsigned int stream_id,
{
struct msm_stream *stream;
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
+ struct msm_session *session;
struct msm_vb2_buffer *msm_vb2 = NULL;
unsigned long flags;
long rc = -EINVAL;
- stream = msm_get_stream(session_id, stream_id);
- if (IS_ERR_OR_NULL(stream))
+ session = msm_get_session(session_id);
+ if (IS_ERR_OR_NULL(session))
return rc;
+ read_lock(&session->stream_rwlock);
+
+ stream = msm_get_stream(session, stream_id);
+ if (IS_ERR_OR_NULL(stream)) {
+ read_unlock(&session->stream_rwlock);
+ return -EINVAL;
+ }
+
spin_lock_irqsave(&stream->stream_lock, flags);
if (!stream->vb2_q) {
@@ -394,6 +499,7 @@ long msm_vb2_return_buf_by_idx(int session_id, unsigned int stream_id,
end:
spin_unlock_irqrestore(&stream->stream_lock, flags);
+ read_unlock(&session->stream_rwlock);
return rc;
}
EXPORT_SYMBOL(msm_vb2_return_buf_by_idx);
@@ -404,10 +510,20 @@ static int msm_vb2_flush_buf(int session_id, unsigned int stream_id)
struct msm_vb2_buffer *msm_vb2;
struct msm_stream *stream;
struct vb2_v4l2_buffer *vb2_v4l2_buf = NULL;
+ struct msm_session *session;
+
+ session = msm_get_session(session_id);
+ if (IS_ERR_OR_NULL(session))
+ return -EINVAL;
- stream = msm_get_stream(session_id, stream_id);
- if (IS_ERR_OR_NULL(stream))
+ read_lock(&session->stream_rwlock);
+
+ stream = msm_get_stream(session, stream_id);
+ if (IS_ERR_OR_NULL(stream)) {
+ read_unlock(&session->stream_rwlock);
return -EINVAL;
+ }
+
spin_lock_irqsave(&stream->stream_lock, flags);
list_for_each_entry(msm_vb2, &(stream->queued_list), list) {
vb2_v4l2_buf = &(msm_vb2->vb2_v4l2_buf);
@@ -416,6 +532,7 @@ static int msm_vb2_flush_buf(int session_id, unsigned int stream_id)
msm_vb2->in_freeq = 0;
}
spin_unlock_irqrestore(&stream->stream_lock, flags);
+ read_unlock(&session->stream_rwlock);
return 0;
}
diff --git a/drivers/media/platform/msm/ais/msm_vb2/msm_vb2.h b/drivers/media/platform/msm/ais/msm_vb2/msm_vb2.h
index 3dbb21332857..0f57112e82f2 100644
--- a/drivers/media/platform/msm/ais/msm_vb2/msm_vb2.h
+++ b/drivers/media/platform/msm/ais/msm_vb2/msm_vb2.h
@@ -68,5 +68,6 @@ struct vb2_mem_ops *msm_vb2_get_q_mem_ops(void);
int msm_vb2_request_cb(struct msm_sd_req_vb2_q *req_sd);
long msm_vb2_return_buf_by_idx(int session_id, unsigned int stream_id,
uint32_t index);
+int msm_vb2_get_stream_state(struct msm_stream *stream);
#endif /*_MSM_VB_H */
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index e2f068a21c28..0352ae9cb595 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -2296,6 +2296,8 @@ static void msm_isp_input_disable(struct vfe_device *vfe_dev, int cmd_type)
ms_res->src_info[src_info->dual_hw_ms_info.index] =
NULL;
ms_res->num_src--;
+ if (ms_res->num_src == 0)
+ ms_res->dual_sync_mode = MSM_ISP_DUAL_CAM_ASYNC;
src_info->dual_hw_ms_info.sync_state =
MSM_ISP_DUAL_CAM_ASYNC;
src_info->dual_hw_type = DUAL_NONE;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
index 5376e1e4b6a4..491b8d31935a 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/flash/msm_flash.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2009-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2009-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1144,13 +1144,13 @@ static long msm_flash_subdev_do_ioctl(
sd = vdev_to_v4l2_subdev(vdev);
u32 = (struct msm_flash_cfg_data_t32 *)arg;
- flash_data.cfg_type = u32->cfg_type;
- for (i = 0; i < MAX_LED_TRIGGERS; i++) {
- flash_data.flash_current[i] = u32->flash_current[i];
- flash_data.flash_duration[i] = u32->flash_duration[i];
- }
switch (cmd) {
case VIDIOC_MSM_FLASH_CFG32:
+ flash_data.cfg_type = u32->cfg_type;
+ for (i = 0; i < MAX_LED_TRIGGERS; i++) {
+ flash_data.flash_current[i] = u32->flash_current[i];
+ flash_data.flash_duration[i] = u32->flash_duration[i];
+ }
cmd = VIDIOC_MSM_FLASH_CFG;
switch (flash_data.cfg_type) {
case CFG_FLASH_OFF:
diff --git a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c
index b3e5dc7f9cb8..c5cdee1bf706 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/io/msm_camera_tz_i2c.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016, 2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -520,14 +520,16 @@ int32_t msm_camera_tz_i2c_power_up(
msm_camera_tz_get_ta_handle(),
sensor_id,
&sensor_secure);
- if (!rc && sensor_secure)
+ if (!rc && sensor_secure) {
/* Sensor validated by TA*/
sensor_info[sensor_id].ready++;
+ msm_camera_tz_unlock();
+ }
else {
+ msm_camera_tz_unlock();
msm_camera_tz_unload_ta();
rc = -EFAULT;
}
- msm_camera_tz_unlock();
}
} else
rc = -EFAULT;
diff --git a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
index c94ee509631f..bfb15846e73c 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/ois/msm_ois.c
@@ -774,11 +774,10 @@ static long msm_ois_subdev_do_ioctl(
u32 = (struct msm_ois_cfg_data32 *)arg;
parg = arg;
- ois_data.cfgtype = u32->cfgtype;
-
switch (cmd) {
case VIDIOC_MSM_OIS_CFG32:
cmd = VIDIOC_MSM_OIS_CFG;
+ ois_data.cfgtype = u32->cfgtype;
switch (u32->cfgtype) {
case CFG_OIS_CONTROL:
@@ -812,7 +811,6 @@ static long msm_ois_subdev_do_ioctl(
settings.reg_setting =
compat_ptr(settings32.reg_setting);
- ois_data.cfgtype = u32->cfgtype;
ois_data.cfg.settings = &settings;
parg = &ois_data;
break;
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 0acbe81eb6ce..24485466704b 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -5230,6 +5230,26 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&ar->conf_mutex);
}
+static int ath10k_change_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ enum nl80211_iftype new_type, bool p2p)
+{
+ struct ath10k *ar = hw->priv;
+ int ret = 0;
+
+ ath10k_dbg(ar, ATH10K_DBG_MAC,
+ "change_interface new: %d (%d), old: %d (%d)\n", new_type,
+ p2p, vif->type, vif->p2p);
+
+ if (new_type != vif->type || vif->p2p != p2p) {
+ ath10k_remove_interface(hw, vif);
+ vif->type = new_type;
+ vif->p2p = p2p;
+ ret = ath10k_add_interface(hw, vif);
+ }
+ return ret;
+}
+
/*
* FIXME: Has to be verified.
*/
@@ -7471,6 +7491,7 @@ static const struct ieee80211_ops ath10k_ops = {
.stop = ath10k_stop,
.config = ath10k_config,
.add_interface = ath10k_add_interface,
+ .change_interface = ath10k_change_interface,
.remove_interface = ath10k_remove_interface,
.configure_filter = ath10k_configure_filter,
.bss_info_changed = ath10k_bss_info_changed,
diff --git a/drivers/net/wireless/cnss/cnss_pci.c b/drivers/net/wireless/cnss/cnss_pci.c
index 48d358c4722a..22c59d8c3c45 100644
--- a/drivers/net/wireless/cnss/cnss_pci.c
+++ b/drivers/net/wireless/cnss/cnss_pci.c
@@ -134,6 +134,7 @@ static DEFINE_SPINLOCK(pci_link_down_lock);
#define FW_IMAGE_MISSION (0x02)
#define FW_IMAGE_BDATA (0x03)
#define FW_IMAGE_PRINT (0x04)
+#define FW_SETUP_DELAY 2000
#define SEG_METADATA (0x01)
#define SEG_NON_PAGED (0x02)
@@ -244,7 +245,7 @@ static struct cnss_data {
struct pci_saved_state *saved_state;
u16 revision_id;
bool recovery_in_progress;
- bool fw_available;
+ atomic_t fw_available;
struct codeswap_codeseg_info *cnss_seg_info;
/* Virtual Address of the DMA page */
void *codeseg_cpuaddr[CODESWAP_MAX_CODESEGS];
@@ -273,6 +274,10 @@ static struct cnss_data {
u32 fw_dma_size;
u32 fw_seg_count;
struct segment_memory fw_seg_mem[MAX_NUM_OF_SEGMENTS];
+ atomic_t fw_store_in_progress;
+ /* Firmware setup complete lock */
+ struct mutex fw_setup_stat_lock;
+ struct completion fw_setup_complete;
void *bdata_cpu;
dma_addr_t bdata_dma;
u32 bdata_dma_size;
@@ -1369,10 +1374,21 @@ int cnss_get_fw_image(struct image_desc_info *image_desc_info)
!penv->fw_seg_count || !penv->bdata_seg_count)
return -EINVAL;
+ /* Check for firmware setup trigger by usersapce is in progress
+ * and wait for complition of firmware setup.
+ */
+
+ if (atomic_read(&penv->fw_store_in_progress)) {
+ wait_for_completion_timeout(&penv->fw_setup_complete,
+ msecs_to_jiffies(FW_SETUP_DELAY));
+ }
+
+ mutex_lock(&penv->fw_setup_stat_lock);
image_desc_info->fw_addr = penv->fw_dma;
image_desc_info->fw_size = penv->fw_dma_size;
image_desc_info->bdata_addr = penv->bdata_dma;
image_desc_info->bdata_size = penv->bdata_dma_size;
+ mutex_unlock(&penv->fw_setup_stat_lock);
return 0;
}
@@ -1552,7 +1568,7 @@ static int cnss_wlan_pci_probe(struct pci_dev *pdev,
penv->pdev = pdev;
penv->id = id;
- penv->fw_available = false;
+ atomic_set(&penv->fw_available, 0);
penv->device_id = pdev->device;
if (penv->smmu_iova_len) {
@@ -1858,8 +1874,19 @@ static ssize_t fw_image_setup_store(struct device *dev,
if (!penv)
return -ENODEV;
- if (sscanf(buf, "%d", &val) != 1)
+ if (atomic_read(&penv->fw_store_in_progress)) {
+ pr_info("%s: Firmware setup in progress\n", __func__);
+ return 0;
+ }
+
+ atomic_set(&penv->fw_store_in_progress, 1);
+ init_completion(&penv->fw_setup_complete);
+
+ if (kstrtoint(buf, 0, &val)) {
+ atomic_set(&penv->fw_store_in_progress, 0);
+ complete(&penv->fw_setup_complete);
return -EINVAL;
+ }
if (val == FW_IMAGE_FTM || val == FW_IMAGE_MISSION
|| val == FW_IMAGE_BDATA) {
@@ -1868,6 +1895,8 @@ static ssize_t fw_image_setup_store(struct device *dev,
if (ret != 0) {
pr_err("%s: Invalid parsing of FW image files %d",
__func__, ret);
+ atomic_set(&penv->fw_store_in_progress, 0);
+ complete(&penv->fw_setup_complete);
return -EINVAL;
}
penv->fw_image_setup = val;
@@ -1877,6 +1906,9 @@ static ssize_t fw_image_setup_store(struct device *dev,
penv->bmi_test = val;
}
+ atomic_set(&penv->fw_store_in_progress, 0);
+ complete(&penv->fw_setup_complete);
+
return count;
}
@@ -1979,7 +2011,7 @@ int cnss_get_codeswap_struct(struct codeswap_codeseg_info *swap_seg)
swap_seg = NULL;
return -ENOENT;
}
- if (!penv->fw_available) {
+ if (!atomic_read(&penv->fw_available)) {
pr_debug("%s: fw is not available\n", __func__);
return -ENOENT;
}
@@ -2003,6 +2035,16 @@ static void cnss_wlan_memory_expansion(void)
u_int32_t total_length = 0;
struct pci_dev *pdev;
+ /* Check for firmware setup trigger by usersapce is in progress
+ * and wait for complition of firmware setup.
+ */
+
+ if (atomic_read(&penv->fw_store_in_progress)) {
+ wait_for_completion_timeout(&penv->fw_setup_complete,
+ msecs_to_jiffies(FW_SETUP_DELAY));
+ }
+
+ mutex_lock(&penv->fw_setup_stat_lock);
filename = cnss_wlan_get_evicted_data_file();
pdev = penv->pdev;
dev = &pdev->dev;
@@ -2010,21 +2052,25 @@ static void cnss_wlan_memory_expansion(void)
if (!cnss_seg_info) {
pr_debug("cnss: cnss_seg_info is NULL\n");
+ mutex_unlock(&penv->fw_setup_stat_lock);
goto end;
}
- if (penv->fw_available) {
+ if (atomic_read(&penv->fw_available)) {
pr_debug("cnss: fw code already copied to host memory\n");
+ mutex_unlock(&penv->fw_setup_stat_lock);
goto end;
}
if (request_firmware(&fw_entry, filename, dev) != 0) {
pr_debug("cnss: failed to get fw: %s\n", filename);
+ mutex_unlock(&penv->fw_setup_stat_lock);
goto end;
}
if (!fw_entry || !fw_entry->data) {
pr_err("%s: INVALID FW entries\n", __func__);
+ mutex_unlock(&penv->fw_setup_stat_lock);
goto release_fw;
}
@@ -2059,7 +2105,9 @@ static void cnss_wlan_memory_expansion(void)
}
pr_debug("cnss: total_bytes copied: %d\n", total_length);
cnss_seg_info->codeseg_total_bytes = total_length;
- penv->fw_available = 1;
+
+ atomic_set(&penv->fw_available, 1);
+ mutex_unlock(&penv->fw_setup_stat_lock);
release_fw:
release_firmware(fw_entry);
@@ -2968,6 +3016,8 @@ skip_ramdump:
memset(phys_to_virt(0), 0, SZ_4K);
#endif
+ atomic_set(&penv->fw_store_in_progress, 0);
+ mutex_init(&penv->fw_setup_stat_lock);
ret = device_create_file(dev, &dev_attr_fw_image_setup);
if (ret) {
pr_err("cnss: fw_image_setup sys file creation failed\n");
diff --git a/drivers/perf/arm_pmu.c b/drivers/perf/arm_pmu.c
index 39400dda27c2..63ec68e6ac2a 100644
--- a/drivers/perf/arm_pmu.c
+++ b/drivers/perf/arm_pmu.c
@@ -552,7 +552,6 @@ static void armpmu_init(struct arm_pmu *armpmu)
.stop = armpmu_stop,
.read = armpmu_read,
.filter_match = armpmu_filter_match,
- .events_across_hotplug = 1,
};
}
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index 08bffc344429..b111a5904952 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -1319,6 +1319,35 @@ int gsi_query_evt_ring_db_addr(unsigned long evt_ring_hdl,
}
EXPORT_SYMBOL(gsi_query_evt_ring_db_addr);
+int gsi_ring_evt_ring_db(unsigned long evt_ring_hdl, uint64_t value)
+{
+ struct gsi_evt_ctx *ctx;
+
+ if (!gsi_ctx) {
+ pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__);
+ return -GSI_STATUS_NODEV;
+ }
+
+ if (evt_ring_hdl >= gsi_ctx->max_ev) {
+ GSIERR("bad params evt_ring_hdl=%lu\n", evt_ring_hdl);
+ return -GSI_STATUS_INVALID_PARAMS;
+ }
+
+ ctx = &gsi_ctx->evtr[evt_ring_hdl];
+
+ if (ctx->state != GSI_EVT_RING_STATE_ALLOCATED) {
+ GSIERR("bad state %d\n",
+ gsi_ctx->evtr[evt_ring_hdl].state);
+ return -GSI_STATUS_UNSUPPORTED_OP;
+ }
+
+ ctx->ring.wp_local = value;
+ gsi_ring_evt_doorbell(ctx);
+
+ return GSI_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(gsi_ring_evt_ring_db);
+
int gsi_reset_evt_ring(unsigned long evt_ring_hdl)
{
uint32_t val;
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index a02247d3e938..5aa39b699bd6 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2016 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -1059,6 +1059,7 @@ static void ipa_mhi_gsi_ev_err_cb(struct gsi_evt_err_notify *notify)
IPA_MHI_ERR("Unexpected err evt: %d\n", notify->evt_id);
}
IPA_MHI_ERR("err_desc=0x%x\n", notify->err_desc);
+ ipa_assert();
}
static void ipa_mhi_gsi_ch_err_cb(struct gsi_chan_err_notify *notify)
@@ -1090,6 +1091,7 @@ static void ipa_mhi_gsi_ch_err_cb(struct gsi_chan_err_notify *notify)
IPA_MHI_ERR("Unexpected err evt: %d\n", notify->evt_id);
}
IPA_MHI_ERR("err_desc=0x%x\n", notify->err_desc);
+ ipa_assert();
}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
index e349ade46075..bc6622d4725b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_client.c
@@ -1668,8 +1668,21 @@ static int ipa3_stop_ul_chan_with_data_drain(u32 qmi_req_id,
if (should_force_clear) {
result = ipa3_enable_force_clear(qmi_req_id, false,
source_pipe_bitmask);
- if (result)
- goto exit;
+ if (result) {
+ struct ipahal_ep_cfg_ctrl_scnd ep_ctrl_scnd = { 0 };
+
+ /*
+ * assuming here modem SSR\shutdown, AP can remove
+ * the delay in this case
+ */
+ IPAERR(
+ "failed to force clear %d, remove delay from SCND reg\n"
+ , result);
+ ep_ctrl_scnd.endp_delay = false;
+ ipahal_write_reg_n_fields(
+ IPA_ENDP_INIT_CTRL_SCND_n, clnt_hdl,
+ &ep_ctrl_scnd);
+ }
}
/* with force clear, wait for emptiness */
for (i = 0; i < IPA_POLL_FOR_EMPTINESS_NUM; i++) {
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index 9e2ffe70170c..cd027c28e597 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
@@ -255,6 +255,24 @@ static int ipa_mhi_start_gsi_channel(enum ipa_client_type client,
ep->gsi_evt_ring_hdl = *params->cached_gsi_evt_ring_hdl;
}
+ if (params->ev_ctx_host->wp == params->ev_ctx_host->rbase) {
+ IPA_MHI_ERR("event ring wp is not updated. base=wp=0x%llx\n",
+ params->ev_ctx_host->wp);
+ goto fail_alloc_ch;
+ return res;
+ }
+
+ IPA_MHI_DBG("Ring event db: evt_ring_hdl=%lu host_wp=0x%llx\n",
+ ep->gsi_evt_ring_hdl, params->ev_ctx_host->wp);
+ res = gsi_ring_evt_ring_db(ep->gsi_evt_ring_hdl,
+ params->ev_ctx_host->wp);
+ if (res) {
+ IPA_MHI_ERR("fail to ring evt ring db %d. hdl=%lu wp=0x%llx\n",
+ res, ep->gsi_evt_ring_hdl, params->ev_ctx_host->wp);
+ goto fail_alloc_ch;
+ return res;
+ }
+
memset(&ch_props, 0, sizeof(ch_props));
ch_props.prot = GSI_CHAN_PROT_MHI;
ch_props.dir = IPA_CLIENT_IS_PROD(client) ?
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index df5454e4776c..5397b6c39419 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -1140,7 +1140,8 @@ send:
memset(&meta, 0, sizeof(meta));
meta.pkt_init_dst_ep_valid = true;
meta.pkt_init_dst_ep_remote = true;
- meta.pkt_init_dst_ep = IPA_CLIENT_Q6_LAN_CONS;
+ meta.pkt_init_dst_ep =
+ ipa3_get_ep_mapping(IPA_CLIENT_Q6_WAN_CONS);
ret = ipa3_tx_dp(IPA_CLIENT_APPS_WAN_PROD, skb, &meta);
} else {
ret = ipa3_tx_dp(IPA_CLIENT_APPS_WAN_PROD, skb, NULL);
diff --git a/drivers/power/reset/msm-poweroff.c b/drivers/power/reset/msm-poweroff.c
index acea4f213484..e17c65c1e4e7 100644
--- a/drivers/power/reset/msm-poweroff.c
+++ b/drivers/power/reset/msm-poweroff.c
@@ -47,7 +47,7 @@
#define SCM_EDLOAD_MODE 0X01
#define SCM_DLOAD_CMD 0x10
#define SCM_DLOAD_MINIDUMP 0X20
-
+#define SCM_DLOAD_BOTHDUMPS (SCM_DLOAD_MINIDUMP | SCM_DLOAD_FULLDUMP)
static int restart_mode;
static void *restart_reason;
@@ -488,7 +488,8 @@ static ssize_t show_dload_mode(struct kobject *kobj, struct attribute *attr,
char *buf)
{
return scnprintf(buf, PAGE_SIZE, "DLOAD dump type: %s\n",
- (dload_type == SCM_DLOAD_MINIDUMP) ? "mini" : "full");
+ (dload_type == SCM_DLOAD_BOTHDUMPS) ? "both" :
+ ((dload_type == SCM_DLOAD_MINIDUMP) ? "mini" : "full"));
}
static size_t store_dload_mode(struct kobject *kobj, struct attribute *attr,
@@ -502,8 +503,16 @@ static size_t store_dload_mode(struct kobject *kobj, struct attribute *attr,
return -ENODEV;
}
dload_type = SCM_DLOAD_MINIDUMP;
- } else {
- pr_err("Invalid value. Use 'full' or 'mini'\n");
+ } else if (sysfs_streq(buf, "both")) {
+ if (!minidump_enabled) {
+ pr_err("Minidump not enabled, setting fulldump only\n");
+ dload_type = SCM_DLOAD_FULLDUMP;
+ return count;
+ }
+ dload_type = SCM_DLOAD_BOTHDUMPS;
+ } else{
+ pr_err("Invalid Dump setup request..\n");
+ pr_err("Supported dumps:'full', 'mini', or 'both'\n");
return -EINVAL;
}
diff --git a/drivers/power/supply/qcom/qpnp-smb2.c b/drivers/power/supply/qcom/qpnp-smb2.c
index 49cd7aa6fdac..0908eea3b186 100644
--- a/drivers/power/supply/qcom/qpnp-smb2.c
+++ b/drivers/power/supply/qcom/qpnp-smb2.c
@@ -465,6 +465,8 @@ static int smb2_usb_get_prop(struct power_supply *psy,
val->intval = 0;
else
val->intval = 1;
+ if (chg->real_charger_type == POWER_SUPPLY_TYPE_UNKNOWN)
+ val->intval = 0;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
val->intval = chg->voltage_min_uv;
@@ -1466,15 +1468,6 @@ static int smb2_configure_typec(struct smb_charger *chg)
return rc;
}
- /* configure power role for dual-role */
- rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
- TYPEC_POWER_ROLE_CMD_MASK, 0);
- if (rc < 0) {
- dev_err(chg->dev,
- "Couldn't configure power role for DRP rc=%d\n", rc);
- return rc;
- }
-
/*
* disable Type-C factory mode and stay in Attached.SRC state when VCONN
* over-current happens
@@ -1852,6 +1845,16 @@ static int smb2_init_hw(struct smb2 *chip)
static int smb2_post_init(struct smb2 *chip)
{
struct smb_charger *chg = &chip->chg;
+ int rc;
+
+ /* configure power role for dual-role */
+ rc = smblib_masked_write(chg, TYPE_C_INTRPT_ENB_SOFTWARE_CTRL_REG,
+ TYPEC_POWER_ROLE_CMD_MASK, 0);
+ if (rc < 0) {
+ dev_err(chg->dev,
+ "Couldn't configure power role for DRP rc=%d\n", rc);
+ return rc;
+ }
rerun_election(chg->usb_irq_enable_votable);
@@ -2419,7 +2422,11 @@ static int smb2_probe(struct platform_device *pdev)
goto cleanup;
}
- smb2_post_init(chip);
+ rc = smb2_post_init(chip);
+ if (rc < 0) {
+ pr_err("Failed in post init rc=%d\n", rc);
+ goto cleanup;
+ }
smb2_create_debugfs(chip);
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index 99caa1c84dce..37193bbb23b7 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -2402,7 +2402,7 @@ static int glink_smem_native_probe(struct platform_device *pdev)
einfo->tx_fifo = smem_alloc(SMEM_GLINK_NATIVE_XPRT_FIFO_0,
einfo->tx_fifo_size,
einfo->remote_proc_id,
- SMEM_ITEM_CACHED_FLAG);
+ 0);
if (!einfo->tx_fifo) {
pr_err("%s: smem alloc of tx fifo failed\n", __func__);
rc = -ENOMEM;
diff --git a/drivers/soc/qcom/msm_glink_pkt.c b/drivers/soc/qcom/msm_glink_pkt.c
index a92e5c416678..0a80016f1942 100644
--- a/drivers/soc/qcom/msm_glink_pkt.c
+++ b/drivers/soc/qcom/msm_glink_pkt.c
@@ -33,7 +33,8 @@
#include <linux/termios.h>
#include <soc/qcom/glink.h>
-
+/* This Limit ensures that auto queue will not exhaust memory on remote side */
+#define MAX_PENDING_GLINK_PKT 5
#define MODULE_NAME "msm_glinkpkt"
#define DEVICE_NAME "glinkpkt"
#define WAKEUPSOURCE_TIMEOUT (2000) /* two seconds */
@@ -136,6 +137,7 @@ struct glink_pkt_dev {
struct glink_link_info link_info;
void *link_state_handle;
bool link_up;
+ bool auto_intent_enabled;
};
/**
@@ -447,8 +449,26 @@ void glink_pkt_notify_state(void *handle, const void *priv, unsigned event)
bool glink_pkt_rmt_rx_intent_req_cb(void *handle, const void *priv, size_t sz)
{
struct queue_rx_intent_work *work_item;
+ int pending_pkt_count = 0;
+ struct glink_rx_pkt *pkt = NULL;
+ unsigned long flags;
+ struct glink_pkt_dev *devp = (struct glink_pkt_dev *)priv;
+
GLINK_PKT_INFO("%s(): QUEUE RX INTENT to receive size[%zu]\n",
__func__, sz);
+ if (devp->auto_intent_enabled) {
+ spin_lock_irqsave(&devp->pkt_list_lock, flags);
+ list_for_each_entry(pkt, &devp->pkt_list, list)
+ pending_pkt_count++;
+ spin_unlock_irqrestore(&devp->pkt_list_lock, flags);
+ if (pending_pkt_count > MAX_PENDING_GLINK_PKT) {
+ GLINK_PKT_ERR("%s failed, max limit reached\n",
+ __func__);
+ return false;
+ }
+ } else {
+ return false;
+ }
work_item = kzalloc(sizeof(*work_item), GFP_ATOMIC);
if (!work_item) {
@@ -457,7 +477,7 @@ bool glink_pkt_rmt_rx_intent_req_cb(void *handle, const void *priv, size_t sz)
}
work_item->intent_size = sz;
- work_item->devp = (struct glink_pkt_dev *)priv;
+ work_item->devp = devp;
INIT_WORK(&work_item->work, glink_pkt_queue_rx_intent_worker);
queue_work(glink_pkt_wq, &work_item->work);
@@ -626,10 +646,11 @@ ssize_t glink_pkt_read(struct file *file,
}
mutex_lock(&devp->ch_lock);
- if (!glink_rx_intent_exists(devp->handle, count)) {
+ if (!glink_pkt_read_avail(devp) &&
+ !glink_rx_intent_exists(devp->handle, count)) {
ret = glink_queue_rx_intent(devp->handle, devp, count);
if (ret) {
- GLINK_PKT_ERR("%s: failed to queue_rx_intent ret[%d]\n",
+ GLINK_PKT_ERR("%s: failed to queue intent ret[%d]\n",
__func__, ret);
mutex_unlock(&devp->ch_lock);
return ret;
@@ -915,6 +936,7 @@ static long glink_pkt_ioctl(struct file *file, unsigned int cmd,
case GLINK_PKT_IOCTL_QUEUE_RX_INTENT:
ret = get_user(size, (uint32_t *)arg);
GLINK_PKT_INFO("%s: intent size[%d]\n", __func__, size);
+ devp->auto_intent_enabled = false;
ret = glink_queue_rx_intent(devp->handle, devp, size);
if (ret) {
GLINK_PKT_ERR("%s: failed to QUEUE_RX_INTENT ret[%d]\n",
@@ -1183,6 +1205,7 @@ static int glink_pkt_init_add_device(struct glink_pkt_dev *devp, int i)
glink_pkt_link_state_cb;
devp->i = i;
devp->poll_mode = 0;
+ devp->auto_intent_enabled = true;
devp->ws_locked = 0;
devp->ch_state = GLINK_LOCAL_DISCONNECTED;
/* Default timeout for open wait is 120sec */
diff --git a/drivers/soc/qcom/wcd-dsp-glink.c b/drivers/soc/qcom/wcd-dsp-glink.c
index 3c9d8efd3956..5fe3c572628b 100644
--- a/drivers/soc/qcom/wcd-dsp-glink.c
+++ b/drivers/soc/qcom/wcd-dsp-glink.c
@@ -58,6 +58,7 @@ struct wdsp_glink_rsp_que {
struct wdsp_glink_tx_buf {
struct work_struct tx_work;
+ struct work_struct free_tx_work;
/* Glink channel information */
struct wdsp_glink_ch *ch;
@@ -125,6 +126,46 @@ static int wdsp_glink_close_ch(struct wdsp_glink_ch *ch);
static int wdsp_glink_open_ch(struct wdsp_glink_ch *ch);
/*
+ * wdsp_glink_free_tx_buf_work - Work function to free tx pkt
+ * work: Work structure
+ */
+static void wdsp_glink_free_tx_buf_work(struct work_struct *work)
+{
+ struct wdsp_glink_tx_buf *tx_buf;
+
+ tx_buf = container_of(work, struct wdsp_glink_tx_buf,
+ free_tx_work);
+ vfree(tx_buf);
+}
+
+/*
+ * wdsp_glink_free_tx_buf - Function to free tx buffer
+ * priv: Pointer to the channel
+ * pkt_priv: Pointer to the tx buffer
+ */
+static void wdsp_glink_free_tx_buf(const void *priv, const void *pkt_priv)
+{
+ struct wdsp_glink_tx_buf *tx_buf = (struct wdsp_glink_tx_buf *)pkt_priv;
+ struct wdsp_glink_priv *wpriv;
+ struct wdsp_glink_ch *ch;
+
+ if (!priv) {
+ pr_err("%s: Invalid priv\n", __func__);
+ return;
+ }
+ if (!tx_buf) {
+ pr_err("%s: Invalid tx_buf\n", __func__);
+ return;
+ }
+
+ ch = (struct wdsp_glink_ch *)priv;
+ wpriv = ch->wpriv;
+ /* Work queue to free tx pkt */
+ INIT_WORK(&tx_buf->free_tx_work, wdsp_glink_free_tx_buf_work);
+ queue_work(wpriv->work_queue, &tx_buf->free_tx_work);
+}
+
+/*
* wdsp_glink_notify_rx - Glink notify rx callback for responses
* handle: Opaque Channel handle returned by GLink
* priv: Private pointer to the channel
@@ -183,14 +224,8 @@ static void wdsp_glink_notify_rx(void *handle, const void *priv,
static void wdsp_glink_notify_tx_done(void *handle, const void *priv,
const void *pkt_priv, const void *ptr)
{
- if (!pkt_priv) {
- pr_err("%s: Invalid parameter\n", __func__);
- return;
- }
- /* Free tx pkt */
- vfree(pkt_priv);
+ wdsp_glink_free_tx_buf(priv, pkt_priv);
}
-
/*
* wdsp_glink_notify_tx_abort - Glink notify tx abort callback to
* free tx buffer
@@ -201,12 +236,7 @@ static void wdsp_glink_notify_tx_done(void *handle, const void *priv,
static void wdsp_glink_notify_tx_abort(void *handle, const void *priv,
const void *pkt_priv)
{
- if (!pkt_priv) {
- pr_err("%s: Invalid parameter\n", __func__);
- return;
- }
- /* Free tx pkt */
- vfree(pkt_priv);
+ wdsp_glink_free_tx_buf(priv, pkt_priv);
}
/*
@@ -555,7 +585,7 @@ static int wdsp_glink_ch_info_init(struct wdsp_glink_priv *wpriv,
goto done;
}
ch = kcalloc(no_of_channels, sizeof(struct wdsp_glink_ch *),
- GFP_KERNEL);
+ GFP_ATOMIC);
if (!ch) {
ret = -ENOMEM;
goto done;
diff --git a/fs/mbcache.c b/fs/mbcache.c
index ab1da987d1ae..de509271d031 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -222,8 +222,19 @@ __mb_cache_entry_release(struct mb_cache_entry *ce)
* then reacquire the lock in the proper order.
*/
spin_lock(&mb_cache_spinlock);
- if (list_empty(&ce->e_lru_list))
- list_add_tail(&ce->e_lru_list, &mb_cache_lru_list);
+ /*
+ * Evaluate the conditions under global lock mb_cache_spinlock,
+ * to check if mb_cache_entry_get() is running now
+ * and has already deleted the entry from mb_cache_lru_list
+ * and incremented ce->e_refcnt to prevent further additions
+ * to mb_cache_lru_list.
+ */
+ if (!(ce->e_used || ce->e_queued ||
+ atomic_read(&ce->e_refcnt))) {
+ if (list_empty(&ce->e_lru_list))
+ list_add_tail(&ce->e_lru_list,
+ &mb_cache_lru_list);
+ }
spin_unlock(&mb_cache_spinlock);
}
__spin_unlock_mb_cache_entry(ce);
diff --git a/include/linux/ipc_router.h b/include/linux/ipc_router.h
index 04a06df66d4b..94f779f6a666 100644
--- a/include/linux/ipc_router.h
+++ b/include/linux/ipc_router.h
@@ -144,6 +144,7 @@ struct msm_ipc_port {
uint32_t num_rx;
unsigned long num_tx_bytes;
unsigned long num_rx_bytes;
+ uint32_t last_served_svc_id;
void *priv;
};
diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h
index d4b4cc7f8737..b95ea88c2424 100644
--- a/include/linux/msm_gsi.h
+++ b/include/linux/msm_gsi.h
@@ -749,6 +749,18 @@ int gsi_query_evt_ring_db_addr(unsigned long evt_ring_hdl,
uint32_t *db_addr_wp_lsb, uint32_t *db_addr_wp_msb);
/**
+ * gsi_ring_evt_ring_db - Peripheral should call this function for
+ * ringing the event ring doorbell with given value
+ *
+ * @evt_ring_hdl: Client handle previously obtained from
+ * gsi_alloc_evt_ring
+ * @value: The value to be used for ringing the doorbell
+ *
+ * @Return gsi_status
+ */
+int gsi_ring_evt_ring_db(unsigned long evt_ring_hdl, uint64_t value);
+
+/**
* gsi_reset_evt_ring - Peripheral should call this function to
* reset an event ring to recover from error state
*
@@ -1138,6 +1150,12 @@ static inline int gsi_query_evt_ring_db_addr(unsigned long evt_ring_hdl,
return -GSI_STATUS_UNSUPPORTED_OP;
}
+static inline int gsi_ring_evt_ring_db(unsigned long evt_ring_hdl,
+ uint64_t value)
+{
+ return -GSI_STATUS_UNSUPPORTED_OP;
+}
+
static inline int gsi_reset_evt_ring(unsigned long evt_ring_hdl)
{
return -GSI_STATUS_UNSUPPORTED_OP;
diff --git a/include/uapi/drm/drm_fourcc.h b/include/uapi/drm/drm_fourcc.h
index 7f203a5f83cb..b3a2c62da965 100644
--- a/include/uapi/drm/drm_fourcc.h
+++ b/include/uapi/drm/drm_fourcc.h
@@ -241,8 +241,23 @@ extern "C" {
*/
#define DRM_FORMAT_MOD_QCOM_COMPRESSED fourcc_mod_code(QCOM, 1)
+/*
+ * QTI DX Format
+ *
+ * Refers to a DX variant of the base format.
+ * Implementation may be platform and base-format specific.
+ */
+#define DRM_FORMAT_MOD_QCOM_DX fourcc_mod_code(QCOM, 0x2)
+
+/*
+ * QTI Tight Format
+ *
+ * Refers to a tightly packed variant of the base format.
+ * Implementation may be platform and base-format specific.
+ */
+#define DRM_FORMAT_MOD_QCOM_TIGHT fourcc_mod_code(QCOM, 0x4)
+
#if defined(__cplusplus)
}
#endif
-
#endif /* DRM_FOURCC_H */
diff --git a/include/uapi/drm/msm_drm.h b/include/uapi/drm/msm_drm.h
index d8b8ef16b14a..a60e84ab905b 100644
--- a/include/uapi/drm/msm_drm.h
+++ b/include/uapi/drm/msm_drm.h
@@ -62,6 +62,41 @@ struct drm_msm_timespec {
__s64 tv_nsec; /* nanoseconds */
};
+/*
+ * HDR Metadata
+ * These are defined as per EDID spec and shall be used by the sink
+ * to set the HDR metadata for playback from userspace.
+ */
+
+#define HDR_PRIMARIES_COUNT 3
+
+struct drm_msm_ext_panel_hdr_metadata {
+ __u32 eotf; /* electro optical transfer function */
+ __u32 hdr_supported; /* HDR supported */
+ __u32 display_primaries_x[HDR_PRIMARIES_COUNT]; /* Primaries x */
+ __u32 display_primaries_y[HDR_PRIMARIES_COUNT]; /* Primaries y */
+ __u32 white_point_x; /* white_point_x */
+ __u32 white_point_y; /* white_point_y */
+ __u32 max_luminance; /* Max luminance */
+ __u32 min_luminance; /* Min Luminance */
+ __u32 max_content_light_level; /* max content light level */
+ __u32 max_average_light_level; /* max average light level */
+};
+
+/**
+ * HDR sink properties
+ * These are defined as per EDID spec and shall be used by the userspace
+ * to determine the HDR properties to be set to the sink.
+ */
+struct drm_msm_ext_panel_hdr_properties {
+ __u8 hdr_metadata_type_one; /* static metadata type one */
+ __u32 hdr_supported; /* HDR supported */
+ __u32 hdr_eotf; /* electro optical transfer function */
+ __u32 hdr_max_luminance; /* Max luminance */
+ __u32 hdr_avg_luminance; /* Avg luminance */
+ __u32 hdr_min_luminance; /* Min Luminance */
+};
+
#define MSM_PARAM_GPU_ID 0x01
#define MSM_PARAM_GMEM_SIZE 0x02
#define MSM_PARAM_CHIP_ID 0x03
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 6cd152e99891..7fee87daac56 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1693,33 +1693,7 @@ static int __perf_remove_from_context(void *info)
return 0;
}
-
-#ifdef CONFIG_SMP
-static void perf_retry_remove(struct perf_event *event,
- struct remove_event *rep)
-{
- int up_ret;
- /*
- * CPU was offline. Bring it online so we can
- * gracefully exit a perf context.
- */
- up_ret = cpu_up(event->cpu);
- if (!up_ret)
- /* Try the remove call once again. */
- cpu_function_call(event->cpu, __perf_remove_from_context,
- rep);
- else
- pr_err("Failed to bring up CPU: %d, ret: %d\n",
- event->cpu, up_ret);
-}
-#else
-static void perf_retry_remove(struct perf_event *event,
- struct remove_event *rep)
-{
-}
-#endif
-
- /*
+/*
* Remove the event from a task's (or a CPU's) list of events.
*
* CPU events are removed with a smp call. For task events we only
@@ -1754,9 +1728,6 @@ static void __ref perf_remove_from_context(struct perf_event *event,
*/
ret = cpu_function_call(event->cpu, __perf_remove_from_context,
&re);
- if (ret == -ENXIO)
- perf_retry_remove(event, &re);
-
return;
}
@@ -7138,8 +7109,6 @@ static struct pmu perf_swevent = {
.start = perf_swevent_start,
.stop = perf_swevent_stop,
.read = perf_swevent_read,
-
- .events_across_hotplug = 1,
};
#ifdef CONFIG_EVENT_TRACING
@@ -7261,8 +7230,6 @@ static struct pmu perf_tracepoint = {
.start = perf_swevent_start,
.stop = perf_swevent_stop,
.read = perf_swevent_read,
-
- .events_across_hotplug = 1,
};
static inline void perf_tp_register(void)
@@ -7550,8 +7517,6 @@ static struct pmu perf_cpu_clock = {
.start = cpu_clock_event_start,
.stop = cpu_clock_event_stop,
.read = cpu_clock_event_read,
-
- .events_across_hotplug = 1,
};
/*
@@ -7633,8 +7598,6 @@ static struct pmu perf_task_clock = {
.start = task_clock_event_start,
.stop = task_clock_event_stop,
.read = task_clock_event_read,
-
- .events_across_hotplug = 1,
};
static void perf_pmu_nop_void(struct pmu *pmu)
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index 7da5b674d16e..92ce5f4ccc26 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -614,8 +614,6 @@ static struct pmu perf_breakpoint = {
.start = hw_breakpoint_start,
.stop = hw_breakpoint_stop,
.read = hw_breakpoint_pmu_read,
-
- .events_across_hotplug = 1,
};
int __init init_hw_breakpoint(void)
diff --git a/net/ipc_router/ipc_router_core.c b/net/ipc_router/ipc_router_core.c
index f08aef9509bb..5cb309a11f82 100644
--- a/net/ipc_router/ipc_router_core.c
+++ b/net/ipc_router/ipc_router_core.c
@@ -364,6 +364,8 @@ static void ipc_router_log_msg(void *log_ctx, uint32_t xchng_type,
svcId = rport_ptr->server->name.service;
svcIns = rport_ptr->server->name.instance;
port_type = CLIENT_PORT;
+ port_ptr->last_served_svc_id =
+ rport_ptr->server->name.service;
} else if (port_ptr && (port_ptr->type == SERVER_PORT)) {
svcId = port_ptr->port_name.service;
svcIns = port_ptr->port_name.instance;
@@ -1329,8 +1331,9 @@ struct msm_ipc_port *msm_ipc_router_create_raw_port(void *endpoint,
mutex_init(&port_ptr->port_rx_q_lock_lhc3);
init_waitqueue_head(&port_ptr->port_rx_wait_q);
snprintf(port_ptr->rx_ws_name, MAX_WS_NAME_SZ,
- "ipc%08x_%s",
+ "ipc%08x_%d_%s",
port_ptr->this_port.port_id,
+ task_pid_nr(current),
current->comm);
port_ptr->port_rx_ws = wakeup_source_register(port_ptr->rx_ws_name);
if (!port_ptr->port_rx_ws) {
@@ -3867,16 +3870,18 @@ static void dump_local_ports(struct seq_file *s)
int j;
struct msm_ipc_port *port_ptr;
- seq_printf(s, "%-11s|%-11s|\n",
- "Node_id", "Port_id");
+ seq_printf(s, "%-11s|%-11s|%-32s|%-11s|\n",
+ "Node_id", "Port_id", "Wakelock", "Last SVCID");
seq_puts(s, "------------------------------------------------------------\n");
down_read(&local_ports_lock_lhc2);
for (j = 0; j < LP_HASH_SIZE; j++) {
list_for_each_entry(port_ptr, &local_ports[j], list) {
mutex_lock(&port_ptr->port_lock_lhc3);
- seq_printf(s, "0x%08x |0x%08x |\n",
- port_ptr->this_port.node_id,
- port_ptr->this_port.port_id);
+ seq_printf(s, "0x%08x |0x%08x |%-32s|0x%08x |\n",
+ port_ptr->this_port.node_id,
+ port_ptr->this_port.port_id,
+ port_ptr->rx_ws_name,
+ port_ptr->last_served_svc_id);
mutex_unlock(&port_ptr->port_lock_lhc3);
}
}