Merge "usb: dwc3-msm: Ensure separate EUD extcon dev is used"
diff --git a/arch/arm64/boot/Makefile b/arch/arm64/boot/Makefile
index 92dc1e6..b97f1de 100644
--- a/arch/arm64/boot/Makefile
+++ b/arch/arm64/boot/Makefile
@@ -28,6 +28,17 @@
DTB_OBJS := $(shell find $(obj)/dts/ -name \*.dtb)
endif
+# Add RTIC DTB to the DTB list if RTIC MPGen is enabled
+ifdef RTIC_MPGEN
+DTB_OBJS += rtic_mp.dtb
+endif
+
+rtic_mp.dtb: vmlinux FORCE
+ $(RTIC_MPGEN) --objcopy="${OBJCOPY}" --objdump="${OBJDUMP}" \
+ --binpath="" --vmlinux="vmlinux" --config=${KCONFIG_CONFIG} \
+ --cc="${CC}" --dts=rtic_mp.dts && \
+ $(DTC) -O dtb -o rtic_mp.dtb -b 0 $(DTC_FLAGS) rtic_mp.dts
+
$(obj)/Image: vmlinux FORCE
$(call if_changed,objcopy)
diff --git a/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi b/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
index 6dd1b749..78dab37 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
@@ -25,8 +25,8 @@
compatible = "qcom,smp2p";
reg = <0x1799000c 0x4>;
qcom,remote-pid = <2>;
- qcom,irq-bitmask = <0x200>;
- interrupts = <GIC_SPI 157 IRQ_TYPE_EDGE_RISING>;
+ qcom,irq-bitmask = <0x4000000>;
+ interrupts = <GIC_SPI 172 IRQ_TYPE_EDGE_RISING>;
};
qcom,smp2p-cdsp@1799000c {
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index 21c40fc..a5e682c 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -1113,8 +1113,8 @@
reg = <0x86000000 0x200000>,
<0x1799000c 0x4>;
reg-names = "smem", "irq-reg-base";
- qcom,irq-mask = <0x100>;
- interrupts = <GIC_SPI 156 IRQ_TYPE_EDGE_RISING>;
+ qcom,irq-mask = <0x1000000>;
+ interrupts = <GIC_SPI 170 IRQ_TYPE_EDGE_RISING>;
label = "lpass";
qcom,qos-config = <&glink_qos_adsp>;
qcom,ramp-time = <0xaf>;
diff --git a/arch/arm64/configs/sdm845-perf_defconfig b/arch/arm64/configs/sdm845-perf_defconfig
index 5872f88..60db878 100644
--- a/arch/arm64/configs/sdm845-perf_defconfig
+++ b/arch/arm64/configs/sdm845-perf_defconfig
@@ -403,6 +403,7 @@
CONFIG_USB_PD_POLICY=y
CONFIG_QPNP_USB_PDPHY=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_MSM_SSPHY_QMP=y
diff --git a/arch/arm64/configs/sdm845_defconfig b/arch/arm64/configs/sdm845_defconfig
index 82455e5..08d3b0f 100644
--- a/arch/arm64/configs/sdm845_defconfig
+++ b/arch/arm64/configs/sdm845_defconfig
@@ -407,6 +407,7 @@
CONFIG_USB_PD_POLICY=y
CONFIG_QPNP_USB_PDPHY=y
CONFIG_USB_EHSET_TEST_FIXTURE=y
+CONFIG_USB_LINK_LAYER_TEST=y
CONFIG_NOP_USB_XCEIV=y
CONFIG_DUAL_ROLE_USB_INTF=y
CONFIG_USB_MSM_SSPHY_QMP=y
diff --git a/drivers/char/diag/diagchar.h b/drivers/char/diag/diagchar.h
index 26e91f9..8051d5d 100644
--- a/drivers/char/diag/diagchar.h
+++ b/drivers/char/diag/diagchar.h
@@ -580,6 +580,7 @@
unsigned char *buf_feature_mask_update;
uint8_t hdlc_disabled;
struct mutex hdlc_disable_mutex;
+ struct mutex hdlc_recovery_mutex;
struct timer_list hdlc_reset_timer;
struct mutex diag_hdlc_mutex;
unsigned char *hdlc_buf;
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 5b507df..e4397c5 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -975,14 +975,34 @@
else
hdlc_disabled = driver->hdlc_disabled;
if (hdlc_disabled) {
+ if (len < 4) {
+ pr_err("diag: In %s, invalid len: %d of non_hdlc pkt",
+ __func__, len);
+ return -EBADMSG;
+ }
payload = *(uint16_t *)(buf + 2);
+ if (payload > DIAG_MAX_HDLC_BUF_SIZE) {
+ pr_err("diag: Dropping packet, payload size is %d\n",
+ payload);
+ return -EBADMSG;
+ }
driver->hdlc_encode_buf_len = payload;
/*
- * Adding 4 bytes for start (1 byte), version (1 byte) and
- * payload (2 bytes)
+ * Adding 5 bytes for start (1 byte), version (1 byte),
+ * payload (2 bytes) and end (1 byte)
*/
- memcpy(driver->hdlc_encode_buf, buf + 4, payload);
- goto send_data;
+ if (len == (payload + 5)) {
+ /*
+ * Adding 4 bytes for start (1 byte), version (1 byte)
+ * and payload (2 bytes)
+ */
+ memcpy(driver->hdlc_encode_buf, buf + 4, payload);
+ goto send_data;
+ } else {
+ pr_err("diag: In %s, invalid len: %d of non_hdlc pkt",
+ __func__, len);
+ return -EBADMSG;
+ }
}
if (hdlc_flag) {
@@ -3468,6 +3488,7 @@
mutex_init(&driver->delayed_rsp_mutex);
mutex_init(&apps_data_mutex);
mutex_init(&driver->msg_mask_lock);
+ mutex_init(&driver->hdlc_recovery_mutex);
for (i = 0; i < NUM_PERIPHERALS; i++)
mutex_init(&driver->diagfwd_channel_mutex[i]);
init_waitqueue_head(&driver->wait_q);
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index cd49f00..3f00a7e 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -1443,7 +1443,9 @@
if (start_ptr) {
/* Discard any partial packet reads */
+ mutex_lock(&driver->hdlc_recovery_mutex);
driver->incoming_pkt.processing = 0;
+ mutex_unlock(&driver->hdlc_recovery_mutex);
diag_process_non_hdlc_pkt(start_ptr, len - i, info);
}
}
@@ -1457,18 +1459,24 @@
const uint32_t header_len = sizeof(struct diag_pkt_frame_t);
struct diag_pkt_frame_t *actual_pkt = NULL;
unsigned char *data_ptr = NULL;
- struct diag_partial_pkt_t *partial_pkt = &driver->incoming_pkt;
+ struct diag_partial_pkt_t *partial_pkt = NULL;
- if (!buf || len <= 0)
+ mutex_lock(&driver->hdlc_recovery_mutex);
+ if (!buf || len <= 0) {
+ mutex_unlock(&driver->hdlc_recovery_mutex);
return;
-
- if (!partial_pkt->processing)
+ }
+ partial_pkt = &driver->incoming_pkt;
+ if (!partial_pkt->processing) {
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto start;
+ }
if (partial_pkt->remaining > len) {
if ((partial_pkt->read_len + len) > partial_pkt->capacity) {
pr_err("diag: Invalid length %d, %d received in %s\n",
partial_pkt->read_len, len, __func__);
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto end;
}
memcpy(partial_pkt->data + partial_pkt->read_len, buf, len);
@@ -1482,6 +1490,7 @@
pr_err("diag: Invalid length during partial read %d, %d received in %s\n",
partial_pkt->read_len,
partial_pkt->remaining, __func__);
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto end;
}
memcpy(partial_pkt->data + partial_pkt->read_len, buf,
@@ -1495,20 +1504,27 @@
if (partial_pkt->remaining == 0) {
actual_pkt = (struct diag_pkt_frame_t *)(partial_pkt->data);
data_ptr = partial_pkt->data + header_len;
- if (*(uint8_t *)(data_ptr + actual_pkt->length) != CONTROL_CHAR)
+ if (*(uint8_t *)(data_ptr + actual_pkt->length) !=
+ CONTROL_CHAR) {
+ mutex_unlock(&driver->hdlc_recovery_mutex);
diag_hdlc_start_recovery(buf, len, info);
+ mutex_lock(&driver->hdlc_recovery_mutex);
+ }
err = diag_process_apps_pkt(data_ptr,
actual_pkt->length, info);
if (err) {
pr_err("diag: In %s, unable to process incoming data packet, err: %d\n",
__func__, err);
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto end;
}
partial_pkt->read_len = 0;
partial_pkt->total_len = 0;
partial_pkt->processing = 0;
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto start;
}
+ mutex_unlock(&driver->hdlc_recovery_mutex);
goto end;
start:
@@ -1521,14 +1537,14 @@
diag_send_error_rsp(buf, len);
goto end;
}
-
+ mutex_lock(&driver->hdlc_recovery_mutex);
if (pkt_len + header_len > partial_pkt->capacity) {
pr_err("diag: In %s, incoming data is too large for the request buffer %d\n",
__func__, pkt_len);
+ mutex_unlock(&driver->hdlc_recovery_mutex);
diag_hdlc_start_recovery(buf, len, info);
break;
}
-
if ((pkt_len + header_len) > (len - read_bytes)) {
partial_pkt->read_len = len - read_bytes;
partial_pkt->total_len = pkt_len + header_len;
@@ -1536,19 +1552,27 @@
partial_pkt->read_len;
partial_pkt->processing = 1;
memcpy(partial_pkt->data, buf, partial_pkt->read_len);
+ mutex_unlock(&driver->hdlc_recovery_mutex);
break;
}
data_ptr = buf + header_len;
- if (*(uint8_t *)(data_ptr + actual_pkt->length) != CONTROL_CHAR)
+ if (*(uint8_t *)(data_ptr + actual_pkt->length) !=
+ CONTROL_CHAR) {
+ mutex_unlock(&driver->hdlc_recovery_mutex);
diag_hdlc_start_recovery(buf, len, info);
+ mutex_lock(&driver->hdlc_recovery_mutex);
+ }
else
hdlc_reset = 0;
err = diag_process_apps_pkt(data_ptr,
actual_pkt->length, info);
- if (err)
+ if (err) {
+ mutex_unlock(&driver->hdlc_recovery_mutex);
break;
+ }
read_bytes += header_len + pkt_len + 1;
buf += header_len + pkt_len + 1; /* advance to next pkt */
+ mutex_unlock(&driver->hdlc_recovery_mutex);
}
end:
return;
diff --git a/drivers/char/diag/diagfwd_glink.c b/drivers/char/diag/diagfwd_glink.c
index 6476684..e9683e0 100644
--- a/drivers/char/diag/diagfwd_glink.c
+++ b/drivers/char/diag/diagfwd_glink.c
@@ -375,8 +375,10 @@
struct diag_glink_read_work, work);
struct diag_glink_info *glink_info = read_work->glink_info;
- if (!glink_info || !glink_info->hdl)
+ if (!glink_info || !glink_info->hdl) {
+ kfree(read_work);
return;
+ }
diagfwd_channel_read_done(glink_info->fwd_ctxt,
(unsigned char *)(read_work->ptr_read_done),
@@ -388,6 +390,7 @@
"diag: Rx done for packet %pK of len: %d periph: %d ch: %d\n",
read_work->ptr_rx_done, (int)read_work->ptr_read_size,
glink_info->peripheral, glink_info->type);
+ kfree(read_work);
}
static void diag_glink_notify_rx(void *hdl, const void *priv,
@@ -411,6 +414,7 @@
if (!read_work) {
DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
"diag: Could not allocate read_work\n");
+ glink_rx_done(glink_info->hdl, ptr, true);
return;
}
diff --git a/drivers/clk/clk-divider.c b/drivers/clk/clk-divider.c
index bb7c862..3e13186 100644
--- a/drivers/clk/clk-divider.c
+++ b/drivers/clk/clk-divider.c
@@ -283,10 +283,14 @@
const struct clk_div_table *table, u8 width,
unsigned long flags)
{
+ struct clk_hw *parent = clk_hw_get_parent(hw);
int i, bestdiv = 0;
unsigned long parent_rate, best = 0, now, maxdiv;
unsigned long parent_rate_saved = *best_parent_rate;
+ if (!parent)
+ return -EINVAL;
+
if (!rate)
rate = 1;
@@ -317,8 +321,7 @@
*best_parent_rate = parent_rate_saved;
return i;
}
- parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw),
- rate * i);
+ parent_rate = clk_hw_round_rate(parent, rate * i);
now = DIV_ROUND_UP_ULL((u64)parent_rate, i);
if (_is_best_div(rate, now, best, flags)) {
bestdiv = i;
@@ -329,7 +332,7 @@
if (!bestdiv) {
bestdiv = _get_maxdiv(table, width, flags);
- *best_parent_rate = clk_hw_round_rate(clk_hw_get_parent(hw), 1);
+ *best_parent_rate = clk_hw_round_rate(parent, 1);
}
return bestdiv;
diff --git a/drivers/clk/qcom/clk-branch.c b/drivers/clk/qcom/clk-branch.c
index 46ced08..fa0ca36 100644
--- a/drivers/clk/qcom/clk-branch.c
+++ b/drivers/clk/qcom/clk-branch.c
@@ -287,20 +287,30 @@
static int clk_branch2_prepare(struct clk_hw *hw)
{
- struct clk_branch *branch = to_clk_branch(hw);
- struct clk_hw *parent = clk_hw_get_parent(hw);
- unsigned long curr_rate, branch_rate = branch->rate;
+ struct clk_branch *branch;
+ struct clk_hw *parent;
+ unsigned long curr_rate;
int ret = 0;
+ if (!hw)
+ return -EINVAL;
+
+ branch = to_clk_branch(hw);
+ parent = clk_hw_get_parent(hw);
+ if (!branch)
+ return -EINVAL;
+
/*
* Do the rate aggregation and scaling of the RCG in the prepare/
* unprepare functions to avoid potential RPM(/h) communication due to
* votes on the voltage rails.
*/
if (branch->aggr_sibling_rates) {
+ if (!parent)
+ return -EINVAL;
curr_rate = clk_aggregate_rate(hw, parent->core);
- if (branch_rate > curr_rate) {
- ret = clk_set_rate(parent->clk, branch_rate);
+ if (branch->rate > curr_rate) {
+ ret = clk_set_rate(parent->clk, branch->rate);
if (ret)
goto exit;
}
@@ -316,13 +326,23 @@
static void clk_branch2_unprepare(struct clk_hw *hw)
{
- struct clk_branch *branch = to_clk_branch(hw);
- struct clk_hw *parent = clk_hw_get_parent(hw);
- unsigned long curr_rate, new_rate, branch_rate = branch->rate;
+ struct clk_branch *branch;
+ struct clk_hw *parent;
+ unsigned long curr_rate, new_rate;
+
+ if (!hw)
+ return;
+
+ branch = to_clk_branch(hw);
+ parent = clk_hw_get_parent(hw);
+ if (!branch)
+ return;
if (branch->aggr_sibling_rates) {
+ if (!parent)
+ return;
new_rate = clk_aggregate_rate(hw, parent->core);
- curr_rate = max(new_rate, branch_rate);
+ curr_rate = max(new_rate, branch->rate);
if (new_rate < curr_rate)
if (clk_set_rate(parent->clk, new_rate))
pr_err("Failed to scale %s to %lu\n",
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index 1d63a86..47e9fab 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -518,6 +518,9 @@
int i;
unsigned long rrate = 0;
+ if (!hw)
+ return -EINVAL;
+
/*
* If the rate passed in is 0, return the first frequency in the
* FMAX table.
@@ -3018,6 +3021,14 @@
clk_data->clk_num = num_clks;
+ rc = clk_osm_resources_init(pdev);
+ if (rc) {
+ if (rc != -EPROBE_DEFER)
+ dev_err(&pdev->dev, "OSM resources init failed, rc=%d\n",
+ rc);
+ return rc;
+ }
+
if (l3_clk.vbases[EFUSE_BASE]) {
/* Multiple speed-bins are supported */
pte_efuse = readl_relaxed(l3_clk.vbases[EFUSE_BASE]);
@@ -3089,14 +3100,6 @@
return rc;
}
- rc = clk_osm_resources_init(pdev);
- if (rc) {
- if (rc != -EPROBE_DEFER)
- dev_err(&pdev->dev, "OSM resources init failed, rc=%d\n",
- rc);
- return rc;
- }
-
rc = clk_osm_acd_resources_init(pdev);
if (rc) {
dev_err(&pdev->dev, "ACD resources init failed, rc=%d\n",
diff --git a/drivers/clk/qcom/clk-rcg2.c b/drivers/clk/qcom/clk-rcg2.c
index b63c3c3..dd69b31 100644
--- a/drivers/clk/qcom/clk-rcg2.c
+++ b/drivers/clk/qcom/clk-rcg2.c
@@ -934,10 +934,11 @@
EXPORT_SYMBOL_GPL(clk_byte2_ops);
static const struct frac_entry frac_table_pixel[] = {
+ { 1, 1 },
+ { 2, 3 },
+ { 4, 9 },
{ 3, 8 },
{ 2, 9 },
- { 4, 9 },
- { 1, 1 },
{ }
};
@@ -1028,6 +1029,7 @@
unsigned long parent_rate)
{
struct clk_rcg2 *rcg = to_clk_rcg2(hw);
+ struct clk_hw *parent = clk_hw_get_parent(hw);
struct freq_tbl f = { 0 };
unsigned long src_rate;
unsigned long num, den;
@@ -1035,7 +1037,12 @@
u32 hid_div, cfg;
int i, num_parents = clk_hw_get_num_parents(hw);
- src_rate = clk_get_rate(clk_hw_get_parent(hw)->clk);
+ if (!parent) {
+ pr_err("RCG parent isn't initialized\n");
+ return -EINVAL;
+ }
+
+ src_rate = clk_get_rate(parent->clk);
if (src_rate <= 0) {
pr_err("Invalid RCG parent rate\n");
return -EINVAL;
@@ -1196,13 +1203,15 @@
u32 *mode, u32 *pre_div)
{
struct clk_rcg2 *rcg;
- int num_parents = clk_hw_get_num_parents(hw);
+ int num_parents;
u32 cfg, mask;
int i, ret;
if (!hw)
return -EINVAL;
+ num_parents = clk_hw_get_num_parents(hw);
+
rcg = to_clk_rcg2(hw);
ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + offset, &cfg);
diff --git a/drivers/clk/qcom/clk-regmap.c b/drivers/clk/qcom/clk-regmap.c
index 1c856d3..aa024c2d 100644
--- a/drivers/clk/qcom/clk-regmap.c
+++ b/drivers/clk/qcom/clk-regmap.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014, 2017, The Linux Foundation. All rights reserved.
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
@@ -103,9 +103,12 @@
*/
int devm_clk_register_regmap(struct device *dev, struct clk_regmap *rclk)
{
- if (dev && dev_get_regmap(dev, NULL))
+ if (!dev || !rclk)
+ return -EINVAL;
+
+ if (dev_get_regmap(dev, NULL))
rclk->regmap = dev_get_regmap(dev, NULL);
- else if (dev && dev->parent)
+ else if (dev->parent)
rclk->regmap = dev_get_regmap(dev->parent, NULL);
return devm_clk_hw_register(dev, &rclk->hw);
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
index 93ad1b0..eb6c658 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
@@ -94,7 +94,6 @@
struct dsi_pll_regs {
u32 pll_prop_gain_rate;
- u32 pll_outdiv_rate;
u32 pll_lockdet_rate;
u32 decimal_div_start;
u32 frac_div_start_low;
@@ -134,6 +133,165 @@
struct dsi_pll_regs reg_setup;
};
+static inline int pll_reg_read(void *context, unsigned int reg,
+ unsigned int *val)
+{
+ int rc = 0;
+ struct mdss_pll_resources *rsc = context;
+
+ rc = mdss_pll_resource_enable(rsc, true);
+ if (rc) {
+ pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
+ return rc;
+ }
+
+ *val = MDSS_PLL_REG_R(rsc->pll_base, reg);
+ (void)mdss_pll_resource_enable(rsc, false);
+
+ return rc;
+}
+
+static inline int pll_reg_write(void *context, unsigned int reg,
+ unsigned int val)
+{
+ int rc = 0;
+ struct mdss_pll_resources *rsc = context;
+
+ rc = mdss_pll_resource_enable(rsc, true);
+ if (rc) {
+ pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
+ return rc;
+ }
+
+ MDSS_PLL_REG_W(rsc->pll_base, reg, val);
+ (void)mdss_pll_resource_enable(rsc, false);
+
+ return rc;
+}
+
+static inline int phy_reg_read(void *context, unsigned int reg,
+ unsigned int *val)
+{
+ int rc = 0;
+ struct mdss_pll_resources *rsc = context;
+
+ rc = mdss_pll_resource_enable(rsc, true);
+ if (rc) {
+ pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
+ return rc;
+ }
+
+ *val = MDSS_PLL_REG_R(rsc->phy_base, reg);
+ (void)mdss_pll_resource_enable(rsc, false);
+
+ return rc;
+}
+
+static inline int phy_reg_write(void *context, unsigned int reg,
+ unsigned int val)
+{
+ int rc = 0;
+ struct mdss_pll_resources *rsc = context;
+
+ rc = mdss_pll_resource_enable(rsc, true);
+ if (rc) {
+ pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
+ return rc;
+ }
+
+ MDSS_PLL_REG_W(rsc->phy_base, reg, val);
+ (void)mdss_pll_resource_enable(rsc, false);
+
+ return rc;
+}
+
+static inline int phy_reg_update_bits_sub(struct mdss_pll_resources *rsc,
+ unsigned int reg, unsigned int mask, unsigned int val)
+{
+ u32 reg_val;
+ int rc = 0;
+
+ reg_val = MDSS_PLL_REG_R(rsc->phy_base, reg);
+ reg_val &= ~mask;
+ reg_val |= (val & mask);
+ MDSS_PLL_REG_W(rsc->phy_base, reg, reg_val);
+
+ return rc;
+}
+
+static inline int phy_reg_update_bits(void *context, unsigned int reg,
+ unsigned int mask, unsigned int val)
+{
+ int rc = 0;
+ struct mdss_pll_resources *rsc = context;
+
+ rc = mdss_pll_resource_enable(rsc, true);
+ if (rc) {
+ pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = phy_reg_update_bits_sub(rsc, reg, mask, val);
+ if (!rc && rsc->slave)
+ rc = phy_reg_update_bits_sub(rsc->slave, reg, mask, val);
+ (void)mdss_pll_resource_enable(rsc, false);
+
+ return rc;
+}
+
+static inline int pclk_mux_read_sel(void *context, unsigned int reg,
+ unsigned int *val)
+{
+ int rc = 0;
+ struct mdss_pll_resources *rsc = context;
+
+ rc = mdss_pll_resource_enable(rsc, true);
+ if (rc)
+ pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
+ else
+ *val = (MDSS_PLL_REG_R(rsc->pll_base, reg) & 0x3);
+
+ (void)mdss_pll_resource_enable(rsc, false);
+ return rc;
+}
+
+
+static inline int pclk_mux_write_sel_sub(struct mdss_pll_resources *rsc,
+ unsigned int reg, unsigned int val)
+{
+ u32 reg_val;
+ int rc = 0;
+
+ reg_val = MDSS_PLL_REG_R(rsc->phy_base, reg);
+ reg_val &= ~0x03;
+ reg_val |= val;
+
+ MDSS_PLL_REG_W(rsc->phy_base, reg, reg_val);
+
+ return rc;
+}
+
+static inline int pclk_mux_write_sel(void *context, unsigned int reg,
+ unsigned int val)
+{
+ int rc = 0;
+ struct mdss_pll_resources *rsc = context;
+
+ rc = mdss_pll_resource_enable(rsc, true);
+ if (rc) {
+ pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
+ return rc;
+ }
+
+ rc = pclk_mux_write_sel_sub(rsc, reg, val);
+ if (!rc && rsc->slave)
+ rc = pclk_mux_write_sel_sub(rsc->slave, reg, val);
+
+ (void)mdss_pll_resource_enable(rsc, false);
+
+ return rc;
+}
+
static struct mdss_pll_resources *pll_rsc_db[DSI_PLL_MAX];
static struct dsi_pll_10nm plls[DSI_PLL_MAX];
@@ -203,54 +361,14 @@
{
struct dsi_pll_config *config = &pll->pll_configuration;
struct dsi_pll_regs *regs = &pll->reg_setup;
- u64 target_freq;
u64 fref = rsc->vco_ref_clk_rate;
- u32 computed_output_div, div_log = 0;
u64 pll_freq;
u64 divider;
u64 dec, dec_multiple;
u32 frac;
u64 multiplier;
- u32 i;
- target_freq = rsc->vco_current_rate;
- pr_debug("target_freq = %llu\n", target_freq);
-
- if (config->div_override) {
- computed_output_div = config->output_div;
-
- /*
- * Computed_output_div = 2 ^ div_log
- * To get div_log from output div just get the index of the
- * 1 bit in the value.
- * div_log ranges from 0-3. so check the 4 lsbs
- */
-
- for (i = 0; i < 4; i++) {
- if (computed_output_div & (1 << i)) {
- div_log = i;
- break;
- }
- }
-
- } else {
- if (target_freq < MHZ_250) {
- computed_output_div = 8;
- div_log = 3;
- } else if (target_freq < MHZ_500) {
- computed_output_div = 4;
- div_log = 2;
- } else if (target_freq < MHZ_1000) {
- computed_output_div = 2;
- div_log = 1;
- } else {
- computed_output_div = 1;
- div_log = 0;
- }
- }
- pr_debug("computed_output_div = %d\n", computed_output_div);
-
- pll_freq = target_freq * computed_output_div;
+ pll_freq = rsc->vco_current_rate;
if (config->disable_prescaler)
divider = fref;
@@ -274,7 +392,6 @@
else
regs->pll_clock_inverters = 0;
- regs->pll_outdiv_rate = div_log;
regs->pll_lockdet_rate = config->lock_timer;
regs->decimal_div_start = dec;
regs->frac_div_start_low = (frac & 0xff);
@@ -394,7 +511,6 @@
MDSS_PLL_REG_W(pll_base, PLL_FRAC_DIV_START_HIGH_1,
reg->frac_div_start_high);
MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCKDET_RATE_1, 0x40);
- MDSS_PLL_REG_W(pll_base, PLL_PLL_OUTDIV_RATE, reg->pll_outdiv_rate);
MDSS_PLL_REG_W(pll_base, PLL_PLL_LOCK_DELAY, 0x06);
MDSS_PLL_REG_W(pll_base, PLL_CMODE, 0x10);
MDSS_PLL_REG_W(pll_base, PLL_CLOCK_INVERTERS, reg->pll_clock_inverters);
@@ -605,7 +721,9 @@
}
pll->cached_cfg0 = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG0);
pll->cached_cfg1 = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG1);
- pr_debug("cfg0=%d,cfg1=%d\n", pll->cached_cfg0, pll->cached_cfg1);
+ pll->cached_outdiv = MDSS_PLL_REG_R(pll->pll_base, PLL_PLL_OUTDIV_RATE);
+ pr_debug("cfg0=%d,cfg1=%d, outdiv=%d\n", pll->cached_cfg0,
+ pll->cached_cfg1, pll->cached_outdiv);
pll->vco_cached_rate = clk_hw_get_rate(hw);
dsi_pll_disable(vco);
@@ -646,6 +764,8 @@
pll->cached_cfg0);
MDSS_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG1,
pll->cached_cfg1);
+ MDSS_PLL_REG_W(pll->pll_base, PLL_PLL_OUTDIV_RATE,
+ pll->cached_outdiv);
}
rc = dsi_pll_enable(vco);
@@ -855,176 +975,6 @@
return rc;
}
-static int post_vco_clk_get_div(void *context, unsigned int reg,
- unsigned int *div)
-{
- int rc;
- struct mdss_pll_resources *pll = context;
- u32 reg_val;
-
- rc = mdss_pll_resource_enable(pll, true);
- if (rc) {
- pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
- return rc;
- }
-
- reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG1);
- reg_val &= 0x3;
-
- if (reg_val == 2)
- *div = 1;
- else if (reg_val == 3)
- *div = 4;
- else
- *div = 1;
-
- /**
- *Common clock framework the divider value is interpreted as one less
- * hence we return one less for all dividers except when zero
- */
- if (*div != 0)
- *div -= 1;
-
- (void)mdss_pll_resource_enable(pll, false);
-
- return rc;
-}
-
-static int post_vco_clk_set_div_sub(struct mdss_pll_resources *pll, int div)
-{
- u32 reg_val;
- int rc = 0;
-
- reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG1);
- reg_val &= ~0x03;
- if (div == 1) {
- reg_val |= 0x2;
- } else if (div == 4) {
- reg_val |= 0x3;
- } else {
- rc = -EINVAL;
- pr_err("unsupported divider %d\n", div);
- goto error;
- }
-
- MDSS_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG1, reg_val);
-
-error:
- return rc;
-}
-
-static int post_vco_clk_set_div(void *context, unsigned int reg,
- unsigned int div)
-{
- int rc = 0;
- struct mdss_pll_resources *pll = context;
-
- rc = mdss_pll_resource_enable(pll, true);
- if (rc) {
- pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
- return rc;
- }
-
- /**
- * In common clock framework the divider value provided is one less and
- * and hence adjusting the divider value by one prior to writing it to
- * hardware
- */
- div++;
- rc = post_vco_clk_set_div_sub(pll, div);
- if (!rc && pll->slave)
- rc = post_vco_clk_set_div_sub(pll->slave, div);
-
- (void)mdss_pll_resource_enable(pll, false);
-
- return rc;
-}
-
-static int post_bit_clk_get_div(void *context, unsigned int reg,
- unsigned int *div)
-{
- int rc;
- struct mdss_pll_resources *pll = context;
- u32 reg_val;
-
- rc = mdss_pll_resource_enable(pll, true);
- if (rc) {
- pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
- return rc;
- }
-
- reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG1);
- reg_val &= 0x3;
-
- if (reg_val == 0)
- *div = 1;
- else if (reg_val == 1)
- *div = 2;
- else
- *div = 1;
-
- /**
- *Common clock framework the divider value is interpreted as one less
- * hence we return one less for all dividers except when zero
- */
- if (*div != 0)
- *div -= 1;
-
- (void)mdss_pll_resource_enable(pll, false);
-
- return rc;
-}
-
-static int post_bit_clk_set_div_sub(struct mdss_pll_resources *pll, int div)
-{
- int rc = 0;
- u32 reg_val;
-
- reg_val = MDSS_PLL_REG_R(pll->phy_base, PHY_CMN_CLK_CFG1);
- reg_val &= ~0x03;
- if (div == 1) {
- reg_val |= 0x0;
- } else if (div == 2) {
- reg_val |= 0x1;
- } else {
- rc = -EINVAL;
- pr_err("unsupported divider %d\n", div);
- goto error;
- }
-
- MDSS_PLL_REG_W(pll->phy_base, PHY_CMN_CLK_CFG1, reg_val);
-
-error:
- return rc;
-}
-
-static int post_bit_clk_set_div(void *context, unsigned int reg,
- unsigned int div)
-{
- int rc = 0;
- struct mdss_pll_resources *pll = context;
-
- rc = mdss_pll_resource_enable(pll, true);
- if (rc) {
- pr_err("Failed to enable dsi pll resources, rc=%d\n", rc);
- return rc;
- }
-
- /**
- * In common clock framework the divider value provided is one less and
- * and hence adjusting the divider value by one prior to writing it to
- * hardware
- */
- div++;
- rc = post_bit_clk_set_div_sub(pll, div);
- if (!rc && pll->slave)
- rc = post_bit_clk_set_div_sub(pll->slave, div);
-
- (void)mdss_pll_resource_enable(pll, false);
-
- return rc;
-}
-
static struct regmap_config dsi_pll_10nm_config = {
.reg_bits = 32,
.reg_stride = 4,
@@ -1032,14 +982,14 @@
.max_register = 0x7c0,
};
-static struct regmap_bus post_vco_regmap_bus = {
- .reg_write = post_vco_clk_set_div,
- .reg_read = post_vco_clk_get_div,
+static struct regmap_bus pll_regmap_bus = {
+ .reg_write = pll_reg_write,
+ .reg_read = pll_reg_read,
};
-static struct regmap_bus post_bit_regmap_bus = {
- .reg_write = post_bit_clk_set_div,
- .reg_read = post_bit_clk_get_div,
+static struct regmap_bus pclk_mux_regmap_bus = {
+ .reg_read = phy_reg_read,
+ .reg_write = pclk_mux_write_sel,
};
static struct regmap_bus pclk_src_regmap_bus = {
@@ -1073,23 +1023,30 @@
* | vco_clk |
* +-------+-------+
* |
- * +--------------------------------------+
- * | |
- * +-------v-------+ |
- * | bitclk_src | |
- * | DIV(1..15) | |
- * +-------+-------+ |
- * | |
- * +--------------------+ |
- * Shadow Path | | |
- * + +-------v-------+ +------v------+ +------v-------+
- * | | byteclk_src | |post_bit_div | |post_vco_div |
- * | | DIV(8) | |DIV(1,2) | |DIV(1,4) |
- * | +-------+-------+ +------+------+ +------+-------+
- * | | | |
- * | | +------+ +----+
- * | +--------+ | |
- * | | +----v-----v------+
+ * |
+ * +---------------+
+ * | pll_out_div |
+ * | DIV(1,2,4,8) |
+ * +-------+-------+
+ * |
+ * +-----------------------------+--------+
+ * | | |
+ * +-------v-------+ | |
+ * | bitclk_src | | |
+ * | DIV(1..15) | | |
+ * +-------+-------+ | |
+ * | | |
+ * +----------+---------+ | |
+ * Shadow Path | | | | |
+ * + +-------v-------+ | +------v------+ | +------v-------+
+ * | | byteclk_src | | |post_bit_div | | |post_vco_div |
+ * | | DIV(8) | | |DIV (2) | | |DIV(4) |
+ * | +-------+-------+ | +------+------+ | +------+-------+
+ * | | | | | | |
+ * | | | +------+ | |
+ * | | +-------------+ | | +----+
+ * | +--------+ | | | |
+ * | | +-v--v-v---v------+
* +-v---------v----+ \ pclk_src_mux /
* \ byteclk_mux / \ /
* \ / +-----+-----+
@@ -1140,13 +1097,45 @@
},
};
+static struct clk_regmap_div dsi0pll_pll_out_div = {
+ .reg = PLL_PLL_OUTDIV_RATE,
+ .shift = 0,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi0pll_pll_out_div",
+ .parent_names = (const char *[]){"dsi0pll_vco_clk"},
+ .num_parents = 1,
+ .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
+ .ops = &clk_regmap_div_ops,
+ },
+ },
+};
+
+static struct clk_regmap_div dsi1pll_pll_out_div = {
+ .reg = PLL_PLL_OUTDIV_RATE,
+ .shift = 0,
+ .width = 2,
+ .flags = CLK_DIVIDER_POWER_OF_TWO,
+ .clkr = {
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi1pll_pll_out_div",
+ .parent_names = (const char *[]){"dsi1pll_vco_clk"},
+ .num_parents = 1,
+ .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
+ .ops = &clk_regmap_div_ops,
+ },
+ },
+};
+
static struct clk_regmap_div dsi0pll_bitclk_src = {
.shift = 0,
.width = 4,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_bitclk_src",
- .parent_names = (const char *[]){"dsi0pll_vco_clk"},
+ .parent_names = (const char *[]){"dsi0pll_pll_out_div"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_regmap_div_ops,
@@ -1160,7 +1149,7 @@
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_bitclk_src",
- .parent_names = (const char *[]){"dsi1pll_vco_clk"},
+ .parent_names = (const char *[]){"dsi1pll_pll_out_div"},
.num_parents = 1,
.flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
.ops = &clk_regmap_div_ops,
@@ -1168,31 +1157,27 @@
},
};
-static struct clk_regmap_div dsi0pll_post_vco_div = {
- .shift = 0,
- .width = 2,
- .clkr = {
- .hw.init = &(struct clk_init_data){
- .name = "dsi0pll_post_vco_div",
- .parent_names = (const char *[]){"dsi0pll_vco_clk"},
- .num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
- .ops = &clk_regmap_div_ops,
- },
+static struct clk_fixed_factor dsi0pll_post_vco_div = {
+ .div = 4,
+ .mult = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi0pll_post_vco_div",
+ .parent_names = (const char *[]){"dsi0pll_pll_out_div"},
+ .num_parents = 1,
+ .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
+ .ops = &clk_fixed_factor_ops,
},
};
-static struct clk_regmap_div dsi1pll_post_vco_div = {
- .shift = 0,
- .width = 2,
- .clkr = {
- .hw.init = &(struct clk_init_data){
- .name = "dsi1pll_post_vco_div",
- .parent_names = (const char *[]){"dsi1pll_vco_clk"},
- .num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
- .ops = &clk_regmap_div_ops,
- },
+static struct clk_fixed_factor dsi1pll_post_vco_div = {
+ .div = 4,
+ .mult = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi1pll_post_vco_div",
+ .parent_names = (const char *[]){"dsi1pll_pll_out_div"},
+ .num_parents = 1,
+ .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
+ .ops = &clk_fixed_factor_ops,
},
};
@@ -1220,31 +1205,27 @@
},
};
-static struct clk_regmap_div dsi0pll_post_bit_div = {
- .shift = 0,
- .width = 1,
- .clkr = {
- .hw.init = &(struct clk_init_data){
- .name = "dsi0pll_post_bit_div",
- .parent_names = (const char *[]){"dsi0pll_bitclk_src"},
- .num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
- .ops = &clk_regmap_div_ops,
- },
+static struct clk_fixed_factor dsi0pll_post_bit_div = {
+ .div = 2,
+ .mult = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi0pll_post_bit_div",
+ .parent_names = (const char *[]){"dsi0pll_bitclk_src"},
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ .ops = &clk_fixed_factor_ops,
},
};
-static struct clk_regmap_div dsi1pll_post_bit_div = {
- .shift = 0,
- .width = 1,
- .clkr = {
- .hw.init = &(struct clk_init_data){
- .name = "dsi1pll_post_bit_div",
- .parent_names = (const char *[]){"dsi1pll_bitclk_src"},
- .num_parents = 1,
- .flags = CLK_GET_RATE_NOCACHE,
- .ops = &clk_regmap_div_ops,
- },
+static struct clk_fixed_factor dsi1pll_post_bit_div = {
+ .div = 2,
+ .mult = 1,
+ .hw.init = &(struct clk_init_data){
+ .name = "dsi1pll_post_bit_div",
+ .parent_names = (const char *[]){"dsi1pll_bitclk_src"},
+ .num_parents = 1,
+ .flags = CLK_GET_RATE_NOCACHE,
+ .ops = &clk_fixed_factor_ops,
},
};
@@ -1277,30 +1258,36 @@
};
static struct clk_regmap_mux dsi0pll_pclk_src_mux = {
+ .reg = PHY_CMN_CLK_CFG1,
.shift = 0,
- .width = 1,
+ .width = 2,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi0pll_pclk_src_mux",
- .parent_names = (const char *[]){"dsi0pll_post_bit_div",
- "dsi0pll_post_vco_div"},
- .num_parents = 2,
- .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
+ .parent_names = (const char *[]){"dsi0pll_bitclk_src",
+ "dsi0pll_post_bit_div",
+ "dsi0pll_pll_out_div",
+ "dsi0pll_post_vco_div"},
+ .num_parents = 4,
+ .flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_regmap_mux_closest_ops,
},
},
};
static struct clk_regmap_mux dsi1pll_pclk_src_mux = {
+ .reg = PHY_CMN_CLK_CFG1,
.shift = 0,
- .width = 1,
+ .width = 2,
.clkr = {
.hw.init = &(struct clk_init_data){
.name = "dsi1pll_pclk_src_mux",
- .parent_names = (const char *[]){"dsi1pll_post_bit_div",
- "dsi1pll_post_vco_div"},
- .num_parents = 2,
- .flags = (CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT),
+ .parent_names = (const char *[]){"dsi1pll_bitclk_src",
+ "dsi1pll_post_bit_div",
+ "dsi1pll_pll_out_div",
+ "dsi1pll_post_vco_div"},
+ .num_parents = 4,
+ .flags = CLK_GET_RATE_NOCACHE,
.ops = &clk_regmap_mux_closest_ops,
},
},
@@ -1366,24 +1353,25 @@
static struct clk_hw *mdss_dsi_pllcc_10nm[] = {
[VCO_CLK_0] = &dsi0pll_vco_clk.hw,
+ [PLL_OUT_DIV_0_CLK] = &dsi0pll_pll_out_div.clkr.hw,
[BITCLK_SRC_0_CLK] = &dsi0pll_bitclk_src.clkr.hw,
[BYTECLK_SRC_0_CLK] = &dsi0pll_byteclk_src.hw,
- [POST_BIT_DIV_0_CLK] = &dsi0pll_post_bit_div.clkr.hw,
- [POST_VCO_DIV_0_CLK] = &dsi0pll_post_vco_div.clkr.hw,
+ [POST_BIT_DIV_0_CLK] = &dsi0pll_post_bit_div.hw,
+ [POST_VCO_DIV_0_CLK] = &dsi0pll_post_vco_div.hw,
[BYTECLK_MUX_0_CLK] = &dsi0pll_byteclk_mux.clkr.hw,
[PCLK_SRC_MUX_0_CLK] = &dsi0pll_pclk_src_mux.clkr.hw,
[PCLK_SRC_0_CLK] = &dsi0pll_pclk_src.clkr.hw,
[PCLK_MUX_0_CLK] = &dsi0pll_pclk_mux.clkr.hw,
[VCO_CLK_1] = &dsi1pll_vco_clk.hw,
+ [PLL_OUT_DIV_1_CLK] = &dsi1pll_pll_out_div.clkr.hw,
[BITCLK_SRC_1_CLK] = &dsi1pll_bitclk_src.clkr.hw,
[BYTECLK_SRC_1_CLK] = &dsi1pll_byteclk_src.hw,
- [POST_BIT_DIV_1_CLK] = &dsi1pll_post_bit_div.clkr.hw,
- [POST_VCO_DIV_1_CLK] = &dsi1pll_post_vco_div.clkr.hw,
+ [POST_BIT_DIV_1_CLK] = &dsi1pll_post_bit_div.hw,
+ [POST_VCO_DIV_1_CLK] = &dsi1pll_post_vco_div.hw,
[BYTECLK_MUX_1_CLK] = &dsi1pll_byteclk_mux.clkr.hw,
[PCLK_SRC_MUX_1_CLK] = &dsi1pll_pclk_src_mux.clkr.hw,
[PCLK_SRC_1_CLK] = &dsi1pll_pclk_src.clkr.hw,
[PCLK_MUX_1_CLK] = &dsi1pll_pclk_mux.clkr.hw,
-
};
int dsi_pll_clock_register_10nm(struct platform_device *pdev,
@@ -1428,13 +1416,10 @@
/* Establish client data */
if (ndx == 0) {
- rmap = devm_regmap_init(&pdev->dev, &post_vco_regmap_bus,
- pll_res, &dsi_pll_10nm_config);
- dsi0pll_post_vco_div.clkr.regmap = rmap;
- rmap = devm_regmap_init(&pdev->dev, &post_bit_regmap_bus,
+ rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus,
pll_res, &dsi_pll_10nm_config);
- dsi0pll_post_bit_div.clkr.regmap = rmap;
+ dsi0pll_pll_out_div.clkr.regmap = rmap;
rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus,
pll_res, &dsi_pll_10nm_config);
@@ -1448,10 +1433,9 @@
pll_res, &dsi_pll_10nm_config);
dsi0pll_pclk_mux.clkr.regmap = rmap;
- rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
+ rmap = devm_regmap_init(&pdev->dev, &pclk_mux_regmap_bus,
pll_res, &dsi_pll_10nm_config);
dsi0pll_pclk_src_mux.clkr.regmap = rmap;
-
rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
pll_res, &dsi_pll_10nm_config);
dsi0pll_byteclk_mux.clkr.regmap = rmap;
@@ -1475,13 +1459,9 @@
} else {
- rmap = devm_regmap_init(&pdev->dev, &post_vco_regmap_bus,
+ rmap = devm_regmap_init(&pdev->dev, &pll_regmap_bus,
pll_res, &dsi_pll_10nm_config);
- dsi1pll_post_vco_div.clkr.regmap = rmap;
-
- rmap = devm_regmap_init(&pdev->dev, &post_bit_regmap_bus,
- pll_res, &dsi_pll_10nm_config);
- dsi1pll_post_bit_div.clkr.regmap = rmap;
+ dsi1pll_pll_out_div.clkr.regmap = rmap;
rmap = devm_regmap_init(&pdev->dev, &bitclk_src_regmap_bus,
pll_res, &dsi_pll_10nm_config);
@@ -1491,14 +1471,13 @@
pll_res, &dsi_pll_10nm_config);
dsi1pll_pclk_src.clkr.regmap = rmap;
- rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
+ rmap = devm_regmap_init(&pdev->dev, &pclk_mux_regmap_bus,
pll_res, &dsi_pll_10nm_config);
dsi1pll_pclk_mux.clkr.regmap = rmap;
rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
pll_res, &dsi_pll_10nm_config);
dsi1pll_pclk_src_mux.clkr.regmap = rmap;
-
rmap = devm_regmap_init(&pdev->dev, &mdss_mux_regmap_bus,
pll_res, &dsi_pll_10nm_config);
dsi1pll_byteclk_mux.clkr.regmap = rmap;
diff --git a/drivers/clk/qcom/mdss/mdss-pll.h b/drivers/clk/qcom/mdss/mdss-pll.h
index 033462d..2f92270 100644
--- a/drivers/clk/qcom/mdss/mdss-pll.h
+++ b/drivers/clk/qcom/mdss/mdss-pll.h
@@ -99,6 +99,7 @@
unsigned long vco_cached_rate;
u32 cached_cfg0;
u32 cached_cfg1;
+ u32 cached_outdiv;
/* dsi/edp/hmdi pll interface type */
u32 pll_interface_type;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
index 3625ed0..5e76ce7 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.c
@@ -56,6 +56,8 @@
dsi_ctrl_hw_cmn_trigger_cmd_test_pattern;
ctrl->ops.clear_phy0_ln_err = dsi_ctrl_hw_dln0_phy_err;
ctrl->ops.phy_reset_config = dsi_ctrl_hw_cmn_phy_reset_config;
+ ctrl->ops.setup_misr = dsi_ctrl_hw_cmn_setup_misr;
+ ctrl->ops.collect_misr = dsi_ctrl_hw_cmn_collect_misr;
switch (version) {
case DSI_CTRL_VERSION_1_4:
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
index 2d7b174..e8a6ab4 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_catalog.h
@@ -147,6 +147,12 @@
void dsi_ctrl_hw_cmn_phy_sw_reset(struct dsi_ctrl_hw *ctrl);
void dsi_ctrl_hw_cmn_soft_reset(struct dsi_ctrl_hw *ctrl);
+void dsi_ctrl_hw_cmn_setup_misr(struct dsi_ctrl_hw *ctrl,
+ enum dsi_op_mode panel_mode,
+ bool enable, u32 frame_count);
+u32 dsi_ctrl_hw_cmn_collect_misr(struct dsi_ctrl_hw *ctrl,
+ enum dsi_op_mode panel_mode);
+
void dsi_ctrl_hw_cmn_kickoff_command(struct dsi_ctrl_hw *ctrl,
struct dsi_ctrl_cmd_dma_info *cmd,
u32 flags);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
index b2aef9c..21ef811 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.c
@@ -2258,6 +2258,28 @@
}
/**
+ * _dsi_ctrl_cache_misr - Cache frame MISR value
+ * @dsi_ctrl: Pointer to associated dsi_ctrl structure
+ */
+static void _dsi_ctrl_cache_misr(struct dsi_ctrl *dsi_ctrl)
+{
+ u32 misr;
+
+ if (!dsi_ctrl || !dsi_ctrl->hw.ops.collect_misr)
+ return;
+
+ misr = dsi_ctrl->hw.ops.collect_misr(&dsi_ctrl->hw,
+ dsi_ctrl->host_config.panel_mode);
+
+ if (misr)
+ dsi_ctrl->misr_cache = misr;
+
+ pr_debug("DSI_%d misr_cache = %x\n", dsi_ctrl->cell_index,
+ dsi_ctrl->misr_cache);
+
+}
+
+/**
* dsi_ctrl_set_power_state() - set power state for dsi controller
* @dsi_ctrl: DSI controller handle.
* @state: Power state.
@@ -2295,6 +2317,9 @@
goto error;
}
} else if (state == DSI_CTRL_POWER_VREG_OFF) {
+ if (dsi_ctrl->misr_enable)
+ _dsi_ctrl_cache_misr(dsi_ctrl);
+
rc = dsi_ctrl_enable_supplies(dsi_ctrl, false);
if (rc) {
pr_err("[%d]failed to disable vreg supplies, rc=%d\n",
@@ -2609,6 +2634,59 @@
}
/**
+ * dsi_ctrl_setup_misr() - Setup frame MISR
+ * @dsi_ctrl: DSI controller handle.
+ * @enable: enable/disable MISR.
+ * @frame_count: Number of frames to accumulate MISR.
+ *
+ * Return: error code.
+ */
+int dsi_ctrl_setup_misr(struct dsi_ctrl *dsi_ctrl,
+ bool enable,
+ u32 frame_count)
+{
+ if (!dsi_ctrl) {
+ pr_err("Invalid params\n");
+ return -EINVAL;
+ }
+
+ if (!dsi_ctrl->hw.ops.setup_misr)
+ return 0;
+
+ mutex_lock(&dsi_ctrl->ctrl_lock);
+ dsi_ctrl->misr_enable = enable;
+ dsi_ctrl->hw.ops.setup_misr(&dsi_ctrl->hw,
+ dsi_ctrl->host_config.panel_mode,
+ enable, frame_count);
+ mutex_unlock(&dsi_ctrl->ctrl_lock);
+ return 0;
+}
+
+/**
+ * dsi_ctrl_collect_misr() - Read frame MISR
+ * @dsi_ctrl: DSI controller handle.
+ *
+ * Return: MISR value.
+ */
+u32 dsi_ctrl_collect_misr(struct dsi_ctrl *dsi_ctrl)
+{
+ u32 misr;
+
+ if (!dsi_ctrl || !dsi_ctrl->hw.ops.collect_misr)
+ return 0;
+
+ misr = dsi_ctrl->hw.ops.collect_misr(&dsi_ctrl->hw,
+ dsi_ctrl->host_config.panel_mode);
+ if (!misr)
+ misr = dsi_ctrl->misr_cache;
+
+ pr_debug("DSI_%d cached misr = %x, final = %x\n",
+ dsi_ctrl->cell_index, dsi_ctrl->misr_cache, misr);
+
+ return misr;
+}
+
+/**
* dsi_ctrl_drv_register() - register platform driver for dsi controller
*/
void dsi_ctrl_drv_register(void)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
index ec535ce11..95dac1c 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl.h
@@ -188,6 +188,8 @@
* @vaddr: CPU virtual address of cmd buffer.
* @cmd_buffer_size: Size of command buffer.
* @debugfs_root: Root for debugfs entries.
+ * @misr_enable: Frame MISR enable/disable
+ * @misr_cache: Cached Frame MISR value
*/
struct dsi_ctrl {
struct platform_device *pdev;
@@ -226,6 +228,10 @@
/* Debug Information */
struct dentry *debugfs_root;
+ /* MISR */
+ bool misr_enable;
+ u32 misr_cache;
+
};
/**
@@ -571,6 +577,26 @@
struct dsi_ctrl *dsi_ctrl, uint32_t intr_idx);
/**
+ * dsi_ctrl_setup_misr() - Setup frame MISR
+ * @dsi_ctrl: DSI controller handle.
+ * @enable: enable/disable MISR.
+ * @frame_count: Number of frames to accumulate MISR.
+ *
+ * Return: error code.
+ */
+int dsi_ctrl_setup_misr(struct dsi_ctrl *dsi_ctrl,
+ bool enable,
+ u32 frame_count);
+
+/**
+ * dsi_ctrl_collect_misr() - Read frame MISR
+ * @dsi_ctrl: DSI controller handle.
+ *
+ * Return: MISR value.
+ */
+u32 dsi_ctrl_collect_misr(struct dsi_ctrl *dsi_ctrl);
+
+/**
* dsi_ctrl_drv_register() - register platform driver for dsi controller
*/
void dsi_ctrl_drv_register(void);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
index 74be279..2130144 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw.h
@@ -675,6 +675,26 @@
ssize_t (*reg_dump_to_buffer)(struct dsi_ctrl_hw *ctrl,
char *buf,
u32 size);
+
+ /**
+ * setup_misr() - Setup frame MISR
+ * @ctrl: Pointer to the controller host hardware.
+ * @panel_mode: CMD or VIDEO mode indicator
+ * @enable: Enable/disable MISR.
+ * @frame_count: Number of frames to accumulate MISR.
+ */
+ void (*setup_misr)(struct dsi_ctrl_hw *ctrl,
+ enum dsi_op_mode panel_mode,
+ bool enable, u32 frame_count);
+
+ /**
+ * collect_misr() - Read frame MISR
+ * @ctrl: Pointer to the controller host hardware.
+ * @panel_mode: CMD or VIDEO mode indicator
+ */
+ u32 (*collect_misr)(struct dsi_ctrl_hw *ctrl,
+ enum dsi_op_mode panel_mode);
+
};
/*
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c
index c22849a..6421dc2 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_2_0.c
@@ -157,6 +157,10 @@
len += snprintf((buf + len), (size - len),
DUMP_REG_VALUE(DSI_RESET_SW_TRIGGER));
len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_MISR_CMD_CTRL));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_MISR_VIDEO_CTRL));
+ len += snprintf((buf + len), (size - len),
DUMP_REG_VALUE(DSI_LANE_STATUS));
len += snprintf((buf + len), (size - len),
DUMP_REG_VALUE(DSI_LANE_CTRL));
@@ -193,6 +197,12 @@
len += snprintf((buf + len), (size - len),
DUMP_REG_VALUE(DSI_AXI2AHB_CTRL));
len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_MISR_CMD_MDP0_32BIT));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_MISR_CMD_MDP1_32BIT));
+ len += snprintf((buf + len), (size - len),
+ DUMP_REG_VALUE(DSI_MISR_VIDEO_32BIT));
+ len += snprintf((buf + len), (size - len),
DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_CTRL2));
len += snprintf((buf + len), (size - len),
DUMP_REG_VALUE(DSI_COMMAND_MODE_MDP_STREAM2_CTRL));
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
index 0af6f25..8e8e353 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_ctrl_hw_cmn.c
@@ -20,9 +20,12 @@
#include "dsi_ctrl_reg.h"
#include "dsi_hw.h"
#include "dsi_panel.h"
+#include "dsi_catalog.h"
#define MMSS_MISC_CLAMP_REG_OFF 0x0014
#define DSI_CTRL_DYNAMIC_FORCE_ON (0x23F|BIT(8)|BIT(9)|BIT(11)|BIT(21))
+#define DSI_CTRL_CMD_MISR_ENABLE BIT(28)
+#define DSI_CTRL_VIDEO_MISR_ENABLE BIT(16)
/* Unsupported formats default to RGB888 */
static const u8 cmd_mode_format_map[DSI_PIXEL_FORMAT_MAX] = {
@@ -149,6 +152,70 @@
}
/**
+ * setup_misr() - Setup frame MISR
+ * @ctrl: Pointer to the controller host hardware.
+ * @panel_mode: CMD or VIDEO mode indicator
+ * @enable: Enable/disable MISR.
+ * @frame_count: Number of frames to accumulate MISR.
+ */
+void dsi_ctrl_hw_cmn_setup_misr(struct dsi_ctrl_hw *ctrl,
+ enum dsi_op_mode panel_mode,
+ bool enable,
+ u32 frame_count)
+{
+ u32 addr;
+ u32 config = 0;
+
+ if (panel_mode == DSI_OP_CMD_MODE) {
+ addr = DSI_MISR_CMD_CTRL;
+ if (enable)
+ config = DSI_CTRL_CMD_MISR_ENABLE;
+ } else {
+ addr = DSI_MISR_VIDEO_CTRL;
+ if (enable)
+ config = DSI_CTRL_VIDEO_MISR_ENABLE;
+ if (frame_count > 255)
+ frame_count = 255;
+ config |= frame_count << 8;
+ }
+
+ pr_debug("[DSI_%d] MISR ctrl: 0x%x\n", ctrl->index,
+ config);
+ DSI_W32(ctrl, addr, config);
+ wmb(); /* make sure MISR is configured */
+}
+
+/**
+ * collect_misr() - Read frame MISR
+ * @ctrl: Pointer to the controller host hardware.
+ * @panel_mode: CMD or VIDEO mode indicator
+ */
+u32 dsi_ctrl_hw_cmn_collect_misr(struct dsi_ctrl_hw *ctrl,
+ enum dsi_op_mode panel_mode)
+{
+ u32 addr;
+ u32 enabled;
+ u32 misr = 0;
+
+ if (panel_mode == DSI_OP_CMD_MODE) {
+ addr = DSI_MISR_CMD_MDP0_32BIT;
+ enabled = DSI_R32(ctrl, DSI_MISR_CMD_CTRL) &
+ DSI_CTRL_CMD_MISR_ENABLE;
+ } else {
+ addr = DSI_MISR_VIDEO_32BIT;
+ enabled = DSI_R32(ctrl, DSI_MISR_VIDEO_CTRL) &
+ DSI_CTRL_VIDEO_MISR_ENABLE;
+ }
+
+ if (enabled)
+ misr = DSI_R32(ctrl, addr);
+
+ pr_debug("[DSI_%d] MISR enabled %x value: 0x%x\n", ctrl->index,
+ enabled, misr);
+ return misr;
+}
+
+/**
* set_video_timing() - set up the timing for video frame
* @ctrl: Pointer to controller host hardware.
* @mode: Video mode information.
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index a4a9fb5..c0c6698 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -32,6 +32,8 @@
#define to_dsi_display(x) container_of(x, struct dsi_display, host)
#define INT_BASE_10 10
+#define MISR_BUFF_SIZE 256
+
static DEFINE_MUTEX(dsi_display_list_lock);
static LIST_HEAD(dsi_display_list);
static char dsi_display_primary[MAX_CMDLINE_PARAM_LEN];
@@ -128,9 +130,20 @@
return format;
}
+static void _dsi_display_setup_misr(struct dsi_display *display)
+{
+ int i;
+
+ for (i = 0; i < display->ctrl_count; i++) {
+ dsi_ctrl_setup_misr(display->ctrl[i].ctrl,
+ display->misr_enable,
+ display->misr_frame_count);
+ }
+}
+
static ssize_t debugfs_dump_info_read(struct file *file,
- char __user *buff,
- size_t count,
+ char __user *user_buf,
+ size_t user_len,
loff_t *ppos)
{
struct dsi_display *display = file->private_data;
@@ -168,7 +181,7 @@
"\tClock master = %s\n",
display->ctrl[display->clk_master_idx].ctrl->name);
- if (copy_to_user(buff, buf, len)) {
+ if (copy_to_user(user_buf, buf, len)) {
kfree(buf);
return -EFAULT;
}
@@ -179,16 +192,151 @@
return len;
}
+static ssize_t debugfs_misr_setup(struct file *file,
+ const char __user *user_buf,
+ size_t user_len,
+ loff_t *ppos)
+{
+ struct dsi_display *display = file->private_data;
+ char *buf;
+ int rc = 0;
+ size_t len;
+ u32 enable, frame_count;
+
+ if (!display)
+ return -ENODEV;
+
+ if (*ppos)
+ return 0;
+
+ buf = kzalloc(MISR_BUFF_SIZE, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ /* leave room for termination char */
+ len = min_t(size_t, user_len, MISR_BUFF_SIZE - 1);
+ if (copy_from_user(buf, user_buf, len)) {
+ rc = -EINVAL;
+ goto error;
+ }
+
+ buf[len] = '\0'; /* terminate the string */
+
+ if (sscanf(buf, "%u %u", &enable, &frame_count) != 2) {
+ rc = -EINVAL;
+ goto error;
+ }
+
+ display->misr_enable = enable;
+ display->misr_frame_count = frame_count;
+
+ mutex_lock(&display->display_lock);
+ rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
+ DSI_CORE_CLK, DSI_CLK_ON);
+ if (rc) {
+ pr_err("[%s] failed to enable DSI core clocks, rc=%d\n",
+ display->name, rc);
+ goto unlock;
+ }
+
+ _dsi_display_setup_misr(display);
+
+ rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
+ DSI_CORE_CLK, DSI_CLK_OFF);
+ if (rc) {
+ pr_err("[%s] failed to disable DSI core clocks, rc=%d\n",
+ display->name, rc);
+ goto unlock;
+ }
+
+ rc = user_len;
+unlock:
+ mutex_unlock(&display->display_lock);
+error:
+ kfree(buf);
+ return rc;
+}
+
+static ssize_t debugfs_misr_read(struct file *file,
+ char __user *user_buf,
+ size_t user_len,
+ loff_t *ppos)
+{
+ struct dsi_display *display = file->private_data;
+ char *buf;
+ u32 len = 0;
+ int rc = 0;
+ struct dsi_ctrl *dsi_ctrl;
+ int i;
+ u32 misr;
+ size_t max_len = min_t(size_t, user_len, MISR_BUFF_SIZE);
+
+ if (!display)
+ return -ENODEV;
+
+ if (*ppos)
+ return 0;
+
+ buf = kzalloc(max_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ mutex_lock(&display->display_lock);
+ rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
+ DSI_CORE_CLK, DSI_CLK_ON);
+ if (rc) {
+ pr_err("[%s] failed to enable DSI core clocks, rc=%d\n",
+ display->name, rc);
+ goto error;
+ }
+
+ for (i = 0; i < display->ctrl_count; i++) {
+ dsi_ctrl = display->ctrl[i].ctrl;
+ misr = dsi_ctrl_collect_misr(display->ctrl[i].ctrl);
+
+ len += snprintf((buf + len), max_len - len,
+ "DSI_%d MISR: 0x%x\n", dsi_ctrl->cell_index, misr);
+
+ if (len >= max_len)
+ break;
+ }
+
+ rc = dsi_display_clk_ctrl(display->dsi_clk_handle,
+ DSI_CORE_CLK, DSI_CLK_OFF);
+ if (rc) {
+ pr_err("[%s] failed to disable DSI core clocks, rc=%d\n",
+ display->name, rc);
+ goto error;
+ }
+
+ if (copy_to_user(user_buf, buf, len)) {
+ rc = -EFAULT;
+ goto error;
+ }
+
+ *ppos += len;
+
+error:
+ mutex_unlock(&display->display_lock);
+ kfree(buf);
+ return len;
+}
static const struct file_operations dump_info_fops = {
.open = simple_open,
.read = debugfs_dump_info_read,
};
+static const struct file_operations misr_data_fops = {
+ .open = simple_open,
+ .read = debugfs_misr_read,
+ .write = debugfs_misr_setup,
+};
+
static int dsi_display_debugfs_init(struct dsi_display *display)
{
int rc = 0;
- struct dentry *dir, *dump_file;
+ struct dentry *dir, *dump_file, *misr_data;
dir = debugfs_create_dir(display->name, NULL);
if (IS_ERR_OR_NULL(dir)) {
@@ -199,13 +347,25 @@
}
dump_file = debugfs_create_file("dump_info",
- 0444,
+ 0400,
dir,
display,
&dump_info_fops);
if (IS_ERR_OR_NULL(dump_file)) {
rc = PTR_ERR(dump_file);
- pr_err("[%s] debugfs create file failed, rc=%d\n",
+ pr_err("[%s] debugfs create dump info file failed, rc=%d\n",
+ display->name, rc);
+ goto error_remove_dir;
+ }
+
+ misr_data = debugfs_create_file("misr_data",
+ 0600,
+ dir,
+ display,
+ &misr_data_fops);
+ if (IS_ERR_OR_NULL(misr_data)) {
+ rc = PTR_ERR(misr_data);
+ pr_err("[%s] debugfs create misr datafile failed, rc=%d\n",
display->name, rc);
goto error_remove_dir;
}
@@ -3533,6 +3693,10 @@
{
int rc = 0;
+ /* check and setup MISR */
+ if (display->misr_enable)
+ _dsi_display_setup_misr(display);
+
rc = dsi_display_set_roi(display, params->rois);
return rc;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index b382e4a..359e04f3 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -154,6 +154,8 @@
* @dsi_clk_handle: DSI clock handle.
* @mdp_clk_handle: MDP clock handle.
* @root: Debugfs root directory
+ * @misr_enable Frame MISR enable/disable
+ * @misr_frame_count Number of frames to accumulate the MISR value
*/
struct dsi_display {
struct platform_device *pdev;
@@ -201,6 +203,9 @@
/* DEBUG FS */
struct dentry *root;
+
+ bool misr_enable;
+ u32 misr_frame_count;
};
int dsi_display_dev_probe(struct platform_device *pdev);
diff --git a/drivers/gpu/drm/msm/msm_prop.c b/drivers/gpu/drm/msm/msm_prop.c
index f2996dd..d1991a4 100644
--- a/drivers/gpu/drm/msm/msm_prop.c
+++ b/drivers/gpu/drm/msm/msm_prop.c
@@ -21,8 +21,6 @@
uint32_t blob_count,
uint32_t state_size)
{
- int i;
-
/* prevent access if any of these are NULL */
if (!base || !dev || !property_array || !property_data) {
property_count = 0;
@@ -60,10 +58,6 @@
0,
sizeof(struct msm_property_data) *
property_count);
- INIT_LIST_HEAD(&info->dirty_list);
-
- for (i = 0; i < property_count; ++i)
- INIT_LIST_HEAD(&property_data[i].dirty_node);
}
}
@@ -72,9 +66,6 @@
if (!info)
return;
- /* reset dirty list */
- INIT_LIST_HEAD(&info->dirty_list);
-
/* free state cache */
while (info->state_cache_size > 0)
kfree(info->state_cache[--(info->state_cache_size)]);
@@ -82,24 +73,25 @@
mutex_destroy(&info->property_lock);
}
-int msm_property_pop_dirty(struct msm_property_info *info)
+int msm_property_pop_dirty(struct msm_property_info *info,
+ struct msm_property_state *property_state)
{
struct list_head *item;
int rc = 0;
- if (!info) {
- DRM_ERROR("invalid info\n");
+ if (!info || !property_state || !property_state->values) {
+ DRM_ERROR("invalid argument(s)\n");
return -EINVAL;
}
mutex_lock(&info->property_lock);
- if (list_empty(&info->dirty_list)) {
+ if (list_empty(&property_state->dirty_list)) {
rc = -EAGAIN;
} else {
- item = info->dirty_list.next;
+ item = property_state->dirty_list.next;
list_del_init(item);
- rc = container_of(item, struct msm_property_data, dirty_node)
- - info->property_data;
+ rc = container_of(item, struct msm_property_value, dirty_node)
+ - property_state->values;
DRM_DEBUG_KMS("property %d dirty\n", rc);
}
mutex_unlock(&info->property_lock);
@@ -112,26 +104,28 @@
* This function doesn't mutex protect the
* dirty linked list.
* @info: Pointer to property info container struct
+ * @property_state: Pointer to property state container struct
* @property_idx: Property index
*/
static void _msm_property_set_dirty_no_lock(
struct msm_property_info *info,
+ struct msm_property_state *property_state,
uint32_t property_idx)
{
- if (!info || property_idx >= info->property_count) {
- DRM_ERROR("invalid argument(s), info %pK, idx %u\n",
- info, property_idx);
+ if (!info || !property_state || !property_state->values ||
+ property_idx >= info->property_count) {
+ DRM_ERROR("invalid argument(s), idx %u\n", property_idx);
return;
}
/* avoid re-inserting if already dirty */
- if (!list_empty(&info->property_data[property_idx].dirty_node)) {
+ if (!list_empty(&property_state->values[property_idx].dirty_node)) {
DRM_DEBUG_KMS("property %u already dirty\n", property_idx);
return;
}
- list_add_tail(&info->property_data[property_idx].dirty_node,
- &info->dirty_list);
+ list_add_tail(&property_state->values[property_idx].dirty_node,
+ &property_state->dirty_list);
}
/**
@@ -371,35 +365,36 @@
return rc;
}
-int msm_property_set_dirty(struct msm_property_info *info, int property_idx)
+int msm_property_set_dirty(struct msm_property_info *info,
+ struct msm_property_state *property_state,
+ int property_idx)
{
- if (!info) {
- DRM_ERROR("invalid property info\n");
+ if (!info || !property_state || !property_state->values) {
+ DRM_ERROR("invalid argument(s)\n");
return -EINVAL;
}
mutex_lock(&info->property_lock);
- _msm_property_set_dirty_no_lock(info, property_idx);
+ _msm_property_set_dirty_no_lock(info, property_state, property_idx);
mutex_unlock(&info->property_lock);
return 0;
}
int msm_property_atomic_set(struct msm_property_info *info,
- uint64_t *property_values,
- struct drm_property_blob **property_blobs,
+ struct msm_property_state *property_state,
struct drm_property *property, uint64_t val)
{
struct drm_property_blob *blob;
int property_idx, rc = -EINVAL;
property_idx = msm_property_index(info, property);
- if (!info || (property_idx == -EINVAL) || !property_values) {
- DRM_DEBUG("Invalid argument(s)\n");
+ if (!info || !property_state ||
+ (property_idx == -EINVAL) || !property_state->values) {
+ DRM_DEBUG("invalid argument(s)\n");
} else {
/* extra handling for incoming properties */
mutex_lock(&info->property_lock);
if ((property->flags & DRM_MODE_PROP_BLOB) &&
- (property_idx < info->blob_count) &&
- property_blobs) {
+ (property_idx < info->blob_count)) {
/* DRM lookup also takes a reference */
blob = drm_property_lookup_blob(info->dev,
(uint32_t)val);
@@ -411,18 +406,21 @@
val = blob->base.id;
/* save blob - need to clear previous ref */
- if (property_blobs[property_idx])
+ if (property_state->values[property_idx].blob)
drm_property_unreference_blob(
- property_blobs[property_idx]);
- property_blobs[property_idx] = blob;
+ property_state->values[
+ property_idx].blob);
+ property_state->values[property_idx].blob =
+ blob;
}
}
/* update value and flag as dirty */
- if (property_values[property_idx] != val ||
+ if (property_state->values[property_idx].value != val ||
info->property_data[property_idx].force_dirty) {
- property_values[property_idx] = val;
- _msm_property_set_dirty_no_lock(info, property_idx);
+ property_state->values[property_idx].value = val;
+ _msm_property_set_dirty_no_lock(info, property_state,
+ property_idx);
DBG("%s - %lld", property->name, val);
}
@@ -434,18 +432,18 @@
}
int msm_property_atomic_get(struct msm_property_info *info,
- uint64_t *property_values,
- struct drm_property_blob **property_blobs,
+ struct msm_property_state *property_state,
struct drm_property *property, uint64_t *val)
{
int property_idx, rc = -EINVAL;
property_idx = msm_property_index(info, property);
- if (!info || (property_idx == -EINVAL) || !property_values || !val) {
+ if (!info || (property_idx == -EINVAL) ||
+ !property_state->values || !val) {
DRM_DEBUG("Invalid argument(s)\n");
} else {
mutex_lock(&info->property_lock);
- *val = property_values[property_idx];
+ *val = property_state->values[property_idx].value;
mutex_unlock(&info->property_lock);
rc = 0;
}
@@ -495,8 +493,8 @@
}
void msm_property_reset_state(struct msm_property_info *info, void *state,
- uint64_t *property_values,
- struct drm_property_blob **property_blobs)
+ struct msm_property_state *property_state,
+ struct msm_property_value *property_values)
{
uint32_t i;
@@ -508,24 +506,29 @@
if (state)
memset(state, 0, info->state_size);
+ if (property_state) {
+ property_state->property_count = info->property_count;
+ property_state->values = property_values;
+ INIT_LIST_HEAD(&property_state->dirty_list);
+ }
+
/*
* Assign default property values. This helper is mostly used
* to initialize newly created state objects.
*/
if (property_values)
- for (i = 0; i < info->property_count; ++i)
- property_values[i] =
+ for (i = 0; i < info->property_count; ++i) {
+ property_values[i].value =
info->property_data[i].default_value;
-
- if (property_blobs)
- for (i = 0; i < info->blob_count; ++i)
- property_blobs[i] = 0;
+ property_values[i].blob = NULL;
+ INIT_LIST_HEAD(&property_values[i].dirty_node);
+ }
}
void msm_property_duplicate_state(struct msm_property_info *info,
void *old_state, void *state,
- uint64_t *property_values,
- struct drm_property_blob **property_blobs)
+ struct msm_property_state *property_state,
+ struct msm_property_value *property_values)
{
uint32_t i;
@@ -536,17 +539,24 @@
memcpy(state, old_state, info->state_size);
- if (property_blobs) {
- /* add ref count for blobs */
- for (i = 0; i < info->blob_count; ++i)
- if (property_blobs[i])
- drm_property_reference_blob(property_blobs[i]);
- }
+ if (!property_state)
+ return;
+
+ INIT_LIST_HEAD(&property_state->dirty_list);
+ property_state->values = property_values;
+
+ if (property_state->values)
+ /* add ref count for blobs and initialize dirty nodes */
+ for (i = 0; i < info->property_count; ++i) {
+ if (property_state->values[i].blob)
+ drm_property_reference_blob(
+ property_state->values[i].blob);
+ INIT_LIST_HEAD(&property_state->values[i].dirty_node);
+ }
}
void msm_property_destroy_state(struct msm_property_info *info, void *state,
- uint64_t *property_values,
- struct drm_property_blob **property_blobs)
+ struct msm_property_state *property_state)
{
uint32_t i;
@@ -554,19 +564,21 @@
DRM_ERROR("invalid argument(s)\n");
return;
}
- if (property_blobs) {
+ if (property_state && property_state->values) {
/* remove ref count for blobs */
- for (i = 0; i < info->blob_count; ++i)
- if (property_blobs[i])
+ for (i = 0; i < info->property_count; ++i)
+ if (property_state->values[i].blob) {
drm_property_unreference_blob(
- property_blobs[i]);
+ property_state->values[i].blob);
+ property_state->values[i].blob = NULL;
+ }
}
_msm_property_free_state(info, state);
}
void *msm_property_get_blob(struct msm_property_info *info,
- struct drm_property_blob **property_blobs,
+ struct msm_property_state *property_state,
size_t *byte_len,
uint32_t property_idx)
{
@@ -574,10 +586,11 @@
size_t len = 0;
void *rc = 0;
- if (!info || !property_blobs || (property_idx >= info->blob_count)) {
+ if (!info || !property_state || !property_state->values ||
+ (property_idx >= info->blob_count)) {
DRM_ERROR("invalid argument(s)\n");
} else {
- blob = property_blobs[property_idx];
+ blob = property_state->values[property_idx].blob;
if (blob) {
len = blob->length;
rc = &blob->data;
@@ -636,14 +649,15 @@
}
int msm_property_set_property(struct msm_property_info *info,
- uint64_t *property_values,
+ struct msm_property_state *property_state,
uint32_t property_idx,
uint64_t val)
{
int rc = -EINVAL;
if (!info || (property_idx >= info->property_count) ||
- property_idx < info->blob_count || !property_values) {
+ property_idx < info->blob_count ||
+ !property_state || !property_state->values) {
DRM_ERROR("invalid argument(s)\n");
} else {
struct drm_property *drm_prop;
@@ -651,8 +665,7 @@
mutex_lock(&info->property_lock);
/* update cached value */
- if (property_values)
- property_values[property_idx] = val;
+ property_state->values[property_idx].value = val;
/* update the new default value for immutables */
drm_prop = info->property_array[property_idx];
diff --git a/drivers/gpu/drm/msm/msm_prop.h b/drivers/gpu/drm/msm/msm_prop.h
index e54c796..9a53e56 100644
--- a/drivers/gpu/drm/msm/msm_prop.h
+++ b/drivers/gpu/drm/msm/msm_prop.h
@@ -22,17 +22,28 @@
* struct msm_property_data - opaque structure for tracking per
* drm-object per property stuff
* @default_value: Default property value for this drm object
- * @dirty_node: Linked list node to track if property is dirty or not
* @force_dirty: Always dirty property on incoming sets, rather than checking
* for modified values
*/
struct msm_property_data {
uint64_t default_value;
- struct list_head dirty_node;
bool force_dirty;
};
/**
+ * struct msm_property_value - opaque structure for tracking per
+ * drm-object per property stuff
+ * @value: Current property value for this drm object
+ * @blob: Pointer to associated blob data, if available
+ * @dirty_node: Linked list node to track if property is dirty or not
+ */
+struct msm_property_value {
+ uint64_t value;
+ struct drm_property_blob *blob;
+ struct list_head dirty_node;
+};
+
+/**
* struct msm_property_info: Structure for property/state helper functions
* @base: Pointer to base drm object (plane/crtc/etc.)
* @dev: Pointer to drm device object
@@ -43,8 +54,6 @@
* @install_request: Total number of property 'install' requests
* @install_count: Total number of successful 'install' requests
* @recent_idx: Index of property most recently accessed by set/get
- * @dirty_list: List of all properties that have been 'atomic_set' but not
- * yet cleared with 'msm_property_pop_dirty'
* @is_active: Whether or not drm component properties are 'active'
* @state_cache: Cache of local states, to prevent alloc/free thrashing
* @state_size: Size of local state structures
@@ -64,7 +73,6 @@
int32_t recent_idx;
- struct list_head dirty_list;
bool is_active;
void *state_cache[MSM_PROP_STATE_CACHE_SIZE];
@@ -74,6 +82,19 @@
};
/**
+ * struct msm_property_state - Structure for local property state information
+ * @property_count: Total number of properties
+ * @values: Pointer to array of msm_property_value objects
+ * @dirty_list: List of all properties that have been 'atomic_set' but not
+ * yet cleared with 'msm_property_pop_dirty'
+ */
+struct msm_property_state {
+ uint32_t property_count;
+ struct msm_property_value *values;
+ struct list_head dirty_list;
+};
+
+/**
* msm_property_get_default - query default value of a property
* @info: Pointer to property info container struct
* @property_idx: Property index
@@ -134,12 +155,14 @@
* msm_property_pop_dirty - determine next dirty property and clear
* its dirty flag
* @info: Pointer to property info container struct
+ * @property_state: Pointer to property state container struct
* Returns: Valid msm property index on success,
* -EAGAIN if no dirty properties are available
* Property indicies returned from this function are similar
* to those returned by the msm_property_index function.
*/
-int msm_property_pop_dirty(struct msm_property_info *info);
+int msm_property_pop_dirty(struct msm_property_info *info,
+ struct msm_property_state *property_state);
/**
* msm_property_init - initialize property info structure
@@ -268,38 +291,37 @@
/**
* msm_property_set_dirty - forcibly flag a property as dirty
* @info: Pointer to property info container struct
+ * @property_state: Pointer to property state container struct
* @property_idx: Property index
* Returns: Zero on success
*/
-int msm_property_set_dirty(struct msm_property_info *info, int property_idx);
+int msm_property_set_dirty(struct msm_property_info *info,
+ struct msm_property_state *property_state,
+ int property_idx);
/**
* msm_property_atomic_set - helper function for atomic property set callback
* @info: Pointer to property info container struct
- * @property_values: Pointer to property values cache array
- * @property_blobs: Pointer to property blobs cache array
+ * @property_state: Pointer to local state structure
* @property: Incoming property pointer
* @val: Incoming property value
* Returns: Zero on success
*/
int msm_property_atomic_set(struct msm_property_info *info,
- uint64_t *property_values,
- struct drm_property_blob **property_blobs,
+ struct msm_property_state *property_state,
struct drm_property *property,
uint64_t val);
/**
* msm_property_atomic_get - helper function for atomic property get callback
* @info: Pointer to property info container struct
- * @property_values: Pointer to property values cache array
- * @property_blobs: Pointer to property blobs cache array
+ * @property_state: Pointer to local state structure
* @property: Incoming property pointer
* @val: Pointer to variable for receiving property value
* Returns: Zero on success
*/
int msm_property_atomic_get(struct msm_property_info *info,
- uint64_t *property_values,
- struct drm_property_blob **property_blobs,
+ struct msm_property_state *property_state,
struct drm_property *property,
uint64_t *val);
@@ -313,50 +335,47 @@
* msm_property_reset_state - helper function for state reset callback
* @info: Pointer to property info container struct
* @state: Pointer to local state structure
+ * @property_state: Pointer to property state container struct
* @property_values: Pointer to property values cache array
- * @property_blobs: Pointer to property blobs cache array
*/
-void msm_property_reset_state(struct msm_property_info *info,
- void *state,
- uint64_t *property_values,
- struct drm_property_blob **property_blobs);
+void msm_property_reset_state(struct msm_property_info *info, void *state,
+ struct msm_property_state *property_state,
+ struct msm_property_value *property_values);
/**
* msm_property_duplicate_state - helper function for duplicate state cb
* @info: Pointer to property info container struct
* @old_state: Pointer to original state structure
* @state: Pointer to newly created state structure
+ * @property_state: Pointer to destination property state container struct
* @property_values: Pointer to property values cache array
- * @property_blobs: Pointer to property blobs cache array
*/
void msm_property_duplicate_state(struct msm_property_info *info,
void *old_state,
void *state,
- uint64_t *property_values,
- struct drm_property_blob **property_blobs);
+ struct msm_property_state *property_state,
+ struct msm_property_value *property_values);
/**
* msm_property_destroy_state - helper function for destroy state cb
* @info: Pointer to property info container struct
* @state: Pointer to local state structure
- * @property_values: Pointer to property values cache array
- * @property_blobs: Pointer to property blobs cache array
+ * @property_state: Pointer to property state container struct
*/
void msm_property_destroy_state(struct msm_property_info *info,
void *state,
- uint64_t *property_values,
- struct drm_property_blob **property_blobs);
+ struct msm_property_state *property_state);
/**
* msm_property_get_blob - obtain cached data pointer for drm blob property
* @info: Pointer to property info container struct
- * @property_blobs: Pointer to property blobs cache array
+ * @property_state: Pointer to property state container struct
* @byte_len: Optional pointer to variable for accepting blob size
* @property_idx: Property index
* Returns: Pointer to blob data
*/
void *msm_property_get_blob(struct msm_property_info *info,
- struct drm_property_blob **property_blobs,
+ struct msm_property_state *property_state,
size_t *byte_len,
uint32_t property_idx);
@@ -385,13 +404,13 @@
* DRM_MODE_PROP_IMMUTABLE flag set.
* Note: This function cannot be called on a blob.
* @info: Pointer to property info container struct
- * @property_values: Pointer to property values cache array
+ * @property_state: Pointer to property state container struct
* @property_idx: Property index
* @val: value of the property to set
* Returns: Zero on success
*/
int msm_property_set_property(struct msm_property_info *info,
- uint64_t *property_values,
+ struct msm_property_state *property_state,
uint32_t property_idx,
uint64_t val);
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.c b/drivers/gpu/drm/msm/sde/sde_connector.c
index e87058e..f5e2ada 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.c
+++ b/drivers/gpu/drm/msm/sde/sde_connector.c
@@ -233,8 +233,8 @@
}
if (!c_conn->ops.get_dst_format) {
- SDE_ERROR("get_dst_format is invalid\n");
- return -EINVAL;
+ SDE_DEBUG("get_dst_format is unavailable\n");
+ return 0;
}
dst_format = c_conn->ops.get_dst_format(c_conn->display);
@@ -331,7 +331,7 @@
/* try to get user config data first */
*cfg = msm_property_get_blob(&c_conn->property_info,
- c_state->property_blobs,
+ &c_state->property_state,
&dither_sz,
CONNECTOR_PROP_PP_DITHER);
/* if user config data doesn't exist, use default dither blob */
@@ -459,13 +459,12 @@
drm_framebuffer_unreference(c_state->out_fb);
c_state->out_fb = NULL;
- if (c_conn) {
- c_state->property_values[CONNECTOR_PROP_OUT_FB] =
+ if (c_conn)
+ c_state->property_values[CONNECTOR_PROP_OUT_FB].value =
msm_property_get_default(&c_conn->property_info,
CONNECTOR_PROP_OUT_FB);
- } else {
- c_state->property_values[CONNECTOR_PROP_OUT_FB] = ~0;
- }
+ else
+ c_state->property_values[CONNECTOR_PROP_OUT_FB].value = ~0;
}
static void sde_connector_atomic_destroy_state(struct drm_connector *connector,
@@ -496,8 +495,7 @@
} else {
/* destroy value helper */
msm_property_destroy_state(&c_conn->property_info, c_state,
- c_state->property_values,
- c_state->property_blobs);
+ &c_state->property_state);
}
}
@@ -526,7 +524,8 @@
/* reset value helper, zero out state structure and reset properties */
msm_property_reset_state(&c_conn->property_info, c_state,
- c_state->property_values, c_state->property_blobs);
+ &c_state->property_state,
+ c_state->property_values);
c_state->base.connector = connector;
connector->state = &c_state->base;
@@ -554,8 +553,8 @@
/* duplicate value helper */
msm_property_duplicate_state(&c_conn->property_info,
- c_oldstate, c_state, c_state->property_values,
- c_state->property_blobs);
+ c_oldstate, c_state,
+ &c_state->property_state, c_state->property_values);
/* additional handling for drm framebuffer objects */
if (c_state->out_fb) {
@@ -755,8 +754,7 @@
/* generic property handling */
rc = msm_property_atomic_set(&c_conn->property_info,
- c_state->property_values, c_state->property_blobs,
- property, val);
+ &c_state->property_state, property, val);
if (rc)
goto end;
@@ -863,8 +861,7 @@
else
/* get cached property value */
rc = msm_property_atomic_get(&c_conn->property_info,
- c_state->property_values,
- c_state->property_blobs, property, val);
+ &c_state->property_state, property, val);
/* allow for custom override */
if (c_conn->ops.get_property)
diff --git a/drivers/gpu/drm/msm/sde/sde_connector.h b/drivers/gpu/drm/msm/sde/sde_connector.h
index 8796c52..1598968 100644
--- a/drivers/gpu/drm/msm/sde/sde_connector.h
+++ b/drivers/gpu/drm/msm/sde/sde_connector.h
@@ -315,6 +315,7 @@
* @base: Base drm connector structure
* @out_fb: Pointer to output frame buffer, if applicable
* @aspace: Address space for accessing frame buffer objects, if applicable
+ * @property_state: Local storage for msm_prop properties
* @property_values: Local cache of current connector property values
* @rois: Regions of interest structure for mapping CRTC to Connector output
* @property_blobs: blob properties
@@ -323,7 +324,8 @@
struct drm_connector_state base;
struct drm_framebuffer *out_fb;
struct msm_gem_address_space *aspace;
- uint64_t property_values[CONNECTOR_PROP_COUNT];
+ struct msm_property_state property_state;
+ struct msm_property_value property_values[CONNECTOR_PROP_COUNT];
struct msm_roi_list rois;
struct drm_property_blob *property_blobs[CONNECTOR_PROP_BLOBCOUNT];
@@ -346,15 +348,15 @@
*/
#define sde_connector_get_property(S, X) \
((S) && ((X) < CONNECTOR_PROP_COUNT) ? \
- (to_sde_connector_state((S))->property_values[(X)]) : 0)
+ (to_sde_connector_state((S))->property_values[(X)].value) : 0)
/**
- * sde_connector_get_property_values - retrieve property values cache
+ * sde_connector_get_property_state - retrieve property state cache
* @S: Pointer to drm connector state
- * Returns: Integer value of requested property
+ * Returns: Pointer to local property state structure
*/
-#define sde_connector_get_property_values(S) \
- ((S) ? (to_sde_connector_state((S))->property_values) : 0)
+#define sde_connector_get_property_state(S) \
+ ((S) ? (&to_sde_connector_state((S))->property_state) : NULL)
/**
* sde_connector_get_out_fb - query out_fb value from sde connector state
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index ff802e6..01e4f93 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -2084,7 +2084,7 @@
/* destroy value helper */
msm_property_destroy_state(&sde_crtc->property_info, cstate,
- cstate->property_values, cstate->property_blobs);
+ &cstate->property_state);
}
static int _sde_crtc_wait_for_frame_done(struct drm_crtc *crtc)
@@ -2344,7 +2344,7 @@
/* duplicate value helper */
msm_property_duplicate_state(&sde_crtc->property_info,
old_cstate, cstate,
- cstate->property_values, cstate->property_blobs);
+ &cstate->property_state, cstate->property_values);
/* duplicate base helper */
__drm_atomic_helper_crtc_duplicate_state(crtc, &cstate->base);
@@ -2389,7 +2389,8 @@
/* reset value helper */
msm_property_reset_state(&sde_crtc->property_info, cstate,
- cstate->property_values, cstate->property_blobs);
+ &cstate->property_state,
+ cstate->property_values);
_sde_crtc_set_input_fence_timeout(cstate);
@@ -3196,8 +3197,7 @@
sde_crtc = to_sde_crtc(crtc);
cstate = to_sde_crtc_state(state);
ret = msm_property_atomic_set(&sde_crtc->property_info,
- cstate->property_values, cstate->property_blobs,
- property, val);
+ &cstate->property_state, property, val);
if (!ret) {
idx = msm_property_index(&sde_crtc->property_info,
property);
@@ -3317,8 +3317,8 @@
SDE_ERROR("fence create failed\n");
} else {
ret = msm_property_atomic_get(&sde_crtc->property_info,
- cstate->property_values,
- cstate->property_blobs, property, val);
+ &cstate->property_state,
+ property, val);
if (ret)
ret = sde_cp_crtc_get_property(crtc,
property, val);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index 86b7855..84f9ce1 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -269,9 +269,9 @@
* @lm_roi : Current LM ROI, possibly sub-rectangle of mode.
* Origin top left of CRTC.
* @user_roi_list : List of user's requested ROIs as from set property
+ * @property_state: Local storage for msm_prop properties
* @property_values: Current crtc property values
* @input_fence_timeout_ns : Cached input fence timeout, in ns
- * @property_blobs: Reference pointers for blob properties
* @num_dim_layers: Number of dim layers
* @dim_layer: Dim layer configs
* @new_perf: new performance state being requested
@@ -296,9 +296,9 @@
struct sde_rect lm_roi[CRTC_DUAL_MIXERS];
struct msm_roi_list user_roi_list;
- uint64_t property_values[CRTC_PROP_COUNT];
+ struct msm_property_state property_state;
+ struct msm_property_value property_values[CRTC_PROP_COUNT];
uint64_t input_fence_timeout_ns;
- struct drm_property_blob *property_blobs[CRTC_PROP_COUNT];
uint32_t num_dim_layers;
struct sde_hw_dim_layer dim_layer[SDE_MAX_DIM_LAYERS];
@@ -320,7 +320,7 @@
* Returns: Integer value of requested property
*/
#define sde_crtc_get_property(S, X) \
- ((S) && ((X) < CRTC_PROP_COUNT) ? ((S)->property_values[(X)]) : 0)
+ ((S) && ((X) < CRTC_PROP_COUNT) ? ((S)->property_values[(X)].value) : 0)
static inline int sde_crtc_mixer_width(struct sde_crtc *sde_crtc,
struct drm_display_mode *mode)
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 665315d..90e6caf 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -957,15 +957,15 @@
cfg->dir_lut = msm_property_get_blob(
&psde->property_info,
- pstate->property_blobs, &cfg->dir_len,
+ &pstate->property_state, &cfg->dir_len,
PLANE_PROP_SCALER_LUT_ED);
cfg->cir_lut = msm_property_get_blob(
&psde->property_info,
- pstate->property_blobs, &cfg->cir_len,
+ &pstate->property_state, &cfg->cir_len,
PLANE_PROP_SCALER_LUT_CIR);
cfg->sep_lut = msm_property_get_blob(
&psde->property_info,
- pstate->property_blobs, &cfg->sep_len,
+ &pstate->property_state, &cfg->sep_len,
PLANE_PROP_SCALER_LUT_SEP);
if (!cfg->dir_lut || !cfg->cir_lut || !cfg->sep_lut)
ret = -ENODATA;
@@ -1276,7 +1276,7 @@
if (psde->pipe_hw->ops.setup_pa_memcolor) {
/* Skin memory color setup */
memcol = msm_property_get_blob(&psde->property_info,
- pstate->property_blobs,
+ &pstate->property_state,
&memcol_sz,
PLANE_PROP_SKIN_COLOR);
psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
@@ -1284,7 +1284,7 @@
/* Sky memory color setup */
memcol = msm_property_get_blob(&psde->property_info,
- pstate->property_blobs,
+ &pstate->property_state,
&memcol_sz,
PLANE_PROP_SKY_COLOR);
psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
@@ -1292,7 +1292,7 @@
/* Foliage memory color setup */
memcol = msm_property_get_blob(&psde->property_info,
- pstate->property_blobs,
+ &pstate->property_state,
&memcol_sz,
PLANE_PROP_FOLIAGE_COLOR);
psde->pipe_hw->ops.setup_pa_memcolor(psde->pipe_hw,
@@ -3250,7 +3250,8 @@
}
/* determine what needs to be refreshed */
- while ((idx = msm_property_pop_dirty(&psde->property_info)) >= 0) {
+ while ((idx = msm_property_pop_dirty(&psde->property_info,
+ &pstate->property_state)) >= 0) {
switch (idx) {
case PLANE_PROP_SCALER_V1:
case PLANE_PROP_SCALER_V2:
@@ -3908,7 +3909,8 @@
}
/* force property to be dirty, even if the pointer didn't change */
- msm_property_set_dirty(&psde->property_info, PLANE_PROP_SCALER_V1);
+ msm_property_set_dirty(&psde->property_info,
+ &pstate->property_state, PLANE_PROP_SCALER_V1);
/* populate from user space */
pe = &pstate->pixel_ext;
@@ -3974,7 +3976,8 @@
}
/* force property to be dirty, even if the pointer didn't change */
- msm_property_set_dirty(&psde->property_info, PLANE_PROP_SCALER_V2);
+ msm_property_set_dirty(&psde->property_info,
+ &pstate->property_state, PLANE_PROP_SCALER_V2);
/* populate from user space */
pe = &pstate->pixel_ext;
@@ -4091,8 +4094,7 @@
} else {
pstate = to_sde_plane_state(state);
ret = msm_property_atomic_set(&psde->property_info,
- pstate->property_values, pstate->property_blobs,
- property, val);
+ &pstate->property_state, property, val);
if (!ret) {
idx = msm_property_index(&psde->property_info,
property);
@@ -4109,7 +4111,7 @@
break;
case PLANE_PROP_SCALER_V2:
_sde_plane_set_scaler_v2(psde, pstate,
- (void *)val);
+ (void *)val);
break;
case PLANE_PROP_EXCL_RECT_V1:
_sde_plane_set_excl_rect_v1(psde, pstate,
@@ -4154,8 +4156,7 @@
pstate = to_sde_plane_state(state);
sde_plane_rot_install_caps(plane);
ret = msm_property_atomic_get(&psde->property_info,
- pstate->property_values, pstate->property_blobs,
- property, val);
+ &pstate->property_state, property, val);
}
return ret;
@@ -4216,7 +4217,7 @@
/* destroy value helper */
msm_property_destroy_state(&psde->property_info, pstate,
- pstate->property_values, pstate->property_blobs);
+ &pstate->property_state);
}
static struct drm_plane_state *
@@ -4247,13 +4248,14 @@
/* duplicate value helper */
msm_property_duplicate_state(&psde->property_info, old_state, pstate,
- pstate->property_values, pstate->property_blobs);
+ &pstate->property_state, pstate->property_values);
/* clear out any input fence */
pstate->input_fence = 0;
input_fence_default = msm_property_get_default(
&psde->property_info, PLANE_PROP_INPUT_FENCE);
- msm_property_set_property(&psde->property_info, pstate->property_values,
+ msm_property_set_property(&psde->property_info,
+ &pstate->property_state,
PLANE_PROP_INPUT_FENCE, input_fence_default);
pstate->dirty = 0x0;
@@ -4293,7 +4295,8 @@
/* reset value helper */
msm_property_reset_state(&psde->property_info, pstate,
- pstate->property_values, pstate->property_blobs);
+ &pstate->property_state,
+ pstate->property_values);
pstate->base.plane = plane;
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.h b/drivers/gpu/drm/msm/sde/sde_plane.h
index 2f0068a..a5599a5 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.h
+++ b/drivers/gpu/drm/msm/sde/sde_plane.h
@@ -119,8 +119,8 @@
/**
* struct sde_plane_state: Define sde extension of drm plane state object
* @base: base drm plane state object
+ * @property_state: Local storage for msm_prop properties
* @property_values: cached plane property values
- * @property_blobs: blob properties
* @aspace: pointer to address space for input/output buffers
* @input_fence: dereferenced input fence pointer
* @stage: assigned by crtc blender
@@ -136,8 +136,8 @@
*/
struct sde_plane_state {
struct drm_plane_state base;
- uint64_t property_values[PLANE_PROP_COUNT];
- struct drm_property_blob *property_blobs[PLANE_PROP_BLOBCOUNT];
+ struct msm_property_state property_state;
+ struct msm_property_value property_values[PLANE_PROP_COUNT];
struct msm_gem_address_space *aspace;
void *input_fence;
enum sde_stage stage;
@@ -178,8 +178,8 @@
* @X: Property index, from enum msm_mdp_plane_property
* Returns: Integer value of requested property
*/
-#define sde_plane_get_property(S, X) \
- ((S) && ((X) < PLANE_PROP_COUNT) ? ((S)->property_values[(X)]) : 0)
+#define sde_plane_get_property(S, X) ((S) && ((X) < PLANE_PROP_COUNT) ? \
+ ((S)->property_values[(X)].value) : 0)
/**
* sde_plane_pipe - return sspp identifier for the given plane
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index 0382ed0..be3a8af 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.c
@@ -1150,7 +1150,7 @@
(void) msm_property_set_property(
sde_connector_get_propinfo(conn),
- sde_connector_get_property_values(conn->state),
+ sde_connector_get_property_state(conn->state),
CONNECTOR_PROP_TOPOLOGY_NAME,
SDE_RM_TOPOLOGY_NONE);
}
@@ -1170,7 +1170,7 @@
ret = msm_property_set_property(
sde_connector_get_propinfo(conn_state->connector),
- sde_connector_get_property_values(conn_state),
+ sde_connector_get_property_state(conn_state),
CONNECTOR_PROP_TOPOLOGY_NAME,
rsvp->topology);
if (ret) {
@@ -1267,7 +1267,7 @@
(void) msm_property_set_property(
sde_connector_get_propinfo(
conn_state->connector),
- sde_connector_get_property_values(conn_state),
+ sde_connector_get_property_state(conn_state),
CONNECTOR_PROP_TOPOLOGY_NAME,
SDE_RM_TOPOLOGY_NONE);
}
diff --git a/drivers/gpu/drm/msm/sde_edid_parser.c b/drivers/gpu/drm/msm/sde_edid_parser.c
index 130bd1f..3c03b92 100644
--- a/drivers/gpu/drm/msm/sde_edid_parser.c
+++ b/drivers/gpu/drm/msm/sde_edid_parser.c
@@ -228,10 +228,17 @@
{
u8 cea_mode = 0;
struct drm_display_mode *mode;
+ u32 mode_fmt_flags = 0;
/* Need to add Y420 support flag to the modes */
list_for_each_entry(mode, &connector->probed_modes, head) {
+ /* Cache the format flags before clearing */
+ mode_fmt_flags = mode->flags;
+ /* Clear the RGB/YUV format flags before calling upstream API */
+ mode->flags &= ~SDE_DRM_MODE_FLAG_FMT_MASK;
cea_mode = drm_match_cea_mode(mode);
+ /* Restore the format flags */
+ mode->flags = mode_fmt_flags;
if ((cea_mode != 0) && (cea_mode == video_format)) {
SDE_EDID_DEBUG("%s found match for %d ", __func__,
video_format);
@@ -245,7 +252,7 @@
const u8 *db)
{
u32 offset = 0;
- u8 len = 0;
+ u8 cmdb_len = 0;
u8 svd_len = 0;
const u8 *svd = NULL;
u32 i = 0, j = 0;
@@ -261,10 +268,8 @@
return;
}
SDE_EDID_DEBUG("%s +\n", __func__);
- len = db[0] & 0x1f;
+ cmdb_len = db[0] & 0x1f;
- if (len < 7)
- return;
/* Byte 3 to L+1 contain SVDs */
offset += 2;
@@ -272,20 +277,24 @@
if (svd) {
/*moving to the next byte as vic info begins there*/
- ++svd;
svd_len = svd[0] & 0x1f;
+ ++svd;
}
for (i = 0; i < svd_len; i++, j++) {
- video_format = *svd & 0x7F;
- if (db[offset] & (1 << j))
+ video_format = *(svd + i) & 0x7F;
+ if (cmdb_len == 1) {
+ /* If cmdb_len is 1, it means all SVDs support YUV */
+ sde_edid_set_y420_support(connector, video_format);
+ } else if (db[offset] & (1 << j)) {
sde_edid_set_y420_support(connector, video_format);
- if (j & 0x80) {
- j = j/8;
- offset++;
- if (offset >= len)
- break;
+ if (j & 0x80) {
+ j = j/8;
+ offset++;
+ if (offset >= cmdb_len)
+ break;
+ }
}
}
diff --git a/drivers/gpu/drm/msm/sde_edid_parser.h b/drivers/gpu/drm/msm/sde_edid_parser.h
index eb68439..b58b322 100644
--- a/drivers/gpu/drm/msm/sde_edid_parser.h
+++ b/drivers/gpu/drm/msm/sde_edid_parser.h
@@ -33,6 +33,8 @@
#define SDE_CEA_EXT 0x02
#define SDE_EXTENDED_TAG 0x07
+#define SDE_DRM_MODE_FLAG_FMT_MASK (0x3 << 20)
+
enum extended_data_block_types {
VIDEO_CAPABILITY_DATA_BLOCK = 0x0,
VENDOR_SPECIFIC_VIDEO_DATA_BLOCK = 0x01,
diff --git a/drivers/mailbox/qti-tcs.c b/drivers/mailbox/qti-tcs.c
index c50fc0e..794ce78 100644
--- a/drivers/mailbox/qti-tcs.c
+++ b/drivers/mailbox/qti-tcs.c
@@ -17,6 +17,7 @@
#include <linux/bitmap.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
+#include <linux/ipc_logging.h>
#include <linux/jiffies.h>
#include <linux/kernel.h>
#include <linux/list.h>
@@ -40,6 +41,8 @@
#define CREATE_TRACE_POINTS
#include <trace/events/rpmh.h>
+#define TCS_DRV_IPC_LOG_SIZE 2
+
#define MAX_CMDS_PER_TCS 16
#define MAX_TCS_PER_TYPE 3
#define MAX_TCS_SLOTS (MAX_CMDS_PER_TCS * MAX_TCS_PER_TYPE)
@@ -140,8 +143,35 @@
u64 tcs_last_recv_ts[MAX_POOL_SIZE];
atomic_t tcs_send_count[MAX_POOL_SIZE];
atomic_t tcs_irq_count[MAX_POOL_SIZE];
+ void *ipc_log_ctx;
};
+/* Log to IPC and Ftrace */
+#define log_send_msg(drv, m, n, i, a, d, c, t) do { \
+ trace_rpmh_send_msg(drv->name, m, n, i, a, d, c, t); \
+ ipc_log_string(drv->ipc_log_ctx, \
+ "send msg: m=%d n=%d msgid=0x%x addr=0x%x data=0x%x cmpl=%d trigger=%d", \
+ m, n, i, a, d, c, t); \
+ } while (0)
+
+#define log_rpmh_notify_irq(drv, m, a, e) do { \
+ trace_rpmh_notify_irq(drv->name, m, a, e); \
+ ipc_log_string(drv->ipc_log_ctx, \
+ "irq response: m=%d addr=0x%x err=%d", m, a, e); \
+ } while (0)
+
+#define log_rpmh_control_msg(drv, d) do { \
+ trace_rpmh_control_msg(drv->name, d); \
+ ipc_log_string(drv->ipc_log_ctx, "ctrlr msg: data=0x%x", d); \
+ } while (0)
+
+#define log_rpmh_notify(drv, m, a, e) do { \
+ trace_rpmh_notify(drv->name, m, a, e); \
+ ipc_log_string(drv->ipc_log_ctx, \
+ "tx done: m=%d addr=0x%x err=%d", m, a, e); \
+ } while (0)
+
+
static int tcs_response_pool_init(struct tcs_drv *drv)
{
struct tcs_response_pool *pool;
@@ -437,7 +467,7 @@
mbox_chan_received_data(resp->chan, resp->msg);
}
- trace_rpmh_notify_irq(drv->name, m, resp->msg->payload[0].addr,
+ log_rpmh_notify_irq(drv, m, resp->msg->payload[0].addr,
resp->err);
/* Clear the AMC mode for non-ACTIVE TCSes */
@@ -480,7 +510,7 @@
{
struct tcs_drv *drv = container_of(chan->mbox, struct tcs_drv, mbox);
- trace_rpmh_notify(drv->name, m, msg->payload[0].addr, err);
+ log_rpmh_notify(drv, m, msg->payload[0].addr, err);
mbox_chan_txdone(chan, err);
}
@@ -546,7 +576,7 @@
write_tcs_reg(base, TCS_DRV_CMD_MSGID, m, n + i, msgid);
write_tcs_reg(base, TCS_DRV_CMD_ADDR, m, n + i, cmd->addr);
write_tcs_reg(base, TCS_DRV_CMD_DATA, m, n + i, cmd->data);
- trace_rpmh_send_msg(drv->name, m, n + i, msgid, cmd->addr,
+ log_send_msg(drv, m, n + i, msgid, cmd->addr,
cmd->data, cmd->complete, trigger);
}
@@ -932,7 +962,7 @@
for (i = 0; i < msg->num_payload; i++) {
/* Only data is write capable */
writel_relaxed(cpu_to_le32(msg->payload[i].data), addr);
- trace_rpmh_control_msg(drv->name, msg->payload[i].data);
+ log_rpmh_control_msg(drv, msg->payload[i].data);
addr += TCS_HIDDEN_CMD_SHIFT;
}
}
@@ -1200,6 +1230,9 @@
for (i = 0; i < ARRAY_SIZE(drv->tcs_in_use); i++)
atomic_set(&drv->tcs_in_use[i], 0);
+ drv->ipc_log_ctx = ipc_log_context_create(TCS_DRV_IPC_LOG_SIZE,
+ drv->name, 0);
+
ret = mbox_controller_register(&drv->mbox);
if (ret)
return ret;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
index 3e686e9..da36e38 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_debug.c
@@ -1136,6 +1136,9 @@
if (sscanf(buf, "%5x %x", &off, &cnt) < 2)
return -EINVAL;
+ if (off % sizeof(u32))
+ return -EINVAL;
+
if (off > dbg->max_offset)
return -EINVAL;
@@ -1204,6 +1207,9 @@
if (cnt < 2)
return -EFAULT;
+ if (off % sizeof(u32))
+ return -EFAULT;
+
if (off >= dbg->max_offset)
return -EFAULT;
@@ -1252,6 +1258,9 @@
goto debug_read_error;
}
+ if (dbg->off % sizeof(u32))
+ return -EFAULT;
+
ptr = dbg->base + dbg->off;
tot = 0;
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_formats.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_formats.c
index 573e0a8..27e9ba6 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_formats.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_formats.c
@@ -783,10 +783,15 @@
if (!fmt_found) {
for (i = 0; i < ARRAY_SIZE(sde_mdp_format_ubwc_map); i++) {
fmt = &sde_mdp_format_ubwc_map[i].mdp_format;
- if (format == fmt->format)
+ if (format == fmt->format) {
+ fmt_found = true;
break;
+ }
}
}
+ /* If format not supported than return NULL */
+ if (!fmt_found)
+ fmt = NULL;
return fmt;
}
diff --git a/drivers/platform/msm/seemp_core/seemp_logk.c b/drivers/platform/msm/seemp_core/seemp_logk.c
index e55260d..204142b 100644
--- a/drivers/platform/msm/seemp_core/seemp_logk.c
+++ b/drivers/platform/msm/seemp_core/seemp_logk.c
@@ -624,16 +624,17 @@
/* determine legitimacy of report */
if (report->report_valid &&
- report->sequence_number <=
- header->num_incidents &&
(last_sequence_number == 0
|| report->sequence_number >
last_sequence_number)) {
seemp_logk_rtic(report->report_type,
- report->report.incident.actor,
- report->report.incident.asset_id,
- report->report.incident.asset_category,
- report->report.incident.response);
+ report->actor,
+ /* leave this empty until
+ * asset id is provided
+ */
+ "",
+ report->asset_category,
+ report->response);
last_sequence_number = report->sequence_number;
} else {
last_pos = cur_pos - 1;
diff --git a/drivers/platform/msm/seemp_core/seemp_logk.h b/drivers/platform/msm/seemp_core/seemp_logk.h
index 871de0e..eecf4f7 100644
--- a/drivers/platform/msm/seemp_core/seemp_logk.h
+++ b/drivers/platform/msm/seemp_core/seemp_logk.h
@@ -164,39 +164,23 @@
__u64 report_version; /* Version of the EL2 report */
__u64 mp_catalog_version;
/* Version of MP catalogue used for kernel protection */
+ __u64 num_incidents; /* Number of Incidents Observed by EL2 */
__u8 protection_enabled; /* Kernel Assets protected by EL2 */
__u8 pad1;
__u8 pad2;
__u8 pad3;
__u32 pad4;
- __u64 num_incidents; /* Number of Incidents Observed by EL2 */
-};
-
-/* individual report contents */
-union el2_report {
- struct {
- __u8 asset_id[0x20]; /* Asset Identifier */
- __u64 actor;
- /* Actor that caused the Incident. */
- __u8 asset_category; /* Asset Category */
- __u8 response; /* Response From EL2 */
- __u16 pad1;
- __u32 pad2;
- } incident;
- struct {
- __u64 reserved; /* TBD */
- } info;
};
/* individual report */
struct el2_report_data_t {
+ __u64 sequence_number; /* Sequence number of the report */
+ __u64 actor; /* Actor that caused the Incident. */
__u8 report_valid;
/* Flag to indicate whether report instance is valid */
__u8 report_type; /* Report Type */
- __u8 pad1;
- __u8 pad2;
- __u64 sequence_number; /* Sequence number of the report */
- union el2_report report; /* Report Contents */
+ __u8 asset_category; /* Asset Category */
+ __u8 response; /* Response From EL2 */
};
#endif
diff --git a/drivers/soc/qcom/icnss.c b/drivers/soc/qcom/icnss.c
index a0982bc..0b6c80d 100644
--- a/drivers/soc/qcom/icnss.c
+++ b/drivers/soc/qcom/icnss.c
@@ -2579,21 +2579,22 @@
if (event_data == NULL)
return notifier_from_errno(-ENOMEM);
+ event_data->crashed = true;
+
if (state == NULL) {
- event_data->crashed = true;
priv->stats.recovery.root_pd_crash++;
goto event_post;
}
switch (*state) {
case ROOT_PD_WDOG_BITE:
- event_data->crashed = true;
event_data->wdog_bite = true;
priv->stats.recovery.root_pd_crash++;
break;
case ROOT_PD_SHUTDOWN:
cause = ICNSS_ROOT_PD_SHUTDOWN;
priv->stats.recovery.root_pd_shutdown++;
+ event_data->crashed = false;
break;
case USER_PD_STATE_CHANGE:
if (test_bit(ICNSS_HOST_TRIGGERED_PDR, &priv->state)) {
@@ -2605,7 +2606,6 @@
}
break;
default:
- event_data->crashed = true;
priv->stats.recovery.root_pd_crash++;
break;
}
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c b/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c
index 3f8b52c..6c69bec 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_dbg_voter.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
@@ -133,7 +133,7 @@
return 0;
}
- if (sscanf(buf, "%s %llu", name, &vote_khz) != 2) {
+ if (sscanf(buf, "%9s %llu", name, &vote_khz) != 2) {
pr_err("%s:return error", __func__);
return -EINVAL;
}
diff --git a/drivers/thermal/msm-tsens.c b/drivers/thermal/msm-tsens.c
index a04ddae..fe0a7c7 100644
--- a/drivers/thermal/msm-tsens.c
+++ b/drivers/thermal/msm-tsens.c
@@ -160,14 +160,18 @@
for (i = 0; i < TSENS_MAX_SENSORS; i++) {
tmdev->sensor[i].tmdev = tmdev;
tmdev->sensor[i].hw_id = i;
- tmdev->sensor[i].tzd =
- devm_thermal_zone_of_sensor_register(
- &tmdev->pdev->dev, i,
- &tmdev->sensor[i], &tsens_tm_thermal_zone_ops);
- if (IS_ERR(tmdev->sensor[i].tzd)) {
- pr_debug("Error registering sensor:%d\n", i);
- sensor_missing++;
- continue;
+ if (tmdev->ops->sensor_en(tmdev, i)) {
+ tmdev->sensor[i].tzd =
+ devm_thermal_zone_of_sensor_register(
+ &tmdev->pdev->dev, i,
+ &tmdev->sensor[i], &tsens_tm_thermal_zone_ops);
+ if (IS_ERR(tmdev->sensor[i].tzd)) {
+ pr_debug("Error registering sensor:%d\n", i);
+ sensor_missing++;
+ continue;
+ }
+ } else {
+ pr_debug("Sensor not enabled:%d\n", i);
}
}
diff --git a/drivers/thermal/tsens.h b/drivers/thermal/tsens.h
index 770b982..a695d57 100644
--- a/drivers/thermal/tsens.h
+++ b/drivers/thermal/tsens.h
@@ -91,6 +91,7 @@
int (*set_trips)(struct tsens_sensor *, int, int);
int (*interrupts_reg)(struct tsens_device *);
int (*dbg)(struct tsens_device *, u32, u32, int *);
+ int (*sensor_en)(struct tsens_device *, u32);
};
struct tsens_irqs {
diff --git a/drivers/thermal/tsens2xxx.c b/drivers/thermal/tsens2xxx.c
index 55be2f9..de9f27f 100644
--- a/drivers/thermal/tsens2xxx.c
+++ b/drivers/thermal/tsens2xxx.c
@@ -61,6 +61,7 @@
#define TSENS_TM_WATCHDOG_LOG(n) ((n) + 0x13c)
#define TSENS_EN BIT(0)
+#define TSENS_CTRL_SENSOR_EN_MASK(n) ((n >> 3) & 0xffff)
static void msm_tsens_convert_temp(int last_temp, int *temp)
{
@@ -499,6 +500,21 @@
return IRQ_HANDLED;
}
+static int tsens2xxx_hw_sensor_en(struct tsens_device *tmdev,
+ u32 sensor_id)
+{
+ void __iomem *srot_addr;
+ unsigned int srot_val, sensor_en;
+
+ srot_addr = TSENS_CTRL_ADDR(tmdev->tsens_srot_addr + 0x4);
+ srot_val = readl_relaxed(srot_addr);
+ srot_val = TSENS_CTRL_SENSOR_EN_MASK(srot_val);
+
+ sensor_en = ((1 << sensor_id) & srot_val);
+
+ return sensor_en;
+}
+
static int tsens2xxx_hw_init(struct tsens_device *tmdev)
{
void __iomem *srot_addr;
@@ -602,6 +618,7 @@
.set_trips = tsens2xxx_set_trip_temp,
.interrupts_reg = tsens2xxx_register_interrupts,
.dbg = tsens2xxx_dbg,
+ .sensor_en = tsens2xxx_hw_sensor_en,
};
const struct tsens_data data_tsens2xxx = {
diff --git a/include/dt-bindings/clock/mdss-10nm-pll-clk.h b/include/dt-bindings/clock/mdss-10nm-pll-clk.h
index 75ddcfa..8108c98 100644
--- a/include/dt-bindings/clock/mdss-10nm-pll-clk.h
+++ b/include/dt-bindings/clock/mdss-10nm-pll-clk.h
@@ -17,23 +17,25 @@
/* DSI PLL clocks */
#define VCO_CLK_0 0
-#define BITCLK_SRC_0_CLK 1
-#define BYTECLK_SRC_0_CLK 2
-#define POST_BIT_DIV_0_CLK 3
-#define POST_VCO_DIV_0_CLK 4
-#define BYTECLK_MUX_0_CLK 5
-#define PCLK_SRC_MUX_0_CLK 6
-#define PCLK_SRC_0_CLK 7
-#define PCLK_MUX_0_CLK 8
-#define VCO_CLK_1 9
-#define BITCLK_SRC_1_CLK 10
-#define BYTECLK_SRC_1_CLK 11
-#define POST_BIT_DIV_1_CLK 12
-#define POST_VCO_DIV_1_CLK 13
-#define BYTECLK_MUX_1_CLK 14
-#define PCLK_SRC_MUX_1_CLK 15
-#define PCLK_SRC_1_CLK 16
-#define PCLK_MUX_1_CLK 17
+#define PLL_OUT_DIV_0_CLK 1
+#define BITCLK_SRC_0_CLK 2
+#define BYTECLK_SRC_0_CLK 3
+#define POST_BIT_DIV_0_CLK 4
+#define POST_VCO_DIV_0_CLK 5
+#define BYTECLK_MUX_0_CLK 6
+#define PCLK_SRC_MUX_0_CLK 7
+#define PCLK_SRC_0_CLK 8
+#define PCLK_MUX_0_CLK 9
+#define VCO_CLK_1 10
+#define PLL_OUT_DIV_1_CLK 11
+#define BITCLK_SRC_1_CLK 12
+#define BYTECLK_SRC_1_CLK 13
+#define POST_BIT_DIV_1_CLK 14
+#define POST_VCO_DIV_1_CLK 15
+#define BYTECLK_MUX_1_CLK 16
+#define PCLK_SRC_MUX_1_CLK 17
+#define PCLK_SRC_1_CLK 18
+#define PCLK_MUX_1_CLK 19
/* DP PLL clocks */
#define DP_VCO_CLK 0
diff --git a/include/trace/events/sched.h b/include/trace/events/sched.h
index bbcb3d5..df323d4 100644
--- a/include/trace/events/sched.h
+++ b/include/trace/events/sched.h
@@ -71,10 +71,8 @@
__field(unsigned long, cpu_load )
__field(unsigned int, rt_nr_running )
__field(unsigned int, cpus_allowed )
-#ifdef CONFIG_SCHED_WALT
__field(unsigned int, demand )
__field(unsigned int, pred_demand )
-#endif
),
TP_fast_assign(
@@ -87,24 +85,17 @@
__entry->cpu_load = task_rq(p)->cpu_load[0];
__entry->rt_nr_running = task_rq(p)->rt.rt_nr_running;
__entry->cpus_allowed = cpus_allowed;
-#ifdef CONFIG_SCHED_WALT
- __entry->demand = p->ravg.demand;
- __entry->pred_demand = p->ravg.pred_demand;
-#endif
+ __entry->demand = task_load(p);
+ __entry->pred_demand = task_pl(p);
),
- TP_printk("cpu=%d %s comm=%s pid=%d prio=%d nr_running=%u cpu_load=%lu rt_nr_running=%u affine=%x"
-#ifdef CONFIG_SCHED_WALT
- " demand=%u pred_demand=%u"
-#endif
- , __entry->cpu,
+ TP_printk("cpu=%d %s comm=%s pid=%d prio=%d nr_running=%u cpu_load=%lu rt_nr_running=%u affine=%x demand=%u pred_demand=%u",
+ __entry->cpu,
__entry->enqueue ? "enqueue" : "dequeue",
__entry->comm, __entry->pid,
__entry->prio, __entry->nr_running,
__entry->cpu_load, __entry->rt_nr_running, __entry->cpus_allowed
-#ifdef CONFIG_SCHED_WALT
, __entry->demand, __entry->pred_demand
-#endif
)
);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 07d7731..f12e67f 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -2536,6 +2536,11 @@
return p->ravg.demand;
}
+static inline unsigned int task_pl(struct task_struct *p)
+{
+ return p->ravg.pred_demand;
+}
+
#define pct_to_real(tunable) \
(div64_u64((u64)tunable * (u64)max_task_load(), 100))
@@ -2798,6 +2803,7 @@
}
static inline u32 task_load(struct task_struct *p) { return 0; }
+static inline u32 task_pl(struct task_struct *p) { return 0; }
static inline int update_preferred_cluster(struct related_thread_group *grp,
struct task_struct *p, u32 old_load)
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index f45f619..227c249 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -687,7 +687,7 @@
NEIGH_CACHE_STAT_INC(neigh->tbl, destroys);
if (!neigh->dead) {
- pr_warn("Destroying alive neighbour %p\n", neigh);
+ pr_warn("Destroying alive neighbour %pK\n", neigh);
dump_stack();
return;
}
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
old mode 100755
new mode 100644
index f742c65..1b9e67b
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -145,6 +145,25 @@
${CC} ${aflags} -c -o ${2} ${afile}
}
+# Generates ${2} .o file with RTIC MP's from the ${1} object file (vmlinux)
+# ${3} the file name where the sizes of the RTIC MP structure are stored
+# just in case, save copy of the RTIC mp to ${4}
+# Note: RTIC_MPGEN has to be set if MPGen is available
+rtic_mp()
+{
+ # assume that RTIC_MP_O generation may fail
+ RTIC_MP_O=
+
+ ${RTIC_MPGEN} --objcopy="${OBJCOPY}" --objdump="${OBJDUMP}" \
+ --binpath='' --vmlinux=${1} --config=${KCONFIG_CONFIG} && \
+ cat rtic_mp.c | ${CC} -c -o ${2} -x c - && \
+ cp rtic_mp.c ${4} && \
+ ${NM} --print-size --size-sort ${2} > ${3} && \
+ RTIC_MP_O=${2}
+ # NM - save generated variable sizes for verification
+ # RTIC_MP_O is our retval - great success if set to generated .o file
+}
+
# Create map file with all symbols from ${1}
# See mksymap for additional details
mksysmap()
@@ -169,6 +188,8 @@
rm -f System.map
rm -f vmlinux
rm -f vmlinux.o
+ rm -f .tmp_rtic_mp_sz*
+ rm -f rtic_mp.*
}
on_exit()
@@ -231,6 +252,15 @@
# final build of init/
${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init GCC_PLUGINS_CFLAGS="${GCC_PLUGINS_CFLAGS}"
+# Generate RTIC MP placeholder compile unit of the correct size
+# and add it to the list of link objects
+# this needs to be done before generating kallsyms
+if [ ! -z ${RTIC_MPGEN+x} ]; then
+ rtic_mp vmlinux.o rtic_mp.o .tmp_rtic_mp_sz1 .tmp_rtic_mp1.c
+ KBUILD_VMLINUX_MAIN+=" "
+ KBUILD_VMLINUX_MAIN+=$RTIC_MP_O
+fi
+
kallsymso=""
kallsyms_vmlinux=""
if [ -n "${CONFIG_KALLSYMS}" ]; then
@@ -276,6 +306,18 @@
fi
fi
+# Update RTIC MP object by replacing the place holder
+# with actual MP data of the same size
+# Also double check that object size did not change
+if [ ! -z ${RTIC_MPGEN+x} ]; then
+ rtic_mp "${kallsyms_vmlinux}" rtic_mp.o .tmp_rtic_mp_sz2 \
+ .tmp_rtic_mp2.c
+ if ! cmp -s .tmp_rtic_mp_sz1 .tmp_rtic_mp_sz2; then
+ echo >&2 'ERROR: RTIC MP object files size mismatch'
+ exit 1
+ fi
+fi
+
info LD vmlinux
vmlinux_link "${kallsymso}" vmlinux