Merge "power: power supply framework : add warm and cool properties"
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 13b4ba3..f9c759f 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -393,6 +393,13 @@
return requeued ? -1 : 0;
}
+static void plist_move(struct plist_head *old, struct plist_head *new)
+{
+ plist_head_init(new);
+ list_splice_tail(&old->node_list, &new->node_list);
+ plist_head_init(old);
+}
+
/**
* _adreno_dispatcher_issuecmds() - Issue commmands from pending contexts
* @adreno_dev: Pointer to the adreno device struct
@@ -403,31 +410,36 @@
static int _adreno_dispatcher_issuecmds(struct adreno_device *adreno_dev)
{
struct adreno_dispatcher *dispatcher = &adreno_dev->dispatcher;
- int last_id = 0;
+ struct plist_head tmp;
+ struct adreno_context *drawctxt, *next;
+ /* Leave early if the dispatcher isn't in a happy state */
+ if ((dispatcher->state != ADRENO_DISPATCHER_ACTIVE) ||
+ adreno_gpu_fault(adreno_dev) != 0)
+ return 0;
+
+ /* Copy the current context list to a temporary list */
+ spin_lock(&dispatcher->plist_lock);
+ plist_move(&dispatcher->pending, &tmp);
+ spin_unlock(&dispatcher->plist_lock);
+
+ /* Try to fill the ringbuffer as much as possible */
while (dispatcher->inflight < _dispatcher_inflight) {
- struct adreno_context *drawctxt = NULL;
- /* Don't do anything if the dispatcher is paused */
- if (dispatcher->state != ADRENO_DISPATCHER_ACTIVE)
+ /* Stop doing things if the dispatcher is paused or faulted */
+ if ((dispatcher->state != ADRENO_DISPATCHER_ACTIVE) ||
+ adreno_gpu_fault(adreno_dev) != 0)
break;
- if (adreno_gpu_fault(adreno_dev) != 0)
+ if (plist_head_empty(&tmp))
break;
- spin_lock(&dispatcher->plist_lock);
+ /* Get the next entry on the list */
+ drawctxt = plist_first_entry(&tmp, struct adreno_context,
+ pending);
- if (!plist_head_empty(&dispatcher->pending)) {
- drawctxt = plist_first_entry(&dispatcher->pending,
- struct adreno_context, pending);
-
- plist_del(&drawctxt->pending, &dispatcher->pending);
- }
-
- spin_unlock(&dispatcher->plist_lock);
-
- if (drawctxt == NULL)
- break;
+ /* Remove it from the list */
+ plist_del(&drawctxt->pending, &tmp);
if (kgsl_context_detached(&drawctxt->base) ||
drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) {
@@ -435,25 +447,26 @@
continue;
}
- /*
- * Don't loop endlessly on the same stalled context - if we see
- * the same context twice in a row then assume that there is
- * nothing else to do and bail. But don't forget to put the
- * stalled context back on the queue otherwise it will get
- * forgotten
- */
-
- if (last_id == drawctxt->base.id) {
- dispatcher_queue_context(adreno_dev, drawctxt);
- kgsl_context_put(&drawctxt->base);
- break;
- }
-
- last_id = drawctxt->base.id;
dispatcher_context_sendcmds(adreno_dev, drawctxt);
kgsl_context_put(&drawctxt->base);
}
+ /* Requeue any remaining contexts for the next go around */
+
+ spin_lock(&dispatcher->plist_lock);
+
+ plist_for_each_entry_safe(drawctxt, next, &tmp, pending) {
+ int prio = drawctxt->pending.prio;
+
+ /* Reset the context node */
+ plist_node_init(&drawctxt->pending, prio);
+
+ /* And put it back in the master list */
+ plist_add(&drawctxt->pending, &dispatcher->pending);
+ }
+
+ spin_unlock(&dispatcher->plist_lock);
+
return 0;
}
diff --git a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
index 2f6e6a7..14dffa8 100644
--- a/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
+++ b/drivers/media/platform/msm/camera_v2/ispif/msm_ispif.c
@@ -86,11 +86,6 @@
long timeout = 0;
struct clk *reset_clk[ARRAY_SIZE(ispif_8974_reset_clk_info)];
- if (ispif->csid_version < CSID_VERSION_V30) {
- /* currently reset is done only for 8974 */
- return 0;
- }
-
rc = msm_cam_clk_enable(&ispif->pdev->dev,
ispif_8974_reset_clk_info, reset_clk,
ARRAY_SIZE(ispif_8974_reset_clk_info), 1);
@@ -802,7 +797,7 @@
ispif_process_irq(ispif, out, VFE0);
}
- if (ispif->vfe_info.num_vfe > 1) {
+ if (ispif->hw_num_isps > 1) {
if (out[VFE1].ispifIrqStatus0 & RESET_DONE_IRQ)
complete(&ispif->reset_complete[VFE1]);
@@ -896,7 +891,13 @@
pr_err("%s: ahb_clk enable failed", __func__);
goto error_ahb;
}
- msm_ispif_reset_hw(ispif);
+
+ if (of_device_is_compatible(ispif->pdev->dev.of_node,
+ "qcom,ispif-v3.0")) {
+ /* currently HW reset is implemented for 8974 only */
+ msm_ispif_reset_hw(ispif);
+ }
+
rc = msm_ispif_reset(ispif);
if (rc == 0) {
ispif->ispif_state = ISPIF_POWER_UP;
diff --git a/drivers/power/qpnp-charger.c b/drivers/power/qpnp-charger.c
index 7f77b75..7ccd49d 100644
--- a/drivers/power/qpnp-charger.c
+++ b/drivers/power/qpnp-charger.c
@@ -338,6 +338,7 @@
struct qpnp_chg_regulator boost_vreg;
struct qpnp_vadc_chip *vadc_dev;
struct qpnp_adc_tm_chip *adc_tm_dev;
+ struct mutex jeita_configure_lock;
};
@@ -1080,7 +1081,13 @@
if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
&& batt_present) {
+ pr_debug("enabling vadc notifications\n");
schedule_work(&chip->adc_measure_work);
+ } else if (chip->cool_bat_decidegc && chip->warm_bat_decidegc
+ && !batt_present) {
+ qpnp_adc_tm_disable_chan_meas(chip->adc_tm_dev,
+ &chip->adc_param);
+ pr_debug("disabling vadc notifications\n");
}
}
@@ -1203,6 +1210,8 @@
case POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL:
case POWER_SUPPLY_PROP_INPUT_CURRENT_MAX:
case POWER_SUPPLY_PROP_VOLTAGE_MIN:
+ case POWER_SUPPLY_PROP_COOL_TEMP:
+ case POWER_SUPPLY_PROP_WARM_TEMP:
return 1;
default:
break;
@@ -1315,6 +1324,8 @@
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
POWER_SUPPLY_PROP_CHARGE_FULL,
POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_COOL_TEMP,
+ POWER_SUPPLY_PROP_WARM_TEMP,
POWER_SUPPLY_PROP_SYSTEM_TEMP_LEVEL,
POWER_SUPPLY_PROP_CYCLE_COUNT,
};
@@ -1688,6 +1699,12 @@
case POWER_SUPPLY_PROP_TEMP:
val->intval = get_prop_batt_temp(chip);
break;
+ case POWER_SUPPLY_PROP_COOL_TEMP:
+ val->intval = chip->cool_bat_decidegc;
+ break;
+ case POWER_SUPPLY_PROP_WARM_TEMP:
+ val->intval = chip->warm_bat_decidegc;
+ break;
case POWER_SUPPLY_PROP_CAPACITY:
val->intval = get_prop_capacity(chip);
break;
@@ -2388,10 +2405,74 @@
qpnp_chg_set_appropriate_vbatdet(chip);
}
+ pr_debug("warm %d, cool %d, low = %d deciDegC, high = %d deciDegC\n",
+ chip->bat_is_warm, chip->bat_is_cool,
+ chip->adc_param.low_temp, chip->adc_param.high_temp);
+
if (qpnp_adc_tm_channel_measure(chip->adc_tm_dev, &chip->adc_param))
pr_err("request ADC error\n");
+}
- power_supply_changed(&chip->batt_psy);
+#define MIN_COOL_TEMP -300
+#define MAX_WARM_TEMP 1000
+
+static int
+qpnp_chg_configure_jeita(struct qpnp_chg_chip *chip,
+ enum power_supply_property psp, int temp_degc)
+{
+ int rc = 0;
+
+ if ((temp_degc < MIN_COOL_TEMP) || (temp_degc > MAX_WARM_TEMP)) {
+ pr_err("Bad temperature request %d\n", temp_degc);
+ return -EINVAL;
+ }
+
+ mutex_lock(&chip->jeita_configure_lock);
+ switch (psp) {
+ case POWER_SUPPLY_PROP_COOL_TEMP:
+ if (temp_degc >=
+ (chip->warm_bat_decidegc - HYSTERISIS_DECIDEGC)) {
+ pr_err("Can't set cool %d higher than warm %d - hysterisis %d\n",
+ temp_degc, chip->warm_bat_decidegc,
+ HYSTERISIS_DECIDEGC);
+ rc = -EINVAL;
+ goto mutex_unlock;
+ }
+ if (chip->bat_is_cool)
+ chip->adc_param.high_temp =
+ temp_degc + HYSTERISIS_DECIDEGC;
+ else if (!chip->bat_is_warm)
+ chip->adc_param.low_temp = temp_degc;
+
+ chip->cool_bat_decidegc = temp_degc;
+ break;
+ case POWER_SUPPLY_PROP_WARM_TEMP:
+ if (temp_degc <=
+ (chip->cool_bat_decidegc + HYSTERISIS_DECIDEGC)) {
+ pr_err("Can't set warm %d higher than cool %d + hysterisis %d\n",
+ temp_degc, chip->warm_bat_decidegc,
+ HYSTERISIS_DECIDEGC);
+ rc = -EINVAL;
+ goto mutex_unlock;
+ }
+ if (chip->bat_is_warm)
+ chip->adc_param.low_temp =
+ temp_degc - HYSTERISIS_DECIDEGC;
+ else if (!chip->bat_is_cool)
+ chip->adc_param.high_temp = temp_degc;
+
+ chip->warm_bat_decidegc = temp_degc;
+ break;
+ default:
+ rc = -EINVAL;
+ goto mutex_unlock;
+ }
+
+ schedule_work(&chip->adc_measure_work);
+
+mutex_unlock:
+ mutex_unlock(&chip->jeita_configure_lock);
+ return rc;
}
static int
@@ -2431,8 +2512,15 @@
{
struct qpnp_chg_chip *chip = container_of(psy, struct qpnp_chg_chip,
batt_psy);
+ int rc = 0;
switch (psp) {
+ case POWER_SUPPLY_PROP_COOL_TEMP:
+ rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
+ break;
+ case POWER_SUPPLY_PROP_WARM_TEMP:
+ rc = qpnp_chg_configure_jeita(chip, psp, val->intval);
+ break;
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
chip->charging_disabled = !(val->intval);
qpnp_chg_charge_en(chip, !chip->charging_disabled);
@@ -2452,7 +2540,7 @@
}
power_supply_changed(&chip->batt_psy);
- return 0;
+ return rc;
}
static void
@@ -3176,6 +3264,7 @@
goto fail_chg_enable;
}
+ mutex_init(&chip->jeita_configure_lock);
/* Get all device tree properties */
rc = qpnp_charger_read_dt_props(chip);
if (rc)
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index de30fe0..5106c71 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -124,6 +124,8 @@
POWER_SUPPLY_PROP_CAPACITY, /* in percents! */
POWER_SUPPLY_PROP_CAPACITY_LEVEL,
POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_COOL_TEMP,
+ POWER_SUPPLY_PROP_WARM_TEMP,
POWER_SUPPLY_PROP_TEMP_AMBIENT,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,