summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/misc/cm3217.c18
-rw-r--r--drivers/media/video/tegra/nvavp/nvavp_dev.c67
-rw-r--r--drivers/power/smb349-charger.c6
-rw-r--r--drivers/usb/otg/tegra-otg.c9
-rw-r--r--drivers/video/tegra/dc/dc.c24
-rw-r--r--drivers/video/tegra/dc/dc_reg.h1
6 files changed, 97 insertions, 28 deletions
diff --git a/drivers/input/misc/cm3217.c b/drivers/input/misc/cm3217.c
index 9c9b60d69619..2e96808284cc 100644
--- a/drivers/input/misc/cm3217.c
+++ b/drivers/input/misc/cm3217.c
@@ -3,6 +3,8 @@
* Copyright (C) 2011 Capella Microsystems Inc.
* Author: Frank Hsieh <pengyueh@gmail.com>
*
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
@@ -36,11 +38,11 @@
#include <asm/mach-types.h>
#include <asm/setup.h>
-#define D(x...) pr_info(x)
+#define D(x...) pr_debug(x)
#define I2C_RETRY_COUNT 10
-#define LS_POLLING_DELAY 500
+#define LS_POLLING_DELAY 1000 /* mSec */
static void report_do_work(struct work_struct *w);
static DECLARE_DELAYED_WORK(report_work, report_do_work);
@@ -460,6 +462,7 @@ static long lightsensor_ioctl(struct file *file, unsigned int cmd,
{
int rc, val;
struct cm3217_info *lpi = lp_info;
+ unsigned long delay;
/* D("[CM3217] %s cmd %d\n", __func__, _IOC_NR(cmd)); */
@@ -481,6 +484,17 @@ static long lightsensor_ioctl(struct file *file, unsigned int cmd,
rc = put_user(val, (unsigned long __user *)arg);
break;
+ case LIGHTSENSOR_IOCTL_SET_DELAY:
+ if (get_user(delay, (unsigned long __user *)arg)) {
+ rc = -EFAULT;
+ break;
+ }
+ D("[LS][CM3217] %s LIGHTSENSOR_IOCTL_SET_DELAY, delay %ld\n",
+ __func__, delay);
+ delay = delay / 1000;
+ lpi->polling_delay = msecs_to_jiffies(delay);
+ break;
+
default:
pr_err("[LS][CM3217 error]%s: invalid cmd %d\n",
__func__, _IOC_NR(cmd));
diff --git a/drivers/media/video/tegra/nvavp/nvavp_dev.c b/drivers/media/video/tegra/nvavp/nvavp_dev.c
index e2bad8150d3a..b695aa16af59 100644
--- a/drivers/media/video/tegra/nvavp/nvavp_dev.c
+++ b/drivers/media/video/tegra/nvavp/nvavp_dev.c
@@ -131,6 +131,8 @@ struct nvavp_info {
/* client for driver allocations, persistent */
struct nvmap_client *nvmap;
+ bool pending;
+
struct nvavp_channel channel_info[NVAVP_NUM_CHANNELS];
struct nvhost_syncpt *nvhost_syncpt;
@@ -239,26 +241,29 @@ static struct clk *nvavp_clk_get(struct nvavp_info *nvavp, int id)
return NULL;
}
-static void nvavp_clk_ctrl(struct nvavp_info *nvavp, u32 clk_en)
+static void nvavp_clks_enable(struct nvavp_info *nvavp)
{
- if (clk_en && !nvavp->clk_enabled) {
+ if (nvavp->clk_enabled++ == 0) {
nvhost_module_busy(nvhost_get_host(nvavp->nvhost_dev)->dev);
clk_enable(nvavp->bsev_clk);
clk_enable(nvavp->vde_clk);
clk_set_rate(nvavp->emc_clk, nvavp->emc_clk_rate);
clk_set_rate(nvavp->sclk, nvavp->sclk_rate);
- nvavp->clk_enabled = 1;
dev_dbg(&nvavp->nvhost_dev->dev, "%s: setting sclk to %lu\n",
__func__, nvavp->sclk_rate);
dev_dbg(&nvavp->nvhost_dev->dev, "%s: setting emc_clk to %lu\n",
__func__, nvavp->emc_clk_rate);
- } else if (!clk_en && nvavp->clk_enabled) {
+ }
+}
+
+static void nvavp_clks_disable(struct nvavp_info *nvavp)
+{
+ if (--nvavp->clk_enabled == 0) {
clk_disable(nvavp->bsev_clk);
clk_disable(nvavp->vde_clk);
clk_set_rate(nvavp->emc_clk, 0);
clk_set_rate(nvavp->sclk, 0);
nvhost_module_idle(nvhost_get_host(nvavp->nvhost_dev)->dev);
- nvavp->clk_enabled = 0;
dev_dbg(&nvavp->nvhost_dev->dev, "%s: resetting emc_clk "
"and sclk\n", __func__);
}
@@ -279,10 +284,15 @@ static void clock_disable_handler(struct work_struct *work)
nvavp = container_of(work, struct nvavp_info,
clock_disable_work);
-
channel_info = nvavp_get_channel_info(nvavp, NVAVP_VIDEO_CHANNEL);
+
mutex_lock(&channel_info->pushbuffer_lock);
- nvavp_clk_ctrl(nvavp, !nvavp_check_idle(nvavp));
+ mutex_lock(&nvavp->open_lock);
+ if (nvavp_check_idle(nvavp) && nvavp->pending) {
+ nvavp->pending = false;
+ nvavp_clks_disable(nvavp);
+ }
+ mutex_unlock(&nvavp->open_lock);
mutex_unlock(&channel_info->pushbuffer_lock);
}
@@ -391,27 +401,29 @@ static int nvavp_reset_avp(struct nvavp_info *nvavp, unsigned long reset_addr)
static void nvavp_halt_vde(struct nvavp_info *nvavp)
{
- if (nvavp->clk_enabled) {
- tegra_periph_reset_assert(nvavp->bsev_clk);
- clk_disable(nvavp->bsev_clk);
- tegra_periph_reset_assert(nvavp->vde_clk);
- clk_disable(nvavp->vde_clk);
- nvhost_module_idle(nvhost_get_host(nvavp->nvhost_dev)->dev);
- nvavp->clk_enabled = 0;
+ if (nvavp->clk_enabled && !nvavp->pending)
+ BUG();
+
+ if (nvavp->pending) {
+ nvavp_clks_disable(nvavp);
+ nvavp->pending = false;
}
+
+ tegra_periph_reset_assert(nvavp->bsev_clk);
+ tegra_periph_reset_assert(nvavp->vde_clk);
}
static int nvavp_reset_vde(struct nvavp_info *nvavp)
{
- if (!nvavp->clk_enabled)
- nvhost_module_busy(nvhost_get_host(nvavp->nvhost_dev)->dev);
+ if (nvavp->clk_enabled)
+ BUG();
+
+ nvavp_clks_enable(nvavp);
- clk_enable(nvavp->bsev_clk);
tegra_periph_reset_assert(nvavp->bsev_clk);
udelay(2);
tegra_periph_reset_deassert(nvavp->bsev_clk);
- clk_enable(nvavp->vde_clk);
tegra_periph_reset_assert(nvavp->vde_clk);
udelay(2);
tegra_periph_reset_deassert(nvavp->vde_clk);
@@ -423,7 +435,8 @@ static int nvavp_reset_vde(struct nvavp_info *nvavp)
*/
clk_set_rate(nvavp->vde_clk, ULONG_MAX);
- nvavp->clk_enabled = 1;
+ nvavp_clks_disable(nvavp);
+
return 0;
}
@@ -592,8 +605,14 @@ static int nvavp_pushbuffer_update(struct nvavp_info *nvavp, u32 phys_addr,
}
/* enable clocks to VDE/BSEV */
- if (IS_VIDEO_CHANNEL_ID(channel_id))
- nvavp_clk_ctrl(nvavp, 1);
+ if (IS_VIDEO_CHANNEL_ID(channel_id)) {
+ mutex_lock(&nvavp->open_lock);
+ if (!nvavp->pending) {
+ nvavp_clks_enable(nvavp);
+ nvavp->pending = true;
+ }
+ mutex_unlock(&nvavp->open_lock);
+ }
/* update put pointer */
channel_info->pushbuf_index = (channel_info->pushbuf_index + wordcount)&
@@ -1214,14 +1233,14 @@ static int nvavp_force_clock_stay_on_ioctl(struct file *filp, unsigned int cmd,
struct nvavp_clock_stay_on_state_args clock;
if (copy_from_user(&clock, (void __user *)arg,
- sizeof(struct nvavp_clock_stay_on_state_args)))
+ sizeof(struct nvavp_clock_stay_on_state_args)))
return -EFAULT;
dev_dbg(&nvavp->nvhost_dev->dev, "%s: state=%d\n",
__func__, clock.state);
if (clock.state != NVAVP_CLOCK_STAY_ON_DISABLED &&
- clock.state != NVAVP_CLOCK_STAY_ON_ENABLED) {
+ clock.state != NVAVP_CLOCK_STAY_ON_ENABLED) {
dev_err(&nvavp->nvhost_dev->dev, "%s: invalid argument=%d\n",
__func__, clock.state);
return -EINVAL;
@@ -1659,7 +1678,7 @@ static int tegra_nvavp_suspend(struct nvhost_device *ndev, pm_message_t state)
mutex_lock(&nvavp->open_lock);
if (nvavp->refcount) {
- if (nvavp_check_idle(nvavp))
+ if (!nvavp->clk_enabled)
nvavp_uninit(nvavp);
else
ret = -EBUSY;
diff --git a/drivers/power/smb349-charger.c b/drivers/power/smb349-charger.c
index 62d516b374b8..58778409b6ba 100644
--- a/drivers/power/smb349-charger.c
+++ b/drivers/power/smb349-charger.c
@@ -449,6 +449,11 @@ static int __devinit smb349_probe(struct i2c_client *client,
charger->client = client;
charger->dev = &client->dev;
pdata = client->dev.platform_data;
+ if(!pdata) {
+ ret = -ENXIO;
+ goto error;
+ }
+
i2c_set_clientdata(client, charger);
/* Check battery presence */
@@ -463,7 +468,6 @@ static int __devinit smb349_probe(struct i2c_client *client,
charger->reg_desc.ops = &smb349_tegra_regulator_ops;
charger->reg_desc.type = REGULATOR_CURRENT;
charger->reg_desc.id = pdata->regulator_id;
- charger->reg_desc.type = REGULATOR_CURRENT;
charger->reg_desc.owner = THIS_MODULE;
charger->reg_init_data.supply_regulator = NULL;
diff --git a/drivers/usb/otg/tegra-otg.c b/drivers/usb/otg/tegra-otg.c
index 2719a62f873d..b5106faf68bd 100644
--- a/drivers/usb/otg/tegra-otg.c
+++ b/drivers/usb/otg/tegra-otg.c
@@ -260,6 +260,15 @@ static void irq_work(struct work_struct *work)
else
to = OTG_STATE_A_SUSPEND;
+ if (from != OTG_STATE_A_HOST) {
+ if (tegra->int_status & USB_VBUS_INT_STATUS) {
+ if (status & USB_VBUS_STATUS)
+ to = OTG_STATE_B_PERIPHERAL;
+ else
+ to = OTG_STATE_A_SUSPEND;
+ }
+ }
+
spin_unlock_irqrestore(&tegra->lock, flags);
tegra_change_otg_state(tegra, to);
}
diff --git a/drivers/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c
index d5d0602838e7..5c960f9e45c0 100644
--- a/drivers/video/tegra/dc/dc.c
+++ b/drivers/video/tegra/dc/dc.c
@@ -2202,6 +2202,26 @@ static void tegra_dc_underflow_handler(struct tegra_dc *dc)
dc->ndev->name, (65 + i));
}
#endif
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+ if (dc->windows[i].underflows > 4) {
+ printk("%s:dc in underflow state."
+ " enable UF_LINE_FLUSH to clear up\n",
+ __func__);
+ tegra_dc_writel(dc, UF_LINE_FLUSH,
+ DC_DISP_DISP_MISC_CONTROL);
+ tegra_dc_writel(dc, GENERAL_UPDATE,
+ DC_CMD_STATE_CONTROL);
+ tegra_dc_writel(dc, GENERAL_ACT_REQ,
+ DC_CMD_STATE_CONTROL);
+
+ tegra_dc_writel(dc, 0,
+ DC_DISP_DISP_MISC_CONTROL);
+ tegra_dc_writel(dc, GENERAL_UPDATE,
+ DC_CMD_STATE_CONTROL);
+ tegra_dc_writel(dc, GENERAL_ACT_REQ,
+ DC_CMD_STATE_CONTROL);
+ }
+#endif
} else {
dc->windows[i].underflows = 0;
}
@@ -2507,7 +2527,9 @@ static int tegra_dc_init(struct tegra_dc *dc)
tegra_dc_writel(dc, 0x0001c700, DC_CMD_INT_POLARITY);
tegra_dc_writel(dc, 0x00202020, DC_DISP_MEM_HIGH_PRIORITY);
tegra_dc_writel(dc, 0x00010101, DC_DISP_MEM_HIGH_PRIORITY_TIMER);
-
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+ tegra_dc_writel(dc, 0x00000000, DC_DISP_DISP_MISC_CONTROL);
+#endif
/* enable interrupts for vblank, frame_end and underflows */
tegra_dc_writel(dc, (FRAME_END_INT | V_BLANK_INT | ALL_UF_INT),
DC_CMD_INT_ENABLE);
diff --git a/drivers/video/tegra/dc/dc_reg.h b/drivers/video/tegra/dc/dc_reg.h
index 5eac27adfbf8..0b628fc7a14a 100644
--- a/drivers/video/tegra/dc/dc_reg.h
+++ b/drivers/video/tegra/dc/dc_reg.h
@@ -367,6 +367,7 @@
#define DC_DISP_MCCIF_DISPLAY1B_HYST 0x484
#define DC_DISP_DAC_CRT_CTRL 0x4c0
#define DC_DISP_DISP_MISC_CONTROL 0x4c1
+#define UF_LINE_FLUSH (1 << 1)
#define DC_WIN_COLOR_PALETTE(x) (0x500 + (x))