Merge "qseecom: Fix memory leak when __check_if_app_exist() fail"
diff --git a/block/Kconfig.iosched b/block/Kconfig.iosched
index 5fd98ea..5751d28 100644
--- a/block/Kconfig.iosched
+++ b/block/Kconfig.iosched
@@ -15,7 +15,7 @@
config IOSCHED_TEST
tristate "Test I/O scheduler"
depends on DEBUG_FS
- default m
+ default y
---help---
The test I/O scheduler is a duplicate of the noop scheduler with
addition of test utlity.
diff --git a/drivers/crypto/msm/qce50.c b/drivers/crypto/msm/qce50.c
index e6c6d98..d605a61 100644
--- a/drivers/crypto/msm/qce50.c
+++ b/drivers/crypto/msm/qce50.c
@@ -250,7 +250,7 @@
pce = cmdlistinfo->go_proc;
if (i == authk_size_in_word) {
- pce->addr = (uint32_t)(CRYPTO_GOPROC_OEM_KEY_REG +
+ pce->addr = (uint32_t)(CRYPTO_GOPROC_QC_KEY_REG +
pce_dev->phy_iobase);
} else {
pce->addr = (uint32_t)(CRYPTO_GOPROC_REG +
@@ -434,7 +434,7 @@
pce = cmdlistinfo->go_proc;
if (i == enck_size_in_word) {
use_hw_key = true;
- pce->addr = (uint32_t)(CRYPTO_GOPROC_OEM_KEY_REG +
+ pce->addr = (uint32_t)(CRYPTO_GOPROC_QC_KEY_REG +
pce_dev->phy_iobase);
} else {
pce->addr = (uint32_t)(CRYPTO_GOPROC_REG +
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index 228f2f5..abaff20 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -2192,178 +2192,225 @@
return hang_detected;
}
-
-/* MUST be called with the device mutex held */
-static int adreno_waittimestamp(struct kgsl_device *device,
- struct kgsl_context *context,
- unsigned int timestamp,
- unsigned int msecs)
+/**
+ * adreno_handle_hang - Process a hang detected in adreno_waittimestamp
+ * @device - pointer to a KGSL device structure
+ * @context - pointer to the active KGSL context
+ * @timestamp - the timestamp that the process was waiting for
+ *
+ * Process a possible GPU hang and try to recover from it cleanly
+ */
+static int adreno_handle_hang(struct kgsl_device *device,
+ struct kgsl_context *context, unsigned int timestamp)
{
- long status = 0;
- uint io = 1;
- static uint io_cnt;
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
- struct kgsl_pwrctrl *pwr = &device->pwrctrl;
- struct adreno_context *adreno_ctx = context ? context->devctxt : NULL;
- int retries = 0;
- unsigned int ts_issued;
unsigned int context_id = _get_context_id(context);
- unsigned int time_elapsed = 0;
- unsigned int prev_reg_val[hang_detect_regs_count];
- unsigned int wait;
- unsigned int retry_ts_cmp = 0;
- unsigned int retry_ts_cmp_msecs = KGSL_SYNCOBJ_SERVER_TIMEOUT;
+ unsigned int ts_issued;
- memset(prev_reg_val, 0, sizeof(prev_reg_val));
+ /* Do one last check to see if we somehow made it through */
+ if (kgsl_check_timestamp(device, context, timestamp))
+ return 0;
ts_issued = adreno_dev->ringbuffer.timestamp[context_id];
- /* Don't wait forever, set a max value for now */
- if (msecs == KGSL_TIMEOUT_DEFAULT)
- msecs = adreno_dev->wait_timeout;
-
- /*
- * With user generated ts, if this check fails perform this check
- * again after 'retry_ts_cmp_msecs' milliseconds.
- */
- if (timestamp_cmp(timestamp, ts_issued) > 0) {
- if (adreno_ctx == NULL ||
- !(adreno_ctx->flags & CTXT_FLAGS_USER_GENERATED_TS)) {
- if (context && !context->wait_on_invalid_ts) {
- KGSL_DRV_ERR(device,
- "Cannot wait for invalid ts <%d:0x%x>, "
- "last issued ts <%d:0x%x>\n",
- context_id, timestamp, context_id, ts_issued);
- /*
- * Prevent the above message from spamming the
- * kernel logs and causing a watchdog
- */
- context->wait_on_invalid_ts = true;
- }
- status = -EINVAL;
- goto done;
- } else
- retry_ts_cmp = 1;
- } else if (context && context->wait_on_invalid_ts) {
- /* Once we wait for a valid ts reset the invalid wait flag */
- context->wait_on_invalid_ts = false;
- }
-
- /*
- * Make the first timeout interval 100 msecs and then try to kick the
- * wptr again. This helps to ensure the wptr is updated properly. If
- * the requested timeout is less than 100 msecs, then wait 20msecs which
- * is the minimum amount of time we can safely wait at 100HZ
- */
-
- if (msecs == 0 || msecs >= 100)
- wait = 100;
- else
- wait = 20;
-
- do {
- /*
- * If the context ID is invalid, we are in a race with
- * the context being destroyed by userspace so bail.
- */
- if (context_id == KGSL_CONTEXT_INVALID) {
- KGSL_DRV_WARN(device, "context was detached");
- status = -EINVAL;
- goto done;
- }
- if (kgsl_check_timestamp(device, context, timestamp)) {
- /* if the timestamp happens while we're not
- * waiting, there's a chance that an interrupt
- * will not be generated and thus the timestamp
- * work needs to be queued.
- */
- queue_work(device->work_queue, &device->ts_expired_ws);
- status = 0;
- goto done;
- }
-
- io_cnt = (io_cnt + 1) % 100;
- if (io_cnt <
- pwr->pwrlevels[pwr->active_pwrlevel].io_fraction)
- io = 0;
-
- if ((retries > 0) &&
- (adreno_hang_detect(device, prev_reg_val)))
- goto hang_dump;
-
- mutex_unlock(&device->mutex);
- /* We need to make sure that the process is
- * placed in wait-q before its condition is called
- */
- status = kgsl_wait_event_interruptible_timeout(
- device->wait_queue,
- kgsl_check_interrupt_timestamp(device,
- context, timestamp),
- msecs_to_jiffies(wait), io);
-
- mutex_lock(&device->mutex);
-
- if (status > 0) {
- /*completed before the wait finished */
- status = 0;
- goto done;
- } else if (status < 0) {
- /*an error occurred*/
- goto done;
- }
- /*this wait timed out*/
-
- time_elapsed += wait;
- wait = KGSL_TIMEOUT_PART;
-
- if (!retry_ts_cmp)
- retries++;
- else if (time_elapsed >= retry_ts_cmp_msecs) {
- ts_issued =
- adreno_dev->ringbuffer.timestamp[context_id];
- if (timestamp_cmp(timestamp, ts_issued) > 0) {
- if (context && !context->wait_on_invalid_ts) {
- KGSL_DRV_ERR(device,
- "Cannot wait for user-generated ts <%d:0x%x>, "
- "not submitted within server timeout period. "
- "last issued ts <%d:0x%x>\n",
- context_id, timestamp, context_id,
- ts_issued);
- context->wait_on_invalid_ts = true;
- }
- status = -EINVAL;
- goto done;
- } else if (context && context->wait_on_invalid_ts) {
- context->wait_on_invalid_ts = false;
- }
- retry_ts_cmp = 0;
- }
-
- } while (!msecs || time_elapsed < msecs);
-
-hang_dump:
- /*
- * Check if timestamp has retired here because we may have hit
- * recovery which can take some time and cause waiting threads
- * to timeout
- */
- if (kgsl_check_timestamp(device, context, timestamp))
- goto done;
- status = -ETIMEDOUT;
KGSL_DRV_ERR(device,
"Device hang detected while waiting for timestamp: "
"<%d:0x%x>, last submitted timestamp: <%d:0x%x>, "
"wptr: 0x%x\n",
context_id, timestamp, context_id, ts_issued,
adreno_dev->ringbuffer.wptr);
- if (!adreno_dump_and_recover(device)) {
- /* The timestamp that this process wanted
- * to wait on may be invalid or expired now
- * after successful recovery */
- status = 0;
+
+ /* Return 0 after a successful recovery */
+ if (!adreno_dump_and_recover(device))
+ return 0;
+
+ return -ETIMEDOUT;
+}
+
+static int _check_pending_timestamp(struct kgsl_device *device,
+ struct kgsl_context *context, unsigned int timestamp)
+{
+ struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
+ unsigned int context_id = _get_context_id(context);
+ unsigned int ts_issued;
+
+ if (context_id == KGSL_CONTEXT_INVALID)
+ return -EINVAL;
+
+ ts_issued = adreno_dev->ringbuffer.timestamp[context_id];
+
+ if (timestamp_cmp(timestamp, ts_issued) <= 0)
+ return 0;
+
+ if (context && !context->wait_on_invalid_ts) {
+ KGSL_DRV_ERR(device, "Cannot wait for invalid ts <%d:0x%x>, last issued ts <%d:0x%x>\n",
+ context_id, timestamp, context_id, ts_issued);
+
+ /* Only print this message once */
+ context->wait_on_invalid_ts = true;
}
-done:
- return (int)status;
+
+ return -EINVAL;
+}
+
+/**
+ * adreno_waittimestamp - sleep while waiting for the specified timestamp
+ * @device - pointer to a KGSL device structure
+ * @context - pointer to the active kgsl context
+ * @timestamp - GPU timestamp to wait for
+ * @msecs - amount of time to wait (in milliseconds)
+ *
+ * Wait 'msecs' milliseconds for the specified timestamp to expire. Wake up
+ * every KGSL_TIMEOUT_PART milliseconds to check for a device hang and process
+ * one if it happened. Otherwise, spend most of our time in an interruptible
+ * wait for the timestamp interrupt to be processed. This function must be
+ * called with the mutex already held.
+ */
+static int adreno_waittimestamp(struct kgsl_device *device,
+ struct kgsl_context *context,
+ unsigned int timestamp,
+ unsigned int msecs)
+{
+ static unsigned int io_cnt;
+ struct adreno_context *adreno_ctx = context ? context->devctxt : NULL;
+ struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+ unsigned int context_id = _get_context_id(context);
+ unsigned int prev_reg_val[hang_detect_regs_count];
+ unsigned int time_elapsed = 0;
+ unsigned int wait;
+ int ts_compare = 1;
+ int io, ret = -ETIMEDOUT;
+
+ /* Get out early if the context has already been destroyed */
+
+ if (context_id == KGSL_CONTEXT_INVALID) {
+ KGSL_DRV_WARN(device, "context was detached");
+ return -EINVAL;
+ }
+
+ /*
+ * Check to see if the requested timestamp is "newer" then the last
+ * timestamp issued. If it is complain once and return error. Only
+ * print the message once per context so that badly behaving
+ * applications don't spam the logs
+ */
+
+ if (adreno_ctx && !(adreno_ctx->flags & CTXT_FLAGS_USER_GENERATED_TS)) {
+ if (_check_pending_timestamp(device, context, timestamp))
+ return -EINVAL;
+
+ /* Reset the invalid timestamp flag on a valid wait */
+ context->wait_on_invalid_ts = false;
+ }
+
+
+ /* Clear the registers used for hang detection */
+ memset(prev_reg_val, 0, sizeof(prev_reg_val));
+
+ /*
+ * On the first time through the loop only wait 100ms.
+ * this gives enough time for the engine to start moving and oddly
+ * provides better hang detection results than just going the full
+ * KGSL_TIMEOUT_PART right off the bat. The exception to this rule
+ * is if msecs happens to be < 100ms then just use the full timeout
+ */
+
+ wait = 100;
+
+ do {
+ long status;
+
+ if (wait > (msecs - time_elapsed))
+ wait = msecs - time_elapsed;
+
+ /*
+ * if the timestamp happens while we're not
+ * waiting, there's a chance that an interrupt
+ * will not be generated and thus the timestamp
+ * work needs to be queued.
+ */
+
+ if (kgsl_check_timestamp(device, context, timestamp)) {
+ queue_work(device->work_queue, &device->ts_expired_ws);
+ ret = 0;
+ break;
+ }
+
+ /* Check to see if the GPU is hung */
+ if (adreno_hang_detect(device, prev_reg_val)) {
+ ret = adreno_handle_hang(device, context, timestamp);
+ break;
+ }
+
+ /*
+ * For proper power accounting sometimes we need to call
+ * io_wait_interruptible_timeout and sometimes we need to call
+ * plain old wait_interruptible_timeout. We call the regular
+ * timeout N times out of 100, where N is a number specified by
+ * the current power level
+ */
+
+ io_cnt = (io_cnt + 1) % 100;
+ io = (io_cnt < pwr->pwrlevels[pwr->active_pwrlevel].io_fraction)
+ ? 0 : 1;
+
+ mutex_unlock(&device->mutex);
+
+ /* Wait for a timestamp event */
+ status = kgsl_wait_event_interruptible_timeout(
+ device->wait_queue,
+ kgsl_check_interrupt_timestamp(device, context,
+ timestamp), msecs_to_jiffies(wait), io);
+
+ mutex_lock(&device->mutex);
+
+ /*
+ * If status is non zero then either the condition was satisfied
+ * or there was an error. In either event, this is the end of
+ * the line for us
+ */
+
+ if (status != 0) {
+ ret = (status > 0) ? 0 : (int) status;
+ break;
+ }
+
+ time_elapsed += wait;
+
+ /* If user specified timestamps are being used, wait at least
+ * KGSL_SYNCOBJ_SERVER_TIMEOUT msecs for the user driver to
+ * issue a IB for a timestamp before checking to see if the
+ * current timestamp we are waiting for is valid or not
+ */
+
+ if (ts_compare && (adreno_ctx &&
+ (adreno_ctx->flags & CTXT_FLAGS_USER_GENERATED_TS))) {
+ if (time_elapsed > KGSL_SYNCOBJ_SERVER_TIMEOUT) {
+ ret = _check_pending_timestamp(device, context,
+ timestamp);
+ if (ret)
+ break;
+
+ /* Don't do this check again */
+ ts_compare = 0;
+
+ /*
+ * Reset the invalid timestamp flag on a valid
+ * wait
+ */
+ context->wait_on_invalid_ts = false;
+ }
+ }
+
+ /*
+ * all subsequent trips through the loop wait the full
+ * KGSL_TIMEOUT_PART interval
+ */
+ wait = KGSL_TIMEOUT_PART;
+
+ } while (!msecs || time_elapsed < msecs);
+
+ return ret;
}
static unsigned int adreno_readtimestamp(struct kgsl_device *device,
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index af31b3a..507c014 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -465,6 +465,90 @@
return NULL;
}
+static int dvr_input_thread_entry(void *arg)
+{
+ struct dmxdev *dmxdev = arg;
+ struct dvb_ringbuffer *src = &dmxdev->dvr_input_buffer;
+ int ret;
+ size_t todo;
+ size_t split;
+
+ while (1) {
+ /* wait for input */
+ ret = wait_event_interruptible(src->queue,
+ (!src->data) ||
+ (dvb_ringbuffer_avail(src)) ||
+ (src->error != 0) ||
+ (dmxdev->dvr_in_exit) ||
+ kthread_should_stop());
+
+ if ((ret < 0) || kthread_should_stop())
+ break;
+
+ spin_lock(&dmxdev->dvr_in_lock);
+
+ if (!src->data || dmxdev->exit || dmxdev->dvr_in_exit) {
+ spin_unlock(&dmxdev->dvr_in_lock);
+ break;
+ }
+
+ if (src->error) {
+ spin_unlock(&dmxdev->dvr_in_lock);
+ wake_up_all(&src->queue);
+ break;
+ }
+
+ dmxdev->dvr_processing_input = 1;
+
+ ret = dvb_ringbuffer_avail(src);
+ todo = ret;
+
+ split = (src->pread + ret > src->size) ?
+ src->size - src->pread :
+ 0;
+
+ /*
+ * In DVR PULL mode, write might block.
+ * Lock on DVR buffer is released before calling to
+ * write, if DVR was released meanwhile, dvr_in_exit is
+ * prompted. Lock is aquired when updating the read pointer
+ * again to preserve read/write pointers consistancy
+ */
+ if (split > 0) {
+ spin_unlock(&dmxdev->dvr_in_lock);
+ dmxdev->demux->write(dmxdev->demux,
+ src->data + src->pread,
+ split);
+
+ if (dmxdev->dvr_in_exit)
+ break;
+
+ spin_lock(&dmxdev->dvr_in_lock);
+
+ todo -= split;
+ DVB_RINGBUFFER_SKIP(src, split);
+ }
+
+ spin_unlock(&dmxdev->dvr_in_lock);
+ dmxdev->demux->write(dmxdev->demux,
+ src->data + src->pread, todo);
+
+ if (dmxdev->dvr_in_exit)
+ break;
+
+ spin_lock(&dmxdev->dvr_in_lock);
+
+ DVB_RINGBUFFER_SKIP(src, todo);
+ dmxdev->dvr_processing_input = 0;
+ spin_unlock(&dmxdev->dvr_in_lock);
+
+ wake_up_all(&src->queue);
+ }
+
+ return 0;
+}
+
+
static int dvb_dvr_open(struct inode *inode, struct file *file)
{
struct dvb_device *dvbdev = file->private_data;
@@ -542,6 +626,17 @@
dmxdev->demux->dvr_input.priv_handle = NULL;
dmxdev->demux->dvr_input.ringbuff = &dmxdev->dvr_input_buffer;
dvbdev->writers--;
+
+ dmxdev->dvr_input_thread =
+ kthread_run(
+ dvr_input_thread_entry,
+ (void *)dmxdev,
+ "dvr_input");
+
+ if (IS_ERR(dmxdev->dvr_input_thread)) {
+ mutex_unlock(&dmxdev->mutex);
+ return -ENOMEM;
+ }
}
dvbdev->users++;
@@ -601,11 +696,11 @@
dmxdev->demux->write_cancel(dmxdev->demux);
/*
- * Now flush dvr-in workqueue so that no one
+ * Now stop dvr-input thread so that no one
* would process data from dvr input buffer any more
* before it gets freed.
*/
- flush_workqueue(dmxdev->dvr_input_workqueue);
+ kthread_stop(dmxdev->dvr_input_thread);
dvbdev->writers++;
dmxdev->demux->disconnect_frontend(dmxdev->demux);
@@ -773,12 +868,7 @@
buf += ret;
mutex_unlock(&dmxdev->mutex);
-
wake_up_all(&src->queue);
-
- if (!work_pending(&dmxdev->dvr_input_work))
- queue_work(dmxdev->dvr_input_workqueue,
- &dmxdev->dvr_input_work);
}
return (count - todo) ? (count - todo) : ret;
@@ -827,87 +917,6 @@
return res;
}
-static void dvr_input_work_func(struct work_struct *worker)
-{
- struct dmxdev *dmxdev =
- container_of(worker, struct dmxdev, dvr_input_work);
- struct dvb_ringbuffer *src = &dmxdev->dvr_input_buffer;
- int ret;
- size_t todo;
- size_t split;
-
- while (1) {
- /* wait for input */
- ret = wait_event_interruptible(src->queue,
- (!src->data) ||
- (dvb_ringbuffer_avail(src)) ||
- (src->error != 0) ||
- (dmxdev->dvr_in_exit));
-
- if (ret < 0)
- break;
-
- spin_lock(&dmxdev->dvr_in_lock);
-
- if (!src->data || dmxdev->exit || dmxdev->dvr_in_exit) {
- spin_unlock(&dmxdev->dvr_in_lock);
- break;
- }
-
- if (src->error) {
- spin_unlock(&dmxdev->dvr_in_lock);
- wake_up_all(&src->queue);
- break;
- }
-
- dmxdev->dvr_processing_input = 1;
-
- ret = dvb_ringbuffer_avail(src);
- todo = ret;
-
- split = (src->pread + ret > src->size) ?
- src->size - src->pread :
- 0;
-
- /*
- * In DVR PULL mode, write might block.
- * Lock on DVR buffer is released before calling to
- * write, if DVR was released meanwhile, dvr_in_exit is
- * prompted. Lock is aquired when updating the read pointer
- * again to preserve read/write pointers consistancy
- */
- if (split > 0) {
- spin_unlock(&dmxdev->dvr_in_lock);
- dmxdev->demux->write(dmxdev->demux,
- src->data + src->pread,
- split);
-
- if (dmxdev->dvr_in_exit)
- break;
-
- spin_lock(&dmxdev->dvr_in_lock);
-
- todo -= split;
- DVB_RINGBUFFER_SKIP(src, split);
- }
-
- spin_unlock(&dmxdev->dvr_in_lock);
- dmxdev->demux->write(dmxdev->demux,
- src->data + src->pread, todo);
-
- if (dmxdev->dvr_in_exit)
- break;
-
- spin_lock(&dmxdev->dvr_in_lock);
-
- DVB_RINGBUFFER_SKIP(src, todo);
- dmxdev->dvr_processing_input = 0;
- spin_unlock(&dmxdev->dvr_in_lock);
-
- wake_up_all(&src->queue);
- }
-}
-
static int dvb_dvr_set_buffer_size(struct dmxdev *dmxdev,
unsigned int f_flags,
unsigned long size)
@@ -1205,10 +1214,6 @@
wake_up_all(&buffer->queue);
- if (!work_pending(&dmxdev->dvr_input_work))
- queue_work(dmxdev->dvr_input_workqueue,
- &dmxdev->dvr_input_work);
-
return 0;
}
@@ -3260,14 +3265,6 @@
if (!dmxdev->filter)
return -ENOMEM;
- dmxdev->dvr_input_workqueue =
- create_singlethread_workqueue("dvr_workqueue");
-
- if (dmxdev->dvr_input_workqueue == NULL) {
- vfree(dmxdev->filter);
- return -ENOMEM;
- }
-
dmxdev->playback_mode = DMX_PB_MODE_PUSH;
mutex_init(&dmxdev->mutex);
@@ -3288,9 +3285,6 @@
dvb_ringbuffer_init(&dmxdev->dvr_buffer, NULL, 8192);
dvb_ringbuffer_init(&dmxdev->dvr_input_buffer, NULL, 8192);
- INIT_WORK(&dmxdev->dvr_input_work,
- dvr_input_work_func);
-
if (dmxdev->demux->debugfs_demux_dir)
debugfs_create_file("filters", S_IRUGO,
dmxdev->demux->debugfs_demux_dir, dmxdev,
@@ -3313,9 +3307,6 @@
dmxdev->dvr_dvbdev->users==1);
}
- flush_workqueue(dmxdev->dvr_input_workqueue);
- destroy_workqueue(dmxdev->dvr_input_workqueue);
-
dvb_unregister_device(dmxdev->dvbdev);
dvb_unregister_device(dmxdev->dvr_dvbdev);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 6c02111..d1c1cc3 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -34,7 +34,7 @@
#include <linux/string.h>
#include <linux/mutex.h>
#include <linux/slab.h>
-#include <linux/workqueue.h>
+#include <linux/kthread.h>
#include <linux/dvb/dmx.h>
#include "dvbdev.h"
@@ -133,8 +133,6 @@
};
struct dmxdev {
- struct work_struct dvr_input_work;
-
struct dvb_device *dvbdev;
struct dvb_device *dvr_dvbdev;
@@ -167,7 +165,7 @@
struct dvb_ringbuffer dvr_input_buffer;
enum dmx_buffer_mode dvr_input_buffer_mode;
- struct workqueue_struct *dvr_input_workqueue;
+ struct task_struct *dvr_input_thread;
#define DVR_BUFFER_SIZE (10*188*1024)
diff --git a/drivers/misc/tspp.c b/drivers/misc/tspp.c
index 3b678c5..f310524 100644
--- a/drivers/misc/tspp.c
+++ b/drivers/misc/tspp.c
@@ -327,10 +327,15 @@
int data_inverse;
int sync_inverse;
int enable_inverse;
+ u32 tsif_irq;
/* debugfs */
struct dentry *dent_tsif;
struct dentry *debugfs_tsif_regs[ARRAY_SIZE(debugfs_tsif_regs)];
+ u32 stat_rx;
+ u32 stat_overflow;
+ u32 stat_lost_sync;
+ u32 stat_timeout;
};
enum tspp_buf_state {
@@ -480,6 +485,49 @@
dev_info(&device->pdev->dev, "broken pipe %i", status & 0xffff);
writel_relaxed(status, device->base + TSPP_IRQ_CLEAR);
+
+ /*
+ * Before returning IRQ_HANDLED to the generic interrupt handling
+ * framework need to make sure all operations including clearing of
+ * interrupt status registers in the hardware is performed.
+ * Thus a barrier after clearing the interrupt status register
+ * is required to guarantee that the interrupt status register has
+ * really been cleared by the time we return from this handler.
+ */
+ wmb();
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t tsif_isr(int irq, void *dev)
+{
+ struct tspp_tsif_device *tsif_device = dev;
+ u32 sts_ctl = ioread32(tsif_device->base + TSIF_STS_CTL_OFF);
+
+ if (!(sts_ctl & (TSIF_STS_CTL_PACK_AVAIL |
+ TSIF_STS_CTL_OVERFLOW |
+ TSIF_STS_CTL_LOST_SYNC |
+ TSIF_STS_CTL_TIMEOUT)))
+ return IRQ_NONE;
+
+ if (sts_ctl & TSIF_STS_CTL_OVERFLOW)
+ tsif_device->stat_overflow++;
+
+ if (sts_ctl & TSIF_STS_CTL_LOST_SYNC)
+ tsif_device->stat_lost_sync++;
+
+ if (sts_ctl & TSIF_STS_CTL_TIMEOUT)
+ tsif_device->stat_timeout++;
+
+ iowrite32(sts_ctl, tsif_device->base + TSIF_STS_CTL_OFF);
+
+ /*
+ * Before returning IRQ_HANDLED to the generic interrupt handling
+ * framework need to make sure all operations including clearing of
+ * interrupt status registers in the hardware is performed.
+ * Thus a barrier after clearing the interrupt status register
+ * is required to guarantee that the interrupt status register has
+ * really been cleared by the time we return from this handler.
+ */
wmb();
return IRQ_HANDLED;
}
@@ -527,6 +575,11 @@
channel->waiting->filled = iovec.size;
channel->waiting->read_index = 0;
+ if (channel->src == TSPP_SOURCE_TSIF0)
+ device->tsif[0].stat_rx++;
+ else if (channel->src == TSPP_SOURCE_TSIF1)
+ device->tsif[1].stat_rx++;
+
/* update the pointers */
channel->waiting = channel->waiting->next;
}
@@ -2326,6 +2379,31 @@
base + debugfs_tsif_regs[i].offset,
&fops_iomem_x32);
}
+
+ debugfs_create_u32(
+ "stat_rx_chunks",
+ S_IRUGO|S_IWUGO,
+ tsif_device->dent_tsif,
+ &tsif_device->stat_rx);
+
+ debugfs_create_u32(
+ "stat_overflow",
+ S_IRUGO|S_IWUGO,
+ tsif_device->dent_tsif,
+ &tsif_device->stat_overflow);
+
+ debugfs_create_u32(
+ "stat_lost_sync",
+ S_IRUGO|S_IWUGO,
+ tsif_device->dent_tsif,
+ &tsif_device->stat_lost_sync);
+
+ debugfs_create_u32(
+ "stat_timeout",
+ S_IRUGO|S_IWUGO,
+ tsif_device->dent_tsif,
+ &tsif_device->stat_timeout);
+
}
}
@@ -2504,6 +2582,21 @@
goto err_irq;
}
+ /* map TSIF IRQs */
+ device->tsif[0].tsif_irq = TSIF1_IRQ;
+ device->tsif[1].tsif_irq = TSIF2_IRQ;
+
+ for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
+ rc = request_irq(device->tsif[i].tsif_irq,
+ tsif_isr, IRQF_SHARED,
+ dev_name(&pdev->dev), &device->tsif[i]);
+ if (rc) {
+ dev_warn(&pdev->dev, "failed to request TSIF%d IRQ: %d",
+ i, rc);
+ device->tsif[i].tsif_irq = 0;
+ }
+ }
+
/* BAM IRQ */
device->bam_irq = TSIF_BAM_IRQ;
@@ -2635,8 +2728,11 @@
sps_deregister_bam_device(device->bam_handle);
- for (i = 0; i < TSPP_TSIF_INSTANCES; i++)
+ for (i = 0; i < TSPP_TSIF_INSTANCES; i++) {
tsif_debugfs_exit(&device->tsif[i]);
+ if (device->tsif[i].tsif_irq)
+ free_irq(device->tsif[i].tsif_irq, &device->tsif[i]);
+ }
wake_lock_destroy(&device->wake_lock);
free_irq(device->tspp_irq, device);
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig
index 33f0600..a1bea00 100644
--- a/drivers/mmc/card/Kconfig
+++ b/drivers/mmc/card/Kconfig
@@ -80,6 +80,7 @@
config MMC_BLOCK_TEST
tristate "MMC block test"
depends on MMC_BLOCK && IOSCHED_TEST
+ default y
help
MMC block test can be used with test iosched to test the MMC block
device.
diff --git a/drivers/mmc/card/mmc_block_test.c b/drivers/mmc/card/mmc_block_test.c
index 35bb4ac..610a822 100644
--- a/drivers/mmc/card/mmc_block_test.c
+++ b/drivers/mmc/card/mmc_block_test.c
@@ -1702,6 +1702,12 @@
(bkops_stat->suspend == 0) &&
(bkops_stat->hpi == 1))
goto exit;
+ /* this might happen due to timing issues */
+ else if
+ ((bkops_stat->bkops_level[BKOPS_SEVERITY_1_INDEX] == 0) &&
+ (bkops_stat->suspend == 0) &&
+ (bkops_stat->hpi == 0))
+ goto ignore;
else
goto fail;
break;
@@ -1735,6 +1741,9 @@
exit:
return 0;
+ignore:
+ test_iosched_set_ignore_round(true);
+ return 0;
fail:
if (td->fs_wr_reqs_during_test) {
test_pr_info("%s: wr reqs during test, cancel the round",
diff --git a/drivers/net/wireless/wcnss/wcnss_wlan.c b/drivers/net/wireless/wcnss/wcnss_wlan.c
index b92d34a..71a9860 100644
--- a/drivers/net/wireless/wcnss/wcnss_wlan.c
+++ b/drivers/net/wireless/wcnss/wcnss_wlan.c
@@ -566,8 +566,6 @@
void __iomem *pmu_spare_reg;
u32 reg = 0;
unsigned long flags;
- struct clk *cxo = clk_get(&penv->pdev->dev, "cxo");
- int rc = 0;
if (!enable_wcnss_suspend_notify)
return;
@@ -576,18 +574,12 @@
return;
/* For Riva */
- rc = clk_prepare_enable(cxo);
- if (rc) {
- pr_err("cxo enable failed\n");
- return;
- }
pmu_spare_reg = penv->msm_wcnss_base + RIVA_SPARE_OFFSET;
spin_lock_irqsave(®_spinlock, flags);
reg = readl_relaxed(pmu_spare_reg);
reg |= RIVA_SUSPEND_BIT;
writel_relaxed(reg, pmu_spare_reg);
spin_unlock_irqrestore(®_spinlock, flags);
- clk_disable_unprepare(cxo);
}
EXPORT_SYMBOL(wcnss_suspend_notify);
@@ -596,8 +588,6 @@
void __iomem *pmu_spare_reg;
u32 reg = 0;
unsigned long flags;
- struct clk *cxo = clk_get(&penv->pdev->dev, "cxo");
- int rc = 0;
if (!enable_wcnss_suspend_notify)
return;
@@ -608,17 +598,11 @@
/* For Riva */
pmu_spare_reg = penv->msm_wcnss_base + RIVA_SPARE_OFFSET;
- rc = clk_prepare_enable(cxo);
- if (rc) {
- pr_err("cxo enable failed\n");
- return;
- }
spin_lock_irqsave(®_spinlock, flags);
reg = readl_relaxed(pmu_spare_reg);
reg &= ~RIVA_SUSPEND_BIT;
writel_relaxed(reg, pmu_spare_reg);
spin_unlock_irqrestore(®_spinlock, flags);
- clk_disable_unprepare(cxo);
}
EXPORT_SYMBOL(wcnss_resume_notify);
diff --git a/drivers/power/pm8921-charger.c b/drivers/power/pm8921-charger.c
index ac007b1..3995cf7 100644
--- a/drivers/power/pm8921-charger.c
+++ b/drivers/power/pm8921-charger.c
@@ -1131,31 +1131,6 @@
PM8921_CHG_LED_SRC_CONFIG_MASK, temp);
}
-static void enable_input_voltage_regulation(struct pm8921_chg_chip *chip)
-{
- u8 temp;
- int rc;
-
- rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, 0x70);
- if (rc) {
- pr_err("Failed to write 0x70 to CTRL_TEST3 rc = %d\n", rc);
- return;
- }
- rc = pm8xxx_readb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, &temp);
- if (rc) {
- pr_err("Failed to read CTRL_TEST3 rc = %d\n", rc);
- return;
- }
- /* unset the input voltage disable bit */
- temp &= 0xFE;
- /* set the write bit */
- temp |= 0x80;
- rc = pm8xxx_writeb(chip->dev->parent, CHG_BUCK_CTRL_TEST3, temp);
- if (rc) {
- pr_err("Failed to write 0x%x to CTRL_TEST3 rc=%d\n", temp, rc);
- return;
- }
-}
static int64_t read_battery_id(struct pm8921_chg_chip *chip)
{
@@ -1539,6 +1514,34 @@
return pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ);
}
+static int get_prop_batt_status(struct pm8921_chg_chip *chip)
+{
+ int batt_state = POWER_SUPPLY_STATUS_DISCHARGING;
+ int fsm_state = pm_chg_get_fsm_state(chip);
+ int i;
+
+ if (chip->ext_psy) {
+ if (chip->ext_charge_done)
+ return POWER_SUPPLY_STATUS_FULL;
+ if (chip->ext_charging)
+ return POWER_SUPPLY_STATUS_CHARGING;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(map); i++)
+ if (map[i].fsm_state == fsm_state)
+ batt_state = map[i].batt_state;
+
+ if (fsm_state == FSM_STATE_ON_CHG_HIGHI_1) {
+ if (!pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ)
+ || !pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ)
+ || pm_chg_get_rt_status(chip, CHGHOT_IRQ)
+ || pm_chg_get_rt_status(chip, VBATDET_LOW_IRQ))
+
+ batt_state = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ }
+ return batt_state;
+}
+
static int get_prop_batt_capacity(struct pm8921_chg_chip *chip)
{
int percent_soc;
@@ -1558,8 +1561,8 @@
pr_warn_ratelimited("low battery charge = %d%%\n",
percent_soc);
- if (chip->recent_reported_soc == (chip->resume_charge_percent + 1)
- && percent_soc == chip->resume_charge_percent) {
+ if (percent_soc <= chip->resume_charge_percent
+ && get_prop_batt_status(chip) == POWER_SUPPLY_STATUS_FULL) {
pr_debug("soc fell below %d. charging enabled.\n",
chip->resume_charge_percent);
if (chip->is_bat_warm)
@@ -1688,34 +1691,6 @@
return POWER_SUPPLY_CHARGE_TYPE_NONE;
}
-static int get_prop_batt_status(struct pm8921_chg_chip *chip)
-{
- int batt_state = POWER_SUPPLY_STATUS_DISCHARGING;
- int fsm_state = pm_chg_get_fsm_state(chip);
- int i;
-
- if (chip->ext_psy) {
- if (chip->ext_charge_done)
- return POWER_SUPPLY_STATUS_FULL;
- if (chip->ext_charging)
- return POWER_SUPPLY_STATUS_CHARGING;
- }
-
- for (i = 0; i < ARRAY_SIZE(map); i++)
- if (map[i].fsm_state == fsm_state)
- batt_state = map[i].batt_state;
-
- if (fsm_state == FSM_STATE_ON_CHG_HIGHI_1) {
- if (!pm_chg_get_rt_status(chip, BATT_INSERTED_IRQ)
- || !pm_chg_get_rt_status(chip, BAT_TEMP_OK_IRQ)
- || pm_chg_get_rt_status(chip, CHGHOT_IRQ)
- || pm_chg_get_rt_status(chip, VBATDET_LOW_IRQ))
-
- batt_state = POWER_SUPPLY_STATUS_NOT_CHARGING;
- }
- return batt_state;
-}
-
#define MAX_TOLERABLE_BATT_TEMP_DDC 680
static int get_prop_batt_temp(struct pm8921_chg_chip *chip)
{
@@ -2276,7 +2251,6 @@
usb_target_ma = 0;
pm8921_chg_disable_irq(chip, CHG_GONE_IRQ);
}
- enable_input_voltage_regulation(chip);
bms_notify_check(chip);
}
@@ -3253,6 +3227,22 @@
pm_chg_vddmax_set(chip, adj_vdd_max_mv);
}
+static void set_appropriate_vbatdet(struct pm8921_chg_chip *chip)
+{
+ if (chip->is_bat_cool)
+ pm_chg_vbatdet_set(the_chip,
+ the_chip->cool_bat_voltage
+ - the_chip->resume_voltage_delta);
+ else if (chip->is_bat_warm)
+ pm_chg_vbatdet_set(the_chip,
+ the_chip->warm_bat_voltage
+ - the_chip->resume_voltage_delta);
+ else
+ pm_chg_vbatdet_set(the_chip,
+ the_chip->max_voltage_mv
+ - the_chip->resume_voltage_delta);
+}
+
enum {
CHG_IN_PROGRESS,
CHG_NOT_IN_PROGRESS,
@@ -3391,8 +3381,7 @@
if (end == CHG_NOT_IN_PROGRESS) {
count = 0;
- wake_unlock(&chip->eoc_wake_lock);
- return;
+ goto eoc_worker_stop;
}
/* If the disable hw clock switching
@@ -3416,21 +3405,6 @@
if (count == CONSECUTIVE_COUNT) {
count = 0;
pr_info("End of Charging\n");
- /* set the vbatdet back, in case it was changed
- * to trigger charging */
- if (chip->is_bat_cool) {
- pm_chg_vbatdet_set(the_chip,
- the_chip->cool_bat_voltage
- - the_chip->resume_voltage_delta);
- } else if (chip->is_bat_warm) {
- pm_chg_vbatdet_set(the_chip,
- the_chip->warm_bat_voltage
- - the_chip->resume_voltage_delta);
- } else {
- pm_chg_vbatdet_set(the_chip,
- the_chip->max_voltage_mv
- - the_chip->resume_voltage_delta);
- }
pm_chg_auto_enable(chip, 0);
@@ -3443,14 +3417,19 @@
chip->bms_notify.is_battery_full = 1;
/* declare end of charging by invoking chgdone interrupt */
chgdone_irq_handler(chip->pmic_chg_irq[CHGDONE_IRQ], chip);
- wake_unlock(&chip->eoc_wake_lock);
} else {
adjust_vdd_max_for_fastchg(chip, vbat_batt_terminal_uv);
pr_debug("EOC count = %d\n", count);
schedule_delayed_work(&chip->eoc_work,
round_jiffies_relative(msecs_to_jiffies
(EOC_CHECK_PERIOD_MS)));
+ return;
}
+
+eoc_worker_stop:
+ wake_unlock(&chip->eoc_wake_lock);
+ /* set the vbatdet back, in case it was changed to trigger charging */
+ set_appropriate_vbatdet(chip);
}
static void btm_configure_work(struct work_struct *work)
@@ -3491,19 +3470,13 @@
if (enter) {
btm_config.low_thr_temp =
the_chip->cool_temp_dc + TEMP_HYSTERISIS_DEGC;
- set_appropriate_battery_current(the_chip);
pm_chg_vddmax_set(the_chip, the_chip->cool_bat_voltage);
- pm_chg_vbatdet_set(the_chip,
- the_chip->cool_bat_voltage
- - the_chip->resume_voltage_delta);
} else {
btm_config.low_thr_temp = the_chip->cool_temp_dc;
- set_appropriate_battery_current(the_chip);
pm_chg_vddmax_set(the_chip, the_chip->max_voltage_mv);
- pm_chg_vbatdet_set(the_chip,
- the_chip->max_voltage_mv
- - the_chip->resume_voltage_delta);
}
+ set_appropriate_battery_current(the_chip);
+ set_appropriate_vbatdet(the_chip);
schedule_work(&btm_config_work);
}
@@ -3516,19 +3489,13 @@
if (enter) {
btm_config.high_thr_temp =
the_chip->warm_temp_dc - TEMP_HYSTERISIS_DEGC;
- set_appropriate_battery_current(the_chip);
pm_chg_vddmax_set(the_chip, the_chip->warm_bat_voltage);
- pm_chg_vbatdet_set(the_chip,
- the_chip->warm_bat_voltage
- - the_chip->resume_voltage_delta);
} else {
btm_config.high_thr_temp = the_chip->warm_temp_dc;
- set_appropriate_battery_current(the_chip);
pm_chg_vddmax_set(the_chip, the_chip->max_voltage_mv);
- pm_chg_vbatdet_set(the_chip,
- the_chip->max_voltage_mv
- - the_chip->resume_voltage_delta);
}
+ set_appropriate_battery_current(the_chip);
+ set_appropriate_vbatdet(the_chip);
schedule_work(&btm_config_work);
}
@@ -4505,6 +4472,9 @@
enable_irq_wake(chip->pmic_chg_irq[LOOP_CHANGE_IRQ]);
}
+ rc = pm8xxx_batt_alarm_enable(PM8XXX_BATT_ALARM_LOWER_COMPARATOR);
+ if (rc < 0)
+ pr_err("Failed to enable lower comparator\n");
return 0;
}
static int __devinit pm8921_charger_probe(struct platform_device *pdev)
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index c6ffaf2..0411baa 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1407,30 +1407,37 @@
struct hdmi_disp_mode_list_type *disp_mode_list,
uint32 video_format)
{
- const struct hdmi_disp_mode_timing_type *timing =
- hdmi_common_get_supported_mode(video_format);
- boolean supported = timing != NULL;
+ const struct hdmi_disp_mode_timing_type *timing;
+ boolean supported = false;
+ boolean mhl_supported = true;
if (video_format >= HDMI_VFRMT_MAX)
return;
+ timing = hdmi_common_get_supported_mode(video_format);
+ supported = timing != NULL;
DEV_DBG("EDID: format: %d [%s], %s\n",
video_format, video_format_2string(video_format),
supported ? "Supported" : "Not-Supported");
- if (supported) {
- if (mhl_is_enabled()) {
- const struct hdmi_disp_mode_timing_type *mhl_timing =
- hdmi_mhl_get_supported_mode(video_format);
- boolean mhl_supported = mhl_timing != NULL;
- DEV_DBG("EDID: format: %d [%s], %s by MHL\n",
+
+ if (mhl_is_enabled()) {
+ const struct hdmi_disp_mode_timing_type *mhl_timing =
+ hdmi_mhl_get_supported_mode(video_format);
+ mhl_supported = mhl_timing != NULL;
+ DEV_DBG("EDID: format: %d [%s], %s by MHL\n",
video_format, video_format_2string(video_format),
- mhl_supported ? "Supported" : "Not-Supported");
- if (mhl_supported)
- disp_mode_list->disp_mode_list[
+ mhl_supported ? "Supported" : "Not-Supported");
+ }
+
+ if (supported && mhl_supported) {
+ disp_mode_list->disp_mode_list[
disp_mode_list->num_of_elements++] = video_format;
- } else
- disp_mode_list->disp_mode_list[
- disp_mode_list->num_of_elements++] = video_format;
+ if (video_format == external_common_state->video_resolution) {
+ DEV_DBG("%s: Default resolution %d [%s] supported\n",
+ __func__, video_format,
+ video_format_2string(video_format));
+ external_common_state->default_res_supported = true;
+ }
}
}
@@ -1866,6 +1873,7 @@
memset(&external_common_state->disp_mode_list, 0,
sizeof(external_common_state->disp_mode_list));
memset(edid_buf, 0, sizeof(edid_buf));
+ external_common_state->default_res_supported = false;
status = hdmi_common_read_edid_block(0, edid_buf);
if (status || !check_edid_header(edid_buf)) {
diff --git a/drivers/video/msm/external_common.h b/drivers/video/msm/external_common.h
index 768e550..70a99ee 100644
--- a/drivers/video/msm/external_common.h
+++ b/drivers/video/msm/external_common.h
@@ -210,6 +210,7 @@
boolean hpd_state;
struct kobject *uevent_kobj;
uint32 video_resolution;
+ boolean default_res_supported;
struct device *dev;
struct switch_dev sdev;
struct switch_dev audio_sdev;
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 9efb898..516c92c 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -785,8 +785,8 @@
/* Build EDID table */
hdmi_msm_read_edid();
switch_set_state(&external_common_state->sdev, 1);
- DEV_INFO("Hdmi state switched to %d: %s\n",
- external_common_state->sdev.state, __func__);
+ DEV_INFO("%s: hdmi state switched to %d\n", __func__,
+ external_common_state->sdev.state);
DEV_INFO("HDMI HPD: CONNECTED: send ONLINE\n");
kobject_uevent(external_common_state->uevent_kobj, KOBJ_ONLINE);
@@ -800,8 +800,8 @@
}
} else {
switch_set_state(&external_common_state->sdev, 0);
- DEV_INFO("hdmi: Hdmi state switch to %d: %s\n",
- external_common_state->sdev.state, __func__);
+ DEV_INFO("%s: hdmi state switch to %d\n", __func__,
+ external_common_state->sdev.state);
DEV_INFO("hdmi: HDMI HPD: sense DISCONNECTED: send OFFLINE\n");
kobject_uevent(external_common_state->uevent_kobj,
KOBJ_OFFLINE);
@@ -929,10 +929,6 @@
DEV_INFO("HDCP: AUTH_FAIL_INT received, LINK0_STATUS=0x%08x\n",
link_status);
if (hdmi_msm_state->full_auth_done) {
- switch_set_state(&external_common_state->sdev, 0);
- DEV_INFO("Hdmi state switched to %d: %s\n",
- external_common_state->sdev.state, __func__);
-
SWITCH_SET_HDMI_AUDIO(0, 0);
envp[0] = "HDCP_STATE=FAIL";
@@ -3016,9 +3012,6 @@
SWITCH_SET_HDMI_AUDIO(1, 0);
}
- switch_set_state(&external_common_state->sdev, 1);
- DEV_INFO("Hdmi state switched to %d: %s\n",
- external_common_state->sdev.state, __func__);
return;
error:
@@ -3038,9 +3031,6 @@
mutex_lock(&hdmi_msm_state_mutex);
hdmi_msm_state->hdcp_activating = FALSE;
mutex_unlock(&hdmi_msm_state_mutex);
- switch_set_state(&external_common_state->sdev, 0);
- DEV_INFO("Hdmi state switched to %d: %s\n",
- external_common_state->sdev.state, __func__);
}
static void hdmi_msm_video_setup(int video_format)
@@ -4345,32 +4335,40 @@
DEV_INFO("power: ON (%dx%d %d)\n", mfd->var_xres, mfd->var_yres,
mfd->var_pixclock);
+ /* Only start transmission with supported resolution */
changed = hdmi_common_get_video_format_from_drv_data(mfd);
- hdmi_msm_audio_info_setup(TRUE, 0, 0, 0, FALSE);
+ if (changed || external_common_state->default_res_supported) {
+ hdmi_msm_audio_info_setup(TRUE, 0, 0, 0, FALSE);
+ mutex_lock(&external_common_state_hpd_mutex);
+ hdmi_msm_state->panel_power_on = TRUE;
+ if (external_common_state->hpd_state &&
+ hdmi_msm_is_power_on()) {
+ DEV_DBG("%s: Turning HDMI on\n", __func__);
+ mutex_unlock(&external_common_state_hpd_mutex);
+ hdmi_msm_turn_on();
- mutex_lock(&external_common_state_hpd_mutex);
- hdmi_msm_state->panel_power_on = TRUE;
- if (external_common_state->hpd_state && hdmi_msm_is_power_on()) {
- DEV_DBG("%s: Turning HDMI on\n", __func__);
- mutex_unlock(&external_common_state_hpd_mutex);
- hdmi_msm_turn_on();
-
- if (hdmi_msm_state->hdcp_enable) {
- /* Kick off HDCP Authentication */
- mutex_lock(&hdcp_auth_state_mutex);
- hdmi_msm_state->reauth = FALSE;
- hdmi_msm_state->full_auth_done = FALSE;
- mutex_unlock(&hdcp_auth_state_mutex);
- mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
+ if (hdmi_msm_state->hdcp_enable) {
+ /* Kick off HDCP Authentication */
+ mutex_lock(&hdcp_auth_state_mutex);
+ hdmi_msm_state->reauth = FALSE;
+ hdmi_msm_state->full_auth_done = FALSE;
+ mutex_unlock(&hdcp_auth_state_mutex);
+ mod_timer(&hdmi_msm_state->hdcp_timer,
+ jiffies + HZ/2);
+ }
+ } else {
+ mutex_unlock(&external_common_state_hpd_mutex);
}
- } else
- mutex_unlock(&external_common_state_hpd_mutex);
- hdmi_msm_dump_regs("HDMI-ON: ");
-
- DEV_INFO("power=%s DVI= %s\n",
- hdmi_msm_is_power_on() ? "ON" : "OFF" ,
- hdmi_msm_is_dvi_mode() ? "ON" : "OFF");
+ hdmi_msm_dump_regs("HDMI-ON: ");
+ DEV_INFO("power=%s DVI= %s\n",
+ hdmi_msm_is_power_on() ? "ON" : "OFF" ,
+ hdmi_msm_is_dvi_mode() ? "ON" : "OFF");
+ } else {
+ DEV_ERR("%s: Video fmt %d not supp. Returning\n",
+ __func__,
+ external_common_state->video_resolution);
+ }
/* Enable HPD interrupt and listen to disconnect interrupts */
hdmi_msm_hpd_polarity_setup(HPD_DISCONNECT_POLARITY,
@@ -4383,9 +4381,6 @@
char *envp[2];
/* Simulating a HPD event based on MHL event */
- switch_set_state(&external_common_state->sdev, 0);
- DEV_INFO("Hdmi state switched to %d: %s\n",
- external_common_state->sdev.state, __func__);
if (on) {
hdmi_msm_read_edid();
hdmi_msm_state->reauth = FALSE ;
@@ -4403,8 +4398,8 @@
kobject_uevent_env(external_common_state->uevent_kobj,
KOBJ_CHANGE, envp);
switch_set_state(&external_common_state->sdev, 1);
- DEV_INFO("Hdmi state switched to %d: %s\n",
- external_common_state->sdev.state, __func__);
+ DEV_INFO("%s: hdmi state switched to %d\n",
+ __func__, external_common_state->sdev.state);
} else {
hdmi_msm_hdcp_enable();
}
@@ -4413,8 +4408,8 @@
kobject_uevent(external_common_state->uevent_kobj,
KOBJ_OFFLINE);
switch_set_state(&external_common_state->sdev, 0);
- DEV_INFO("Hdmi state switched to %d: %s\n",
- external_common_state->sdev.state, __func__);
+ DEV_INFO("%s: hdmi state switched to %d\n", __func__,
+ external_common_state->sdev.state);
}
}
EXPORT_SYMBOL(mhl_connect_api);
@@ -4741,6 +4736,8 @@
/* Set HDMI switch node to 0 on HPD feature disable */
switch_set_state(&external_common_state->sdev, 0);
+ DEV_INFO("%s: hdmi state switched to %d\n", __func__,
+ external_common_state->sdev.state);
}
return rc;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 9c1aef2..e11b985 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -3035,7 +3035,7 @@
msecs_to_jiffies(300));
}
/* apply the digital gain after the decimator is enabled*/
- if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+ if ((w->shift + offset) < ARRAY_SIZE(tx_digital_gain_reg))
snd_soc_write(codec,
tx_digital_gain_reg[w->shift + offset],
snd_soc_read(codec,
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index a27dc48..5ffb60a 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -2247,7 +2247,7 @@
msecs_to_jiffies(300));
}
/* apply the digital gain after the decimator is enabled*/
- if ((w->shift) < ARRAY_SIZE(rx_digital_gain_reg))
+ if ((w->shift + offset) < ARRAY_SIZE(tx_digital_gain_reg))
snd_soc_write(codec,
tx_digital_gain_reg[w->shift + offset],
snd_soc_read(codec,