diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/input/misc/cm3217.c | 18 | ||||
-rw-r--r-- | drivers/media/video/tegra/nvavp/nvavp_dev.c | 67 | ||||
-rw-r--r-- | drivers/power/smb349-charger.c | 6 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc.c | 24 | ||||
-rw-r--r-- | drivers/video/tegra/dc/dc_reg.h | 1 |
5 files changed, 88 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 bdb649f3e87f..c593a0ad756b 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/video/tegra/dc/dc.c b/drivers/video/tegra/dc/dc.c index 2fee71d7dcfb..f4844f1eecfc 100644 --- a/drivers/video/tegra/dc/dc.c +++ b/drivers/video/tegra/dc/dc.c @@ -1877,6 +1877,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; } @@ -2182,7 +2202,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)) |