M7350v3_en_gpl

This commit is contained in:
T
2024-09-09 08:55:19 +00:00
parent 801e6d2ad8
commit 2d95e8761a
2791 changed files with 89608 additions and 390711 deletions

View File

@ -152,6 +152,4 @@ source "drivers/coresight/Kconfig"
source "drivers/bif/Kconfig"
source "drivers/oled/Kconfig"
endmenu

View File

@ -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/

View File

@ -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

View File

@ -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);
}

View File

@ -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 */

View File

@ -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, &reg);
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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}
}

View File

@ -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
View 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));

View File

@ -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"}
};

View File

@ -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) {

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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");

View File

@ -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

View File

@ -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");

View File

@ -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__ */

View File

@ -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");

View File

@ -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__ */

View File

@ -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;

View File

@ -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);

View File

@ -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
View 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
View 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

View File

@ -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", &current_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
View 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),

View File

@ -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)

View File

@ -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]);
}
}

View File

@ -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);

View File

@ -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

View File

@ -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");
}

View File

@ -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;
}

View File

@ -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;

View File

@ -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);

View File

@ -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
View 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;