M7350v3_en_gpl
This commit is contained in:
@ -152,6 +152,4 @@ source "drivers/coresight/Kconfig"
|
||||
|
||||
source "drivers/bif/Kconfig"
|
||||
|
||||
source "drivers/oled/Kconfig"
|
||||
|
||||
endmenu
|
||||
|
@ -85,8 +85,8 @@ obj-y += i2c/ media/
|
||||
obj-$(CONFIG_PPS) += pps/
|
||||
obj-$(CONFIG_PTP_1588_CLOCK) += ptp/
|
||||
obj-$(CONFIG_W1) += w1/
|
||||
obj-$(CONFIG_HWMON) += hwmon/
|
||||
obj-$(CONFIG_POWER_SUPPLY) += power/
|
||||
obj-$(CONFIG_HWMON) += hwmon/
|
||||
obj-$(CONFIG_THERMAL) += thermal/
|
||||
obj-$(CONFIG_WATCHDOG) += watchdog/
|
||||
obj-$(CONFIG_MD) += md/
|
||||
@ -144,5 +144,3 @@ obj-$(CONFIG_MOBICORE_SUPPORT) += gud/
|
||||
obj-$(CONFIG_CORESIGHT) += coresight/
|
||||
|
||||
obj-$(CONFIG_BIF) += bif/
|
||||
|
||||
obj-$(CONFIG_OLED) += oled/
|
||||
|
@ -822,6 +822,44 @@ static const struct file_operations oldmem_fops = {
|
||||
};
|
||||
#endif
|
||||
|
||||
static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv,
|
||||
unsigned long count, loff_t pos)
|
||||
{
|
||||
char *line, *p;
|
||||
int i;
|
||||
ssize_t ret = -EFAULT;
|
||||
size_t len = iov_length(iv, count);
|
||||
|
||||
line = kmalloc(len + 1, GFP_KERNEL);
|
||||
if (line == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
/*
|
||||
* copy all vectors into a single string, to ensure we do
|
||||
* not interleave our log line with other printk calls
|
||||
*/
|
||||
p = line;
|
||||
for (i = 0; i < count; i++) {
|
||||
if (copy_from_user(p, iv[i].iov_base, iv[i].iov_len))
|
||||
goto out;
|
||||
p += iv[i].iov_len;
|
||||
}
|
||||
p[0] = '\0';
|
||||
|
||||
ret = printk("%s", line);
|
||||
/* printk can add a prefix */
|
||||
if (ret > len)
|
||||
ret = len;
|
||||
out:
|
||||
kfree(line);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct file_operations kmsg_fops = {
|
||||
.aio_write = kmsg_writev,
|
||||
.llseek = noop_llseek,
|
||||
};
|
||||
|
||||
static const struct memdev {
|
||||
const char *name;
|
||||
umode_t mode;
|
||||
@ -842,9 +880,7 @@ static const struct memdev {
|
||||
[7] = { "full", 0666, &full_fops, NULL },
|
||||
[8] = { "random", 0666, &random_fops, NULL },
|
||||
[9] = { "urandom", 0666, &urandom_fops, NULL },
|
||||
#ifdef CONFIG_PRINTK
|
||||
[11] = { "kmsg", 0644, &kmsg_fops, NULL },
|
||||
#endif
|
||||
[11] = { "kmsg", 0, &kmsg_fops, NULL },
|
||||
#ifdef CONFIG_CRASH_DUMP
|
||||
[12] = { "oldmem", 0, &oldmem_fops, NULL },
|
||||
#endif
|
||||
|
@ -822,7 +822,9 @@ static void adreno_iommu_setstate(struct kgsl_device *device,
|
||||
uint32_t flags)
|
||||
{
|
||||
phys_addr_t pt_val;
|
||||
unsigned int *link = NULL, *cmds;
|
||||
unsigned int link[230];
|
||||
unsigned int *cmds = &link[0];
|
||||
int sizedwords = 0;
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
int num_iommu_units;
|
||||
struct kgsl_context *context;
|
||||
@ -846,12 +848,6 @@ static void adreno_iommu_setstate(struct kgsl_device *device,
|
||||
|
||||
adreno_ctx = context->devctxt;
|
||||
|
||||
link = kmalloc(PAGE_SIZE, GFP_KERNEL);
|
||||
if (link == NULL)
|
||||
goto done;
|
||||
|
||||
cmds = link;
|
||||
|
||||
if (kgsl_mmu_enable_clk(&device->mmu,
|
||||
KGSL_IOMMU_CONTEXT_USER))
|
||||
return;
|
||||
@ -870,11 +866,17 @@ static void adreno_iommu_setstate(struct kgsl_device *device,
|
||||
cmds += _adreno_iommu_setstate_v1(device, cmds, pt_val,
|
||||
num_iommu_units, flags);
|
||||
|
||||
sizedwords += (cmds - &link[0]);
|
||||
if (sizedwords == 0) {
|
||||
KGSL_DRV_ERR(device, "no commands generated\n");
|
||||
BUG();
|
||||
}
|
||||
/* invalidate all base pointers */
|
||||
*cmds++ = cp_type3_packet(CP_INVALIDATE_STATE, 1);
|
||||
*cmds++ = 0x7fff;
|
||||
sizedwords += 2;
|
||||
|
||||
if ((unsigned int) (cmds - link) > (PAGE_SIZE / sizeof(unsigned int))) {
|
||||
if (sizedwords > (ARRAY_SIZE(link))) {
|
||||
KGSL_DRV_ERR(device, "Temp command buffer overflow\n");
|
||||
BUG();
|
||||
}
|
||||
@ -882,15 +884,12 @@ static void adreno_iommu_setstate(struct kgsl_device *device,
|
||||
* This returns the per context timestamp but we need to
|
||||
* use the global timestamp for iommu clock disablement
|
||||
*/
|
||||
|
||||
adreno_ringbuffer_issuecmds(device, adreno_ctx, KGSL_CMD_FLAGS_PMODE,
|
||||
link, (unsigned int) (cmds - link));
|
||||
&link[0], sizedwords);
|
||||
|
||||
kgsl_mmu_disable_clk_on_ts(&device->mmu,
|
||||
rb->timestamp[KGSL_MEMSTORE_GLOBAL], true);
|
||||
|
||||
done:
|
||||
kfree(link);
|
||||
kgsl_context_put(context);
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,6 @@
|
||||
#include "kgsl_iommu.h"
|
||||
#include <mach/ocmem.h>
|
||||
|
||||
#include "a3xx_reg.h"
|
||||
|
||||
#define DEVICE_3D_NAME "kgsl-3d"
|
||||
#define DEVICE_3D0_NAME "kgsl-3d0"
|
||||
|
||||
@ -508,11 +506,6 @@ static inline int adreno_add_read_cmds(struct kgsl_device *device,
|
||||
*cmds++ = val;
|
||||
*cmds++ = 0xFFFFFFFF;
|
||||
*cmds++ = 0xFFFFFFFF;
|
||||
|
||||
/* WAIT_REG_MEM turns back on protected mode - push it off */
|
||||
*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
|
||||
*cmds++ = 0;
|
||||
|
||||
cmds += __adreno_add_idle_indirect_cmds(cmds, nop_gpuaddr);
|
||||
return cmds - start;
|
||||
}
|
||||
@ -561,42 +554,4 @@ static inline int adreno_wait_reg_eq(unsigned int *cmds, unsigned int addr,
|
||||
return cmds - start;
|
||||
}
|
||||
|
||||
/*
|
||||
* adreno_set_protected_registers() - Protect the specified range of registers
|
||||
* from being accessed by the GPU
|
||||
* @device: pointer to the KGSL device
|
||||
* @index: Pointer to the index of the protect mode register to write to
|
||||
* @reg: Starting dword register to write
|
||||
* @mask_len: Size of the mask to protect (# of registers = 2 ** mask_len)
|
||||
*
|
||||
* Add the range of registers to the list of protected mode registers that will
|
||||
* cause an exception if the GPU accesses them. There are 16 available
|
||||
* protected mode registers. Index is used to specify which register to write
|
||||
* to - the intent is to call this function multiple times with the same index
|
||||
* pointer for each range and the registers will be magically programmed in
|
||||
* incremental fashion
|
||||
*/
|
||||
static inline void adreno_set_protected_registers(struct kgsl_device *device,
|
||||
unsigned int *index, unsigned int reg, int mask_len)
|
||||
{
|
||||
struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
|
||||
unsigned int val;
|
||||
|
||||
/* This function is only for adreno A3XX and beyond */
|
||||
BUG_ON(adreno_is_a2xx(adreno_dev));
|
||||
|
||||
/* There are only 16 registers available */
|
||||
BUG_ON(*index >= 16);
|
||||
|
||||
val = 0x60000000 | ((mask_len & 0x1F) << 24) | ((reg << 2) & 0x1FFFF);
|
||||
|
||||
/*
|
||||
* Write the protection range to the next available protection
|
||||
* register
|
||||
*/
|
||||
|
||||
kgsl_regwrite(device, A3XX_CP_PROTECT_REG_0 + *index, val);
|
||||
*index = *index + 1;
|
||||
}
|
||||
|
||||
#endif /*__ADRENO_H */
|
||||
|
@ -2526,8 +2526,8 @@ static int a3xx_rb_init(struct adreno_device *adreno_dev,
|
||||
GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000001);
|
||||
GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
|
||||
GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
|
||||
/* Enable protected mode */
|
||||
GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x20000000);
|
||||
/* Protected mode control - turned off for A3XX */
|
||||
GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
|
||||
GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
|
||||
GSL_RB_WRITE(rb->device, cmds, cmds_gpu, 0x00000000);
|
||||
|
||||
@ -2589,16 +2589,9 @@ static void a3xx_err_callback(struct adreno_device *adreno_dev, int bit)
|
||||
case A3XX_INT_CP_HW_FAULT:
|
||||
err = "ringbuffer hardware fault";
|
||||
break;
|
||||
case A3XX_INT_CP_REG_PROTECT_FAULT: {
|
||||
unsigned int reg;
|
||||
kgsl_regread(device, A3XX_CP_PROTECT_STATUS, ®);
|
||||
|
||||
KGSL_DRV_CRIT(device,
|
||||
"CP | Protected mode error| %s | addr=%x\n",
|
||||
reg & (1 << 24) ? "WRITE" : "READ",
|
||||
(reg & 0x1FFFF) >> 2);
|
||||
return;
|
||||
}
|
||||
case A3XX_INT_CP_REG_PROTECT_FAULT:
|
||||
err = "ringbuffer protected mode error interrupt";
|
||||
break;
|
||||
case A3XX_INT_CP_AHB_ERROR_HALT:
|
||||
err = "ringbuffer AHB error interrupt";
|
||||
break;
|
||||
@ -3171,46 +3164,6 @@ static void a3xx_perfcounter_init(struct adreno_device *adreno_dev)
|
||||
NULL, PERFCOUNTER_FLAG_KERNEL);
|
||||
}
|
||||
|
||||
/**
|
||||
* a3xx_protect_init() - Initializes register protection on a3xx
|
||||
* @device: Pointer to the device structure
|
||||
* Performs register writes to enable protected access to sensitive
|
||||
* registers
|
||||
*/
|
||||
static void a3xx_protect_init(struct kgsl_device *device)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
/* enable access protection to privileged registers */
|
||||
kgsl_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
|
||||
|
||||
/* RBBM registers */
|
||||
adreno_set_protected_registers(device, &index, 0x18, 0);
|
||||
adreno_set_protected_registers(device, &index, 0x20, 2);
|
||||
adreno_set_protected_registers(device, &index, 0x33, 0);
|
||||
adreno_set_protected_registers(device, &index, 0x42, 0);
|
||||
adreno_set_protected_registers(device, &index, 0x50, 4);
|
||||
adreno_set_protected_registers(device, &index, 0x63, 0);
|
||||
adreno_set_protected_registers(device, &index, 0x100, 4);
|
||||
|
||||
/* CP registers */
|
||||
adreno_set_protected_registers(device, &index, 0x1C0, 5);
|
||||
adreno_set_protected_registers(device, &index, 0x1EC, 1);
|
||||
adreno_set_protected_registers(device, &index, 0x1F6, 1);
|
||||
adreno_set_protected_registers(device, &index, 0x1F8, 2);
|
||||
adreno_set_protected_registers(device, &index, 0x45E, 2);
|
||||
adreno_set_protected_registers(device, &index, 0x460, 4);
|
||||
|
||||
/* RB registers */
|
||||
adreno_set_protected_registers(device, &index, 0xCC0, 0);
|
||||
|
||||
/* VBIF registers */
|
||||
adreno_set_protected_registers(device, &index, 0x3000, 6);
|
||||
|
||||
/* SMMU registers */
|
||||
adreno_set_protected_registers(device, &index, 0x4000, 14);
|
||||
}
|
||||
|
||||
static void a3xx_start(struct adreno_device *adreno_dev)
|
||||
{
|
||||
struct kgsl_device *device = &adreno_dev->dev;
|
||||
@ -3275,8 +3228,6 @@ static void a3xx_start(struct adreno_device *adreno_dev)
|
||||
adreno_regwrite(device, A3XX_RB_GMEM_BASE_ADDR,
|
||||
(unsigned int)(adreno_dev->ocmem_base >> 14));
|
||||
}
|
||||
/* Turn on protection */
|
||||
a3xx_protect_init(device);
|
||||
|
||||
/* Turn on performance counters */
|
||||
adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01);
|
||||
|
@ -407,6 +407,32 @@ int _ringbuffer_start_common(struct adreno_ringbuffer *rb)
|
||||
rb->memptrs_desc.gpuaddr +
|
||||
GSL_RB_MEMPTRS_RPTR_OFFSET);
|
||||
|
||||
if (adreno_is_a3xx(adreno_dev)) {
|
||||
/* enable access protection to privileged registers */
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_CTRL, 0x00000007);
|
||||
|
||||
/* RBBM registers */
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_0, 0x63000040);
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_1, 0x62000080);
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_2, 0x600000CC);
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_3, 0x60000108);
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_4, 0x64000140);
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_5, 0x66000400);
|
||||
|
||||
/* CP registers */
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_6, 0x65000700);
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_7, 0x610007D8);
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_8, 0x620007E0);
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_9, 0x61001178);
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_A, 0x64001180);
|
||||
|
||||
/* RB registers */
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_B, 0x60003300);
|
||||
|
||||
/* VBIF registers */
|
||||
adreno_regwrite(device, A3XX_CP_PROTECT_REG_C, 0x6B00C000);
|
||||
}
|
||||
|
||||
if (adreno_is_a2xx(adreno_dev)) {
|
||||
/* explicitly clear all cp interrupts */
|
||||
adreno_regwrite(device, REG_CP_INT_ACK, 0xFFFFFFFF);
|
||||
|
@ -989,10 +989,6 @@ inline unsigned int kgsl_iommu_sync_lock(struct kgsl_mmu *mmu,
|
||||
*cmds++ = 0x1;
|
||||
*cmds++ = 0x1;
|
||||
|
||||
/* WAIT_REG_MEM turns back on protected mode - push it off */
|
||||
*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
|
||||
*cmds++ = 0;
|
||||
|
||||
*cmds++ = cp_type3_packet(CP_MEM_WRITE, 2);
|
||||
*cmds++ = lock_vars->turn;
|
||||
*cmds++ = 0;
|
||||
@ -1007,19 +1003,11 @@ inline unsigned int kgsl_iommu_sync_lock(struct kgsl_mmu *mmu,
|
||||
*cmds++ = 0x1;
|
||||
*cmds++ = 0x1;
|
||||
|
||||
/* WAIT_REG_MEM turns back on protected mode - push it off */
|
||||
*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
|
||||
*cmds++ = 0;
|
||||
|
||||
*cmds++ = cp_type3_packet(CP_TEST_TWO_MEMS, 3);
|
||||
*cmds++ = lock_vars->flag[PROC_APPS];
|
||||
*cmds++ = lock_vars->turn;
|
||||
*cmds++ = 0;
|
||||
|
||||
/* TEST_TWO_MEMS turns back on protected mode - push it off */
|
||||
*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
|
||||
*cmds++ = 0;
|
||||
|
||||
cmds += adreno_add_idle_cmds(adreno_dev, cmds);
|
||||
|
||||
return cmds - start;
|
||||
@ -1057,10 +1045,6 @@ inline unsigned int kgsl_iommu_sync_unlock(struct kgsl_mmu *mmu,
|
||||
*cmds++ = 0x1;
|
||||
*cmds++ = 0x1;
|
||||
|
||||
/* WAIT_REG_MEM turns back on protected mode - push it off */
|
||||
*cmds++ = cp_type3_packet(CP_SET_PROTECTED_MODE, 1);
|
||||
*cmds++ = 0;
|
||||
|
||||
cmds += adreno_add_idle_cmds(adreno_dev, cmds);
|
||||
|
||||
return cmds - start;
|
||||
|
@ -372,10 +372,6 @@ int kgsl_mmu_init(struct kgsl_device *device)
|
||||
status = kgsl_allocate_contiguous(&mmu->setstate_memory, PAGE_SIZE);
|
||||
if (status)
|
||||
return status;
|
||||
|
||||
/* Mark the setstate memory as read only */
|
||||
mmu->setstate_memory.flags |= KGSL_MEMFLAGS_GPUREADONLY;
|
||||
|
||||
kgsl_sharedmem_set(device, &mmu->setstate_memory, 0, 0,
|
||||
mmu->setstate_memory.size);
|
||||
|
||||
|
@ -29,7 +29,6 @@
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/wakelock.h>
|
||||
|
||||
struct gpio_button_data {
|
||||
const struct gpio_keys_button *button;
|
||||
@ -52,7 +51,6 @@ struct gpio_keys_drvdata {
|
||||
struct gpio_button_data data[0];
|
||||
};
|
||||
|
||||
struct wake_lock gpio_keys_wlock;
|
||||
/*
|
||||
* SYSFS interface for enabling/disabling keys and switches:
|
||||
*
|
||||
@ -368,8 +366,7 @@ static irqreturn_t gpio_keys_gpio_isr(int irq, void *dev_id)
|
||||
jiffies + msecs_to_jiffies(bdata->timer_debounce));
|
||||
else
|
||||
schedule_work(&bdata->work);
|
||||
// [houjihai] add timeout wake lock
|
||||
wake_lock_timeout(&gpio_keys_wlock, 5 * HZ);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@ -648,20 +645,6 @@ static void gpio_remove_key(struct gpio_button_data *bdata)
|
||||
gpio_free(bdata->button->gpio);
|
||||
}
|
||||
|
||||
/* [houjihai start] add pm domain for gpio keys */
|
||||
static int no_suppend_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dev_pm_domain gpio_keys_pm_domain = {
|
||||
.ops = {
|
||||
.suspend = no_suppend_resume,
|
||||
.resume = no_suppend_resume,
|
||||
}
|
||||
};
|
||||
/* [houjihai end] */
|
||||
|
||||
static int __devinit gpio_keys_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct gpio_keys_platform_data *pdata = pdev->dev.platform_data;
|
||||
@ -701,8 +684,6 @@ static int __devinit gpio_keys_probe(struct platform_device *pdev)
|
||||
input->name = pdata->name ? : pdev->name;
|
||||
input->phys = "gpio-keys/input0";
|
||||
input->dev.parent = &pdev->dev;
|
||||
// [houjihai] add pm domain for gpio keys
|
||||
input->dev.pm_domain = &gpio_keys_pm_domain;
|
||||
input->open = gpio_keys_open;
|
||||
input->close = gpio_keys_close;
|
||||
|
||||
@ -824,14 +805,11 @@ static int gpio_keys_resume(struct device *dev)
|
||||
struct gpio_button_data *bdata = &ddata->data[i];
|
||||
if (bdata->button->wakeup && device_may_wakeup(dev))
|
||||
disable_irq_wake(bdata->irq);
|
||||
/* [houjihai start] no need pass up event when resume*/
|
||||
#if 0
|
||||
|
||||
if (gpio_is_valid(bdata->button->gpio))
|
||||
gpio_keys_gpio_report_event(bdata);
|
||||
#endif
|
||||
}
|
||||
//input_sync(ddata->input);
|
||||
/* [houjihai end]*/
|
||||
input_sync(ddata->input);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -852,13 +830,11 @@ static struct platform_driver gpio_keys_device_driver = {
|
||||
|
||||
static int __init gpio_keys_init(void)
|
||||
{
|
||||
wake_lock_init(&gpio_keys_wlock, WAKE_LOCK_SUSPEND, "gpiokeys");
|
||||
return platform_driver_register(&gpio_keys_device_driver);
|
||||
}
|
||||
|
||||
static void __exit gpio_keys_exit(void)
|
||||
{
|
||||
wake_lock_destroy(&gpio_keys_wlock);
|
||||
platform_driver_unregister(&gpio_keys_device_driver);
|
||||
}
|
||||
|
||||
|
@ -4531,14 +4531,11 @@ msmsdcc_check_status(unsigned long data)
|
||||
" is ACTIVE_HIGH\n",
|
||||
mmc_hostname(host->mmc),
|
||||
host->oldstat, status);
|
||||
|
||||
/* [linyunfeng] 0 -> HZ >> 1, set debounce time */
|
||||
mmc_detect_change(host->mmc, HZ >> 1);
|
||||
mmc_detect_change(host->mmc, 0);
|
||||
}
|
||||
host->oldstat = status;
|
||||
} else {
|
||||
/* [linyunfeng] 0 -> HZ >> 1, set debounce time */
|
||||
mmc_detect_change(host->mmc, HZ >> 1);
|
||||
mmc_detect_change(host->mmc, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,8 +357,4 @@ config MTD_DOCPROBE_55AA
|
||||
LinuxBIOS or if you need to recover a DiskOnChip Millennium on which
|
||||
you have managed to wipe the first block.
|
||||
|
||||
config FLASH_TYPE_ETRON
|
||||
bool "Etron Flash"
|
||||
default n
|
||||
|
||||
endmenu
|
||||
|
24
kernel/drivers/mtd/devices/msm_qpic_nand.c
Executable file → Normal file
24
kernel/drivers/mtd/devices/msm_qpic_nand.c
Executable file → Normal file
@ -718,7 +718,7 @@ static int msm_nand_flash_onfi_probe(struct msm_nand_info *info)
|
||||
if (!ret && !(nandc_version.nand_major == 1 &&
|
||||
nandc_version.nand_minor == 1 &&
|
||||
nandc_version.qpic_major == 1 &&
|
||||
nandc_version.qpic_minor >= 1)) {
|
||||
nandc_version.qpic_minor == 1)) {
|
||||
ret = -EPERM;
|
||||
goto out;
|
||||
}
|
||||
@ -2068,7 +2068,7 @@ int msm_nand_scan(struct mtd_info *mtd)
|
||||
int flash_id = 0, err = 0;
|
||||
uint32_t i, mtd_writesize;
|
||||
uint8_t dev_found = 0, wide_bus;
|
||||
uint32_t manid = 0, devid = 0, devcfg;
|
||||
uint32_t manid, devid, devcfg;
|
||||
uint32_t bad_block_byte;
|
||||
struct nand_flash_dev *flashdev = NULL;
|
||||
struct nand_manufacturers *flashman = NULL;
|
||||
@ -2107,16 +2107,6 @@ int msm_nand_scan(struct mtd_info *mtd)
|
||||
((devcfg >> 4) & 0x3);
|
||||
supported_flash->oobsize = (8 << ((devcfg >> 2) & 1)) *
|
||||
(supported_flash->pagesize >> 9);
|
||||
|
||||
#if 0
|
||||
#ifdef CONFIG_FLASH_TYPE_ETRON
|
||||
supported_flash->oobsize = 128;
|
||||
#endif
|
||||
#endif
|
||||
if((manid == ETRON_2G1G_MANID) && (devid == ETRON_2G1G_DEVID)) {
|
||||
supported_flash->oobsize = 128;
|
||||
}
|
||||
|
||||
} else {
|
||||
supported_flash->widebus = flashdev->options &
|
||||
NAND_BUSWIDTH_16 ? 1 : 0;
|
||||
@ -2126,7 +2116,6 @@ int msm_nand_scan(struct mtd_info *mtd)
|
||||
}
|
||||
supported_flash->flash_id = flash_id;
|
||||
supported_flash->density = flashdev->chipsize << 20;
|
||||
//supported_flash->oobsize = 128;
|
||||
}
|
||||
|
||||
if (dev_found) {
|
||||
@ -2143,15 +2132,6 @@ int msm_nand_scan(struct mtd_info *mtd)
|
||||
else
|
||||
chip->bch_caps = MSM_NAND_CAP_4_BIT_BCH;
|
||||
|
||||
#if 0
|
||||
#ifdef CONFIG_FLASH_TYPE_ETRON
|
||||
chip->bch_caps = MSM_NAND_CAP_8_BIT_BCH;
|
||||
#endif
|
||||
#endif
|
||||
if((manid == ETRON_2G1G_MANID) && (devid == ETRON_2G1G_DEVID)) {
|
||||
chip->bch_caps = MSM_NAND_CAP_8_BIT_BCH;
|
||||
}
|
||||
|
||||
pr_info("NAND Id: 0x%x Buswidth: %dBits Density: %lld MByte\n",
|
||||
supported_flash->flash_id, (wide_bus) ? 16 : 8,
|
||||
(mtd->size >> 20));
|
||||
|
@ -169,14 +169,7 @@ struct nand_flash_dev nand_flash_ids[] = {
|
||||
* Manufacturer ID list
|
||||
*/
|
||||
struct nand_manufacturers nand_manuf_ids[] = {
|
||||
#if 0
|
||||
#ifdef CONFIG_FLASH_TYPE_ETRON
|
||||
{NAND_MFR_ETRON, "Etron"},
|
||||
#else
|
||||
{NAND_MFR_TOSHIBA, "Toshiba"},
|
||||
#endif
|
||||
#endif
|
||||
{NAND_MFR_ETRON, "Etron"},
|
||||
{NAND_MFR_SAMSUNG, "Samsung"},
|
||||
{NAND_MFR_FUJITSU, "Fujitsu"},
|
||||
{NAND_MFR_NATIONAL, "National"},
|
||||
@ -186,7 +179,6 @@ struct nand_manufacturers nand_manuf_ids[] = {
|
||||
{NAND_MFR_MICRON, "Micron"},
|
||||
{NAND_MFR_AMD, "AMD"},
|
||||
{NAND_MFR_MACRONIX, "Macronix"},
|
||||
{NAND_MFR_ESMT, "ESMT"},
|
||||
{0x0, "Unknown"}
|
||||
};
|
||||
|
||||
|
@ -89,8 +89,6 @@ struct wwan_private {
|
||||
|
||||
static struct net_device *netdevs[WWAN_DEVICE_COUNT];
|
||||
|
||||
static unsigned long rmnet_jiffies;
|
||||
|
||||
static __be16 wwan_ip_type_trans(struct sk_buff *skb)
|
||||
{
|
||||
__be16 protocol = 0;
|
||||
@ -491,17 +489,13 @@ static int wwan_xmit(struct sk_buff *skb, struct net_device *dev)
|
||||
struct wwan_private *wwan_ptr = netdev_priv(dev);
|
||||
unsigned long flags;
|
||||
int ret = 0;
|
||||
int i;
|
||||
|
||||
if (netif_queue_stopped(dev)) {
|
||||
pr_err("[%s]fatal: wwan_xmit called when netif_queue stopped\n",
|
||||
dev->name);
|
||||
return 0;
|
||||
}
|
||||
rmnet_jiffies = jiffies;
|
||||
for (i = 0; i < dev->num_tx_queues; i++)
|
||||
netdev_get_tx_queue(dev, i)->trans_start = rmnet_jiffies;
|
||||
dev->trans_start = rmnet_jiffies;
|
||||
dev->trans_start = jiffies;
|
||||
ret = ipa_rm_inactivity_timer_request_resource(
|
||||
ipa_rm_resource_by_ch_id[wwan_ptr->ch_id]);
|
||||
if (ret == -EINPROGRESS) {
|
||||
|
@ -1,19 +0,0 @@
|
||||
config OLED
|
||||
bool "Support OLED display"
|
||||
default n
|
||||
---help---
|
||||
Say Y here if you use OLED display
|
||||
|
||||
config OLED_SSD1306_PT
|
||||
bool "Driver for OLED SSD1306"
|
||||
select OLED
|
||||
default n
|
||||
---help---
|
||||
Say Y here if you use OLED SSD1306
|
||||
|
||||
config OLED_S90319_PT
|
||||
bool "Driver for OLED s90319"
|
||||
select OLED
|
||||
default n
|
||||
---help---
|
||||
Say Y here if you use OLED S90319
|
@ -1,6 +0,0 @@
|
||||
obj-$(CONFIG_OLED_SSD1306_PT) += oled_ssd1306_pt.o
|
||||
obj-$(CONFIG_OLED_S90319_PT) += oled_s90319_pt.o
|
||||
obj-$(CONFIG_OLED) += oled_pt.o oled_display.o
|
||||
|
||||
clean:
|
||||
rm *.o .*cmd
|
@ -1,184 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 2014, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_display.h
|
||||
Description : oled sysfs interface.
|
||||
Author : Luowei
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2014-05-13, Luowei create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include "oled_display.h"
|
||||
|
||||
struct class *oled_display_class;
|
||||
EXPORT_SYMBOL_GPL(oled_display_class);
|
||||
|
||||
static struct device_type oled_display_dev_type;
|
||||
|
||||
#define DISPLAY_ATTR(_name) \
|
||||
{ \
|
||||
.attr = { .name = #_name }, \
|
||||
.show = oled_display_show_property, \
|
||||
.store = oled_display_store_property, \
|
||||
}
|
||||
|
||||
static struct device_attribute oled_display_attrs[];
|
||||
|
||||
static ssize_t oled_display_show_property(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct oled_display *display = dev_get_drvdata(dev);
|
||||
const ptrdiff_t off = attr - oled_display_attrs;
|
||||
ssize_t ret = 0;
|
||||
|
||||
if (!display)
|
||||
goto show_failed;
|
||||
|
||||
if ((off >= DISPLAY_PROP_BUFFER && off < DISPLAY_PROP_NUMBER)
|
||||
&& display->show_property[off])
|
||||
ret = display->show_property[off](dev, attr, buf);
|
||||
|
||||
return ret;
|
||||
show_failed:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t oled_display_store_property(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct oled_display *display = dev_get_drvdata(dev);
|
||||
const ptrdiff_t off = attr - oled_display_attrs;
|
||||
ssize_t ret = 0;
|
||||
|
||||
if (!display)
|
||||
goto show_failed;
|
||||
|
||||
if ((off >= DISPLAY_PROP_BUFFER && off < DISPLAY_PROP_NUMBER)
|
||||
&& display->store_property[off])
|
||||
ret = display->store_property[off](dev, attr, buf, count);
|
||||
|
||||
return ret;
|
||||
show_failed:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_attribute oled_display_attrs[] = {
|
||||
DISPLAY_ATTR(oled_buffer),
|
||||
DISPLAY_ATTR(backlight_on),
|
||||
DISPLAY_ATTR(panel_on),
|
||||
};
|
||||
|
||||
static struct attribute *__oled_display_attrs[ARRAY_SIZE(oled_display_attrs) + 1];
|
||||
|
||||
static umode_t oled_display_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
int attrno)
|
||||
{
|
||||
return (S_IRUGO | S_IWUGO);
|
||||
}
|
||||
|
||||
static struct attribute_group oled_display_attr_group = {
|
||||
.attrs = __oled_display_attrs,
|
||||
.is_visible = oled_display_attr_is_visible,
|
||||
};
|
||||
|
||||
static const struct attribute_group *oled_display_attr_groups[] = {
|
||||
&oled_display_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void oled_display_init_attrs(struct device_type *dev_type)
|
||||
{
|
||||
int i;
|
||||
|
||||
dev_type->groups = oled_display_attr_groups;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(oled_display_attrs); i++)
|
||||
__oled_display_attrs[i] = &oled_display_attrs[i].attr;
|
||||
}
|
||||
|
||||
static void oled_display_dev_release(struct device *dev)
|
||||
{
|
||||
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
int oled_display_register(struct device *parent, struct oled_display *display)
|
||||
{
|
||||
struct device *dev;
|
||||
int rc;
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
device_initialize(dev);
|
||||
|
||||
dev->class = oled_display_class;
|
||||
dev->type = &oled_display_dev_type;
|
||||
dev->parent = parent;
|
||||
dev->release = oled_display_dev_release;
|
||||
dev_set_drvdata(dev, display);
|
||||
display->dev = dev;
|
||||
|
||||
rc = kobject_set_name(&dev->kobj, "%s", display->name);
|
||||
if (rc)
|
||||
goto kobject_set_name_failed;
|
||||
|
||||
rc = device_add(dev);
|
||||
if (rc)
|
||||
goto device_add_failed;
|
||||
|
||||
spin_lock_init(&display->lock);
|
||||
|
||||
return 0;
|
||||
|
||||
kobject_set_name_failed:
|
||||
put_device(dev);
|
||||
kfree(dev->p);
|
||||
kfree(dev);
|
||||
return rc;
|
||||
device_add_failed:
|
||||
device_del(dev);
|
||||
put_device(dev);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(oled_display_register);
|
||||
|
||||
void oled_display_unregister(struct oled_display *display)
|
||||
{
|
||||
device_unregister(display->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(oled_display_unregister);
|
||||
|
||||
static int __init oled_display_class_init(void)
|
||||
{
|
||||
oled_display_class = class_create(THIS_MODULE, "display");
|
||||
|
||||
if (IS_ERR(oled_display_class))
|
||||
return PTR_ERR(oled_display_class);
|
||||
|
||||
oled_display_init_attrs(&oled_display_dev_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit oled_display_class_exit(void)
|
||||
{
|
||||
class_destroy(oled_display_class);
|
||||
}
|
||||
|
||||
subsys_initcall(oled_display_class_init);
|
||||
module_exit(oled_display_class_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Universal display class");
|
||||
MODULE_AUTHOR("LuoWei <luoweisj@tp-link.net>");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,40 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 2014, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_display.h
|
||||
Description : Header file of oled sysfs interface.
|
||||
Author : Luowei
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2014-05-13, Luowei create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __OLED_DISPLAY_H__
|
||||
#define __OLED_DISPLAY_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum oled_display_property {
|
||||
DISPLAY_PROP_BUFFER = 0,
|
||||
DISPLAY_PROP_BACKLIGHTON,
|
||||
DISPLAY_PROP_PANELON,
|
||||
DISPLAY_PROP_NUMBER
|
||||
};
|
||||
|
||||
struct oled_display {
|
||||
const char *name;
|
||||
enum oled_display_property *properties;
|
||||
size_t num_properties;
|
||||
|
||||
ssize_t (*show_property[DISPLAY_PROP_NUMBER]) (struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
ssize_t (*store_property[DISPLAY_PROP_NUMBER]) (struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count);
|
||||
|
||||
struct device *dev;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
int oled_display_register(struct device *parent, struct oled_display *display);
|
||||
|
||||
#endif
|
@ -1,274 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 1996-2012, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_pt.c
|
||||
Description : Driver for OLED s90319.
|
||||
Author : linyunfeng
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2011-08-16, linyunfeng create file.
|
||||
*******************************************************************************/
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <mach/board.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/wakelock.h>
|
||||
|
||||
#include "oled_pt.h"
|
||||
#include "oled_display.h"
|
||||
|
||||
//#define OLED_DEBUG
|
||||
|
||||
struct mutex oled_mutex;
|
||||
struct wake_lock oled_wlock;
|
||||
|
||||
static struct oled_panel_data *oled_pdata;
|
||||
|
||||
#ifdef CONFIG_OLED_SSD1306_PT
|
||||
extern uint8_t oled_ssd1306_buf[];
|
||||
extern struct oled_panel_data oled_ssd1306_panel_data;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OLED_S90319_PT
|
||||
extern uint8_t oled_s90319_buf[];
|
||||
extern struct oled_panel_data oled_s90319_panel_data;
|
||||
#endif
|
||||
|
||||
static uint32_t oled_buf_size = 0;
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_buffer_show
|
||||
Description : Print the oled buffer data, hex
|
||||
Input : None
|
||||
Output : buf: Command line buffer
|
||||
Return : The number of characters will display in command
|
||||
line.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static ssize_t oled_buffer_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return oled_pdata->oled_print_buffer(buf);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_buffer_store
|
||||
Description : Write data to oled buffer.
|
||||
Input : buf: Input format is: x,y,width,height,data.
|
||||
count: Length of input.
|
||||
Output : None
|
||||
Return : Length of input or error number.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static ssize_t oled_buffer_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
uint32_t data_length = 0;
|
||||
uint8_t x = buf[0];
|
||||
uint8_t y = buf[1];
|
||||
uint8_t width = buf[2];
|
||||
uint8_t height = buf[3];
|
||||
|
||||
if ('\n' == *(buf + count - 1)){
|
||||
data_length = count - 5;
|
||||
} else {
|
||||
data_length = count - 4;
|
||||
}
|
||||
|
||||
if (data_length > oled_buf_size) {
|
||||
printk("%s, data_length=%d, oled_buf_size=%d, oled buffer overflow!\n",
|
||||
__func__, data_length, oled_buf_size);
|
||||
mutex_unlock(&oled_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mutex_lock(&oled_mutex);
|
||||
|
||||
#ifdef CONFIG_OLED_SSD1306_PT
|
||||
memcpy(oled_ssd1306_buf, buf + 4, data_length);
|
||||
|
||||
oled_pdata->oled_fill_with_pic(oled_ssd1306_buf,
|
||||
x, y, width, height);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OLED_S90319_PT
|
||||
memcpy(oled_s90319_buf, buf + 4, buf[2] * buf[3] / 8);
|
||||
oled_pdata->oled_fill_with_pic(oled_s90319_buf,
|
||||
x, y, width, height);
|
||||
#endif
|
||||
|
||||
mutex_unlock(&oled_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : backlight_on_store
|
||||
Description : Control backlight.
|
||||
Input : buf: 0: off, 1: on.
|
||||
count: Length of input.
|
||||
Output : None
|
||||
Return : Length of input.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static ssize_t backlight_on_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
uint8_t on = simple_strtoul(buf, NULL, 10);
|
||||
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s, buf=%s\n", __func__, buf);
|
||||
#endif
|
||||
|
||||
oled_pdata->oled_set_backlight(on);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : panel_on_store
|
||||
Description : Control panel.
|
||||
Input : buf: 0: off, 1: on.
|
||||
count: Length of input.
|
||||
Output : None
|
||||
Return : Length of input.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static ssize_t panel_on_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
uint8_t on = simple_strtoul(buf, NULL, 10);
|
||||
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s, buf=%s\n", __func__, buf);
|
||||
#endif
|
||||
|
||||
if (0 == on) {
|
||||
oled_pdata->oled_panel_off();
|
||||
|
||||
if (wake_lock_active(&oled_wlock)) {
|
||||
wake_unlock(&oled_wlock);
|
||||
}
|
||||
} else {
|
||||
if (!wake_lock_active(&oled_wlock)) {
|
||||
wake_lock(&oled_wlock);
|
||||
}
|
||||
|
||||
oled_pdata->oled_panel_on();
|
||||
}
|
||||
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s end\n", __func__);
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static enum oled_display_property oled_display_prop[] = {
|
||||
DISPLAY_PROP_BUFFER,
|
||||
DISPLAY_PROP_BACKLIGHTON,
|
||||
DISPLAY_PROP_PANELON
|
||||
};
|
||||
|
||||
static struct oled_display oled_display = {
|
||||
.name = "oled",
|
||||
.properties = oled_display_prop,
|
||||
.num_properties = ARRAY_SIZE(oled_display_prop),
|
||||
.show_property = {oled_buffer_show},
|
||||
.store_property = {oled_buffer_store, backlight_on_store, panel_on_store}
|
||||
};
|
||||
|
||||
/* Function to load the device */
|
||||
static int __devinit oled_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device *dev = &(pdev->dev);
|
||||
printk("%s\n", __func__);
|
||||
|
||||
ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
|
||||
if (ret)
|
||||
pr_err("%s: of_platform_populate failed %d\n", __func__, ret);
|
||||
|
||||
#ifdef CONFIG_OLED_SSD1306_PT
|
||||
pdev->dev.platform_data = &oled_ssd1306_panel_data;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OLED_S90319_PT
|
||||
pdev->dev.platform_data = &oled_s90319_panel_data;
|
||||
#endif
|
||||
|
||||
oled_pdata = pdev->dev.platform_data;
|
||||
|
||||
oled_buf_size = oled_pdata->panel_width * oled_pdata->panel_height;
|
||||
|
||||
oled_display.dev = dev;
|
||||
ret = oled_display_register(dev, &oled_display);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: oled_display_register failed, ret=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_init(&oled_mutex);
|
||||
|
||||
wake_lock_init(&oled_wlock, WAKE_LOCK_SUSPEND, "oled");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit oled_remove(struct platform_device *pdev)
|
||||
{
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
wake_lock_destroy(&oled_wlock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id tp_oled_pt_table[] = {
|
||||
{ .compatible = "tp,oled_pt",},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver oled_device_driver = {
|
||||
.probe = oled_probe,
|
||||
.remove = __devexit_p(oled_remove),
|
||||
.driver = {
|
||||
.name = "oled",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = tp_oled_pt_table,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init oled_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
rc = platform_driver_register(&oled_device_driver);
|
||||
|
||||
if (!rc)
|
||||
printk("oled init success!\n");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit oled_exit(void)
|
||||
{
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
platform_driver_unregister(&oled_device_driver);
|
||||
}
|
||||
|
||||
module_init(oled_init);
|
||||
module_exit(oled_exit);
|
||||
|
||||
MODULE_AUTHOR("Lin Yunfeng");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_DESCRIPTION("OLED display driver");
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 2014, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_pt.h
|
||||
Description : Driver for OLED.
|
||||
Author : Zhang Tao<zhangtao@tp-link.net>
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2014-04-14, ZhangTao create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _OLED_PT_H
|
||||
#define _OLED_PT_H
|
||||
|
||||
#ifdef CONFIG_OLED_SSD1306_PT
|
||||
struct oled_panel_data {
|
||||
void (*oled_gpio_config)(int on);
|
||||
int (*oled_power_save)(int);
|
||||
int (*oled_panel_on)(void);
|
||||
int (*oled_panel_off)(void);
|
||||
int (*oled_horizontal_scroll)(const uint8_t y, const uint8_t height,
|
||||
const uint8_t t_interval_scroll, const uint8_t direction);
|
||||
int (*oled_scroll_stop)(void);
|
||||
int (*oled_fade_blink)(const uint8_t mode, const uint8_t t_interval_scroll);
|
||||
int (*oled_fill_with_pic)(const uint8_t *pic, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height);
|
||||
int (*oled_fill_with_value)(const uint8_t value, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height);
|
||||
int (*oled_print_buffer)(char *buf);
|
||||
int (*oled_set_backlight)(const uint8_t on);
|
||||
int panel_width;
|
||||
int panel_height;
|
||||
int *gpio_num;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OLED_S90319_PT
|
||||
struct oled_panel_data {
|
||||
void (*oled_gpio_config)(int on);
|
||||
int (*oled_power_save)(int);
|
||||
int (*oled_panel_on)(void);
|
||||
int (*oled_panel_off)(void);
|
||||
int (*oled_fill_with_pic)(const uint8_t *pic, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height);
|
||||
int (*oled_set_backlight)(const uint8_t on);
|
||||
int (*oled_print_buffer)(char *buf);
|
||||
int panel_width;
|
||||
int panel_height;
|
||||
int *gpio_num;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif //end of _OLED_PT_H
|
@ -1,781 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 1996-2014, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_s90319_pt.c
|
||||
Description : Driver for OLED s90319.
|
||||
Author : xiongsizhe
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2014-03-28, xiongsizhe create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/pmic.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <mach/board.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/gpiomux.h>
|
||||
#include <linux/device.h>
|
||||
#include "oled_pt.h"
|
||||
#include "oled_s90319_pt.h"
|
||||
|
||||
//#define OLED_S90319_DEBUG
|
||||
|
||||
typedef unsigned int boolean;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
static int s90319_spi_write_cmd(const uint8_t *data, const uint16_t len);
|
||||
static int s90319_spi_write_data(const uint8_t *data, const uint16_t len);
|
||||
|
||||
uint8_t oled_s90319_buf[COLUMN_NUM * ROW_NUM * 2] = {0};
|
||||
static uint8_t frame_data[COLUMN_NUM * ROW_NUM * 2] ={0};
|
||||
|
||||
static uint8_t frame_data_buf[COLUMN_NUM * ROW_NUM * 2] ={0};
|
||||
|
||||
struct s90319_state_type{
|
||||
boolean disp_initialized;
|
||||
boolean display_on;
|
||||
boolean disp_powered_up;
|
||||
};
|
||||
|
||||
static struct s90319_state_type s90319_state = {0};
|
||||
|
||||
struct oled_panel_data oled_s90319_panel_data;
|
||||
static struct oled_panel_data *oled_s90319_pdata;
|
||||
|
||||
static struct mutex flush_mutex;
|
||||
static struct mutex oled_panel_mutex;
|
||||
|
||||
#define BUFFER_SIZE 4<<10
|
||||
struct spi_message spi_msg;
|
||||
//struct spi_transfer spi_xfer;
|
||||
unsigned char *tx_buf;
|
||||
|
||||
struct s90319_work_t {
|
||||
struct work_struct work;
|
||||
};
|
||||
static DECLARE_WAIT_QUEUE_HEAD(s90319_wait_queue);
|
||||
|
||||
static struct s90319_work_t *s90319_sensorw;
|
||||
static struct spi_device *s90319_spi;
|
||||
|
||||
static int oled_s90319_rsx;
|
||||
|
||||
static int oled_s90319_cs;
|
||||
static int oled_s90319_boost_en;
|
||||
|
||||
enum GPIO_OLED_S90319 {
|
||||
GPIO_OLED_CS = 0,
|
||||
GPIO_OLED_RESET,
|
||||
GPIO_OLED_BOOST_EN,
|
||||
GPIO_OLED_RSX,
|
||||
GPIO_OLED_VDD0,
|
||||
GPIO_OLED_VDD1,
|
||||
|
||||
GPIO_OLED_END,
|
||||
};
|
||||
|
||||
static const char *dts_gpio_name[] = {
|
||||
[GPIO_OLED_CS] = "qcom,oled-cs-gpio",
|
||||
[GPIO_OLED_RESET] = "qcom,oled-reset-gpio",
|
||||
[GPIO_OLED_BOOST_EN] = "qcom,oled-boost-en-gpio",
|
||||
[GPIO_OLED_RSX] = "qcom,oled-rsx-gpio",
|
||||
[GPIO_OLED_VDD0] = "qcom,oled-vdd0-gpio",
|
||||
[GPIO_OLED_VDD1] = "qcom,oled-vdd1-gpio",
|
||||
|
||||
[GPIO_OLED_END] = "",
|
||||
};
|
||||
|
||||
static int oled_s90319_gpio[GPIO_OLED_END] = {0};
|
||||
|
||||
/************************************************************
|
||||
Function : wr_comm
|
||||
Description: transfer command to oled
|
||||
Input : commond
|
||||
Return :
|
||||
************************************************************/
|
||||
void wr_comm(uint8_t cmd)
|
||||
{
|
||||
s90319_spi_write_cmd(&cmd, 1);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : wr_dat
|
||||
Description: transfer data to oled
|
||||
Input : data
|
||||
Return :
|
||||
************************************************************/
|
||||
void wr_dat(uint8_t data)
|
||||
{
|
||||
s90319_spi_write_data(&data, 1);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : Delay
|
||||
Description: delay time
|
||||
Input : t
|
||||
Return :
|
||||
************************************************************/
|
||||
void Delay(unsigned int t)
|
||||
{
|
||||
mdelay(t);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : get_gpio_by_dtsname
|
||||
Description: get gpio number by dtsname
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void get_gpio_by_dtsname(struct device_node *node, const char *gpio_name[], u32 *gpio_num, int len)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
gpio_num[i] = of_get_named_gpio(node, gpio_name[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_config_gpios
|
||||
Description: config gpio
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void oled_s90319_config_gpios(int enable)
|
||||
{
|
||||
int i, rc = 0;
|
||||
for (i = 0; i < GPIO_OLED_END; i++)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
rc = gpio_request(oled_s90319_gpio[i], dts_gpio_name[i]);
|
||||
if (rc)
|
||||
{
|
||||
pr_err("request gpio %s failed, rc=%d\n", dts_gpio_name[i], rc);
|
||||
gpio_free(oled_s90319_gpio[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_free(oled_s90319_gpio[i]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_power_save
|
||||
Description: open or close power supply
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_power_save(int on)
|
||||
{
|
||||
int rc = 0;
|
||||
if (on)
|
||||
{
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_RESET], 0);
|
||||
mdelay(1);
|
||||
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_VDD0], 1);
|
||||
mdelay(1);
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_VDD1], 1);
|
||||
mdelay(1);
|
||||
|
||||
gpio_set_value_cansleep(oled_s90319_gpio[GPIO_OLED_RESET], 1);
|
||||
mdelay(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_BOOST_EN], 0);
|
||||
mdelay(1);
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_VDD1], 0);
|
||||
mdelay(1);
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_VDD0], 0);
|
||||
mdelay(1);
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_RESET], 0);
|
||||
mdelay(1);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_spi_txdata
|
||||
Description: transfer data by spi
|
||||
Input : txdata: data to transfer
|
||||
length: length of txdata
|
||||
Return :
|
||||
************************************************************/
|
||||
static int s90319_spi_txdata(uint8_t *txdata, const uint16_t length)
|
||||
{
|
||||
struct spi_transfer spi_xfer = {
|
||||
.tx_buf = txdata,
|
||||
.len = length,
|
||||
};
|
||||
spi_message_init(&spi_msg);
|
||||
|
||||
spi_message_add_tail(&spi_xfer, &spi_msg);
|
||||
|
||||
return spi_sync(s90319_spi, &spi_msg);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_spi_write_cmd
|
||||
Description: transfer cmd by spi
|
||||
Input : data: cmd to transfer
|
||||
len: length of cmd
|
||||
Return :
|
||||
************************************************************/
|
||||
static int s90319_spi_write_cmd(const uint8_t *data, const uint16_t len)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
#ifdef OLED_S90319_DEBUG
|
||||
int i = 0;
|
||||
printk("%s, data = 0x%x, len = %d\n", __func__, *data, len);
|
||||
#endif
|
||||
|
||||
if (TRUE == s90319_state.disp_powered_up) {
|
||||
|
||||
memcpy(frame_data, data, len);
|
||||
|
||||
#ifdef OLED_S90319_DEBUG
|
||||
for (i = 0; i < len; i++){
|
||||
printk("0x%x ", *(frame_data+i));
|
||||
}
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
gpio_set_value_cansleep(oled_s90319_rsx, 0);
|
||||
|
||||
rc = s90319_spi_txdata(frame_data, len);
|
||||
if (rc < 0) {
|
||||
printk("%s fail, data = 0x%x, len = %d, rc = %d\n",
|
||||
__func__, *data, len, rc);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_spi_write_data
|
||||
Description: data need to be write
|
||||
Input : data: data need to be write
|
||||
len: length of data
|
||||
Return :
|
||||
************************************************************/
|
||||
static int s90319_spi_write_data(const uint8_t *data, const uint16_t len)
|
||||
{
|
||||
int rc = -EFAULT;
|
||||
|
||||
#ifdef OLED_S90319_DEBUG
|
||||
printk("%s, data = 0x%x, len = %d\n", __func__, *data, len);
|
||||
#endif
|
||||
|
||||
if (TRUE == s90319_state.disp_powered_up) {
|
||||
|
||||
memcpy(frame_data, data, len);
|
||||
|
||||
gpio_set_value_cansleep(oled_s90319_rsx, 1);
|
||||
|
||||
rc = s90319_spi_txdata(frame_data, len);
|
||||
if (rc < 0) {
|
||||
printk("%s fail, data = 0x%x, len = %d, rc = %d\n",
|
||||
__func__, *data, len, rc);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_area_check
|
||||
Description: check data area bigger than oled area or not
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_area_check(const uint8_t x, const uint8_t y,
|
||||
const uint8_t width, const uint8_t height)
|
||||
{
|
||||
if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)
|
||||
|| (x + width > COLUMN_NUM) || (y + height > ROW_NUM)){
|
||||
printk("%s error, row_start=%d, col_start=%d, width=%d, height=%d",
|
||||
__func__, x, y, width, height);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_fill_with_pic
|
||||
Description: write pic data on location assign
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_fill_with_pic(const uint8_t *pic, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height)
|
||||
{
|
||||
int i = 0, m = 0, j = 0;
|
||||
uint8_t data;
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s,width=%d, height=%d\n", __func__, width, height);
|
||||
#endif
|
||||
|
||||
if (oled_s90319_area_check(x, y, width, height)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
oled_s90319_set_col_addr[1] = x + X_OFFSET;
|
||||
oled_s90319_set_col_addr[3] = x + width - 1 + X_OFFSET;
|
||||
oled_s90319_set_row_addr[1] = y + Y_OFFSET;
|
||||
oled_s90319_set_row_addr[3] = y + height - 1 + Y_OFFSET;
|
||||
|
||||
for (i = 0; i < width * height / 8; i++)
|
||||
{
|
||||
data = *pic;
|
||||
for(m = 7; (m >= 0)&&(m <= 7); m--)
|
||||
{
|
||||
if((data >> m) & 0x01)
|
||||
{
|
||||
frame_data_buf[j] = 0x00;
|
||||
frame_data_buf[j + 1] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_data_buf[j] = 0xFF;
|
||||
frame_data_buf[j + 1] = 0xFF;
|
||||
}
|
||||
j = j + 2;
|
||||
}
|
||||
pic++;
|
||||
}
|
||||
|
||||
if (TRUE == s90319_state.disp_initialized) {
|
||||
mutex_lock(&flush_mutex);
|
||||
|
||||
s90319_spi_write_cmd(oled_set_col_cmd, sizeof(oled_set_col_cmd));
|
||||
s90319_spi_write_data(oled_s90319_set_col_addr, sizeof(oled_s90319_set_col_addr));
|
||||
|
||||
s90319_spi_write_cmd(oled_set_row_cmd, sizeof(oled_set_row_cmd));
|
||||
s90319_spi_write_data(oled_s90319_set_row_addr, sizeof(oled_s90319_set_row_addr));
|
||||
|
||||
s90319_spi_write_cmd(oled_write_data_cmd, sizeof(oled_write_data_cmd));
|
||||
s90319_spi_write_data(frame_data_buf, width * height * 2);
|
||||
|
||||
mutex_unlock(&flush_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oled_s90319_print_buffer(char* buf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_set_backlight
|
||||
Description: backlight on/off
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_set_backlight(const uint8_t on)
|
||||
{
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s, on =%u\n", __func__, on);
|
||||
#endif
|
||||
|
||||
if (0 == on) {
|
||||
gpio_direction_output(oled_s90319_boost_en, 0);
|
||||
} else {
|
||||
gpio_direction_output(oled_s90319_boost_en, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_panel_init
|
||||
Description: init panel
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void oled_s90319_panel_init(void)
|
||||
{
|
||||
/* End Reset Sequence */
|
||||
wr_comm(0x11); //Sleep out
|
||||
Delay (120); //Delay 120ms
|
||||
/* Frame Rate */
|
||||
wr_comm(0xB1);
|
||||
wr_dat(0x05);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x3A);
|
||||
wr_comm(0xB2);
|
||||
wr_dat(0x05);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x3A);
|
||||
wr_comm(0xB3);
|
||||
wr_dat(0x05);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x05);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x3A);
|
||||
/* End Frame Rate */
|
||||
wr_comm(0xB4); //Column inversion
|
||||
wr_dat(0x07);
|
||||
/* Power Sequence */
|
||||
wr_comm(0xC0);
|
||||
wr_dat(0xC8);
|
||||
wr_dat(0x08);
|
||||
wr_dat(0x84);
|
||||
wr_comm(0xC1);
|
||||
wr_dat(0XC5);
|
||||
wr_comm(0xC2);
|
||||
wr_dat(0x0A);
|
||||
wr_dat(0x00);
|
||||
wr_comm(0xC3);
|
||||
wr_dat(0x8A);
|
||||
wr_dat(0x2A);
|
||||
wr_comm(0xC4);
|
||||
wr_dat(0x8A);
|
||||
wr_dat(0xEE);
|
||||
/* End Power Sequence*/
|
||||
wr_comm(0xC5); //VCOM
|
||||
wr_dat(0x0C);
|
||||
wr_comm(0x36); //MX, MY, RGB mode
|
||||
wr_dat(0xc8);
|
||||
/* Gamma Sequence */
|
||||
wr_comm(0xE0);
|
||||
wr_dat(0x05);
|
||||
wr_dat(0x1A);
|
||||
wr_dat(0x0C);
|
||||
wr_dat(0x0E);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x34);
|
||||
wr_dat(0x2D);
|
||||
wr_dat(0x2F);
|
||||
wr_dat(0x2D);
|
||||
wr_dat(0x2A);
|
||||
wr_dat(0x2F);
|
||||
wr_dat(0x3C);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x01);
|
||||
wr_dat(0x02);
|
||||
wr_dat(0x10);
|
||||
wr_comm(0xE1);
|
||||
wr_dat(0x04);
|
||||
wr_dat(0x1B);
|
||||
wr_dat(0x0D);
|
||||
wr_dat(0x0E);
|
||||
wr_dat(0x2D);
|
||||
wr_dat(0x29);
|
||||
wr_dat(0x24);
|
||||
wr_dat(0x29);
|
||||
wr_dat(0x28);
|
||||
wr_dat(0x26);
|
||||
wr_dat(0x31);
|
||||
wr_dat(0x3B);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x03);
|
||||
wr_dat(0x12);
|
||||
/* End Gamma Sequence */
|
||||
wr_comm(0x3A); //65k mode
|
||||
wr_dat(0x05);
|
||||
|
||||
wr_comm(0x2a);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x02);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x81);
|
||||
|
||||
wr_comm(0x2b);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x03);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x82);
|
||||
|
||||
wr_comm(0x29); //Display on
|
||||
wr_comm(0x2C);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_disp_on
|
||||
Description: init oled and display on
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void s90319_disp_on(void)
|
||||
{
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if (s90319_state.disp_powered_up && !s90319_state.display_on) {
|
||||
oled_s90319_panel_init();
|
||||
s90319_state.display_on = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_disp_powerup
|
||||
Description: power on
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void s90319_disp_powerup(void)
|
||||
{
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if (!s90319_state.disp_powered_up && !s90319_state.display_on) {
|
||||
/* Reset the hardware first */
|
||||
s90319_state.disp_powered_up = TRUE;
|
||||
if (oled_s90319_pdata->oled_power_save)
|
||||
oled_s90319_pdata->oled_power_save(1);
|
||||
|
||||
gpio_direction_output(oled_s90319_cs, 0);
|
||||
/* 1 data, 0 command*/
|
||||
gpio_direction_output(oled_s90319_rsx, 0);
|
||||
mdelay(5);
|
||||
|
||||
gpio_set_value_cansleep(oled_s90319_cs, 0);
|
||||
|
||||
mdelay(3);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_panel_on
|
||||
Description: init oled and power on
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_panel_on(void)
|
||||
{
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
mutex_lock(&oled_panel_mutex);
|
||||
if (!s90319_state.disp_initialized) {
|
||||
gpio_direction_output(oled_s90319_boost_en, 0);
|
||||
s90319_disp_powerup();
|
||||
s90319_disp_on();
|
||||
|
||||
s90319_state.disp_initialized = TRUE;
|
||||
|
||||
}
|
||||
mutex_unlock(&oled_panel_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_panel_off
|
||||
Description: panel off
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_panel_off(void)
|
||||
{
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
mutex_lock(&oled_panel_mutex);
|
||||
if (s90319_state.disp_powered_up && s90319_state.display_on) {
|
||||
/* Main panel power off (Deep standby in) */
|
||||
s90319_spi_write_cmd(oled_s90319_panel_off_cmd,
|
||||
sizeof(oled_s90319_panel_off_cmd));
|
||||
mdelay(100); /* Typical 100ms */
|
||||
|
||||
if (oled_s90319_pdata->oled_power_save)
|
||||
oled_s90319_pdata->oled_power_save(0);
|
||||
|
||||
//if (oled_s90319_pdata->oled_gpio_config)
|
||||
//oled_s90319_pdata->oled_gpio_config(0);
|
||||
s90319_state.disp_powered_up = FALSE;
|
||||
s90319_state.display_on = FALSE;
|
||||
s90319_state.disp_initialized = FALSE;
|
||||
}
|
||||
mutex_unlock(&oled_panel_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id s90319__spi_table[] = {
|
||||
{ .compatible = "tplink,oled",},
|
||||
{ },
|
||||
};
|
||||
|
||||
static int s90319_init_spi(struct spi_device *spi)
|
||||
{
|
||||
/* Initialize the MSM_CAMI2C Chip */
|
||||
init_waitqueue_head(&s90319_wait_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_spi_probe
|
||||
Description: spi driver probe
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int __devinit s90319_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
tx_buf = kmalloc(BUFFER_SIZE, GFP_ATOMIC);
|
||||
if (tx_buf == NULL)
|
||||
{
|
||||
printk("kmalloc failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
s90319_sensorw = kzalloc(sizeof(struct s90319_work_t), GFP_KERNEL);
|
||||
if (!s90319_sensorw) {
|
||||
printk("kzalloc failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, s90319_sensorw);
|
||||
s90319_init_spi(spi);
|
||||
s90319_spi = spi;
|
||||
|
||||
msleep(50);
|
||||
|
||||
printk("%s successed!\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_pin_assign
|
||||
Description: assign gpio number
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void oled_s90319_pin_assign(void)
|
||||
{
|
||||
/* Setting the Default GPIO's */
|
||||
oled_s90319_cs = oled_s90319_gpio[GPIO_OLED_CS];
|
||||
oled_s90319_rsx = oled_s90319_gpio[GPIO_OLED_RSX];
|
||||
oled_s90319_boost_en = oled_s90319_gpio[GPIO_OLED_BOOST_EN];
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_probe
|
||||
Description: platform device driver probe
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int __devinit oled_s90319_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
if (!node)
|
||||
{
|
||||
dev_err(&pdev->dev, "%s: device tree information missing\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
printk("%s\n", __func__);
|
||||
|
||||
pdev->dev.platform_data = &oled_s90319_panel_data;
|
||||
oled_s90319_pdata = pdev->dev.platform_data;
|
||||
|
||||
get_gpio_by_dtsname(node, dts_gpio_name, oled_s90319_gpio, GPIO_OLED_END);
|
||||
oled_s90319_pin_assign();
|
||||
|
||||
oled_s90319_pdata->oled_gpio_config = oled_s90319_config_gpios;
|
||||
oled_s90319_pdata->oled_power_save = oled_s90319_power_save;
|
||||
oled_s90319_pdata->oled_panel_on = oled_s90319_panel_on;
|
||||
oled_s90319_pdata->oled_panel_off = oled_s90319_panel_off;
|
||||
oled_s90319_pdata->oled_fill_with_pic = oled_s90319_fill_with_pic;
|
||||
oled_s90319_pdata->oled_set_backlight = oled_s90319_set_backlight;
|
||||
oled_s90319_pdata->oled_print_buffer = oled_s90319_print_buffer;
|
||||
oled_s90319_pdata->panel_width = COLUMN_NUM;
|
||||
oled_s90319_pdata->panel_height = ROW_NUM;
|
||||
|
||||
oled_s90319_config_gpios(ENABLE);
|
||||
|
||||
mutex_init(&flush_mutex);
|
||||
mutex_init(&oled_panel_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit oled_s90319_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver s90319_spi_driver = {
|
||||
.driver = {
|
||||
.name = "oleds90319",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = s90319__spi_table,
|
||||
},
|
||||
.probe = s90319_spi_probe,
|
||||
};
|
||||
|
||||
static struct of_device_id qcom_s90319_pt_table[] = {
|
||||
{ .compatible = "qcom,oled_s90319_pt",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver this_driver = {
|
||||
.probe = oled_s90319_probe,
|
||||
.remove = __devexit_p(oled_s90319_remove),
|
||||
.driver = {
|
||||
.name = "oled_s90319_pt",
|
||||
.of_match_table = qcom_s90319_pt_table,
|
||||
},
|
||||
};
|
||||
|
||||
/************************************************************
|
||||
Function : oled_90319_panel_init
|
||||
Description: init function
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int __init oled_90319_panel_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = platform_driver_register(&this_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = spi_register_driver(&s90319_spi_driver);
|
||||
if (ret < 0 || s90319_spi == NULL)
|
||||
{
|
||||
ret = -ENOTSUPP;
|
||||
printk("SPI add driver failed.\n");
|
||||
goto fail_driver;
|
||||
}
|
||||
printk("oled_90319_panel_init success.\n");
|
||||
return ret;
|
||||
|
||||
fail_driver:
|
||||
platform_driver_unregister(&this_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_initcall(oled_90319_panel_init);
|
||||
|
||||
MODULE_AUTHOR("Xiong Sizhe");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_DESCRIPTION("OLED 90319 driver");
|
@ -1,145 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 1996-2012, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_s90319_pt.h
|
||||
Description : Driver for OLED S90319.
|
||||
Author : xiongsizhe
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2014-03-30, xiongsizhe create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __OLED_S90319_PT_H__
|
||||
#define __OLED_S90319_PT_H__
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
|
||||
#define ROW_NUM 128 /* 0~7 */
|
||||
#define PAGE_NUM 128
|
||||
#define COLUMN_NUM 128
|
||||
|
||||
#define ENABLE 1
|
||||
#define DISABLE 0
|
||||
|
||||
#define COLUMN_NUM_EXP 7 /* 2^7 = 128 */
|
||||
|
||||
/*
|
||||
* Four Formats:
|
||||
* 1. CMD_CONTROL BYTE . CMD . CMD . CMD <20><><EFBFBD><EFBFBD>
|
||||
* 2. CMD_CONTROL BYTE . CMD . CMD_CONTROL_BYTE . CMD <20><><EFBFBD><EFBFBD>
|
||||
* 3. DAT_CONTROL BYTE . DATA . DATA . DATA <20><><EFBFBD><EFBFBD>
|
||||
* 4. DAT_CONTROL BYTE . DATA . DAT_CONTROL_BYTE . DATA <20><><EFBFBD><EFBFBD>
|
||||
*/
|
||||
#define OLED_CONTROL_CMDS 0x00
|
||||
#define OLED_CONTROL_CMD_PAIRS 0x80
|
||||
#define OLED_CONTROL_DATAS 0x40
|
||||
#define OLED_CONTROL_DATA_PAIRS 0xC0
|
||||
|
||||
/* SINGLE CMDS */
|
||||
#define CMD_DUMMY_BYTE_ZERO 0x00
|
||||
#define CMD_DUMMY_BYTE_FF 0xFF
|
||||
#define CMD_GRAM_IGNORE(bit) (0xA4|(bit)) /* 0: No, 1: Yes */
|
||||
#define CMD_DISPLAY_OFF_ON(bit) (0xAE|(bit)) /* v: 0|1 */
|
||||
#define CMD_SCAN_DIRECTION_0_TO_N 0xC0
|
||||
#define CMD_SCAN_DIRECTION_N_TO_0 0xC8
|
||||
#define CMD_LOWER_COL_ADDR(addr) (0x00|(addr)) /* addr: 0~F */
|
||||
#define CMD_HIGHER_COL_ADDR(addr) (0x10|(addr)) /* addr: 0~F */
|
||||
#define CMD_SEGMENT_REMAP(dir) (0xA0|(dir)) /* dir:0 normal direction, dir:1 reverse direction */
|
||||
#define CMD_START_LINE(line) (0x40|(line)) /* line: 0 ~ 63 */
|
||||
#define CMD_NORMAL_REV_DISPLAY(bit) (0xA6|(bit)) /* bit:0 normal display, bit:1 reverse display */
|
||||
#define CMD_HORIZONTAL_SCROLL(dir) (0x26|(dir)) /* 0: L->R, 1:R->L */
|
||||
#define CMD_SCROLL_ENABLE(ena) (0x2E|(ena)) /* 0:Disable, 1:Enable */
|
||||
|
||||
/* DOUBLE CMDS */
|
||||
#define CMD_DOUBLE_CLOCK_DIVIDE_RATIO 0xD5
|
||||
#define CMD_DOUBLE_MULTIPLEX_RATIO 0xA8
|
||||
#define CMD_DOUBLE_PRECHARGE_PERIOD 0xD9
|
||||
#define CMD_DOUBLE_PADS_HW_CONFIG 0xDA /* Sequence: 0x02; Alternative: 0x12*/
|
||||
#define CMD_DOUBLE_CONTRAST_CONTROL 0x81
|
||||
#define CMD_DOUBLE_DISPLAY_OFFSET 0xD3 /* 0x00 ~ 3f */
|
||||
#define CMD_DOUBLE_VCOM_HLEVEL 0xDB /* 0x00 ~ 0xff */
|
||||
#define CMD_DOUBLE_SET_CHARGE_PUMP 0x8D /* Enable: 0x14, Disable: 0x10*/
|
||||
#define CMD_DOUBLE_MEMORY_ADDRESSING_MODE 0x20 /* 00: Horizontal 01: Vertial 10: Page 11: Invalid*/
|
||||
#define CMD_DOUBLE_FADE_BLINK_MODE 0x23 /* Fade out or blinking mode */
|
||||
|
||||
/* TRIPLE CMDS */
|
||||
#define CMD_TRIPE_COLUMN_ADDRESS 0x21 /* 0~127, 0~127 */
|
||||
#define CMD_TRIPE_PAGE_ADDRESS 0x22 /* 0~7, 0~7 */
|
||||
|
||||
#define OLED_MATREIAL_STANDARD_CONTRAST 0xAF
|
||||
#define OLED_MATREIAL_LOW_CONTRAST 0x0F
|
||||
|
||||
#define OLED_SET_COL_CMD 0x2A
|
||||
#define OLED_SET_ROW_CMD 0x2B
|
||||
#define OLED_WRITE_DATA_CMD 0x2C
|
||||
|
||||
#define X_OFFSET 2
|
||||
#define Y_OFFSET 3
|
||||
|
||||
uint8_t CMD_HORIZONTAL_SCROLL_ARRAY[] = {CMD_HORIZONTAL_SCROLL(0), CMD_HORIZONTAL_SCROLL(1)};
|
||||
uint8_t CMD_BACKLIGHT_ARRAY[] = {
|
||||
CMD_DISPLAY_OFF_ON(0), /* Backlight off */
|
||||
CMD_DISPLAY_OFF_ON(1) /* Backlight oN */
|
||||
};
|
||||
|
||||
/* set col command */
|
||||
uint8_t oled_set_col_cmd[] = {
|
||||
OLED_SET_COL_CMD,
|
||||
};
|
||||
|
||||
/* set row command */
|
||||
uint8_t oled_set_row_cmd[] = {
|
||||
OLED_SET_ROW_CMD,
|
||||
};
|
||||
|
||||
/* write data command */
|
||||
uint8_t oled_write_data_cmd[] = {
|
||||
OLED_WRITE_DATA_CMD,
|
||||
};
|
||||
|
||||
/* set backlight command */
|
||||
uint8_t oled_s90319_backlight_cmd[] = {
|
||||
CMD_DISPLAY_OFF_ON(0)
|
||||
};
|
||||
|
||||
/* panel on/off command */
|
||||
uint8_t oled_s90319_panel_off_cmd[] = {
|
||||
CMD_DISPLAY_OFF_ON(0), /* manual display on */
|
||||
CMD_DOUBLE_SET_CHARGE_PUMP, 0x10 /* set charge pump enable*/
|
||||
};
|
||||
|
||||
uint8_t oled_s90319_scroll_stop_cmd[] = {
|
||||
CMD_SCROLL_ENABLE(0)
|
||||
};
|
||||
|
||||
/* Fade out or blinking mode */
|
||||
uint8_t oled_s90319_fade_blink_cmd[] = {
|
||||
CMD_DOUBLE_FADE_BLINK_MODE,
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* fade_blink_parameter:
|
||||
* A[5:4] = 00b Disable Fade Out / Blinking Mode
|
||||
* A[5:4] = 10b Enable Fade Out mode
|
||||
* A[5:4] = 11b Enable Blinking mode
|
||||
* A[3:0] : Set time interval for each fade step, (8 * (A[3:0] + 1))frames
|
||||
*/
|
||||
struct oled_s90319_fade_blink_cmd_config_struct {
|
||||
uint8_t *fade_blink_parameter;
|
||||
};
|
||||
|
||||
uint8_t oled_s90319_set_col_addr[] = {
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
uint8_t oled_s90319_set_row_addr[] = {
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
#endif /* __OLED_S90319_PT__ */
|
||||
|
||||
|
@ -1,840 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 1996-2012, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_ssd1306_pt.c
|
||||
Description : Driver for OLED SSD1306.
|
||||
Author : linyunfeng
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.2, 2014-04-16, zhangtao modified oled_ssd1306_pt driver for dts of the new kernel.
|
||||
V0.1, 2011-08-16, linyunfeng create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/pmic.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <mach/board.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/gpiomux.h>
|
||||
|
||||
#include "oled_ssd1306_pt.h"
|
||||
#include "oled_pt.h"
|
||||
|
||||
//#define OLED_SSD1306_DEBUG
|
||||
|
||||
typedef unsigned int boolean;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
uint8_t oled_ssd1306_buf[COLUMN_NUM * PAGE_NUM] = {0};
|
||||
static uint8_t frame_data[COLUMN_NUM * PAGE_NUM + 1] ={0};
|
||||
static uint8_t oled_ssd1306_image[COLUMN_NUM * PAGE_NUM] = {0};
|
||||
|
||||
struct ssd1306_state_type{
|
||||
boolean disp_initialized;
|
||||
boolean display_on;
|
||||
boolean disp_powered_up;
|
||||
};
|
||||
|
||||
struct ssd1306_work_t {
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
struct ssd1306_i2c_reg_conf {
|
||||
unsigned short waddr;
|
||||
unsigned short wdata;
|
||||
};
|
||||
|
||||
static struct ssd1306_state_type ssd1306_state = {0};
|
||||
struct oled_panel_data oled_ssd1306_panel_data;
|
||||
static struct oled_panel_data *oled_ssd1306_pdata;
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(ssd1306_wait_queue);
|
||||
static struct ssd1306_work_t *ssd1306_sensorw;
|
||||
static struct i2c_client *ssd1306_client;
|
||||
static struct mutex flush_mutex;
|
||||
static struct mutex oled_panel_mutex;
|
||||
|
||||
/* Data/Command flag, 0: Command, 1: Data */
|
||||
static int oled_ssd1306_sa0;
|
||||
|
||||
/* Chip select, always 0 in I2C mode */
|
||||
static int oled_ssd1306_cs;
|
||||
|
||||
/* [ZhangTao start] for getting the gpio number configered in the dts file */
|
||||
enum ENUM_OLED_SSD1306_GPIO {
|
||||
GPIO_OLED_CS = 0,
|
||||
GPIO_OLED_A0,
|
||||
GPIO_OLED_RES,
|
||||
GPIO_OLED_BOOST_EN,
|
||||
|
||||
GPIO_OLED_END
|
||||
};
|
||||
|
||||
/* enum the gpio name defined in the dts config file */
|
||||
static const char *dts_gpio_name[] = {
|
||||
[GPIO_OLED_CS] = "qcom,oled-cs-gpio",
|
||||
[GPIO_OLED_A0] = "qcom,oled-a0-gpio",
|
||||
[GPIO_OLED_RES] = "qcom,oled-res-gpio",
|
||||
[GPIO_OLED_BOOST_EN] = "qcom,oled-boost-en-gpio",
|
||||
|
||||
[GPIO_OLED_END] = "",
|
||||
};
|
||||
|
||||
/* Store oled ssd1306 gpio pin number, will be filled by get_gpio_by_dtsname() */
|
||||
static int oled_ssd1306_gpio[GPIO_OLED_END] = {0};
|
||||
|
||||
/*******************************************************************************
|
||||
Function : get_gpio_by_dtsname
|
||||
Description : get gpio pin number by name defined in dts config file.
|
||||
Input : @node, the device node defined in dts which we get the gpio pin number form
|
||||
@gpio_name[], the string array which store the gpio name defined in dts file
|
||||
@gpio_num, we will store the gpio pin number getted from dts file in the int array gpio_num point to
|
||||
@len, the numbers of gpio we will get
|
||||
Output : gpio_num: the request gpios pin number which gpio_num point to
|
||||
Return : void
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static void get_gpio_by_dtsname(struct device_node *node, const char *gpio_name[], u32 *gpio_num, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; ++ i)
|
||||
{
|
||||
gpio_num[i] = of_get_named_gpio(node, gpio_name[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_config_gpios
|
||||
Description : request/free for specific gpio
|
||||
Input : @enable, 0: free gpios, 1: request gpios
|
||||
Output : request or free the specific gpio stored in oled_ssd1306_gpio[]
|
||||
Return : void
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static void oled_ssd1306_config_gpios(int enable)
|
||||
{
|
||||
int i, rc = 0;
|
||||
|
||||
for (i = 0; i < GPIO_OLED_END; ++ i)
|
||||
{
|
||||
if (enable) {
|
||||
rc = gpio_request(oled_ssd1306_gpio[i], dts_gpio_name[i]);
|
||||
if (rc)
|
||||
{
|
||||
pr_err("request gpio %s failed, rc=%d\n", dts_gpio_name[i], rc);
|
||||
gpio_free(oled_ssd1306_gpio[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
gpio_free(oled_ssd1306_gpio[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_power_save
|
||||
Description : power on/off the oled
|
||||
Input : @on, 0: power off, 1: power on
|
||||
Output :
|
||||
Return : None
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_power_save(int on)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (on) {
|
||||
gpio_direction_output(oled_ssd1306_gpio[GPIO_OLED_RES], 0);
|
||||
mdelay(1);
|
||||
|
||||
gpio_direction_output(oled_ssd1306_gpio[GPIO_OLED_BOOST_EN], 1);
|
||||
mdelay(1);
|
||||
|
||||
__gpio_set_value(oled_ssd1306_gpio[GPIO_OLED_RES], 1);
|
||||
mdelay(1);
|
||||
} else {
|
||||
gpio_direction_output(oled_ssd1306_gpio[GPIO_OLED_BOOST_EN], 0);
|
||||
mdelay(1);
|
||||
|
||||
gpio_direction_output(oled_ssd1306_gpio[GPIO_OLED_RES], 0);
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
/* [ZhangTao end]*/
|
||||
|
||||
static int ssd1306_i2c_txdata(const uint16_t saddr,
|
||||
uint8_t *txdata, const uint16_t length)
|
||||
{
|
||||
struct i2c_msg msg[] = {
|
||||
{
|
||||
.addr = saddr,
|
||||
.flags = 0,
|
||||
.len = length,
|
||||
.buf = txdata,
|
||||
},
|
||||
};
|
||||
|
||||
if (i2c_transfer(ssd1306_client->adapter, msg, 1) < 0) {
|
||||
printk("ssd1306_i2c_txdata faild 0x%x\n", saddr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_print_buffer
|
||||
Description : print the oled buffer data, hex
|
||||
Input : None
|
||||
Output : buf: Command line buffer
|
||||
Return : The number of characters will display in command
|
||||
line.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_print_buffer(char *buf)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
for (i = 0; i < PAGE_NUM; i++){
|
||||
for (j = 0; j < COLUMN_NUM; j++) {
|
||||
sprintf(buf + 3 *(i * (COLUMN_NUM + 1) + j), "%02x ",
|
||||
*(oled_ssd1306_image
|
||||
+ (i << COLUMN_NUM_EXP) + j));
|
||||
}
|
||||
sprintf(buf + (i + 1) * 3 * (COLUMN_NUM + 1) - 3, " \n" );
|
||||
}
|
||||
|
||||
return (COLUMN_NUM + 1) * 3 * PAGE_NUM;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : ssd1306_i2c_write_cmd
|
||||
Description : Send command by I2C
|
||||
Input : data: Command will be send
|
||||
len: The length of Command
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int ssd1306_i2c_write_cmd(const uint8_t *data, const uint16_t len)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
#ifdef OLED_SSD1306_DEBUG
|
||||
int i = 0;
|
||||
printk("%s, data = 0x%x, len = %d\n", __func__, *data, len);
|
||||
#endif
|
||||
|
||||
if (TRUE == ssd1306_state.disp_powered_up) {
|
||||
|
||||
*frame_data = OLED_CONTROL_CMDS;
|
||||
memcpy(frame_data + 1, data, len);
|
||||
|
||||
#ifdef OLED_SSD1306_DEBUG
|
||||
for (i = 0; i < len + 1; i++){
|
||||
printk("0x%x ", *(frame_data+i));
|
||||
}
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
rc = ssd1306_i2c_txdata(ssd1306_client->addr, frame_data, len + 1);
|
||||
|
||||
if (rc < 0) {
|
||||
printk("%s fail, data = 0x%x, len = %d\n",
|
||||
__func__, *data, len);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : ssd1306_i2c_write_data
|
||||
Description : Send data by I2C
|
||||
Input : data: Data will be send
|
||||
len: The length of data
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int ssd1306_i2c_write_data(const uint8_t *data, const uint16_t len)
|
||||
{
|
||||
int rc = -EFAULT;
|
||||
|
||||
#ifdef OLED_SSD1306_DEBUG
|
||||
printk("%s, data = 0x%x, len = %d\n", __func__, *data, len);
|
||||
#endif
|
||||
|
||||
if (TRUE == ssd1306_state.disp_powered_up) {
|
||||
|
||||
*frame_data = OLED_CONTROL_DATAS;
|
||||
memcpy(frame_data + 1, data, len);
|
||||
|
||||
rc = ssd1306_i2c_txdata((ssd1306_client->addr),
|
||||
frame_data, len + 1);
|
||||
if (rc < 0) {
|
||||
printk("%s fail, data = 0x%x, len = %d\n",
|
||||
__func__, *data, len);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void oled_ssd1306_pin_assign(void)
|
||||
{
|
||||
/* Setting the Default GPIO's */
|
||||
oled_ssd1306_sa0 = oled_ssd1306_gpio[GPIO_OLED_A0];
|
||||
oled_ssd1306_cs = oled_ssd1306_gpio[GPIO_OLED_CS];
|
||||
}
|
||||
|
||||
static int oled_ssd1306_area_check(const uint8_t x, const uint8_t y,
|
||||
const uint8_t width, const uint8_t height)
|
||||
{
|
||||
if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)
|
||||
|| (x + width > COLUMN_NUM) || (y + height > PAGE_NUM)){
|
||||
printk("%s error, row_start=%d, col_start=%d, width=%d, height=%d",
|
||||
__func__, x, y, width, height);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* [wuzhong start] */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
|
||||
static int oled_sh1106_and_ssd1306_fill_with_pic(const uint8_t *pic, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s,width=%d, height=%d\n", __func__, width, height);
|
||||
#endif
|
||||
|
||||
if (oled_ssd1306_area_check(x, y, width, height)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (TRUE == ssd1306_state.disp_initialized) {
|
||||
mutex_lock(&flush_mutex);
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
oled_sh1106_flush_cmd[1] = 0xb0 + y + i;
|
||||
oled_sh1106_flush_cmd[2] = (x + SH1106_OFFSET) & 0x0f;
|
||||
oled_sh1106_flush_cmd[3] = (((x + SH1106_OFFSET) & 0xf0) >> 4) | 0x10;
|
||||
|
||||
ssd1306_i2c_write_cmd(oled_sh1106_flush_cmd, sizeof(oled_sh1106_flush_cmd));
|
||||
ssd1306_i2c_write_data(pic + i * width, width);
|
||||
}
|
||||
|
||||
for (i = y; i < y + height; i++) {
|
||||
memcpy(oled_ssd1306_image + (i << COLUMN_NUM_EXP) + x,
|
||||
pic + width * (i - y), width);
|
||||
}
|
||||
|
||||
mutex_unlock(&flush_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_fill_with_pic
|
||||
Description : Fill and flush certain area with picture.
|
||||
Input : pic: Picture to fill
|
||||
x: Start point, x coordinate, 0 ~ COLUMN_NUM - 1
|
||||
y: Start point, y coordiante, 0 ~ PAGE_NUM - 1
|
||||
width: Area width
|
||||
height: Area height
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_fill_with_pic(const uint8_t *pic, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s,width=%d, height=%d\n", __func__, width, height);
|
||||
#endif
|
||||
|
||||
if (oled_ssd1306_area_check(x, y, width, height)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (TRUE == ssd1306_state.disp_initialized) {
|
||||
mutex_lock(&flush_mutex);
|
||||
*(oled_ssd1306_flush_cmd_config.col_addr_start) = x;
|
||||
*(oled_ssd1306_flush_cmd_config.col_addr_end) = x + width - 1;
|
||||
*(oled_ssd1306_flush_cmd_config.page_addr_start) = y;
|
||||
*(oled_ssd1306_flush_cmd_config.page_addr_end) = y + height - 1;
|
||||
|
||||
ssd1306_i2c_write_cmd(oled_ssd1306_flush_cmd, sizeof(oled_ssd1306_flush_cmd));
|
||||
|
||||
ssd1306_i2c_write_data(pic, width * height);
|
||||
|
||||
for (i = y; i < y + height; i++) {
|
||||
memcpy(oled_ssd1306_image + (i << COLUMN_NUM_EXP) + x,
|
||||
pic + width * (i - y), width);
|
||||
}
|
||||
|
||||
mutex_unlock(&flush_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
/* [wuzhong end] */
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_fill_with_value
|
||||
Description : Fill and flush certain area with value.
|
||||
Input : value: Value to fill
|
||||
x: Start point, x coordinate, 0 ~ COLUMN_NUM - 1
|
||||
y: Start point, y coordiante, 0 ~ PAGE_NUM - 1
|
||||
width: Area width
|
||||
height: Area height
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_fill_with_value(const uint8_t value, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if (oled_ssd1306_area_check(x, y, width, height)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(oled_ssd1306_buf, value, width * height);
|
||||
|
||||
/* [wuzhong start] */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
return oled_sh1106_and_ssd1306_fill_with_pic(oled_ssd1306_buf, x, y, width, height);
|
||||
#else
|
||||
return oled_ssd1306_fill_with_pic(oled_ssd1306_buf, x, y, width, height);
|
||||
#endif
|
||||
/* [wuzhong end] */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_fade_blink
|
||||
Description : Fade out or blink.
|
||||
Input : mode: 0: Disable Fade Out / Blinking Mode.
|
||||
2: Enable Fade Out mode.
|
||||
3: Enable Blinking mode.
|
||||
t_interval_scroll: Set time interval for each fade step, 0~7,
|
||||
(8 * t_interval_scroll + 1))frames
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_fade_blink(const uint8_t mode, const uint8_t t_interval_scroll)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if ((mode < 0) || (t_interval_scroll < 0) || (mode > 3)
|
||||
|| (1 == mode) || (t_interval_scroll > 15)) {
|
||||
printk("%s error, mode=%d, t_interval_scroll=%d",
|
||||
__func__, mode, t_interval_scroll);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*(oled_ssd1306_fade_blink_cmd_config.fade_blink_parameter)
|
||||
= (mode << 4) | t_interval_scroll;
|
||||
|
||||
return ssd1306_i2c_write_cmd(oled_ssd1306_fade_blink_cmd, sizeof(oled_ssd1306_fade_blink_cmd));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_scroll_stop
|
||||
Description : Stop scroll.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_scroll_stop(void)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
return ssd1306_i2c_write_cmd(oled_ssd1306_scroll_stop_cmd, sizeof(oled_ssd1306_scroll_stop_cmd));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_horizontal_scroll
|
||||
Description : Horizontal scroll.
|
||||
Input : y: Start point, y coordiante, 0 ~ PAGE_NUM - 1
|
||||
height: Scroll area height
|
||||
t_interval_scroll: 0: 5 frame, 1: 64, 2: 128, 3: 256,
|
||||
4: 3, 5: 4, 6: 25, 7: 2
|
||||
direction: 0: Left->Right, 1:Right->Left
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_horizontal_scroll(const uint8_t y, const uint8_t height,
|
||||
const uint8_t t_interval_scroll, const uint8_t direction)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if ((y < 0) || (height < 0) || (y + height > PAGE_NUM)
|
||||
|| (t_interval_scroll < 0) || (t_interval_scroll > 7)
|
||||
|| (direction < 0) || (direction > 1)) {
|
||||
printk("%s error, y=%d, height=%d, t_interval_scroll=%d, direction=%d",
|
||||
__func__, y, height, t_interval_scroll, direction);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
oled_ssd1306_scroll_stop();
|
||||
mdelay(1);
|
||||
|
||||
*(oled_ssd1306_h_scroll_cmd_config.horizontal_scroll_direction) = CMD_HORIZONTAL_SCROLL_ARRAY[direction];
|
||||
*(oled_ssd1306_h_scroll_cmd_config.page_addr_start) = y;
|
||||
*(oled_ssd1306_h_scroll_cmd_config.time_interval_scroll) = t_interval_scroll;
|
||||
*(oled_ssd1306_h_scroll_cmd_config.page_addr_end) = y + height - 1;
|
||||
|
||||
return ssd1306_i2c_write_cmd(oled_ssd1306_h_scroll_cmd, sizeof(oled_ssd1306_h_scroll_cmd));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_set_backlight
|
||||
Description : Set backlight on or off.
|
||||
Input : on: 0: off, 1: on.
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_set_backlight(const uint8_t on)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s, on =%u\n", __func__, on);
|
||||
#endif
|
||||
|
||||
if (0 == on) {
|
||||
oled_ssd1306_backlight_cmd[0] = CMD_DISPLAY_OFF_ON(0);
|
||||
} else {
|
||||
oled_ssd1306_backlight_cmd[0] = CMD_DISPLAY_OFF_ON(1);
|
||||
}
|
||||
|
||||
return ssd1306_i2c_write_cmd(oled_ssd1306_backlight_cmd, sizeof(oled_ssd1306_backlight_cmd));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : ssd1306_disp_on
|
||||
Description : initial oled.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static void ssd1306_disp_on(void)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if (ssd1306_state.disp_powered_up && !ssd1306_state.display_on) {
|
||||
ssd1306_i2c_write_cmd(oled_ssd1306_init_cmd, sizeof(oled_ssd1306_init_cmd));
|
||||
|
||||
ssd1306_state.display_on = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : ssd1306_disp_powerup
|
||||
Description : Power and initial.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static void ssd1306_disp_powerup(void)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if (!ssd1306_state.disp_powered_up && !ssd1306_state.display_on) {
|
||||
/* Reset the hardware first */
|
||||
ssd1306_state.disp_powered_up = TRUE;
|
||||
if (oled_ssd1306_pdata->oled_power_save)
|
||||
oled_ssd1306_pdata->oled_power_save(1);
|
||||
|
||||
gpio_direction_output(oled_ssd1306_cs, 0);
|
||||
gpio_direction_output(oled_ssd1306_sa0, 0);
|
||||
mdelay(5);
|
||||
|
||||
/* CS will be always 0 in I2C mode */
|
||||
__gpio_set_value(oled_ssd1306_cs, 0);
|
||||
/* SA0 is used to determine the I2C address in I2C mode */
|
||||
__gpio_set_value(oled_ssd1306_sa0, 0);
|
||||
mdelay(3);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_panel_on
|
||||
Description : Power and initial oled SSD1306.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_panel_on(void)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
mutex_lock(&oled_panel_mutex);
|
||||
if (!ssd1306_state.disp_initialized) {
|
||||
/* Configure reset GPIO that drives DAC */
|
||||
if (oled_ssd1306_pdata->oled_gpio_config)
|
||||
oled_ssd1306_pdata->oled_gpio_config(1);
|
||||
ssd1306_disp_powerup();
|
||||
ssd1306_disp_on();
|
||||
ssd1306_state.disp_initialized = TRUE;
|
||||
}
|
||||
mutex_unlock(&oled_panel_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_panel_off
|
||||
Description : Power down oled SSD1306.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_panel_off(void)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
mutex_lock(&oled_panel_mutex);
|
||||
if (ssd1306_state.disp_powered_up && ssd1306_state.display_on) {
|
||||
/* Main panel power off (Deep standby in) */
|
||||
ssd1306_i2c_write_cmd(oled_ssd1306_panel_off_cmd,
|
||||
sizeof(oled_ssd1306_panel_off_cmd));
|
||||
mdelay(100); /* Typical 100ms */
|
||||
|
||||
if (oled_ssd1306_pdata->oled_power_save)
|
||||
oled_ssd1306_pdata->oled_power_save(0);
|
||||
|
||||
if (oled_ssd1306_pdata->oled_gpio_config)
|
||||
oled_ssd1306_pdata->oled_gpio_config(0);
|
||||
ssd1306_state.disp_powered_up = FALSE;
|
||||
ssd1306_state.display_on = FALSE;
|
||||
ssd1306_state.disp_initialized = FALSE;
|
||||
}
|
||||
mutex_unlock(&oled_panel_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit oled_ssd1306_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
if (!node)
|
||||
{
|
||||
dev_err(&pdev->dev, "%s: device tree information missing\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
printk("%s\n", __func__);
|
||||
|
||||
pdev->dev.platform_data = &oled_ssd1306_panel_data;
|
||||
oled_ssd1306_pdata = pdev->dev.platform_data;
|
||||
|
||||
/* get gpios' number by name defined in the dts config file and store them in oled_ssd1306_gpio array */
|
||||
get_gpio_by_dtsname(node, dts_gpio_name, oled_ssd1306_gpio, GPIO_OLED_END);
|
||||
|
||||
oled_ssd1306_pin_assign();
|
||||
|
||||
/* [ZhangTao start] */
|
||||
oled_ssd1306_pdata->oled_gpio_config = oled_ssd1306_config_gpios;
|
||||
oled_ssd1306_pdata->oled_power_save = oled_ssd1306_power_save;
|
||||
/* [ZhangTao end] */
|
||||
|
||||
oled_ssd1306_pdata->oled_panel_on = oled_ssd1306_panel_on;
|
||||
oled_ssd1306_pdata->oled_panel_off = oled_ssd1306_panel_off;
|
||||
oled_ssd1306_pdata->oled_horizontal_scroll = oled_ssd1306_horizontal_scroll;
|
||||
oled_ssd1306_pdata->oled_scroll_stop = oled_ssd1306_scroll_stop;
|
||||
oled_ssd1306_pdata->oled_fade_blink = oled_ssd1306_fade_blink;
|
||||
|
||||
/* [wuzhong start] */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
oled_ssd1306_pdata->oled_fill_with_pic = oled_sh1106_and_ssd1306_fill_with_pic;
|
||||
#else
|
||||
oled_ssd1306_pdata->oled_fill_with_pic = oled_ssd1306_fill_with_pic;
|
||||
#endif
|
||||
/* [wuzhong end] */
|
||||
|
||||
oled_ssd1306_pdata->oled_fill_with_value = oled_ssd1306_fill_with_value;
|
||||
oled_ssd1306_pdata->oled_print_buffer = oled_ssd1306_print_buffer;
|
||||
oled_ssd1306_pdata->oled_set_backlight = oled_ssd1306_set_backlight;
|
||||
oled_ssd1306_pdata->panel_width = COLUMN_NUM;
|
||||
oled_ssd1306_pdata->panel_height = PAGE_NUM;
|
||||
|
||||
mutex_init(&flush_mutex);
|
||||
mutex_init(&oled_panel_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit oled_ssd1306_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit ssd1306_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct ssd1306_work_t *ssd1306 = i2c_get_clientdata(client);
|
||||
free_irq(client->irq, ssd1306);
|
||||
ssd1306_client = NULL;
|
||||
kfree(ssd1306);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1306_init_client(struct i2c_client *client)
|
||||
{
|
||||
/* Initialize the MSM_CAMI2C Chip */
|
||||
init_waitqueue_head(&ssd1306_wait_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1306_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int rc = 0;
|
||||
printk("%s called!\n", __func__);
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
printk("i2c_check_functionality failed\n");
|
||||
goto probe_failure;
|
||||
}
|
||||
|
||||
ssd1306_sensorw = kzalloc(sizeof(struct ssd1306_work_t), GFP_KERNEL);
|
||||
if (!ssd1306_sensorw) {
|
||||
printk("kzalloc failed.\n");
|
||||
rc = -ENOMEM;
|
||||
goto probe_failure;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, ssd1306_sensorw);
|
||||
ssd1306_init_client(client);
|
||||
ssd1306_client = client;
|
||||
|
||||
msleep(50);
|
||||
|
||||
printk("%s successed! rc = %d\n", __func__, rc);
|
||||
return 0;
|
||||
|
||||
probe_failure:
|
||||
printk("%s failed! rc = %d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct of_device_id qcom_ssd1306_i2c_table[] = {
|
||||
{ .compatible = "qcom,ssd1306",},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct i2c_device_id ssd1306_i2c_id[] = {
|
||||
{"ssd1306", 0},
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct i2c_driver ssd1306_i2c_driver = {
|
||||
.id_table = ssd1306_i2c_id,
|
||||
.probe = ssd1306_i2c_probe,
|
||||
.remove = __exit_p(ssd1306_i2c_remove),
|
||||
.driver = {
|
||||
.name = "ssd1306",
|
||||
.of_match_table = qcom_ssd1306_i2c_table,
|
||||
},
|
||||
};
|
||||
|
||||
static struct of_device_id qcom_ssd1306_pt_table[] = {
|
||||
{ .compatible = "qcom,oled_ssd1306_pt",},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver this_driver = {
|
||||
.probe = oled_ssd1306_probe,
|
||||
.remove = __devexit_p(oled_ssd1306_remove),
|
||||
.driver = {
|
||||
.name = "oled_ssd1306_pt",
|
||||
.of_match_table = qcom_ssd1306_pt_table,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init oled_ssd1306_panel_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
ret = platform_driver_register(&this_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = i2c_add_driver(&ssd1306_i2c_driver);
|
||||
|
||||
if (ret < 0 || ssd1306_client == NULL) {
|
||||
ret = -ENOTSUPP;
|
||||
printk("I2C add driver failed");
|
||||
goto fail_driver;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
fail_driver:
|
||||
platform_driver_unregister(&this_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_initcall(oled_ssd1306_panel_init);
|
||||
|
||||
MODULE_AUTHOR("Lin Yunfeng");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_DESCRIPTION("OLED SSD1306 driver");
|
||||
|
@ -1,272 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 1996-2012, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_ssd1306_pt.h
|
||||
Description : Driver for OLED SSD1306.
|
||||
Author : linyunfeng
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2011-08-16, linyunfeng create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __OLED_SSD1306_PT_H__
|
||||
#define __OLED_SSD1306_PT_H__
|
||||
|
||||
/* [wuzhong start] 2012-11-29 */
|
||||
#define __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
/* [wuzhong end] */
|
||||
|
||||
|
||||
#define PAGE_NUM 8 /* 0~7 */
|
||||
|
||||
/* [wuzhong start] 2012-11-29 */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
#define COLUMN_NUM 132
|
||||
#else
|
||||
#define COLUMN_NUM 128
|
||||
#endif
|
||||
/* [wuzhong end] */
|
||||
|
||||
#define COLUMN_NUM_EXP 7 /* 2^7 = 128 */
|
||||
|
||||
/*
|
||||
* Four Formats:
|
||||
* 1. CMD_CONTROL BYTE . CMD . CMD . CMD <20><><EFBFBD><EFBFBD>
|
||||
* 2. CMD_CONTROL BYTE . CMD . CMD_CONTROL_BYTE . CMD <20><><EFBFBD><EFBFBD>
|
||||
* 3. DAT_CONTROL BYTE . DATA . DATA . DATA <20><><EFBFBD><EFBFBD>
|
||||
* 4. DAT_CONTROL BYTE . DATA . DAT_CONTROL_BYTE . DATA <20><><EFBFBD><EFBFBD>
|
||||
*/
|
||||
#define OLED_CONTROL_CMDS 0x00
|
||||
#define OLED_CONTROL_CMD_PAIRS 0x80
|
||||
#define OLED_CONTROL_DATAS 0x40
|
||||
#define OLED_CONTROL_DATA_PAIRS 0xC0
|
||||
|
||||
/* SINGLE CMDS */
|
||||
#define CMD_DUMMY_BYTE_ZERO 0x00
|
||||
#define CMD_DUMMY_BYTE_FF 0xFF
|
||||
#define CMD_GRAM_IGNORE(bit) (0xA4|(bit)) /* 0: No, 1: Yes */
|
||||
#define CMD_DISPLAY_OFF_ON(bit) (0xAE|(bit)) /* v: 0|1 */
|
||||
#define CMD_SCAN_DIRECTION_0_TO_N 0xC0
|
||||
#define CMD_SCAN_DIRECTION_N_TO_0 0xC8
|
||||
#define CMD_LOWER_COL_ADDR(addr) (0x00|(addr)) /* addr: 0~F */
|
||||
#define CMD_HIGHER_COL_ADDR(addr) (0x10|(addr)) /* addr: 0~F */
|
||||
#define CMD_SEGMENT_REMAP(dir) (0xA0|(dir)) /* dir:0 normal direction, dir:1 reverse direction */
|
||||
#define CMD_START_LINE(line) (0x40|(line)) /* line: 0 ~ 63 */
|
||||
#define CMD_NORMAL_REV_DISPLAY(bit) (0xA6|(bit)) /* bit:0 normal display, bit:1 reverse display */
|
||||
#define CMD_HORIZONTAL_SCROLL(dir) (0x26|(dir)) /* 0: L->R, 1:R->L */
|
||||
#define CMD_SCROLL_ENABLE(ena) (0x2E|(ena)) /* 0:Disable, 1:Enable */
|
||||
|
||||
/* DOUBLE CMDS */
|
||||
#define CMD_DOUBLE_CLOCK_DIVIDE_RATIO 0xD5
|
||||
#define CMD_DOUBLE_MULTIPLEX_RATIO 0xA8
|
||||
#define CMD_DOUBLE_PRECHARGE_PERIOD 0xD9
|
||||
#define CMD_DOUBLE_PADS_HW_CONFIG 0xDA /* Sequence: 0x02; Alternative: 0x12*/
|
||||
#define CMD_DOUBLE_CONTRAST_CONTROL 0x81
|
||||
#define CMD_DOUBLE_DISPLAY_OFFSET 0xD3 /* 0x00 ~ 3f */
|
||||
#define CMD_DOUBLE_VCOM_HLEVEL 0xDB /* 0x00 ~ 0xff */
|
||||
#define CMD_DOUBLE_SET_CHARGE_PUMP 0x8D /* Enable: 0x14, Disable: 0x10*/
|
||||
#define CMD_DOUBLE_MEMORY_ADDRESSING_MODE 0x20 /* 00: Horizontal 01: Vertial 10: Page 11: Invalid*/
|
||||
#define CMD_DOUBLE_FADE_BLINK_MODE 0x23 /* Fade out or blinking mode */
|
||||
|
||||
/* TRIPLE CMDS */
|
||||
#define CMD_TRIPE_COLUMN_ADDRESS 0x21 /* 0~127, 0~127 */
|
||||
#define CMD_TRIPE_PAGE_ADDRESS 0x22 /* 0~7, 0~7 */
|
||||
|
||||
#define OLED_MATREIAL_STANDARD_CONTRAST 0xAF
|
||||
#define OLED_MATREIAL_LOW_CONTRAST 0x0F
|
||||
|
||||
uint8_t CMD_HORIZONTAL_SCROLL_ARRAY[] = {CMD_HORIZONTAL_SCROLL(0), CMD_HORIZONTAL_SCROLL(1)};
|
||||
uint8_t CMD_BACKLIGHT_ARRAY[] = {
|
||||
CMD_DISPLAY_OFF_ON(0), /* Backlight off */
|
||||
CMD_DISPLAY_OFF_ON(1) /* Backlight oN */
|
||||
};
|
||||
|
||||
|
||||
/* [wuzhong start] 2012-11-29 */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
#define CMD_DC_DC_CONTROL 0xad
|
||||
#define CMD_DC_DC_ON 0x8b /* POR */
|
||||
#define CMD_DC_DC_OFF 0x8a
|
||||
#endif
|
||||
/* [wuzhong end] */
|
||||
|
||||
|
||||
uint8_t oled_ssd1306_init_cmd[] = {
|
||||
#if 0
|
||||
CMD_DISPLAY_OFF_ON(0),
|
||||
CMD_LOWER_COL_ADDR(0),
|
||||
CMD_HIGHER_COL_ADDR(0),
|
||||
CMD_START_LINE(0),
|
||||
CMD_DOUBLE_CONTRAST_CONTROL,
|
||||
OLED_MATREIAL_STANDARD_CONTRAST,
|
||||
CMD_SEGMENT_REMAP(1), /* left-right */
|
||||
CMD_NORMAL_REV_DISPLAY(0),
|
||||
CMD_SCAN_DIRECTION_N_TO_0, /* up-down */
|
||||
CMD_DOUBLE_MULTIPLEX_RATIO, 0x3F, /* something influence */
|
||||
CMD_DOUBLE_DISPLAY_OFFSET, 0x00,
|
||||
CMD_DOUBLE_CLOCK_DIVIDE_RATIO, 0xF0, /* something influence */
|
||||
CMD_DOUBLE_PRECHARGE_PERIOD, 0x22, /* something influence */
|
||||
CMD_DOUBLE_PADS_HW_CONFIG, 0x12,
|
||||
CMD_DOUBLE_VCOM_HLEVEL, 0x40, /* something influence */
|
||||
CMD_DOUBLE_SET_CHARGE_PUMP, 0x14, /* set charge pump enable*/
|
||||
CMD_DISPLAY_OFF_ON(1) /* manual display on */
|
||||
#else /* From vendor */
|
||||
|
||||
/* [wuzhong start] */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
|
||||
CMD_DISPLAY_OFF_ON(0),
|
||||
CMD_DOUBLE_CLOCK_DIVIDE_RATIO, 0x80, /* something influence */
|
||||
CMD_DOUBLE_MULTIPLEX_RATIO, 0x3f, /* something influence */
|
||||
CMD_DOUBLE_DISPLAY_OFFSET, 0x00,
|
||||
CMD_START_LINE(0),
|
||||
//CMD_DC_DC_CONTROL, CMD_DC_DC_ON, /* same with POR in sh1106, no this command in ssd1306 */
|
||||
CMD_DOUBLE_SET_CHARGE_PUMP, 0x14, /* set charge pump enable for ssd1306, no this command in sh1106 */
|
||||
//CMD_DOUBLE_MEMORY_ADDRESSING_MODE, 0x10, /* POR in ssd1306 , no this command in sh1106 */
|
||||
CMD_SEGMENT_REMAP(1), /* left-right */
|
||||
CMD_SCAN_DIRECTION_N_TO_0,
|
||||
CMD_DOUBLE_PADS_HW_CONFIG, 0x12,
|
||||
CMD_DOUBLE_CONTRAST_CONTROL,OLED_MATREIAL_STANDARD_CONTRAST, /* 0x40 was given in sh1106 init code(0x80 is recommended in sh1106 datasheet ), while SSD1306 use 0xaf */
|
||||
CMD_DOUBLE_PRECHARGE_PERIOD, 0xF1, /* TODO: */
|
||||
CMD_DOUBLE_VCOM_HLEVEL, 0x40, /* something influence */
|
||||
CMD_GRAM_IGNORE(0),
|
||||
CMD_NORMAL_REV_DISPLAY(0),
|
||||
//CMD_DISPLAY_OFF_ON(1) /* Backlight on */
|
||||
|
||||
#else /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
|
||||
CMD_DISPLAY_OFF_ON(0),
|
||||
CMD_DOUBLE_CLOCK_DIVIDE_RATIO, 0x80, /* something influence */
|
||||
CMD_DOUBLE_MULTIPLEX_RATIO, 0x3f, /* something influence */
|
||||
CMD_DOUBLE_DISPLAY_OFFSET, 0x00,
|
||||
CMD_START_LINE(0),
|
||||
CMD_DOUBLE_SET_CHARGE_PUMP, 0x14, /* set charge pump enable*/
|
||||
CMD_DOUBLE_MEMORY_ADDRESSING_MODE, 0x00,
|
||||
CMD_SEGMENT_REMAP(1), /* left-right */
|
||||
CMD_SCAN_DIRECTION_N_TO_0,
|
||||
CMD_DOUBLE_PADS_HW_CONFIG, 0x12,
|
||||
CMD_DOUBLE_CONTRAST_CONTROL,
|
||||
OLED_MATREIAL_STANDARD_CONTRAST,
|
||||
CMD_DOUBLE_PRECHARGE_PERIOD, 0xF1, /* something influence */
|
||||
CMD_DOUBLE_VCOM_HLEVEL, 0x40, /* something influence */
|
||||
CMD_GRAM_IGNORE(0),
|
||||
CMD_NORMAL_REV_DISPLAY(0),
|
||||
//CMD_DISPLAY_OFF_ON(1) /* Backlight on */
|
||||
|
||||
#endif /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
/* [wuzhong end] */
|
||||
|
||||
#endif /* From vendor */
|
||||
};
|
||||
|
||||
uint8_t oled_ssd1306_backlight_cmd[] = {
|
||||
CMD_DISPLAY_OFF_ON(0)
|
||||
};
|
||||
|
||||
uint8_t oled_ssd1306_panel_off_cmd[] = {
|
||||
CMD_DISPLAY_OFF_ON(0), /* manual display on */
|
||||
CMD_DOUBLE_SET_CHARGE_PUMP, 0x10 /* set charge pump enable*/
|
||||
};
|
||||
|
||||
uint8_t oled_ssd1306_scroll_stop_cmd[] = {
|
||||
CMD_SCROLL_ENABLE(0)
|
||||
};
|
||||
|
||||
/* Fade out or blinking mode */
|
||||
uint8_t oled_ssd1306_fade_blink_cmd[] = {
|
||||
CMD_DOUBLE_FADE_BLINK_MODE,
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* fade_blink_parameter:
|
||||
* A[5:4] = 00b Disable Fade Out / Blinking Mode
|
||||
* A[5:4] = 10b Enable Fade Out mode
|
||||
* A[5:4] = 11b Enable Blinking mode
|
||||
* A[3:0] : Set time interval for each fade step, (8 * (A[3:0] + 1))frames
|
||||
*/
|
||||
struct oled_ssd1306_fade_blink_cmd_config_struct {
|
||||
uint8_t *fade_blink_parameter;
|
||||
};
|
||||
|
||||
static struct oled_ssd1306_fade_blink_cmd_config_struct oled_ssd1306_fade_blink_cmd_config = {
|
||||
.fade_blink_parameter = &oled_ssd1306_fade_blink_cmd[1],
|
||||
};
|
||||
|
||||
/* [wuzhong start] */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
|
||||
// sh1106 is 4 pixel widder then ssd1306
|
||||
#define SH1106_OFFSET 2
|
||||
|
||||
//struct oled_sh1106_flush_cmd {
|
||||
// uint8_t* line_start;
|
||||
// uint8_t* low_column;
|
||||
// uint8_t* high_column;
|
||||
// uint8_t* page_number;
|
||||
//};
|
||||
|
||||
// line: 0x40 as default
|
||||
// page: range 0xb0~0xb7
|
||||
// low column: range 0x00~0x0f
|
||||
// high column: range 0x10~0x1f
|
||||
uint8_t oled_sh1106_flush_cmd[] = {
|
||||
0x40, 0xb0, 0x00, 0x10
|
||||
};
|
||||
|
||||
#else /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
|
||||
/* Flush the screen */
|
||||
uint8_t oled_ssd1306_flush_cmd[] = {
|
||||
CMD_DOUBLE_MEMORY_ADDRESSING_MODE, 0,
|
||||
CMD_TRIPE_COLUMN_ADDRESS, 0, (COLUMN_NUM - 1),
|
||||
CMD_TRIPE_PAGE_ADDRESS, 0, (PAGE_NUM - 1)
|
||||
};
|
||||
|
||||
struct oled_ssd1306_flush_cmd_config_struct {
|
||||
uint8_t *col_addr_start;
|
||||
uint8_t *col_addr_end;
|
||||
uint8_t *page_addr_start;
|
||||
uint8_t *page_addr_end;
|
||||
};
|
||||
|
||||
static struct oled_ssd1306_flush_cmd_config_struct oled_ssd1306_flush_cmd_config = {
|
||||
.col_addr_start = &oled_ssd1306_flush_cmd[3], /* Start column address, 0~127 */
|
||||
.col_addr_end = &oled_ssd1306_flush_cmd[4], /* End column address, 0~127 */
|
||||
.page_addr_start = &oled_ssd1306_flush_cmd[6], /* Start page address, 0~7 */
|
||||
.page_addr_end = &oled_ssd1306_flush_cmd[7], /* End page address, 0~7 */
|
||||
};
|
||||
|
||||
#endif /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
/* [wuzhong end] */
|
||||
|
||||
/* Horizontal scroll */
|
||||
uint8_t oled_ssd1306_h_scroll_cmd[] = {
|
||||
CMD_HORIZONTAL_SCROLL(0), /* Direction, 0: L->R, 1:R->L */
|
||||
CMD_DUMMY_BYTE_ZERO,
|
||||
0, /* Start page address */
|
||||
0, /* Frames interval between each scroll,
|
||||
* 0: 5 frame, 1: 64, 2: 128, 3: 256,
|
||||
* 4: 3, 5: 4, 6: 25, 7: 2 */
|
||||
(PAGE_NUM - 1), /* End page address */
|
||||
CMD_DUMMY_BYTE_ZERO,
|
||||
CMD_DUMMY_BYTE_FF,
|
||||
CMD_SCROLL_ENABLE(1)
|
||||
};
|
||||
|
||||
struct oled_ssd1306_h_scroll_cmd_config_struct {
|
||||
uint8_t *horizontal_scroll_direction;
|
||||
uint8_t *page_addr_start;
|
||||
uint8_t *time_interval_scroll;
|
||||
uint8_t *page_addr_end;
|
||||
};
|
||||
|
||||
static struct oled_ssd1306_h_scroll_cmd_config_struct oled_ssd1306_h_scroll_cmd_config = {
|
||||
.horizontal_scroll_direction = &oled_ssd1306_h_scroll_cmd[0],
|
||||
.page_addr_start = &oled_ssd1306_h_scroll_cmd[2],
|
||||
.time_interval_scroll = &oled_ssd1306_h_scroll_cmd[3],
|
||||
.page_addr_end = &oled_ssd1306_h_scroll_cmd[4],
|
||||
};
|
||||
|
||||
#endif /* __OLED_SSD1306_PT__ */
|
||||
|
@ -25,7 +25,6 @@
|
||||
#include <mach/msm_smsm.h>
|
||||
#include <mach/socinfo.h>
|
||||
#include <mach/ipa.h>
|
||||
#include <mach/msm_iomap.h>
|
||||
#include "ipa_i.h"
|
||||
|
||||
#define A2_NUM_PIPES 6
|
||||
@ -115,38 +114,6 @@ static struct a2_mux_context_type *a2_mux_ctx;
|
||||
|
||||
static void handle_a2_mux_cmd(struct sk_buff *rx_skb);
|
||||
|
||||
/* [chenchao start] Do not excute BUG() in recovery */
|
||||
static bool is_recovery_mode(void)
|
||||
{
|
||||
unsigned int value = 0;
|
||||
static bool is_recovery = 0;
|
||||
static bool checked = 0;
|
||||
void* restart_reason = 0;
|
||||
|
||||
if (checked == 1)
|
||||
{
|
||||
return is_recovery;
|
||||
}
|
||||
|
||||
checked = 1;
|
||||
restart_reason = MSM_IMEM_BASE + 0x65C;
|
||||
value = __raw_readl(restart_reason);
|
||||
/* [chenchao] Fix always go into recovery */
|
||||
__raw_writel(0, restart_reason);
|
||||
pr_info("CCCC restart_reason %x\r\n", value);
|
||||
is_recovery = (value == 0x77665502);
|
||||
return is_recovery;
|
||||
}
|
||||
|
||||
static void bug_not_recovery(void)
|
||||
{
|
||||
if (!is_recovery_mode())
|
||||
{
|
||||
BUG();
|
||||
}
|
||||
}
|
||||
/* [chenchao end] */
|
||||
|
||||
static bool bam_ch_is_open(int index)
|
||||
{
|
||||
return a2_mux_ctx->bam_ch[index].status ==
|
||||
@ -340,7 +307,7 @@ static void ul_wakeup(void)
|
||||
return;
|
||||
bail:
|
||||
mutex_unlock(&a2_mux_ctx->wakeup_lock);
|
||||
bug_not_recovery();
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -374,7 +341,7 @@ static void a2_mux_write_done(bool is_tethered, struct sk_buff *skb)
|
||||
}
|
||||
spin_unlock_irqrestore(&a2_mux_ctx->bam_tx_pool_spinlock,
|
||||
flags);
|
||||
bug_not_recovery();
|
||||
BUG();
|
||||
}
|
||||
list_del(&info->list_node);
|
||||
spin_unlock_irqrestore(&a2_mux_ctx->bam_tx_pool_spinlock, flags);
|
||||
@ -486,7 +453,7 @@ static void kickoff_ul_wakeup_func(struct work_struct *work)
|
||||
if (unlikely(ret == 0)) {
|
||||
IPAERR("%s timeout waiting for A2 PROD granted\n",
|
||||
__func__);
|
||||
bug_not_recovery();
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -512,7 +479,7 @@ static void kickoff_ul_request_resource_func(struct work_struct *work)
|
||||
if (unlikely(ret == 0)) {
|
||||
IPAERR("%s timeout waiting for A2 PROD granted\n",
|
||||
__func__);
|
||||
bug_not_recovery();
|
||||
BUG();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -1683,9 +1650,6 @@ int a2_mux_init(void)
|
||||
*/
|
||||
a2_mux_ctx->bam_ch[A2_MUX_TETHERED_0].status |= BAM_CH_REMOTE_OPEN;
|
||||
|
||||
/* [chenchao] init restart reason */
|
||||
is_recovery_mode();
|
||||
|
||||
rc = 0;
|
||||
goto bail;
|
||||
|
||||
|
@ -23,7 +23,6 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/log2.h>
|
||||
#include <linux/qpnp/power-on.h>
|
||||
#include <linux/wakelock.h>
|
||||
|
||||
/* Common PNP defines */
|
||||
#define QPNP_PON_REVISION2(base) (base + 0x01)
|
||||
@ -110,7 +109,6 @@ struct qpnp_pon {
|
||||
};
|
||||
|
||||
static struct qpnp_pon *sys_reset_dev;
|
||||
struct wake_lock powerkey_wlock;
|
||||
|
||||
static u32 s1_delay[PON_S1_COUNT_MAX + 1] = {
|
||||
0 , 32, 56, 80, 138, 184, 272, 408, 608, 904, 1352, 2048,
|
||||
@ -334,7 +332,6 @@ qpnp_pon_input_dispatch(struct qpnp_pon *pon, u32 pon_type)
|
||||
input_report_key(pon->pon_input, cfg->key_code,
|
||||
(pon_rt_sts & pon_rt_bit));
|
||||
input_sync(pon->pon_input);
|
||||
wake_lock_timeout(&powerkey_wlock, 5 * HZ);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -642,20 +639,6 @@ qpnp_pon_request_irqs(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* [chenchao start] Fix send up event when resume from sleep */
|
||||
static int no_suppend_resume(struct device *dev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct dev_pm_domain input_device_pm_domain = {
|
||||
.ops = {
|
||||
.suspend = no_suppend_resume,
|
||||
.resume = no_suppend_resume,
|
||||
}
|
||||
};
|
||||
/* [chenchao end] */
|
||||
|
||||
static int __devinit
|
||||
qpnp_pon_config_input(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
|
||||
{
|
||||
@ -668,8 +651,6 @@ qpnp_pon_config_input(struct qpnp_pon *pon, struct qpnp_pon_config *cfg)
|
||||
}
|
||||
pon->pon_input->name = "qpnp_pon";
|
||||
pon->pon_input->phys = "qpnp_pon/input0";
|
||||
/* [chenchao] Fix send up event when resume from sleep */
|
||||
pon->pon_input->dev.pm_domain = &input_device_pm_domain;
|
||||
}
|
||||
|
||||
input_set_capability(pon->pon_input, EV_KEY, cfg->key_code);
|
||||
@ -1018,14 +999,12 @@ static struct spmi_driver qpnp_pon_driver = {
|
||||
|
||||
static int __init qpnp_pon_init(void)
|
||||
{
|
||||
wake_lock_init(&powerkey_wlock, WAKE_LOCK_SUSPEND, "powerkey");
|
||||
return spmi_driver_register(&qpnp_pon_driver);
|
||||
}
|
||||
module_init(qpnp_pon_init);
|
||||
|
||||
static void __exit qpnp_pon_exit(void)
|
||||
{
|
||||
wake_lock_destroy(&powerkey_wlock);
|
||||
return spmi_driver_unregister(&qpnp_pon_driver);
|
||||
}
|
||||
module_exit(qpnp_pon_exit);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2011-2013, 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
|
||||
@ -144,7 +144,6 @@ struct usb_bam_ipa_handshake_info {
|
||||
bool in_lpm;
|
||||
bool pending_lpm;
|
||||
u8 prod_pipes_enabled_per_bam;
|
||||
bool pending_bam_reset;
|
||||
|
||||
int (*wake_cb)(void *);
|
||||
void *wake_param;
|
||||
@ -1540,65 +1539,9 @@ void msm_bam_hsic_notify_on_resume(void)
|
||||
spin_unlock(&usb_bam_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
* msm_bam_hsic_host_pipe_empty - Check all HSIC host BAM pipe state
|
||||
*
|
||||
* return true if all BAM pipe used for HSIC Host mode is empty.
|
||||
*/
|
||||
bool msm_bam_hsic_host_pipe_empty(void)
|
||||
{
|
||||
struct usb_bam_pipe_connect *pipe_connect;
|
||||
struct sps_pipe *pipe = NULL;
|
||||
enum usb_bam bam = HSIC_BAM;
|
||||
int i, ret;
|
||||
u32 status;
|
||||
|
||||
pr_debug("%s: enter\n", __func__);
|
||||
|
||||
for (i = 0; i < ctx.max_connections; i++) {
|
||||
pipe_connect = &usb_bam_connections[i];
|
||||
if (pipe_connect->bam_type == bam &&
|
||||
pipe_connect->enabled) {
|
||||
|
||||
pipe = ctx.usb_bam_sps.sps_pipes[i];
|
||||
ret = sps_is_pipe_empty(pipe, &status);
|
||||
if (ret) {
|
||||
pr_err("%s(): sps_is_pipe_empty() failed\n",
|
||||
__func__);
|
||||
pr_err("%s(): SRC index(%d), DEST index(%d):\n",
|
||||
__func__,
|
||||
pipe_connect->src_pipe_index,
|
||||
pipe_connect->dst_pipe_index);
|
||||
WARN_ON(1);
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
pr_err("%s(): pipe is not empty.\n", __func__);
|
||||
pr_err("%s(): SRC index(%d), DEST index(%d):\n",
|
||||
__func__,
|
||||
pipe_connect->src_pipe_index,
|
||||
pipe_connect->dst_pipe_index);
|
||||
return false;
|
||||
} else {
|
||||
pr_debug("%s(): SRC index(%d), DEST index(%d):\n",
|
||||
__func__,
|
||||
pipe_connect->src_pipe_index,
|
||||
pipe_connect->dst_pipe_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!pipe)
|
||||
pr_err("%s: Bam %s has no connected pipes\n", __func__,
|
||||
bam_enable_strings[bam]);
|
||||
|
||||
return true;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_bam_hsic_host_pipe_empty);
|
||||
|
||||
bool msm_bam_hsic_lpm_ok(void)
|
||||
{
|
||||
int i, ret;
|
||||
int i;
|
||||
struct usb_bam_pipe_connect *pipe_iter;
|
||||
|
||||
if (hsic_host_info.dev) {
|
||||
@ -1621,17 +1564,6 @@ bool msm_bam_hsic_lpm_ok(void)
|
||||
IPA_RM_RESOURCE_RELEASED &&
|
||||
ctx.is_bam_inactivity[HSIC_BAM] && info[HSIC_BAM].in_lpm) {
|
||||
|
||||
|
||||
pr_err("%s(): checking HSIC Host pipe state\n",
|
||||
__func__);
|
||||
ret = msm_bam_hsic_host_pipe_empty();
|
||||
if (!ret) {
|
||||
pr_err("%s(): HSIC HOST Pipe is not empty.\n",
|
||||
__func__);
|
||||
spin_unlock(&usb_bam_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* HSIC host will go now to lpm */
|
||||
pr_debug("%s: vote for suspend hsic %x\n",
|
||||
__func__, (int)hsic_host_info.dev);
|
||||
@ -1743,18 +1675,13 @@ int usb_bam_connect_ipa(struct usb_bam_connect_ipa_params *ipa_params)
|
||||
(ctx.pipes_enabled_per_bam[cur_bam] == 0)) {
|
||||
spin_unlock(&usb_bam_lock);
|
||||
|
||||
if (cur_bam == HSUSB_BAM) {
|
||||
if (cur_bam == HSUSB_BAM)
|
||||
msm_hw_bam_disable(1);
|
||||
|
||||
if (sps_device_reset(ctx.h_bam[cur_bam]))
|
||||
pr_err("%s: BAM reset failed\n", __func__);
|
||||
sps_device_reset(ctx.h_bam[cur_bam]);
|
||||
|
||||
if (cur_bam == HSUSB_BAM)
|
||||
msm_hw_bam_disable(0);
|
||||
} else if (info[HSIC_BAM].pending_bam_reset &&
|
||||
cur_bam == HSIC_BAM) {
|
||||
if (sps_device_reset(ctx.h_bam[cur_bam]))
|
||||
pr_err("%s: BAM reset failed\n", __func__);
|
||||
}
|
||||
|
||||
/* On re-connect assume out from lpm for HSIC BAM */
|
||||
if (cur_bam == HSIC_BAM && hsic_host_info.dev &&
|
||||
@ -3009,28 +2936,6 @@ void msm_bam_notify_lpm_resume()
|
||||
}
|
||||
EXPORT_SYMBOL(msm_bam_notify_lpm_resume);
|
||||
|
||||
|
||||
void msm_bam_hsic_reset(void)
|
||||
{
|
||||
struct msm_usb_bam_platform_data *pdata;
|
||||
|
||||
if (!ctx.usb_bam_pdev) {
|
||||
pr_debug("%s: setting pending_bam_reset\n", __func__);
|
||||
info[HSIC_BAM].pending_bam_reset = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
pdata = ctx.usb_bam_pdev->dev.platform_data;
|
||||
|
||||
WARN_ON(ctx.pipes_enabled_per_bam[HSIC_BAM] != 0);
|
||||
if (pdata->reset_on_connect[HSIC_BAM] == true) {
|
||||
pr_debug("%s: reset the HSIC BAM", __func__);
|
||||
if (sps_device_reset(ctx.h_bam[HSIC_BAM]))
|
||||
pr_err("%s: HSIC BAM reset failed\n", __func__);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL(msm_bam_hsic_reset);
|
||||
|
||||
static int usb_bam_remove(struct platform_device *pdev)
|
||||
{
|
||||
destroy_workqueue(ctx.usb_bam_wq);
|
||||
|
13
kernel/drivers/power/Kconfig
Executable file → Normal file
13
kernel/drivers/power/Kconfig
Executable file → Normal file
@ -350,12 +350,6 @@ config SMB137C_CHARGER
|
||||
charging, setting the input current limit, and enabling USB OTG mode
|
||||
in order to supply 5 V on the VBUS line.
|
||||
|
||||
config MP2617_CHARGER
|
||||
tristate "Summit MP2617 Battery Charger"
|
||||
help
|
||||
The MP2617 charger chip is a charging solution. This driver supports
|
||||
enabling and disabling charging, setting the input current limit.
|
||||
|
||||
config SMB349_CHARGER
|
||||
tristate "smb349 charger"
|
||||
depends on I2C
|
||||
@ -501,11 +495,4 @@ config QPNP_BMS
|
||||
Say Y here to enable support for QPNP chip bms device.
|
||||
It registers a fuelgauge bms power supply to report
|
||||
State of Charge.
|
||||
|
||||
config POWER_BANK_DETECT_SUPPORT
|
||||
tristate "Support Power Bank Detection"
|
||||
default n
|
||||
help
|
||||
If support power bank detection, we can get the current
|
||||
output.
|
||||
endif # POWER_SUPPLY
|
||||
|
1
kernel/drivers/power/Makefile
Executable file → Normal file
1
kernel/drivers/power/Makefile
Executable file → Normal file
@ -56,7 +56,6 @@ obj-$(CONFIG_BATTERY_BQ27541) += bq27541_fuelgauger.o
|
||||
obj-$(CONFIG_BATTERY_BQ28400) += bq28400_battery.o
|
||||
obj-$(CONFIG_SMB137B_CHARGER) += smb137b.o
|
||||
obj-$(CONFIG_SMB137C_CHARGER) += smb137c-charger.o
|
||||
obj-$(CONFIG_MP2617_CHARGER) += mp2617-charger.o
|
||||
obj-$(CONFIG_PM8XXX_CCADC) += pm8xxx-ccadc.o
|
||||
obj-$(CONFIG_PM8921_BMS) += pm8921-bms.o
|
||||
obj-$(CONFIG_QPNP_BMS) += qpnp-bms.o
|
||||
|
@ -1,879 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 2014, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : mp2617-charger.c
|
||||
Description : Driver for charge ic mp2617.
|
||||
Author : linyunfeng
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.2, 2014-04-29, linyunfeng complete the driver of mp2617.
|
||||
V0.1, 2014-03-29, linyunfeng create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/power_supply.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/qpnp/qpnp-adc.h>
|
||||
|
||||
#ifdef MP2617_DEBUG
|
||||
#undef dev_dbg
|
||||
#define dev_dbg(dev, format, arg...) dev_printk(KERN_INFO, dev, format, ##arg)
|
||||
#endif
|
||||
|
||||
/* USB, set 500mA limit */
|
||||
#define USB_INPUT_CURRENT_LIMIT_UA 500000
|
||||
|
||||
/* Charger, set 1000mA limit */
|
||||
#define CHARGER_INPUT_CURRENT_LIMIT_UA 1000000
|
||||
|
||||
static u32 supported_input_current[] = {
|
||||
USB_INPUT_CURRENT_LIMIT_UA,
|
||||
CHARGER_INPUT_CURRENT_LIMIT_UA,
|
||||
};
|
||||
|
||||
#define DEFAULT_INPUT_CURRENT_LIMIT_UA CHARGER_INPUT_CURRENT_LIMIT_UA
|
||||
|
||||
/* Default resistor used for detection */
|
||||
#define DEFAULT_CHARGE_DET_RESISTOR 100
|
||||
|
||||
/* Default battery resistor */
|
||||
#define DEFAULT_BATTERY_RESISTOR 120
|
||||
|
||||
/* Correspondence table of voltage and temperature */
|
||||
static const int adc_map_temp[][2] =
|
||||
{
|
||||
{1800, -100},
|
||||
{1577, -20},
|
||||
{1524, -15},
|
||||
{1463, -10},
|
||||
{1396, -5},
|
||||
{1322, 0},
|
||||
{1243, 5},
|
||||
{1159, 10},
|
||||
{1073, 15},
|
||||
{986, 20},
|
||||
{900, 25},
|
||||
{816, 30},
|
||||
{736, 35},
|
||||
{660, 40},
|
||||
{590, 45},
|
||||
{526, 50},
|
||||
{468, 55},
|
||||
{416, 60},
|
||||
{369, 65},
|
||||
{327, 70},
|
||||
{0, 1000}
|
||||
};
|
||||
|
||||
struct mp2617_chip {
|
||||
struct platform_device *client;
|
||||
struct power_supply psy;
|
||||
struct power_supply *usb_psy;
|
||||
struct mutex lock;
|
||||
int input_current_limit_ua;
|
||||
#ifdef CONFIG_POWER_BANK_DETECT_SUPPORT
|
||||
int charging_det_resistor;
|
||||
int battery_resistor;
|
||||
u32 boost_en_gpio;
|
||||
#endif
|
||||
int battery_health;
|
||||
int charging_vbat_div;
|
||||
bool battery_present;
|
||||
bool charging_enabled;
|
||||
bool charging_allowed;
|
||||
u32 charging_en_gpio;
|
||||
u32 charging_ok_gpio;
|
||||
u32 charging_m0_gpio;
|
||||
u32 charging_m1_gpio;
|
||||
};
|
||||
|
||||
static enum power_supply_property mp2617_power_properties[] = {
|
||||
POWER_SUPPLY_PROP_HEALTH,
|
||||
POWER_SUPPLY_PROP_PRESENT,
|
||||
POWER_SUPPLY_PROP_VOLTAGE_NOW,
|
||||
POWER_SUPPLY_PROP_TEMP,
|
||||
POWER_SUPPLY_PROP_CHARGING_ENABLED,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX,
|
||||
POWER_SUPPLY_PROP_TECHNOLOGY,
|
||||
POWER_SUPPLY_PROP_MODEL_NAME,
|
||||
POWER_SUPPLY_PROP_MANUFACTURER,
|
||||
POWER_SUPPLY_PROP_CHG_OK,
|
||||
#ifdef CONFIG_POWER_BANK_DETECT_SUPPORT
|
||||
POWER_SUPPLY_PROP_VOLTAGE_DROP,
|
||||
#endif
|
||||
};
|
||||
|
||||
#ifdef CONFIG_POWER_BANK_DETECT_SUPPORT
|
||||
/*******************************************************************************
|
||||
Function : mp2617_enable_boost
|
||||
Description : Enable or disable the boost chip
|
||||
Input : chip: chip data
|
||||
enable: true: enable, false: disable
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_enable_boost(struct mp2617_chip *chip, bool enable)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (true == enable) {
|
||||
rc = gpio_direction_output(chip->boost_en_gpio, 1);
|
||||
} else {
|
||||
rc = gpio_direction_output(chip->boost_en_gpio, 0);
|
||||
}
|
||||
|
||||
if (rc < 0) {
|
||||
dev_err(&chip->client->dev, "%s: enable or disable boost error\n",
|
||||
__func__);
|
||||
}
|
||||
|
||||
dev_dbg(&chip->client->dev, "%s, enable=%d, rc = %d\n", __func__, enable, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_get_property_voltage_drop
|
||||
Description : Get the voltage drop by power supply
|
||||
Input : chip: chip data
|
||||
Output : None
|
||||
Return : voltage or error code
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_get_property_voltage_drop(struct mp2617_chip *chip)
|
||||
{
|
||||
int rc = 0;
|
||||
int vol_drop = 0;
|
||||
|
||||
struct qpnp_vadc_result results;
|
||||
|
||||
rc = qpnp_vadc_read(P_MUX1_1_1, &results);
|
||||
if (rc) {
|
||||
pr_err("Unable to read vbat rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
vol_drop = ((int)(results.physical)/chip->charging_det_resistor)
|
||||
* chip->battery_resistor / 1000;
|
||||
return vol_drop;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_enable_charging
|
||||
Description : Enable charging
|
||||
Input : chip: chip data
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_enable_charging(struct mp2617_chip *chip)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if ((!chip->charging_enabled) && (true == chip->charging_allowed)
|
||||
&& (true == chip->battery_present)) {
|
||||
rc = gpio_direction_output(chip->charging_en_gpio, 1);
|
||||
|
||||
if (!rc) {
|
||||
chip->charging_enabled = true;
|
||||
#ifdef CONFIG_POWER_BANK_DETECT_SUPPORT
|
||||
mp2617_enable_boost(chip, false);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(&chip->client->dev, "%s, rc = %d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_disable_charging
|
||||
Description : Disable charging
|
||||
Input : chip: chip data
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_disable_charging(struct mp2617_chip *chip)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (chip->charging_enabled) {
|
||||
rc = gpio_direction_output(chip->charging_en_gpio, 0);
|
||||
|
||||
if (!rc) {
|
||||
chip->charging_enabled = false;
|
||||
#ifdef CONFIG_POWER_BANK_DETECT_SUPPORT
|
||||
mp2617_enable_boost(chip, true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(&chip->client->dev, "%s, rc = %d\n", __func__, rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_get_property_chg_ok_level
|
||||
Description : Get the level of chg_ok gpio
|
||||
Input : chip: chip data
|
||||
Output : None
|
||||
Return : Gpio level
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_get_property_chg_ok_level(struct mp2617_chip *chip)
|
||||
{
|
||||
int rc = 0;
|
||||
int result = 0;
|
||||
|
||||
rc = gpio_direction_input(chip->charging_ok_gpio);
|
||||
if (!rc) {
|
||||
result = gpio_get_value_cansleep(chip->charging_ok_gpio);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_set_input_current_limit
|
||||
Description : Set the limit of input current
|
||||
Input : chip: chip data
|
||||
current_limit_ua: the limit of input current
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_set_input_current_limit(struct mp2617_chip *chip,
|
||||
int current_limit_ua)
|
||||
{
|
||||
int rc = 0;
|
||||
int i = 0;
|
||||
|
||||
for (i = ARRAY_SIZE(supported_input_current) - 1; i >= 0; i--) {
|
||||
if (current_limit_ua >= supported_input_current[i]) {
|
||||
current_limit_ua = supported_input_current[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (current_limit_ua) {
|
||||
case USB_INPUT_CURRENT_LIMIT_UA:
|
||||
gpio_direction_output(chip->charging_m0_gpio, 0);
|
||||
gpio_direction_output(chip->charging_m1_gpio, 0);
|
||||
break;
|
||||
|
||||
case CHARGER_INPUT_CURRENT_LIMIT_UA:
|
||||
gpio_direction_output(chip->charging_m0_gpio, 1);
|
||||
gpio_direction_output(chip->charging_m1_gpio, 0);
|
||||
break;
|
||||
|
||||
default:
|
||||
dev_err(&chip->client->dev, "%s: Unsupported current_limit_ua=%d uA\n",
|
||||
__func__, current_limit_ua);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (!rc) {
|
||||
chip->input_current_limit_ua = current_limit_ua;
|
||||
|
||||
dev_dbg(&chip->client->dev, "%s: current_limit_ua=%d uA\n", __func__,
|
||||
current_limit_ua);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_set_property_battery_present
|
||||
Description : Set the present state of battery
|
||||
Input : chip: chip data
|
||||
batt_present_state: the present state of battery
|
||||
Output : None
|
||||
Return : 0: OK
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_set_property_battery_present(struct mp2617_chip *chip,
|
||||
bool batt_present_state)
|
||||
{
|
||||
chip->battery_present = batt_present_state;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_get_property_battery_present
|
||||
Description : Get the present state of battery
|
||||
Input : chip: chip data
|
||||
Output : None
|
||||
Return : The present state of battery
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_get_property_battery_present(struct mp2617_chip *chip)
|
||||
{
|
||||
return chip->battery_present;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_set_property_battery_health
|
||||
Description : Set the health state of battery
|
||||
Input : chip: chip data
|
||||
health_state: the health state of battery
|
||||
Output : None
|
||||
Return : 0: OK
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_set_property_battery_health(struct mp2617_chip *chip,
|
||||
int health_state)
|
||||
{
|
||||
if ((health_state > POWER_SUPPLY_HEALTH_UNKNOWN) &&
|
||||
(health_state <= POWER_SUPPLY_HEALTH_DEAD_OVERCOLD))
|
||||
{
|
||||
chip->battery_health = health_state;
|
||||
|
||||
if (POWER_SUPPLY_HEALTH_GOOD == health_state)
|
||||
{
|
||||
chip->charging_allowed = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
chip->charging_allowed = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chip->battery_health = POWER_SUPPLY_HEALTH_UNKNOWN;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_get_property_battery_health
|
||||
Description : Get the health state of battery
|
||||
Input : chip: chip data
|
||||
Output : None
|
||||
Return : The health state of battery
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_get_property_battery_health(struct mp2617_chip *chip)
|
||||
{
|
||||
return chip->battery_health;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_get_property_battery_voltage
|
||||
Description : Get the voltage of battery
|
||||
Input : chip: chip data
|
||||
Output : None
|
||||
Return : The voltage of battery
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_get_property_battery_voltage(struct mp2617_chip *chip)
|
||||
{
|
||||
int rc = 0;
|
||||
struct qpnp_vadc_result results;
|
||||
|
||||
rc = qpnp_vadc_read(P_MUX2_1_1, &results);
|
||||
if (rc) {
|
||||
pr_err("Unable to read vbat rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return ((int)(results.physical * chip->charging_vbat_div)/1000);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : em_batt_map_linear
|
||||
Description : Get the result form table by linear map
|
||||
Input : table: linear map table
|
||||
table_size: table size
|
||||
in_num: number input
|
||||
Output : out_num: result with linear map
|
||||
Return : 0: OK, Others: Error
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int em_batt_map_linear(const int (*table)[2], const u32 table_size,
|
||||
int in_num, int *out_num)
|
||||
{
|
||||
u32 i = 0;
|
||||
|
||||
if ((NULL == table) || (NULL == out_num)) {
|
||||
pr_err("Invalid input or output parameter\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
while (i < table_size) {
|
||||
if (table[i][0] < in_num) {
|
||||
break;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (i == 0) {
|
||||
*out_num = table[0][1];
|
||||
} else if (i == table_size) {
|
||||
*out_num = table[table_size-1][1];
|
||||
} else {
|
||||
/* result is between search_index and search_index-1, interpolate linearly */
|
||||
*out_num = (((table[i][1] - table[i-1][1]) * (in_num - table[i-1][0]))
|
||||
/ (table[i][0] - table[i-1][0])) + table[i-1][1];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_get_property_battery_id_therm
|
||||
Description : Get the temperature of battery
|
||||
Input : chip: chip data
|
||||
Output : None
|
||||
Return : The temperature of battery or error code
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int mp2617_get_property_battery_id_therm(struct mp2617_chip *chip)
|
||||
{
|
||||
int rc = 0;
|
||||
int temp_value = 0;
|
||||
struct qpnp_vadc_result results;
|
||||
|
||||
rc = qpnp_vadc_read(LR_MUX2_BAT_ID, &results);
|
||||
if (rc) {
|
||||
pr_err("Unable to read battery temperature, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
temp_value = ((int)results.physical) / 1000; /* convert to mV */
|
||||
|
||||
rc = em_batt_map_linear(adc_map_temp,
|
||||
sizeof(adc_map_temp)/sizeof(adc_map_temp[0]),
|
||||
temp_value, &temp_value);
|
||||
if(rc) {
|
||||
pr_err("Unable to get battery temperature, rc=%d\n", rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return temp_value;
|
||||
}
|
||||
|
||||
static int mp2617_property_is_writeable(struct power_supply *psy,
|
||||
enum power_supply_property psp)
|
||||
{
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
return 1;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mp2617_power_set_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
const union power_supply_propval *val)
|
||||
{
|
||||
struct mp2617_chip *chip = container_of(psy, struct mp2617_chip, psy);
|
||||
|
||||
mutex_lock(&chip->lock);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
|
||||
if (val->intval) {
|
||||
mp2617_enable_charging(chip);
|
||||
} else {
|
||||
mp2617_disable_charging(chip);
|
||||
}
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
mp2617_set_input_current_limit(chip, val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
mp2617_set_property_battery_health(chip, val->intval);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
mp2617_set_property_battery_present(chip, (bool)val->intval);
|
||||
break;
|
||||
default:
|
||||
mutex_unlock(&chip->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&chip->lock);
|
||||
|
||||
power_supply_changed(&chip->psy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mp2617_power_get_property(struct power_supply *psy,
|
||||
enum power_supply_property psp,
|
||||
union power_supply_propval *val)
|
||||
{
|
||||
struct mp2617_chip *chip = container_of(psy, struct mp2617_chip, psy);
|
||||
|
||||
mutex_lock(&chip->lock);
|
||||
|
||||
switch (psp) {
|
||||
case POWER_SUPPLY_PROP_HEALTH:
|
||||
val->intval = mp2617_get_property_battery_health(chip);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_PRESENT:
|
||||
val->intval = mp2617_get_property_battery_present(chip);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
|
||||
val->intval = mp2617_get_property_battery_voltage(chip);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TEMP:
|
||||
val->intval = mp2617_get_property_battery_id_therm(chip);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHG_OK:
|
||||
val->intval = mp2617_get_property_chg_ok_level(chip);
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CHARGING_ENABLED:
|
||||
val->intval = chip->charging_enabled;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_CURRENT_MAX:
|
||||
val->intval = chip->input_current_limit_ua;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_TECHNOLOGY:
|
||||
val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_MODEL_NAME:
|
||||
val->strval = "MP2617";
|
||||
break;
|
||||
case POWER_SUPPLY_PROP_MANUFACTURER:
|
||||
val->strval = "MPS";
|
||||
break;
|
||||
#ifdef CONFIG_POWER_BANK_DETECT_SUPPORT
|
||||
case POWER_SUPPLY_PROP_VOLTAGE_DROP:
|
||||
val->intval = mp2617_get_property_voltage_drop(chip);
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
mutex_unlock(&chip->lock);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_unlock(&chip->lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_external_power_changed
|
||||
Description : Set charging parameters because power supply device changes
|
||||
Input : psy: power supply psy
|
||||
Output : None
|
||||
Return : None
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static void mp2617_external_power_changed(struct power_supply *psy)
|
||||
{
|
||||
struct mp2617_chip *chip = container_of(psy, struct mp2617_chip, psy);
|
||||
union power_supply_propval prop = {0,};
|
||||
int scope = POWER_SUPPLY_SCOPE_DEVICE;
|
||||
int current_limit = 0;
|
||||
int online = 0;
|
||||
int rc;
|
||||
|
||||
mutex_lock(&chip->lock);
|
||||
dev_dbg(&chip->client->dev, "%s: start\n", __func__);
|
||||
|
||||
rc = chip->usb_psy->get_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_ONLINE, &prop);
|
||||
if (rc) {
|
||||
dev_err(&chip->client->dev,
|
||||
"%s: could not read USB online property, rc=%d\n", __func__, rc);
|
||||
} else {
|
||||
online = prop.intval;
|
||||
}
|
||||
|
||||
rc = chip->usb_psy->get_property(chip->usb_psy, POWER_SUPPLY_PROP_SCOPE,
|
||||
&prop);
|
||||
if (rc) {
|
||||
dev_err(&chip->client->dev,
|
||||
"%s: could not read USB scope property, rc=%d\n", __func__, rc);
|
||||
} else {
|
||||
scope = prop.intval;
|
||||
}
|
||||
|
||||
rc = chip->usb_psy->get_property(chip->usb_psy,
|
||||
POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
|
||||
if (rc) {
|
||||
dev_err(&chip->client->dev,
|
||||
"%s: could not read USB current max property, rc=%d\n", __func__, rc);
|
||||
} else {
|
||||
current_limit = prop.intval;
|
||||
}
|
||||
|
||||
dev_dbg(&chip->client->dev,
|
||||
"%s: online=%d, scope=%d, current_limit=%d, present=%d\n",
|
||||
__func__, online, scope, current_limit, chip->battery_present);
|
||||
|
||||
if (scope == POWER_SUPPLY_SCOPE_DEVICE) {
|
||||
if (online && chip->battery_present) {
|
||||
mp2617_set_input_current_limit(chip, current_limit);
|
||||
|
||||
if (current_limit != 0 &&
|
||||
POWER_SUPPLY_HEALTH_GOOD == chip->battery_health) {
|
||||
mp2617_enable_charging(chip);
|
||||
}
|
||||
} else {
|
||||
mp2617_disable_charging(chip);
|
||||
}
|
||||
}
|
||||
|
||||
dev_dbg(&chip->client->dev, "%s: end\n", __func__);
|
||||
mutex_unlock(&chip->lock);
|
||||
|
||||
power_supply_changed(&chip->psy);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_apply_dt_configs
|
||||
Description : Set default config
|
||||
Input : chip: chip data
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int __devinit mp2617_apply_dt_configs(struct mp2617_chip *chip)
|
||||
{
|
||||
struct device *dev = &chip->client->dev;
|
||||
struct device_node *node = chip->client->dev.of_node;
|
||||
int current_ma = 0;
|
||||
int value = 0;
|
||||
int rc = 0;
|
||||
|
||||
chip->input_current_limit_ua = DEFAULT_INPUT_CURRENT_LIMIT_UA;
|
||||
#ifdef CONFIG_POWER_BANK_DETECT_SUPPORT
|
||||
chip->charging_det_resistor = DEFAULT_CHARGE_DET_RESISTOR;
|
||||
chip->battery_resistor = DEFAULT_BATTERY_RESISTOR;
|
||||
mp2617_enable_boost(chip, true);
|
||||
#endif
|
||||
chip->battery_health = POWER_SUPPLY_HEALTH_GOOD;
|
||||
chip->battery_present = true;
|
||||
chip->charging_allowed = true;
|
||||
|
||||
mp2617_disable_charging(chip);
|
||||
|
||||
/*
|
||||
* All device tree parameters are optional so it is ok if read calls
|
||||
* fail.
|
||||
*/
|
||||
rc = of_property_read_u32(node, "mps,chg-current-ma", ¤t_ma);
|
||||
if (rc == 0) {
|
||||
chip->input_current_limit_ua = current_ma * 1000;
|
||||
} else {
|
||||
dev_err(dev, "%s: Failed to get charge current node, rc=%d\n",
|
||||
__func__, rc);
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node, "mps,chg-vbat-div", &value);
|
||||
if (rc == 0) {
|
||||
chip->charging_vbat_div = value;
|
||||
} else {
|
||||
chip->charging_vbat_div = 1;
|
||||
|
||||
dev_err(dev, "%s: Failed to get battery voltage division, rc=%d\n",
|
||||
__func__, rc);
|
||||
}
|
||||
|
||||
rc = mp2617_set_input_current_limit(chip, chip->input_current_limit_ua);
|
||||
if (rc) {
|
||||
dev_err(dev, "%s: Failed to set charge current, rc=%d\n",
|
||||
__func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_POWER_BANK_DETECT_SUPPORT
|
||||
rc = of_property_read_u32(node, "mps,chg-det-resistor", &value);
|
||||
if (rc == 0) {
|
||||
chip->charging_det_resistor = value;
|
||||
} else {
|
||||
dev_err(dev, "%s: Failed to get detection resistor, rc=%d\n",
|
||||
__func__, rc);
|
||||
}
|
||||
|
||||
rc = of_property_read_u32(node, "mps,chg-batt-resistor", &value);
|
||||
if (rc == 0) {
|
||||
chip->battery_resistor = value;
|
||||
} else {
|
||||
dev_err(dev, "%s: Failed to get battery resistor, rc=%d\n",
|
||||
__func__, rc);
|
||||
}
|
||||
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : mp2617_gpio_configs
|
||||
Description : Set gpio default config
|
||||
Input : chip: chip data
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int __devinit mp2617_gpio_configs(struct mp2617_chip *chip)
|
||||
{
|
||||
struct device_node *node = chip->client->dev.of_node;
|
||||
int rc = 0;
|
||||
|
||||
chip->charging_en_gpio = of_get_named_gpio(node, "mps,chg-en-gpio", 0);
|
||||
rc = gpio_request(chip->charging_en_gpio, "mps,chg-en-gpio");
|
||||
if (rc) {
|
||||
pr_err("request charge en gpio failed, rc=%d\n", rc);
|
||||
gpio_free(chip->charging_en_gpio);
|
||||
return rc;
|
||||
}
|
||||
|
||||
chip->charging_ok_gpio = of_get_named_gpio(node, "mps,chg-ok-gpio", 0);
|
||||
rc = gpio_request(chip->charging_ok_gpio, "mps,chg-ok-gpio");
|
||||
if (rc) {
|
||||
pr_err("request charge ok gpio failed, rc=%d\n",rc);
|
||||
gpio_free(chip->charging_ok_gpio);
|
||||
return rc;
|
||||
}
|
||||
|
||||
chip->charging_m0_gpio = of_get_named_gpio(node, "mps,chg-m0-gpio", 0);
|
||||
rc = gpio_request(chip->charging_m0_gpio, "mps,chg-m0-gpio");
|
||||
if (rc) {
|
||||
pr_err("request charge m0 gpio failed, rc=%d\n",
|
||||
rc);
|
||||
gpio_free(chip->charging_m0_gpio);
|
||||
return rc;
|
||||
}
|
||||
|
||||
chip->charging_m1_gpio = of_get_named_gpio(node, "mps,chg-m1-gpio", 0);
|
||||
rc = gpio_request(chip->charging_m1_gpio, "mps,chg-m1-gpio");
|
||||
if (rc) {
|
||||
pr_err("request charge m1 gpio failed, rc=%d\n",
|
||||
rc);
|
||||
gpio_free(chip->charging_m1_gpio);
|
||||
return rc;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_POWER_BANK_DETECT_SUPPORT
|
||||
chip->boost_en_gpio = of_get_named_gpio(node, "mps,chg-boost-en-gpio", 0);
|
||||
rc = gpio_request(chip->boost_en_gpio, "mps,chg-boost-en-gpio");
|
||||
if (rc) {
|
||||
pr_err("request charge m1 gpio failed, rc=%d\n",
|
||||
rc);
|
||||
gpio_free(chip->boost_en_gpio);
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __devinit mp2617_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct mp2617_chip *chip;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
int rc = 0;
|
||||
|
||||
if (!node) {
|
||||
dev_err(dev, "%s: device tree information missing\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
chip = devm_kzalloc(dev, sizeof(*chip), GFP_KERNEL);
|
||||
if (!chip) {
|
||||
dev_err(dev, "%s: devm_kzalloc failed\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
mutex_init(&chip->lock);
|
||||
chip->client = pdev;
|
||||
|
||||
chip->usb_psy = power_supply_get_by_name("usb");
|
||||
if (!chip->usb_psy) {
|
||||
dev_dbg(dev, "%s: USB supply not found; deferring charger probe\n",
|
||||
__func__);
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
|
||||
rc = mp2617_gpio_configs(chip);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
rc = mp2617_apply_dt_configs(chip);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
chip->psy.name = "battery";
|
||||
chip->psy.type = POWER_SUPPLY_TYPE_BATTERY;
|
||||
chip->psy.properties = mp2617_power_properties;
|
||||
chip->psy.num_properties = ARRAY_SIZE(mp2617_power_properties);
|
||||
chip->psy.get_property = mp2617_power_get_property;
|
||||
chip->psy.set_property = mp2617_power_set_property;
|
||||
chip->psy.property_is_writeable = mp2617_property_is_writeable;
|
||||
chip->psy.external_power_changed = mp2617_external_power_changed;
|
||||
|
||||
rc = power_supply_register(dev, &chip->psy);
|
||||
if (rc < 0) {
|
||||
dev_err(dev, "%s: power_supply_register failed, rc=%d\n",
|
||||
__func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
mp2617_external_power_changed(&chip->psy);
|
||||
|
||||
dev_info(dev, "%s: MP2617 charger probed successfully\n", __func__);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __devexit mp2617_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct of_device_id mp2617_match[] = {
|
||||
{ .compatible = "mps,mp2617", },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver mp2617_driver = {
|
||||
.driver = {
|
||||
.name = "mp2617",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = mp2617_match,
|
||||
},
|
||||
.probe = mp2617_probe,
|
||||
.remove = __devexit_p(mp2617_remove),
|
||||
};
|
||||
|
||||
static int __init mp2617_init(void)
|
||||
{
|
||||
return platform_driver_register(&mp2617_driver);
|
||||
}
|
||||
module_init(mp2617_init);
|
||||
|
||||
static void __exit mp2617_exit(void)
|
||||
{
|
||||
return platform_driver_unregister(&mp2617_driver);
|
||||
}
|
||||
module_exit(mp2617_exit);
|
||||
|
||||
MODULE_DESCRIPTION("MP2617 Charger");
|
||||
MODULE_LICENSE("GPL v2");
|
||||
MODULE_ALIAS("mp2617");
|
6
kernel/drivers/power/power_supply_sysfs.c
Executable file → Normal file
6
kernel/drivers/power/power_supply_sysfs.c
Executable file → Normal file
@ -55,7 +55,7 @@ static ssize_t power_supply_show_property(struct device *dev,
|
||||
};
|
||||
static char *health_text[] = {
|
||||
"Unknown", "Good", "Overheat", "Dead", "Over voltage",
|
||||
"Unspecified failure", "Cold","Dead over cold",
|
||||
"Unspecified failure", "Cold",
|
||||
};
|
||||
static char *technology_text[] = {
|
||||
"Unknown", "NiMH", "Li-ion", "Li-poly", "LiFe", "NiCd",
|
||||
@ -177,10 +177,6 @@ static struct device_attribute power_supply_attrs[] = {
|
||||
POWER_SUPPLY_ATTR(scope),
|
||||
POWER_SUPPLY_ATTR(system_temp_level),
|
||||
POWER_SUPPLY_ATTR(resistance),
|
||||
POWER_SUPPLY_ATTR(chg_ok), /* [linyunfeng] Charge ok gpio level */
|
||||
#ifdef CONFIG_POWER_BANK_DETECT_SUPPORT
|
||||
POWER_SUPPLY_ATTR(voltage_drop),
|
||||
#endif
|
||||
/* Properties of type `const char *' */
|
||||
POWER_SUPPLY_ATTR(model_name),
|
||||
POWER_SUPPLY_ATTR(manufacturer),
|
||||
|
@ -728,11 +728,9 @@ static struct logger_log VAR = { \
|
||||
.size = SIZE, \
|
||||
};
|
||||
|
||||
//DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 64*1024)
|
||||
DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 256*1024)
|
||||
DEFINE_LOGGER_DEVICE(log_main, LOGGER_LOG_MAIN, 64*1024)
|
||||
DEFINE_LOGGER_DEVICE(log_events, LOGGER_LOG_EVENTS, 64*1024)
|
||||
//DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 64*1024)
|
||||
DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 256*1024)
|
||||
DEFINE_LOGGER_DEVICE(log_radio, LOGGER_LOG_RADIO, 64*1024)
|
||||
DEFINE_LOGGER_DEVICE(log_system, LOGGER_LOG_SYSTEM, 64*1024)
|
||||
|
||||
static struct logger_log *get_log_from_minor(int minor)
|
||||
|
@ -1218,21 +1218,7 @@ static int usb_suspend_both(struct usb_device *udev, pm_message_t msg)
|
||||
} else {
|
||||
udev->can_submit = 0;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
struct urb *urb;
|
||||
struct usb_host_endpoint *ep = udev->ep_out[i];
|
||||
bool hbm_enabled_ep = false;
|
||||
if (ep && !list_empty(&ep->urb_list)) {
|
||||
urb = list_first_entry(&ep->urb_list,
|
||||
struct urb, urb_list);
|
||||
if (urb->priv_data)
|
||||
hbm_enabled_ep = true;
|
||||
}
|
||||
if (hbm_enabled_ep) {
|
||||
pr_info("Not flushing HBM-EP on susp:%p:%p\n",
|
||||
urb, urb->priv_data);
|
||||
} else {
|
||||
usb_hcd_flush_endpoint(udev, udev->ep_out[i]);
|
||||
}
|
||||
usb_hcd_flush_endpoint(udev, udev->ep_out[i]);
|
||||
usb_hcd_flush_endpoint(udev, udev->ep_in[i]);
|
||||
}
|
||||
}
|
||||
|
@ -1756,7 +1756,7 @@ static int mass_storage_function_init(struct android_usb_function *f,
|
||||
config->fsg.nluns = 2;
|
||||
config->fsg.luns[1].cdrom = 1;
|
||||
config->fsg.luns[1].ro = 1;
|
||||
config->fsg.luns[1].removable = 1;
|
||||
config->fsg.luns[1].removable = 0;
|
||||
name[1] = "lun0";
|
||||
}
|
||||
|
||||
@ -1825,29 +1825,8 @@ static DEVICE_ATTR(inquiry_string, S_IRUGO | S_IWUSR,
|
||||
mass_storage_inquiry_show,
|
||||
mass_storage_inquiry_store);
|
||||
|
||||
|
||||
//[yanghuaying start] export whether mass storage is connect to pc
|
||||
static int in_suspend_mode = 0;
|
||||
static ssize_t mass_storage_connect2pc_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct android_usb_function *f = dev_get_drvdata(dev);
|
||||
struct mass_storage_function_config *config = f->config;
|
||||
int available = 0;
|
||||
if(config->common->new_fsg != NULL && !in_suspend_mode)
|
||||
available = 1;
|
||||
pr_info("in_suspend_mode = %d\n", in_suspend_mode);
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", available);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(connect2pc, 0444,
|
||||
mass_storage_connect2pc_show,
|
||||
NULL);
|
||||
//[yanghuaying end]
|
||||
|
||||
static struct device_attribute *mass_storage_function_attributes[] = {
|
||||
&dev_attr_inquiry_string,
|
||||
&dev_attr_connect2pc,
|
||||
NULL
|
||||
};
|
||||
|
||||
@ -2693,11 +2672,6 @@ android_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *c)
|
||||
if (value < 0)
|
||||
value = composite_setup(gadget, c);
|
||||
|
||||
/*[yanghuaying] when device discnnect from pc, it will first receive a
|
||||
suspend event,but when reconnect to pc,may not receive corresponding
|
||||
resume event(may just receive a connect event), now reinit in_suspend_mode*/
|
||||
in_suspend_mode = 0;
|
||||
|
||||
spin_lock_irqsave(&cdev->lock, flags);
|
||||
if (!dev->connected) {
|
||||
dev->connected = 1;
|
||||
@ -2736,11 +2710,6 @@ static void android_suspend(struct usb_gadget *gadget)
|
||||
struct android_dev *dev = cdev_to_android_dev(cdev);
|
||||
unsigned long flags;
|
||||
|
||||
/*[yanghuaying] when device connect to pc by hub, afetr hub disconnect
|
||||
from pc,device will go into suspend mode(a suspend event,not a
|
||||
disconnect event),mass storage function is unusable*/
|
||||
in_suspend_mode = 1;
|
||||
|
||||
spin_lock_irqsave(&cdev->lock, flags);
|
||||
dev->suspended = 1;
|
||||
schedule_work(&dev->work);
|
||||
@ -2755,10 +2724,6 @@ static void android_resume(struct usb_gadget *gadget)
|
||||
struct android_dev *dev = cdev_to_android_dev(cdev);
|
||||
unsigned long flags;
|
||||
|
||||
/*[yanghuaying] when device connect to pc by hub, afetr hub reconnect to pc
|
||||
device will leave suspend mode,mass storage function is usable again*/
|
||||
in_suspend_mode = 0;
|
||||
|
||||
spin_lock_irqsave(&cdev->lock, flags);
|
||||
dev->suspended = 0;
|
||||
schedule_work(&dev->work);
|
||||
|
@ -3004,11 +3004,6 @@ buffhds_first_it:
|
||||
i = 0x0399;
|
||||
}
|
||||
}
|
||||
/* [ouyangyi] Change mass storage device's name to "TP-LINK MMC Storage USB Device" */
|
||||
#if 1
|
||||
snprintf(common->inquiry_string, sizeof common->inquiry_string,
|
||||
"TP-LINK MMC Storage");
|
||||
#else
|
||||
snprintf(common->inquiry_string, sizeof common->inquiry_string,
|
||||
"%-8s%-16s%04x", cfg->vendor_name ?: "Linux",
|
||||
/* Assume product name dependent on the first LUN */
|
||||
@ -3016,7 +3011,6 @@ buffhds_first_it:
|
||||
? "File-Stor Gadget"
|
||||
: "File-CD Gadget"),
|
||||
i);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some peripheral controllers are known not to be able to
|
||||
|
@ -663,9 +663,7 @@ static void ecm_qc_suspend(struct usb_function *f)
|
||||
{
|
||||
struct f_ecm_qc *ecm = func_to_ecm_qc(f);
|
||||
|
||||
//[yanghuaying] fix reconnect fail after ecm_qc disconnect from MacOS Virtual machine
|
||||
//if (f->config->cdev->gadget->remote_wakeup) {
|
||||
if (1) {
|
||||
if (f->config->cdev->gadget->remote_wakeup) {
|
||||
bam_data_suspend(ECM_QC_ACTIVE_PORT);
|
||||
} else {
|
||||
/*
|
||||
@ -680,7 +678,6 @@ static void ecm_qc_suspend(struct usb_function *f)
|
||||
ecm_qc_bam_disconnect(ecm);
|
||||
}
|
||||
|
||||
pr_info("%s remote_wakeup=%d\n",__func__,f->config->cdev->gadget->remote_wakeup);
|
||||
pr_debug("ecm suspended\n");
|
||||
}
|
||||
|
||||
@ -688,9 +685,7 @@ static void ecm_qc_resume(struct usb_function *f)
|
||||
{
|
||||
struct f_ecm_qc *ecm = func_to_ecm_qc(f);
|
||||
|
||||
//[yanghuaying] fix reconnect fail after ecm_qc disconnect from MacOS Virtual machine
|
||||
//if (f->config->cdev->gadget->remote_wakeup) {
|
||||
if (1) {
|
||||
if (f->config->cdev->gadget->remote_wakeup) {
|
||||
bam_data_resume(ECM_QC_ACTIVE_PORT);
|
||||
} else {
|
||||
/* Restore endpoint descriptors info. */
|
||||
@ -698,7 +693,7 @@ static void ecm_qc_resume(struct usb_function *f)
|
||||
ecm->bam_port.out->desc = ecm->out_ep_desc_backup;
|
||||
ecm_qc_bam_connect(ecm);
|
||||
}
|
||||
pr_info("%s remote_wakeup=%d\n",__func__,f->config->cdev->gadget->remote_wakeup);
|
||||
|
||||
pr_debug("ecm resumed\n");
|
||||
}
|
||||
|
||||
|
@ -126,12 +126,7 @@ static unsigned int bitrate(struct usb_gadget *g)
|
||||
if (gadget_is_superspeed(g) && g->speed == USB_SPEED_SUPER)
|
||||
return 13 * 1024 * 8 * 1000 * 8;
|
||||
else if (gadget_is_dualspeed(g) && g->speed == USB_SPEED_HIGH)
|
||||
/* [ouyangyi] change rndis' peak rate from 425.9Mbps to 150Mbps */
|
||||
#if 1
|
||||
return 150 * 1000 * 1000;
|
||||
#else
|
||||
return 13 * 512 * 8 * 1000 * 8;
|
||||
#endif
|
||||
else
|
||||
return 19 * 64 * 1 * 1000 * 8;
|
||||
}
|
||||
|
@ -118,8 +118,8 @@ static int grmnet_ctrl_qti_send_cpkt_tomodem(u8 portno,
|
||||
|
||||
/* drop cpkt if port is not open */
|
||||
if (!port->is_open) {
|
||||
// pr_err("rmnet file handler %p(index=%d) is not open",
|
||||
// port, port->index);
|
||||
pr_err("rmnet file handler %p(index=%d) is not open",
|
||||
port, port->index);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
free_rmnet_ctrl_pkt(cpkt);
|
||||
return 0;
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* ehci-msm-hsic.c - HSUSB Host Controller Driver Implementation
|
||||
*
|
||||
* Copyright (c) 2011-2014, The Linux Foundation. All rights reserved.
|
||||
* Copyright (c) 2011-2013, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* Partly derived from ehci-fsl.c and ehci-hcd.c
|
||||
* Copyright (c) 2000-2004 by David Brownell
|
||||
@ -53,7 +53,7 @@
|
||||
|
||||
#define MSM_USB_BASE (hcd->regs)
|
||||
#define USB_REG_START_OFFSET 0x90
|
||||
#define USB_REG_END_OFFSET 0x324
|
||||
#define USB_REG_END_OFFSET 0x250
|
||||
|
||||
static struct workqueue_struct *ehci_wq;
|
||||
struct ehci_timer {
|
||||
@ -127,9 +127,6 @@ module_param(ep_addr_rxdbg_mask, uint, S_IRUGO | S_IWUSR);
|
||||
static unsigned int ep_addr_txdbg_mask = 9;
|
||||
module_param(ep_addr_txdbg_mask, uint, S_IRUGO | S_IWUSR);
|
||||
|
||||
static unsigned int dbg_qh_addr;
|
||||
module_param(dbg_qh_addr, uint, S_IRUGO | S_IWUSR);
|
||||
|
||||
/* Maximum debug message length */
|
||||
#define DBG_MSG_LEN 128UL
|
||||
|
||||
@ -321,44 +318,6 @@ static inline struct usb_hcd *hsic_to_hcd(struct msm_hsic_hcd *mehci)
|
||||
return container_of((void *) mehci, struct usb_hcd, hcd_priv);
|
||||
}
|
||||
|
||||
static void dbg_msm_qh(struct ehci_hcd *ehci, struct ehci_qh *qh)
|
||||
{
|
||||
struct ehci_qh_hw *hw = qh->hw;
|
||||
|
||||
pr_info("EP:%x qh %p info %x %x c_qtd-%08x\n",
|
||||
(hw->hw_info1 & 0xF00) >> 8, qh, hw->hw_info1,
|
||||
hw->hw_info2, hw->hw_current);
|
||||
pr_info("overlay n%08x %08x t-%08x nak-%x c_err %x\n",
|
||||
hw->hw_qtd_next, hw->hw_alt_next,
|
||||
hw->hw_token,
|
||||
(hw->hw_alt_next & 0xE)>>1, (hw->hw_token & 0xC00) >> 10);
|
||||
}
|
||||
|
||||
static void dump_msm_qhs(struct usb_hcd *hcd)
|
||||
{
|
||||
struct ehci_hcd *ehci = hcd_to_ehci(hcd);
|
||||
struct ehci_qh *qh, *qh_next;
|
||||
unsigned long flags;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 5; i++) {
|
||||
pr_info("Dump QHs, iteration:%d\n", i);
|
||||
spin_lock_irqsave(&ehci->lock, flags);
|
||||
qh_next = ehci->async->qh_next.qh;
|
||||
while (qh_next) {
|
||||
qh = qh_next;
|
||||
qh_next = qh->qh_next.qh;
|
||||
|
||||
if (!dbg_qh_addr ||
|
||||
((struct ehci_qh *)dbg_qh_addr) == qh)
|
||||
dbg_msm_qh(ehci, qh);
|
||||
}
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
usleep_range(5000, 10000);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void dump_hsic_regs(struct usb_hcd *hcd)
|
||||
{
|
||||
int i;
|
||||
@ -979,14 +938,6 @@ static int msm_hsic_resume(struct msm_hsic_hcd *mehci)
|
||||
|
||||
skip_phy_resume:
|
||||
|
||||
/* Check HSIC host pipe state before resume. Pipe should be empty. */
|
||||
if (pdata->consider_ipa_handshake) {
|
||||
if (!msm_bam_hsic_host_pipe_empty()) {
|
||||
dev_err(mehci->dev, "Data pending without resumed.\n");
|
||||
BUG_ON(1);
|
||||
}
|
||||
}
|
||||
|
||||
usb_hcd_resume_root_hub(hcd);
|
||||
|
||||
atomic_set(&mehci->in_lpm, 0);
|
||||
@ -1840,27 +1791,6 @@ const struct file_operations ehci_hsic_msm_dbg_ctrl_fops = {
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static int ehci_hsic_msm_qh_show(struct seq_file *s, void *unused)
|
||||
{
|
||||
struct msm_hsic_hcd *mehci = s->private;
|
||||
|
||||
dump_msm_qhs(hsic_to_hcd(mehci));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ehci_hsic_msm_qh_open(struct inode *inode, struct file *f)
|
||||
{
|
||||
return single_open(f, ehci_hsic_msm_qh_show, inode->i_private);
|
||||
}
|
||||
|
||||
const struct file_operations ehci_hsic_msm_qh_fops = {
|
||||
.open = ehci_hsic_msm_qh_open,
|
||||
.read = seq_read,
|
||||
.llseek = seq_lseek,
|
||||
.release = single_release,
|
||||
};
|
||||
|
||||
static struct dentry *ehci_hsic_msm_dbg_root;
|
||||
static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
|
||||
{
|
||||
@ -1911,16 +1841,6 @@ static int ehci_hsic_msm_debugfs_init(struct msm_hsic_hcd *mehci)
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
ehci_hsic_msm_dentry = debugfs_create_file("show_hsic_qh",
|
||||
S_IRUGO,
|
||||
ehci_hsic_msm_dbg_root, mehci,
|
||||
&ehci_hsic_msm_qh_fops);
|
||||
|
||||
if (!ehci_hsic_msm_dentry) {
|
||||
debugfs_remove_recursive(ehci_hsic_msm_dbg_root);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2232,10 +2152,8 @@ static int __devinit ehci_hsic_msm_probe(struct platform_device *pdev)
|
||||
if (pdev->dev.parent)
|
||||
pm_runtime_put_sync(pdev->dev.parent);
|
||||
|
||||
if (mehci->enable_hbm) {
|
||||
if (mehci->enable_hbm)
|
||||
hbm_init(hcd, pdata->disable_park_mode);
|
||||
msm_bam_hsic_reset();
|
||||
}
|
||||
|
||||
if (pdata && pdata->consider_ipa_handshake)
|
||||
msm_bam_set_hsic_host_dev(&pdev->dev);
|
||||
|
@ -1,4 +1,4 @@
|
||||
/* Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.
|
||||
/* Copyright (c) 2013, 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
|
||||
@ -165,16 +165,6 @@ int hbm_pipe_init(u32 QH_addr, u32 pipe_num, bool is_consumer)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Disable HBM pipe */
|
||||
hbm_msm_write_reg_field(hbm_ctx->base, USB_OTG_HS_HBM_PIPE_EN,
|
||||
1 << pipe_num, 0);
|
||||
|
||||
/* Reset HBM SideBand */
|
||||
hbm_msm_write_reg_field(hbm_ctx->base, USB_OTG_HS_HBM_SB_SW_RST,
|
||||
1 << pipe_num, 1);
|
||||
hbm_msm_write_reg_field(hbm_ctx->base, USB_OTG_HS_HBM_SB_SW_RST,
|
||||
1 << pipe_num, 0);
|
||||
|
||||
/* map QH(ep) <> pipe */
|
||||
hbm_msm_write_reg(hbm_ctx->base,
|
||||
USB_OTG_HS_HBM_QH_MAP_PIPE(pipe_num), QH_addr);
|
||||
@ -230,11 +220,10 @@ static int hbm_submit_async(struct ehci_hcd *ehci, struct urb *urb,
|
||||
{
|
||||
int epnum;
|
||||
unsigned long flags;
|
||||
struct ehci_qh *qh = (struct ehci_qh *) urb->ep->hcpriv;
|
||||
struct ehci_qh *qh = NULL;
|
||||
int rc;
|
||||
struct usb_host_bam_type *bam =
|
||||
(struct usb_host_bam_type *)urb->priv_data;
|
||||
int cmd;
|
||||
|
||||
epnum = urb->ep->desc.bEndpointAddress;
|
||||
|
||||
@ -247,9 +236,6 @@ static int hbm_submit_async(struct ehci_hcd *ehci, struct urb *urb,
|
||||
if (unlikely(rc))
|
||||
goto done;
|
||||
|
||||
if (qh != NULL)
|
||||
pr_debug("%s: QH NOT NULL (%p)\n", __func__, qh);
|
||||
|
||||
qh = qh_append_tds(ehci, urb, qtd_list, epnum, &urb->ep->hcpriv);
|
||||
if (unlikely(qh == NULL)) {
|
||||
usb_hcd_unlink_urb_from_ep(ehci_to_hcd(ehci), urb);
|
||||
@ -257,38 +243,15 @@ static int hbm_submit_async(struct ehci_hcd *ehci, struct urb *urb,
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Stop Async Scheduler */
|
||||
cmd = ehci_readl(ehci, &ehci->regs->command);
|
||||
if (ehci->rh_state != EHCI_RH_HALTED && !ehci->reclaim) {
|
||||
ehci_writel(ehci, cmd & ~CMD_ASE, &ehci->regs->command);
|
||||
wmb();
|
||||
}
|
||||
|
||||
hbm_pipe_init(qh->qh_dma, bam->pipe_num, bam->dir);
|
||||
|
||||
if (likely(qh->qh_state == QH_STATE_IDLE)) {
|
||||
pr_debug("%s: QH was IDLE (%p)\n", __func__, qh);
|
||||
if (likely(qh->qh_state == QH_STATE_IDLE))
|
||||
qh_link_async(ehci, qh);
|
||||
}
|
||||
|
||||
/* Start Async Scheduler */
|
||||
cmd = ehci_readl(ehci, &ehci->regs->command);
|
||||
if (!(cmd & CMD_ASE)) {
|
||||
/* in case a clear of CMD_ASE didn't take yet */
|
||||
(void)handshake(ehci, &ehci->regs->status, STS_ASS, 0, 150);
|
||||
cmd |= CMD_ASE;
|
||||
ehci_writel(ehci, cmd, &ehci->regs->command);
|
||||
}
|
||||
|
||||
done:
|
||||
spin_unlock_irqrestore(&ehci->lock, flags);
|
||||
|
||||
pr_debug("QH:%p urb:%p <--> pipe:%u ep:%d(out:%u)\n",
|
||||
urb->ep->hcpriv, urb, bam->pipe_num, epnum, bam->dir);
|
||||
|
||||
if (unlikely(qh == NULL))
|
||||
qtd_list_free(ehci, urb, qtd_list);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
27
kernel/drivers/usb/otg/msm_otg.c
Executable file → Normal file
27
kernel/drivers/usb/otg/msm_otg.c
Executable file → Normal file
@ -1327,14 +1327,13 @@ static int msm_otg_notify_power_supply(struct msm_otg *motg, unsigned mA)
|
||||
goto psy_error;
|
||||
}
|
||||
|
||||
/* [chenchao] Fix reboot when pc reboot */
|
||||
if (motg->cur_power == 0 && mA > 2) {
|
||||
/* Enable charging */
|
||||
if (power_supply_set_online(psy, true))
|
||||
goto psy_error;
|
||||
if (power_supply_set_current_limit(psy, 1000*mA))
|
||||
goto psy_error;
|
||||
} else if (motg->cur_power > 0 && (mA == 0)) {
|
||||
} else if (motg->cur_power > 0 && (mA == 0 || mA == 2)) {
|
||||
/* Disable charging */
|
||||
if (power_supply_set_online(psy, false))
|
||||
goto psy_error;
|
||||
@ -2318,7 +2317,6 @@ static void msm_chg_detect_work(struct work_struct *w)
|
||||
bool is_dcd = false, tmout, vout, is_aca;
|
||||
u32 line_state, dm_vlgc;
|
||||
unsigned long delay;
|
||||
static bool det_time_out = false;
|
||||
|
||||
dev_dbg(phy->dev, "chg detection work\n");
|
||||
|
||||
@ -2360,11 +2358,6 @@ static void msm_chg_detect_work(struct work_struct *w)
|
||||
is_dcd = msm_chg_check_dcd(motg);
|
||||
motg->dcd_time += MSM_CHG_DCD_POLL_TIME;
|
||||
tmout = motg->dcd_time >= MSM_CHG_DCD_TIMEOUT;
|
||||
|
||||
if (tmout) {
|
||||
det_time_out = true;
|
||||
}
|
||||
|
||||
if (is_dcd || tmout) {
|
||||
msm_chg_disable_dcd(motg);
|
||||
msm_chg_enable_primary_det(motg);
|
||||
@ -2402,17 +2395,11 @@ static void msm_chg_detect_work(struct work_struct *w)
|
||||
break;
|
||||
}
|
||||
|
||||
if (line_state) { /* DP > VLGC or/and DM > VLGC */
|
||||
if (line_state) /* DP > VLGC or/and DM > VLGC */
|
||||
motg->chg_type = USB_PROPRIETARY_CHARGER;
|
||||
} else {
|
||||
else
|
||||
motg->chg_type = USB_SDP_CHARGER;
|
||||
|
||||
if (det_time_out) {
|
||||
det_time_out = false;
|
||||
motg->chg_type = USB_DCP_CHARGER;
|
||||
}
|
||||
}
|
||||
|
||||
motg->chg_state = USB_CHG_STATE_DETECTED;
|
||||
delay = 0;
|
||||
}
|
||||
@ -2583,9 +2570,8 @@ static void msm_otg_sm_work(struct work_struct *w)
|
||||
case USB_PROPRIETARY_CHARGER:
|
||||
msm_otg_notify_charger(motg,
|
||||
IDEV_CHG_MAX);
|
||||
/* [chenchao] Not suspend when charge with power adapter */
|
||||
/* pm_runtime_put_noidle(otg->phy->dev); */
|
||||
/* pm_runtime_suspend(otg->phy->dev); */
|
||||
pm_runtime_put_noidle(otg->phy->dev);
|
||||
pm_runtime_suspend(otg->phy->dev);
|
||||
break;
|
||||
case USB_ACA_B_CHARGER:
|
||||
msm_otg_notify_charger(motg,
|
||||
@ -2610,9 +2596,6 @@ static void msm_otg_sm_work(struct work_struct *w)
|
||||
OTG_STATE_B_PERIPHERAL;
|
||||
break;
|
||||
case USB_SDP_CHARGER:
|
||||
/* [chenchao] Fix always reboot when connect some notebook */
|
||||
msm_otg_notify_charger(motg,
|
||||
IDEV_CHG_MIN);
|
||||
msm_otg_start_peripheral(otg, 1);
|
||||
otg->phy->state =
|
||||
OTG_STATE_B_PERIPHERAL;
|
||||
|
Reference in New Issue
Block a user