M7350v3_en_gpl
This commit is contained in:
@ -1,19 +0,0 @@
|
||||
config OLED
|
||||
bool "Support OLED display"
|
||||
default n
|
||||
---help---
|
||||
Say Y here if you use OLED display
|
||||
|
||||
config OLED_SSD1306_PT
|
||||
bool "Driver for OLED SSD1306"
|
||||
select OLED
|
||||
default n
|
||||
---help---
|
||||
Say Y here if you use OLED SSD1306
|
||||
|
||||
config OLED_S90319_PT
|
||||
bool "Driver for OLED s90319"
|
||||
select OLED
|
||||
default n
|
||||
---help---
|
||||
Say Y here if you use OLED S90319
|
@ -1,6 +0,0 @@
|
||||
obj-$(CONFIG_OLED_SSD1306_PT) += oled_ssd1306_pt.o
|
||||
obj-$(CONFIG_OLED_S90319_PT) += oled_s90319_pt.o
|
||||
obj-$(CONFIG_OLED) += oled_pt.o oled_display.o
|
||||
|
||||
clean:
|
||||
rm *.o .*cmd
|
@ -1,184 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 2014, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_display.h
|
||||
Description : oled sysfs interface.
|
||||
Author : Luowei
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2014-05-13, Luowei create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/err.h>
|
||||
#include "oled_display.h"
|
||||
|
||||
struct class *oled_display_class;
|
||||
EXPORT_SYMBOL_GPL(oled_display_class);
|
||||
|
||||
static struct device_type oled_display_dev_type;
|
||||
|
||||
#define DISPLAY_ATTR(_name) \
|
||||
{ \
|
||||
.attr = { .name = #_name }, \
|
||||
.show = oled_display_show_property, \
|
||||
.store = oled_display_store_property, \
|
||||
}
|
||||
|
||||
static struct device_attribute oled_display_attrs[];
|
||||
|
||||
static ssize_t oled_display_show_property(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct oled_display *display = dev_get_drvdata(dev);
|
||||
const ptrdiff_t off = attr - oled_display_attrs;
|
||||
ssize_t ret = 0;
|
||||
|
||||
if (!display)
|
||||
goto show_failed;
|
||||
|
||||
if ((off >= DISPLAY_PROP_BUFFER && off < DISPLAY_PROP_NUMBER)
|
||||
&& display->show_property[off])
|
||||
ret = display->show_property[off](dev, attr, buf);
|
||||
|
||||
return ret;
|
||||
show_failed:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t oled_display_store_property(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
struct oled_display *display = dev_get_drvdata(dev);
|
||||
const ptrdiff_t off = attr - oled_display_attrs;
|
||||
ssize_t ret = 0;
|
||||
|
||||
if (!display)
|
||||
goto show_failed;
|
||||
|
||||
if ((off >= DISPLAY_PROP_BUFFER && off < DISPLAY_PROP_NUMBER)
|
||||
&& display->store_property[off])
|
||||
ret = display->store_property[off](dev, attr, buf, count);
|
||||
|
||||
return ret;
|
||||
show_failed:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct device_attribute oled_display_attrs[] = {
|
||||
DISPLAY_ATTR(oled_buffer),
|
||||
DISPLAY_ATTR(backlight_on),
|
||||
DISPLAY_ATTR(panel_on),
|
||||
};
|
||||
|
||||
static struct attribute *__oled_display_attrs[ARRAY_SIZE(oled_display_attrs) + 1];
|
||||
|
||||
static umode_t oled_display_attr_is_visible(struct kobject *kobj,
|
||||
struct attribute *attr,
|
||||
int attrno)
|
||||
{
|
||||
return (S_IRUGO | S_IWUGO);
|
||||
}
|
||||
|
||||
static struct attribute_group oled_display_attr_group = {
|
||||
.attrs = __oled_display_attrs,
|
||||
.is_visible = oled_display_attr_is_visible,
|
||||
};
|
||||
|
||||
static const struct attribute_group *oled_display_attr_groups[] = {
|
||||
&oled_display_attr_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void oled_display_init_attrs(struct device_type *dev_type)
|
||||
{
|
||||
int i;
|
||||
|
||||
dev_type->groups = oled_display_attr_groups;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(oled_display_attrs); i++)
|
||||
__oled_display_attrs[i] = &oled_display_attrs[i].attr;
|
||||
}
|
||||
|
||||
static void oled_display_dev_release(struct device *dev)
|
||||
{
|
||||
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
|
||||
kfree(dev);
|
||||
}
|
||||
|
||||
int oled_display_register(struct device *parent, struct oled_display *display)
|
||||
{
|
||||
struct device *dev;
|
||||
int rc;
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
if (!dev)
|
||||
return -ENOMEM;
|
||||
|
||||
device_initialize(dev);
|
||||
|
||||
dev->class = oled_display_class;
|
||||
dev->type = &oled_display_dev_type;
|
||||
dev->parent = parent;
|
||||
dev->release = oled_display_dev_release;
|
||||
dev_set_drvdata(dev, display);
|
||||
display->dev = dev;
|
||||
|
||||
rc = kobject_set_name(&dev->kobj, "%s", display->name);
|
||||
if (rc)
|
||||
goto kobject_set_name_failed;
|
||||
|
||||
rc = device_add(dev);
|
||||
if (rc)
|
||||
goto device_add_failed;
|
||||
|
||||
spin_lock_init(&display->lock);
|
||||
|
||||
return 0;
|
||||
|
||||
kobject_set_name_failed:
|
||||
put_device(dev);
|
||||
kfree(dev->p);
|
||||
kfree(dev);
|
||||
return rc;
|
||||
device_add_failed:
|
||||
device_del(dev);
|
||||
put_device(dev);
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(oled_display_register);
|
||||
|
||||
void oled_display_unregister(struct oled_display *display)
|
||||
{
|
||||
device_unregister(display->dev);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(oled_display_unregister);
|
||||
|
||||
static int __init oled_display_class_init(void)
|
||||
{
|
||||
oled_display_class = class_create(THIS_MODULE, "display");
|
||||
|
||||
if (IS_ERR(oled_display_class))
|
||||
return PTR_ERR(oled_display_class);
|
||||
|
||||
oled_display_init_attrs(&oled_display_dev_type);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void __exit oled_display_class_exit(void)
|
||||
{
|
||||
class_destroy(oled_display_class);
|
||||
}
|
||||
|
||||
subsys_initcall(oled_display_class_init);
|
||||
module_exit(oled_display_class_exit);
|
||||
|
||||
MODULE_DESCRIPTION("Universal display class");
|
||||
MODULE_AUTHOR("LuoWei <luoweisj@tp-link.net>");
|
||||
MODULE_LICENSE("GPL");
|
@ -1,40 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 2014, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_display.h
|
||||
Description : Header file of oled sysfs interface.
|
||||
Author : Luowei
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2014-05-13, Luowei create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __OLED_DISPLAY_H__
|
||||
#define __OLED_DISPLAY_H__
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
enum oled_display_property {
|
||||
DISPLAY_PROP_BUFFER = 0,
|
||||
DISPLAY_PROP_BACKLIGHTON,
|
||||
DISPLAY_PROP_PANELON,
|
||||
DISPLAY_PROP_NUMBER
|
||||
};
|
||||
|
||||
struct oled_display {
|
||||
const char *name;
|
||||
enum oled_display_property *properties;
|
||||
size_t num_properties;
|
||||
|
||||
ssize_t (*show_property[DISPLAY_PROP_NUMBER]) (struct device *dev,
|
||||
struct device_attribute *attr, char *buf);
|
||||
ssize_t (*store_property[DISPLAY_PROP_NUMBER]) (struct device *dev,
|
||||
struct device_attribute *attr, const char *buf, size_t count);
|
||||
|
||||
struct device *dev;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
int oled_display_register(struct device *parent, struct oled_display *display);
|
||||
|
||||
#endif
|
@ -1,274 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 1996-2012, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_pt.c
|
||||
Description : Driver for OLED s90319.
|
||||
Author : linyunfeng
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2011-08-16, linyunfeng create file.
|
||||
*******************************************************************************/
|
||||
#include <linux/module.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <mach/board.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/wakelock.h>
|
||||
|
||||
#include "oled_pt.h"
|
||||
#include "oled_display.h"
|
||||
|
||||
//#define OLED_DEBUG
|
||||
|
||||
struct mutex oled_mutex;
|
||||
struct wake_lock oled_wlock;
|
||||
|
||||
static struct oled_panel_data *oled_pdata;
|
||||
|
||||
#ifdef CONFIG_OLED_SSD1306_PT
|
||||
extern uint8_t oled_ssd1306_buf[];
|
||||
extern struct oled_panel_data oled_ssd1306_panel_data;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OLED_S90319_PT
|
||||
extern uint8_t oled_s90319_buf[];
|
||||
extern struct oled_panel_data oled_s90319_panel_data;
|
||||
#endif
|
||||
|
||||
static uint32_t oled_buf_size = 0;
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_buffer_show
|
||||
Description : Print the oled buffer data, hex
|
||||
Input : None
|
||||
Output : buf: Command line buffer
|
||||
Return : The number of characters will display in command
|
||||
line.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static ssize_t oled_buffer_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return oled_pdata->oled_print_buffer(buf);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_buffer_store
|
||||
Description : Write data to oled buffer.
|
||||
Input : buf: Input format is: x,y,width,height,data.
|
||||
count: Length of input.
|
||||
Output : None
|
||||
Return : Length of input or error number.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static ssize_t oled_buffer_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
uint32_t data_length = 0;
|
||||
uint8_t x = buf[0];
|
||||
uint8_t y = buf[1];
|
||||
uint8_t width = buf[2];
|
||||
uint8_t height = buf[3];
|
||||
|
||||
if ('\n' == *(buf + count - 1)){
|
||||
data_length = count - 5;
|
||||
} else {
|
||||
data_length = count - 4;
|
||||
}
|
||||
|
||||
if (data_length > oled_buf_size) {
|
||||
printk("%s, data_length=%d, oled_buf_size=%d, oled buffer overflow!\n",
|
||||
__func__, data_length, oled_buf_size);
|
||||
mutex_unlock(&oled_mutex);
|
||||
return -1;
|
||||
}
|
||||
|
||||
mutex_lock(&oled_mutex);
|
||||
|
||||
#ifdef CONFIG_OLED_SSD1306_PT
|
||||
memcpy(oled_ssd1306_buf, buf + 4, data_length);
|
||||
|
||||
oled_pdata->oled_fill_with_pic(oled_ssd1306_buf,
|
||||
x, y, width, height);
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OLED_S90319_PT
|
||||
memcpy(oled_s90319_buf, buf + 4, buf[2] * buf[3] / 8);
|
||||
oled_pdata->oled_fill_with_pic(oled_s90319_buf,
|
||||
x, y, width, height);
|
||||
#endif
|
||||
|
||||
mutex_unlock(&oled_mutex);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : backlight_on_store
|
||||
Description : Control backlight.
|
||||
Input : buf: 0: off, 1: on.
|
||||
count: Length of input.
|
||||
Output : None
|
||||
Return : Length of input.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static ssize_t backlight_on_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
uint8_t on = simple_strtoul(buf, NULL, 10);
|
||||
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s, buf=%s\n", __func__, buf);
|
||||
#endif
|
||||
|
||||
oled_pdata->oled_set_backlight(on);
|
||||
return count;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : panel_on_store
|
||||
Description : Control panel.
|
||||
Input : buf: 0: off, 1: on.
|
||||
count: Length of input.
|
||||
Output : None
|
||||
Return : Length of input.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static ssize_t panel_on_store(struct device *dev, struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
uint8_t on = simple_strtoul(buf, NULL, 10);
|
||||
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s, buf=%s\n", __func__, buf);
|
||||
#endif
|
||||
|
||||
if (0 == on) {
|
||||
oled_pdata->oled_panel_off();
|
||||
|
||||
if (wake_lock_active(&oled_wlock)) {
|
||||
wake_unlock(&oled_wlock);
|
||||
}
|
||||
} else {
|
||||
if (!wake_lock_active(&oled_wlock)) {
|
||||
wake_lock(&oled_wlock);
|
||||
}
|
||||
|
||||
oled_pdata->oled_panel_on();
|
||||
}
|
||||
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s end\n", __func__);
|
||||
#endif
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static enum oled_display_property oled_display_prop[] = {
|
||||
DISPLAY_PROP_BUFFER,
|
||||
DISPLAY_PROP_BACKLIGHTON,
|
||||
DISPLAY_PROP_PANELON
|
||||
};
|
||||
|
||||
static struct oled_display oled_display = {
|
||||
.name = "oled",
|
||||
.properties = oled_display_prop,
|
||||
.num_properties = ARRAY_SIZE(oled_display_prop),
|
||||
.show_property = {oled_buffer_show},
|
||||
.store_property = {oled_buffer_store, backlight_on_store, panel_on_store}
|
||||
};
|
||||
|
||||
/* Function to load the device */
|
||||
static int __devinit oled_probe(struct platform_device *pdev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct device *dev = &(pdev->dev);
|
||||
printk("%s\n", __func__);
|
||||
|
||||
ret = of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
|
||||
if (ret)
|
||||
pr_err("%s: of_platform_populate failed %d\n", __func__, ret);
|
||||
|
||||
#ifdef CONFIG_OLED_SSD1306_PT
|
||||
pdev->dev.platform_data = &oled_ssd1306_panel_data;
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OLED_S90319_PT
|
||||
pdev->dev.platform_data = &oled_s90319_panel_data;
|
||||
#endif
|
||||
|
||||
oled_pdata = pdev->dev.platform_data;
|
||||
|
||||
oled_buf_size = oled_pdata->panel_width * oled_pdata->panel_height;
|
||||
|
||||
oled_display.dev = dev;
|
||||
ret = oled_display_register(dev, &oled_display);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: oled_display_register failed, ret=%d\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
mutex_init(&oled_mutex);
|
||||
|
||||
wake_lock_init(&oled_wlock, WAKE_LOCK_SUSPEND, "oled");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int __devexit oled_remove(struct platform_device *pdev)
|
||||
{
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
wake_lock_destroy(&oled_wlock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id tp_oled_pt_table[] = {
|
||||
{ .compatible = "tp,oled_pt",},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver oled_device_driver = {
|
||||
.probe = oled_probe,
|
||||
.remove = __devexit_p(oled_remove),
|
||||
.driver = {
|
||||
.name = "oled",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = tp_oled_pt_table,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init oled_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
rc = platform_driver_register(&oled_device_driver);
|
||||
|
||||
if (!rc)
|
||||
printk("oled init success!\n");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit oled_exit(void)
|
||||
{
|
||||
#if defined(OLED_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
platform_driver_unregister(&oled_device_driver);
|
||||
}
|
||||
|
||||
module_init(oled_init);
|
||||
module_exit(oled_exit);
|
||||
|
||||
MODULE_AUTHOR("Lin Yunfeng");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_DESCRIPTION("OLED display driver");
|
||||
|
@ -1,54 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 2014, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_pt.h
|
||||
Description : Driver for OLED.
|
||||
Author : Zhang Tao<zhangtao@tp-link.net>
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2014-04-14, ZhangTao create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _OLED_PT_H
|
||||
#define _OLED_PT_H
|
||||
|
||||
#ifdef CONFIG_OLED_SSD1306_PT
|
||||
struct oled_panel_data {
|
||||
void (*oled_gpio_config)(int on);
|
||||
int (*oled_power_save)(int);
|
||||
int (*oled_panel_on)(void);
|
||||
int (*oled_panel_off)(void);
|
||||
int (*oled_horizontal_scroll)(const uint8_t y, const uint8_t height,
|
||||
const uint8_t t_interval_scroll, const uint8_t direction);
|
||||
int (*oled_scroll_stop)(void);
|
||||
int (*oled_fade_blink)(const uint8_t mode, const uint8_t t_interval_scroll);
|
||||
int (*oled_fill_with_pic)(const uint8_t *pic, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height);
|
||||
int (*oled_fill_with_value)(const uint8_t value, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height);
|
||||
int (*oled_print_buffer)(char *buf);
|
||||
int (*oled_set_backlight)(const uint8_t on);
|
||||
int panel_width;
|
||||
int panel_height;
|
||||
int *gpio_num;
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_OLED_S90319_PT
|
||||
struct oled_panel_data {
|
||||
void (*oled_gpio_config)(int on);
|
||||
int (*oled_power_save)(int);
|
||||
int (*oled_panel_on)(void);
|
||||
int (*oled_panel_off)(void);
|
||||
int (*oled_fill_with_pic)(const uint8_t *pic, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height);
|
||||
int (*oled_set_backlight)(const uint8_t on);
|
||||
int (*oled_print_buffer)(char *buf);
|
||||
int panel_width;
|
||||
int panel_height;
|
||||
int *gpio_num;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif //end of _OLED_PT_H
|
@ -1,781 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 1996-2014, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_s90319_pt.c
|
||||
Description : Driver for OLED s90319.
|
||||
Author : xiongsizhe
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2014-03-28, xiongsizhe create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/pmic.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <mach/board.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/gpiomux.h>
|
||||
#include <linux/device.h>
|
||||
#include "oled_pt.h"
|
||||
#include "oled_s90319_pt.h"
|
||||
|
||||
//#define OLED_S90319_DEBUG
|
||||
|
||||
typedef unsigned int boolean;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
static int s90319_spi_write_cmd(const uint8_t *data, const uint16_t len);
|
||||
static int s90319_spi_write_data(const uint8_t *data, const uint16_t len);
|
||||
|
||||
uint8_t oled_s90319_buf[COLUMN_NUM * ROW_NUM * 2] = {0};
|
||||
static uint8_t frame_data[COLUMN_NUM * ROW_NUM * 2] ={0};
|
||||
|
||||
static uint8_t frame_data_buf[COLUMN_NUM * ROW_NUM * 2] ={0};
|
||||
|
||||
struct s90319_state_type{
|
||||
boolean disp_initialized;
|
||||
boolean display_on;
|
||||
boolean disp_powered_up;
|
||||
};
|
||||
|
||||
static struct s90319_state_type s90319_state = {0};
|
||||
|
||||
struct oled_panel_data oled_s90319_panel_data;
|
||||
static struct oled_panel_data *oled_s90319_pdata;
|
||||
|
||||
static struct mutex flush_mutex;
|
||||
static struct mutex oled_panel_mutex;
|
||||
|
||||
#define BUFFER_SIZE 4<<10
|
||||
struct spi_message spi_msg;
|
||||
//struct spi_transfer spi_xfer;
|
||||
unsigned char *tx_buf;
|
||||
|
||||
struct s90319_work_t {
|
||||
struct work_struct work;
|
||||
};
|
||||
static DECLARE_WAIT_QUEUE_HEAD(s90319_wait_queue);
|
||||
|
||||
static struct s90319_work_t *s90319_sensorw;
|
||||
static struct spi_device *s90319_spi;
|
||||
|
||||
static int oled_s90319_rsx;
|
||||
|
||||
static int oled_s90319_cs;
|
||||
static int oled_s90319_boost_en;
|
||||
|
||||
enum GPIO_OLED_S90319 {
|
||||
GPIO_OLED_CS = 0,
|
||||
GPIO_OLED_RESET,
|
||||
GPIO_OLED_BOOST_EN,
|
||||
GPIO_OLED_RSX,
|
||||
GPIO_OLED_VDD0,
|
||||
GPIO_OLED_VDD1,
|
||||
|
||||
GPIO_OLED_END,
|
||||
};
|
||||
|
||||
static const char *dts_gpio_name[] = {
|
||||
[GPIO_OLED_CS] = "qcom,oled-cs-gpio",
|
||||
[GPIO_OLED_RESET] = "qcom,oled-reset-gpio",
|
||||
[GPIO_OLED_BOOST_EN] = "qcom,oled-boost-en-gpio",
|
||||
[GPIO_OLED_RSX] = "qcom,oled-rsx-gpio",
|
||||
[GPIO_OLED_VDD0] = "qcom,oled-vdd0-gpio",
|
||||
[GPIO_OLED_VDD1] = "qcom,oled-vdd1-gpio",
|
||||
|
||||
[GPIO_OLED_END] = "",
|
||||
};
|
||||
|
||||
static int oled_s90319_gpio[GPIO_OLED_END] = {0};
|
||||
|
||||
/************************************************************
|
||||
Function : wr_comm
|
||||
Description: transfer command to oled
|
||||
Input : commond
|
||||
Return :
|
||||
************************************************************/
|
||||
void wr_comm(uint8_t cmd)
|
||||
{
|
||||
s90319_spi_write_cmd(&cmd, 1);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : wr_dat
|
||||
Description: transfer data to oled
|
||||
Input : data
|
||||
Return :
|
||||
************************************************************/
|
||||
void wr_dat(uint8_t data)
|
||||
{
|
||||
s90319_spi_write_data(&data, 1);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : Delay
|
||||
Description: delay time
|
||||
Input : t
|
||||
Return :
|
||||
************************************************************/
|
||||
void Delay(unsigned int t)
|
||||
{
|
||||
mdelay(t);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : get_gpio_by_dtsname
|
||||
Description: get gpio number by dtsname
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void get_gpio_by_dtsname(struct device_node *node, const char *gpio_name[], u32 *gpio_num, int len)
|
||||
{
|
||||
int i = 0;
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
gpio_num[i] = of_get_named_gpio(node, gpio_name[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_config_gpios
|
||||
Description: config gpio
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void oled_s90319_config_gpios(int enable)
|
||||
{
|
||||
int i, rc = 0;
|
||||
for (i = 0; i < GPIO_OLED_END; i++)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
rc = gpio_request(oled_s90319_gpio[i], dts_gpio_name[i]);
|
||||
if (rc)
|
||||
{
|
||||
pr_err("request gpio %s failed, rc=%d\n", dts_gpio_name[i], rc);
|
||||
gpio_free(oled_s90319_gpio[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_free(oled_s90319_gpio[i]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_power_save
|
||||
Description: open or close power supply
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_power_save(int on)
|
||||
{
|
||||
int rc = 0;
|
||||
if (on)
|
||||
{
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_RESET], 0);
|
||||
mdelay(1);
|
||||
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_VDD0], 1);
|
||||
mdelay(1);
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_VDD1], 1);
|
||||
mdelay(1);
|
||||
|
||||
gpio_set_value_cansleep(oled_s90319_gpio[GPIO_OLED_RESET], 1);
|
||||
mdelay(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_BOOST_EN], 0);
|
||||
mdelay(1);
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_VDD1], 0);
|
||||
mdelay(1);
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_VDD0], 0);
|
||||
mdelay(1);
|
||||
gpio_direction_output(oled_s90319_gpio[GPIO_OLED_RESET], 0);
|
||||
mdelay(1);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_spi_txdata
|
||||
Description: transfer data by spi
|
||||
Input : txdata: data to transfer
|
||||
length: length of txdata
|
||||
Return :
|
||||
************************************************************/
|
||||
static int s90319_spi_txdata(uint8_t *txdata, const uint16_t length)
|
||||
{
|
||||
struct spi_transfer spi_xfer = {
|
||||
.tx_buf = txdata,
|
||||
.len = length,
|
||||
};
|
||||
spi_message_init(&spi_msg);
|
||||
|
||||
spi_message_add_tail(&spi_xfer, &spi_msg);
|
||||
|
||||
return spi_sync(s90319_spi, &spi_msg);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_spi_write_cmd
|
||||
Description: transfer cmd by spi
|
||||
Input : data: cmd to transfer
|
||||
len: length of cmd
|
||||
Return :
|
||||
************************************************************/
|
||||
static int s90319_spi_write_cmd(const uint8_t *data, const uint16_t len)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
#ifdef OLED_S90319_DEBUG
|
||||
int i = 0;
|
||||
printk("%s, data = 0x%x, len = %d\n", __func__, *data, len);
|
||||
#endif
|
||||
|
||||
if (TRUE == s90319_state.disp_powered_up) {
|
||||
|
||||
memcpy(frame_data, data, len);
|
||||
|
||||
#ifdef OLED_S90319_DEBUG
|
||||
for (i = 0; i < len; i++){
|
||||
printk("0x%x ", *(frame_data+i));
|
||||
}
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
gpio_set_value_cansleep(oled_s90319_rsx, 0);
|
||||
|
||||
rc = s90319_spi_txdata(frame_data, len);
|
||||
if (rc < 0) {
|
||||
printk("%s fail, data = 0x%x, len = %d, rc = %d\n",
|
||||
__func__, *data, len, rc);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_spi_write_data
|
||||
Description: data need to be write
|
||||
Input : data: data need to be write
|
||||
len: length of data
|
||||
Return :
|
||||
************************************************************/
|
||||
static int s90319_spi_write_data(const uint8_t *data, const uint16_t len)
|
||||
{
|
||||
int rc = -EFAULT;
|
||||
|
||||
#ifdef OLED_S90319_DEBUG
|
||||
printk("%s, data = 0x%x, len = %d\n", __func__, *data, len);
|
||||
#endif
|
||||
|
||||
if (TRUE == s90319_state.disp_powered_up) {
|
||||
|
||||
memcpy(frame_data, data, len);
|
||||
|
||||
gpio_set_value_cansleep(oled_s90319_rsx, 1);
|
||||
|
||||
rc = s90319_spi_txdata(frame_data, len);
|
||||
if (rc < 0) {
|
||||
printk("%s fail, data = 0x%x, len = %d, rc = %d\n",
|
||||
__func__, *data, len, rc);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_area_check
|
||||
Description: check data area bigger than oled area or not
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_area_check(const uint8_t x, const uint8_t y,
|
||||
const uint8_t width, const uint8_t height)
|
||||
{
|
||||
if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)
|
||||
|| (x + width > COLUMN_NUM) || (y + height > ROW_NUM)){
|
||||
printk("%s error, row_start=%d, col_start=%d, width=%d, height=%d",
|
||||
__func__, x, y, width, height);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_fill_with_pic
|
||||
Description: write pic data on location assign
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_fill_with_pic(const uint8_t *pic, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height)
|
||||
{
|
||||
int i = 0, m = 0, j = 0;
|
||||
uint8_t data;
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s,width=%d, height=%d\n", __func__, width, height);
|
||||
#endif
|
||||
|
||||
if (oled_s90319_area_check(x, y, width, height)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
oled_s90319_set_col_addr[1] = x + X_OFFSET;
|
||||
oled_s90319_set_col_addr[3] = x + width - 1 + X_OFFSET;
|
||||
oled_s90319_set_row_addr[1] = y + Y_OFFSET;
|
||||
oled_s90319_set_row_addr[3] = y + height - 1 + Y_OFFSET;
|
||||
|
||||
for (i = 0; i < width * height / 8; i++)
|
||||
{
|
||||
data = *pic;
|
||||
for(m = 7; (m >= 0)&&(m <= 7); m--)
|
||||
{
|
||||
if((data >> m) & 0x01)
|
||||
{
|
||||
frame_data_buf[j] = 0x00;
|
||||
frame_data_buf[j + 1] = 0x00;
|
||||
}
|
||||
else
|
||||
{
|
||||
frame_data_buf[j] = 0xFF;
|
||||
frame_data_buf[j + 1] = 0xFF;
|
||||
}
|
||||
j = j + 2;
|
||||
}
|
||||
pic++;
|
||||
}
|
||||
|
||||
if (TRUE == s90319_state.disp_initialized) {
|
||||
mutex_lock(&flush_mutex);
|
||||
|
||||
s90319_spi_write_cmd(oled_set_col_cmd, sizeof(oled_set_col_cmd));
|
||||
s90319_spi_write_data(oled_s90319_set_col_addr, sizeof(oled_s90319_set_col_addr));
|
||||
|
||||
s90319_spi_write_cmd(oled_set_row_cmd, sizeof(oled_set_row_cmd));
|
||||
s90319_spi_write_data(oled_s90319_set_row_addr, sizeof(oled_s90319_set_row_addr));
|
||||
|
||||
s90319_spi_write_cmd(oled_write_data_cmd, sizeof(oled_write_data_cmd));
|
||||
s90319_spi_write_data(frame_data_buf, width * height * 2);
|
||||
|
||||
mutex_unlock(&flush_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oled_s90319_print_buffer(char* buf)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_set_backlight
|
||||
Description: backlight on/off
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_set_backlight(const uint8_t on)
|
||||
{
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s, on =%u\n", __func__, on);
|
||||
#endif
|
||||
|
||||
if (0 == on) {
|
||||
gpio_direction_output(oled_s90319_boost_en, 0);
|
||||
} else {
|
||||
gpio_direction_output(oled_s90319_boost_en, 1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_panel_init
|
||||
Description: init panel
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void oled_s90319_panel_init(void)
|
||||
{
|
||||
/* End Reset Sequence */
|
||||
wr_comm(0x11); //Sleep out
|
||||
Delay (120); //Delay 120ms
|
||||
/* Frame Rate */
|
||||
wr_comm(0xB1);
|
||||
wr_dat(0x05);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x3A);
|
||||
wr_comm(0xB2);
|
||||
wr_dat(0x05);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x3A);
|
||||
wr_comm(0xB3);
|
||||
wr_dat(0x05);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x05);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x3A);
|
||||
/* End Frame Rate */
|
||||
wr_comm(0xB4); //Column inversion
|
||||
wr_dat(0x07);
|
||||
/* Power Sequence */
|
||||
wr_comm(0xC0);
|
||||
wr_dat(0xC8);
|
||||
wr_dat(0x08);
|
||||
wr_dat(0x84);
|
||||
wr_comm(0xC1);
|
||||
wr_dat(0XC5);
|
||||
wr_comm(0xC2);
|
||||
wr_dat(0x0A);
|
||||
wr_dat(0x00);
|
||||
wr_comm(0xC3);
|
||||
wr_dat(0x8A);
|
||||
wr_dat(0x2A);
|
||||
wr_comm(0xC4);
|
||||
wr_dat(0x8A);
|
||||
wr_dat(0xEE);
|
||||
/* End Power Sequence*/
|
||||
wr_comm(0xC5); //VCOM
|
||||
wr_dat(0x0C);
|
||||
wr_comm(0x36); //MX, MY, RGB mode
|
||||
wr_dat(0xc8);
|
||||
/* Gamma Sequence */
|
||||
wr_comm(0xE0);
|
||||
wr_dat(0x05);
|
||||
wr_dat(0x1A);
|
||||
wr_dat(0x0C);
|
||||
wr_dat(0x0E);
|
||||
wr_dat(0x3A);
|
||||
wr_dat(0x34);
|
||||
wr_dat(0x2D);
|
||||
wr_dat(0x2F);
|
||||
wr_dat(0x2D);
|
||||
wr_dat(0x2A);
|
||||
wr_dat(0x2F);
|
||||
wr_dat(0x3C);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x01);
|
||||
wr_dat(0x02);
|
||||
wr_dat(0x10);
|
||||
wr_comm(0xE1);
|
||||
wr_dat(0x04);
|
||||
wr_dat(0x1B);
|
||||
wr_dat(0x0D);
|
||||
wr_dat(0x0E);
|
||||
wr_dat(0x2D);
|
||||
wr_dat(0x29);
|
||||
wr_dat(0x24);
|
||||
wr_dat(0x29);
|
||||
wr_dat(0x28);
|
||||
wr_dat(0x26);
|
||||
wr_dat(0x31);
|
||||
wr_dat(0x3B);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x03);
|
||||
wr_dat(0x12);
|
||||
/* End Gamma Sequence */
|
||||
wr_comm(0x3A); //65k mode
|
||||
wr_dat(0x05);
|
||||
|
||||
wr_comm(0x2a);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x02);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x81);
|
||||
|
||||
wr_comm(0x2b);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x03);
|
||||
wr_dat(0x00);
|
||||
wr_dat(0x82);
|
||||
|
||||
wr_comm(0x29); //Display on
|
||||
wr_comm(0x2C);
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_disp_on
|
||||
Description: init oled and display on
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void s90319_disp_on(void)
|
||||
{
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if (s90319_state.disp_powered_up && !s90319_state.display_on) {
|
||||
oled_s90319_panel_init();
|
||||
s90319_state.display_on = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_disp_powerup
|
||||
Description: power on
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void s90319_disp_powerup(void)
|
||||
{
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if (!s90319_state.disp_powered_up && !s90319_state.display_on) {
|
||||
/* Reset the hardware first */
|
||||
s90319_state.disp_powered_up = TRUE;
|
||||
if (oled_s90319_pdata->oled_power_save)
|
||||
oled_s90319_pdata->oled_power_save(1);
|
||||
|
||||
gpio_direction_output(oled_s90319_cs, 0);
|
||||
/* 1 data, 0 command*/
|
||||
gpio_direction_output(oled_s90319_rsx, 0);
|
||||
mdelay(5);
|
||||
|
||||
gpio_set_value_cansleep(oled_s90319_cs, 0);
|
||||
|
||||
mdelay(3);
|
||||
}
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_panel_on
|
||||
Description: init oled and power on
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_panel_on(void)
|
||||
{
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
mutex_lock(&oled_panel_mutex);
|
||||
if (!s90319_state.disp_initialized) {
|
||||
gpio_direction_output(oled_s90319_boost_en, 0);
|
||||
s90319_disp_powerup();
|
||||
s90319_disp_on();
|
||||
|
||||
s90319_state.disp_initialized = TRUE;
|
||||
|
||||
}
|
||||
mutex_unlock(&oled_panel_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_panel_off
|
||||
Description: panel off
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int oled_s90319_panel_off(void)
|
||||
{
|
||||
#if defined(OLED_S90319_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
mutex_lock(&oled_panel_mutex);
|
||||
if (s90319_state.disp_powered_up && s90319_state.display_on) {
|
||||
/* Main panel power off (Deep standby in) */
|
||||
s90319_spi_write_cmd(oled_s90319_panel_off_cmd,
|
||||
sizeof(oled_s90319_panel_off_cmd));
|
||||
mdelay(100); /* Typical 100ms */
|
||||
|
||||
if (oled_s90319_pdata->oled_power_save)
|
||||
oled_s90319_pdata->oled_power_save(0);
|
||||
|
||||
//if (oled_s90319_pdata->oled_gpio_config)
|
||||
//oled_s90319_pdata->oled_gpio_config(0);
|
||||
s90319_state.disp_powered_up = FALSE;
|
||||
s90319_state.display_on = FALSE;
|
||||
s90319_state.disp_initialized = FALSE;
|
||||
}
|
||||
mutex_unlock(&oled_panel_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct of_device_id s90319__spi_table[] = {
|
||||
{ .compatible = "tplink,oled",},
|
||||
{ },
|
||||
};
|
||||
|
||||
static int s90319_init_spi(struct spi_device *spi)
|
||||
{
|
||||
/* Initialize the MSM_CAMI2C Chip */
|
||||
init_waitqueue_head(&s90319_wait_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : s90319_spi_probe
|
||||
Description: spi driver probe
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int __devinit s90319_spi_probe(struct spi_device *spi)
|
||||
{
|
||||
tx_buf = kmalloc(BUFFER_SIZE, GFP_ATOMIC);
|
||||
if (tx_buf == NULL)
|
||||
{
|
||||
printk("kmalloc failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
s90319_sensorw = kzalloc(sizeof(struct s90319_work_t), GFP_KERNEL);
|
||||
if (!s90319_sensorw) {
|
||||
printk("kzalloc failed.\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
spi_set_drvdata(spi, s90319_sensorw);
|
||||
s90319_init_spi(spi);
|
||||
s90319_spi = spi;
|
||||
|
||||
msleep(50);
|
||||
|
||||
printk("%s successed!\n", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_pin_assign
|
||||
Description: assign gpio number
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static void oled_s90319_pin_assign(void)
|
||||
{
|
||||
/* Setting the Default GPIO's */
|
||||
oled_s90319_cs = oled_s90319_gpio[GPIO_OLED_CS];
|
||||
oled_s90319_rsx = oled_s90319_gpio[GPIO_OLED_RSX];
|
||||
oled_s90319_boost_en = oled_s90319_gpio[GPIO_OLED_BOOST_EN];
|
||||
}
|
||||
|
||||
/************************************************************
|
||||
Function : oled_s90319_probe
|
||||
Description: platform device driver probe
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int __devinit oled_s90319_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
if (!node)
|
||||
{
|
||||
dev_err(&pdev->dev, "%s: device tree information missing\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
printk("%s\n", __func__);
|
||||
|
||||
pdev->dev.platform_data = &oled_s90319_panel_data;
|
||||
oled_s90319_pdata = pdev->dev.platform_data;
|
||||
|
||||
get_gpio_by_dtsname(node, dts_gpio_name, oled_s90319_gpio, GPIO_OLED_END);
|
||||
oled_s90319_pin_assign();
|
||||
|
||||
oled_s90319_pdata->oled_gpio_config = oled_s90319_config_gpios;
|
||||
oled_s90319_pdata->oled_power_save = oled_s90319_power_save;
|
||||
oled_s90319_pdata->oled_panel_on = oled_s90319_panel_on;
|
||||
oled_s90319_pdata->oled_panel_off = oled_s90319_panel_off;
|
||||
oled_s90319_pdata->oled_fill_with_pic = oled_s90319_fill_with_pic;
|
||||
oled_s90319_pdata->oled_set_backlight = oled_s90319_set_backlight;
|
||||
oled_s90319_pdata->oled_print_buffer = oled_s90319_print_buffer;
|
||||
oled_s90319_pdata->panel_width = COLUMN_NUM;
|
||||
oled_s90319_pdata->panel_height = ROW_NUM;
|
||||
|
||||
oled_s90319_config_gpios(ENABLE);
|
||||
|
||||
mutex_init(&flush_mutex);
|
||||
mutex_init(&oled_panel_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit oled_s90319_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct spi_driver s90319_spi_driver = {
|
||||
.driver = {
|
||||
.name = "oleds90319",
|
||||
.owner = THIS_MODULE,
|
||||
.of_match_table = s90319__spi_table,
|
||||
},
|
||||
.probe = s90319_spi_probe,
|
||||
};
|
||||
|
||||
static struct of_device_id qcom_s90319_pt_table[] = {
|
||||
{ .compatible = "qcom,oled_s90319_pt",},
|
||||
{},
|
||||
};
|
||||
|
||||
static struct platform_driver this_driver = {
|
||||
.probe = oled_s90319_probe,
|
||||
.remove = __devexit_p(oled_s90319_remove),
|
||||
.driver = {
|
||||
.name = "oled_s90319_pt",
|
||||
.of_match_table = qcom_s90319_pt_table,
|
||||
},
|
||||
};
|
||||
|
||||
/************************************************************
|
||||
Function : oled_90319_panel_init
|
||||
Description: init function
|
||||
Input :
|
||||
Return :
|
||||
************************************************************/
|
||||
static int __init oled_90319_panel_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = platform_driver_register(&this_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = spi_register_driver(&s90319_spi_driver);
|
||||
if (ret < 0 || s90319_spi == NULL)
|
||||
{
|
||||
ret = -ENOTSUPP;
|
||||
printk("SPI add driver failed.\n");
|
||||
goto fail_driver;
|
||||
}
|
||||
printk("oled_90319_panel_init success.\n");
|
||||
return ret;
|
||||
|
||||
fail_driver:
|
||||
platform_driver_unregister(&this_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_initcall(oled_90319_panel_init);
|
||||
|
||||
MODULE_AUTHOR("Xiong Sizhe");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_DESCRIPTION("OLED 90319 driver");
|
@ -1,145 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 1996-2012, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_s90319_pt.h
|
||||
Description : Driver for OLED S90319.
|
||||
Author : xiongsizhe
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2014-03-30, xiongsizhe create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __OLED_S90319_PT_H__
|
||||
#define __OLED_S90319_PT_H__
|
||||
|
||||
typedef unsigned char uint8_t;
|
||||
typedef signed char int8_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
|
||||
#define ROW_NUM 128 /* 0~7 */
|
||||
#define PAGE_NUM 128
|
||||
#define COLUMN_NUM 128
|
||||
|
||||
#define ENABLE 1
|
||||
#define DISABLE 0
|
||||
|
||||
#define COLUMN_NUM_EXP 7 /* 2^7 = 128 */
|
||||
|
||||
/*
|
||||
* Four Formats:
|
||||
* 1. CMD_CONTROL BYTE . CMD . CMD . CMD <20><><EFBFBD><EFBFBD>
|
||||
* 2. CMD_CONTROL BYTE . CMD . CMD_CONTROL_BYTE . CMD <20><><EFBFBD><EFBFBD>
|
||||
* 3. DAT_CONTROL BYTE . DATA . DATA . DATA <20><><EFBFBD><EFBFBD>
|
||||
* 4. DAT_CONTROL BYTE . DATA . DAT_CONTROL_BYTE . DATA <20><><EFBFBD><EFBFBD>
|
||||
*/
|
||||
#define OLED_CONTROL_CMDS 0x00
|
||||
#define OLED_CONTROL_CMD_PAIRS 0x80
|
||||
#define OLED_CONTROL_DATAS 0x40
|
||||
#define OLED_CONTROL_DATA_PAIRS 0xC0
|
||||
|
||||
/* SINGLE CMDS */
|
||||
#define CMD_DUMMY_BYTE_ZERO 0x00
|
||||
#define CMD_DUMMY_BYTE_FF 0xFF
|
||||
#define CMD_GRAM_IGNORE(bit) (0xA4|(bit)) /* 0: No, 1: Yes */
|
||||
#define CMD_DISPLAY_OFF_ON(bit) (0xAE|(bit)) /* v: 0|1 */
|
||||
#define CMD_SCAN_DIRECTION_0_TO_N 0xC0
|
||||
#define CMD_SCAN_DIRECTION_N_TO_0 0xC8
|
||||
#define CMD_LOWER_COL_ADDR(addr) (0x00|(addr)) /* addr: 0~F */
|
||||
#define CMD_HIGHER_COL_ADDR(addr) (0x10|(addr)) /* addr: 0~F */
|
||||
#define CMD_SEGMENT_REMAP(dir) (0xA0|(dir)) /* dir:0 normal direction, dir:1 reverse direction */
|
||||
#define CMD_START_LINE(line) (0x40|(line)) /* line: 0 ~ 63 */
|
||||
#define CMD_NORMAL_REV_DISPLAY(bit) (0xA6|(bit)) /* bit:0 normal display, bit:1 reverse display */
|
||||
#define CMD_HORIZONTAL_SCROLL(dir) (0x26|(dir)) /* 0: L->R, 1:R->L */
|
||||
#define CMD_SCROLL_ENABLE(ena) (0x2E|(ena)) /* 0:Disable, 1:Enable */
|
||||
|
||||
/* DOUBLE CMDS */
|
||||
#define CMD_DOUBLE_CLOCK_DIVIDE_RATIO 0xD5
|
||||
#define CMD_DOUBLE_MULTIPLEX_RATIO 0xA8
|
||||
#define CMD_DOUBLE_PRECHARGE_PERIOD 0xD9
|
||||
#define CMD_DOUBLE_PADS_HW_CONFIG 0xDA /* Sequence: 0x02; Alternative: 0x12*/
|
||||
#define CMD_DOUBLE_CONTRAST_CONTROL 0x81
|
||||
#define CMD_DOUBLE_DISPLAY_OFFSET 0xD3 /* 0x00 ~ 3f */
|
||||
#define CMD_DOUBLE_VCOM_HLEVEL 0xDB /* 0x00 ~ 0xff */
|
||||
#define CMD_DOUBLE_SET_CHARGE_PUMP 0x8D /* Enable: 0x14, Disable: 0x10*/
|
||||
#define CMD_DOUBLE_MEMORY_ADDRESSING_MODE 0x20 /* 00: Horizontal 01: Vertial 10: Page 11: Invalid*/
|
||||
#define CMD_DOUBLE_FADE_BLINK_MODE 0x23 /* Fade out or blinking mode */
|
||||
|
||||
/* TRIPLE CMDS */
|
||||
#define CMD_TRIPE_COLUMN_ADDRESS 0x21 /* 0~127, 0~127 */
|
||||
#define CMD_TRIPE_PAGE_ADDRESS 0x22 /* 0~7, 0~7 */
|
||||
|
||||
#define OLED_MATREIAL_STANDARD_CONTRAST 0xAF
|
||||
#define OLED_MATREIAL_LOW_CONTRAST 0x0F
|
||||
|
||||
#define OLED_SET_COL_CMD 0x2A
|
||||
#define OLED_SET_ROW_CMD 0x2B
|
||||
#define OLED_WRITE_DATA_CMD 0x2C
|
||||
|
||||
#define X_OFFSET 2
|
||||
#define Y_OFFSET 3
|
||||
|
||||
uint8_t CMD_HORIZONTAL_SCROLL_ARRAY[] = {CMD_HORIZONTAL_SCROLL(0), CMD_HORIZONTAL_SCROLL(1)};
|
||||
uint8_t CMD_BACKLIGHT_ARRAY[] = {
|
||||
CMD_DISPLAY_OFF_ON(0), /* Backlight off */
|
||||
CMD_DISPLAY_OFF_ON(1) /* Backlight oN */
|
||||
};
|
||||
|
||||
/* set col command */
|
||||
uint8_t oled_set_col_cmd[] = {
|
||||
OLED_SET_COL_CMD,
|
||||
};
|
||||
|
||||
/* set row command */
|
||||
uint8_t oled_set_row_cmd[] = {
|
||||
OLED_SET_ROW_CMD,
|
||||
};
|
||||
|
||||
/* write data command */
|
||||
uint8_t oled_write_data_cmd[] = {
|
||||
OLED_WRITE_DATA_CMD,
|
||||
};
|
||||
|
||||
/* set backlight command */
|
||||
uint8_t oled_s90319_backlight_cmd[] = {
|
||||
CMD_DISPLAY_OFF_ON(0)
|
||||
};
|
||||
|
||||
/* panel on/off command */
|
||||
uint8_t oled_s90319_panel_off_cmd[] = {
|
||||
CMD_DISPLAY_OFF_ON(0), /* manual display on */
|
||||
CMD_DOUBLE_SET_CHARGE_PUMP, 0x10 /* set charge pump enable*/
|
||||
};
|
||||
|
||||
uint8_t oled_s90319_scroll_stop_cmd[] = {
|
||||
CMD_SCROLL_ENABLE(0)
|
||||
};
|
||||
|
||||
/* Fade out or blinking mode */
|
||||
uint8_t oled_s90319_fade_blink_cmd[] = {
|
||||
CMD_DOUBLE_FADE_BLINK_MODE,
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* fade_blink_parameter:
|
||||
* A[5:4] = 00b Disable Fade Out / Blinking Mode
|
||||
* A[5:4] = 10b Enable Fade Out mode
|
||||
* A[5:4] = 11b Enable Blinking mode
|
||||
* A[3:0] : Set time interval for each fade step, (8 * (A[3:0] + 1))frames
|
||||
*/
|
||||
struct oled_s90319_fade_blink_cmd_config_struct {
|
||||
uint8_t *fade_blink_parameter;
|
||||
};
|
||||
|
||||
uint8_t oled_s90319_set_col_addr[] = {
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
uint8_t oled_s90319_set_row_addr[] = {
|
||||
0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
#endif /* __OLED_S90319_PT__ */
|
||||
|
||||
|
@ -1,840 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 1996-2012, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_ssd1306_pt.c
|
||||
Description : Driver for OLED SSD1306.
|
||||
Author : linyunfeng
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.2, 2014-04-16, zhangtao modified oled_ssd1306_pt driver for dts of the new kernel.
|
||||
V0.1, 2011-08-16, linyunfeng create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/slab.h>
|
||||
#include <mach/gpio.h>
|
||||
#include <mach/pmic.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <mach/board.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_i2c.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <mach/board.h>
|
||||
#include <mach/gpiomux.h>
|
||||
|
||||
#include "oled_ssd1306_pt.h"
|
||||
#include "oled_pt.h"
|
||||
|
||||
//#define OLED_SSD1306_DEBUG
|
||||
|
||||
typedef unsigned int boolean;
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
uint8_t oled_ssd1306_buf[COLUMN_NUM * PAGE_NUM] = {0};
|
||||
static uint8_t frame_data[COLUMN_NUM * PAGE_NUM + 1] ={0};
|
||||
static uint8_t oled_ssd1306_image[COLUMN_NUM * PAGE_NUM] = {0};
|
||||
|
||||
struct ssd1306_state_type{
|
||||
boolean disp_initialized;
|
||||
boolean display_on;
|
||||
boolean disp_powered_up;
|
||||
};
|
||||
|
||||
struct ssd1306_work_t {
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
struct ssd1306_i2c_reg_conf {
|
||||
unsigned short waddr;
|
||||
unsigned short wdata;
|
||||
};
|
||||
|
||||
static struct ssd1306_state_type ssd1306_state = {0};
|
||||
struct oled_panel_data oled_ssd1306_panel_data;
|
||||
static struct oled_panel_data *oled_ssd1306_pdata;
|
||||
|
||||
static DECLARE_WAIT_QUEUE_HEAD(ssd1306_wait_queue);
|
||||
static struct ssd1306_work_t *ssd1306_sensorw;
|
||||
static struct i2c_client *ssd1306_client;
|
||||
static struct mutex flush_mutex;
|
||||
static struct mutex oled_panel_mutex;
|
||||
|
||||
/* Data/Command flag, 0: Command, 1: Data */
|
||||
static int oled_ssd1306_sa0;
|
||||
|
||||
/* Chip select, always 0 in I2C mode */
|
||||
static int oled_ssd1306_cs;
|
||||
|
||||
/* [ZhangTao start] for getting the gpio number configered in the dts file */
|
||||
enum ENUM_OLED_SSD1306_GPIO {
|
||||
GPIO_OLED_CS = 0,
|
||||
GPIO_OLED_A0,
|
||||
GPIO_OLED_RES,
|
||||
GPIO_OLED_BOOST_EN,
|
||||
|
||||
GPIO_OLED_END
|
||||
};
|
||||
|
||||
/* enum the gpio name defined in the dts config file */
|
||||
static const char *dts_gpio_name[] = {
|
||||
[GPIO_OLED_CS] = "qcom,oled-cs-gpio",
|
||||
[GPIO_OLED_A0] = "qcom,oled-a0-gpio",
|
||||
[GPIO_OLED_RES] = "qcom,oled-res-gpio",
|
||||
[GPIO_OLED_BOOST_EN] = "qcom,oled-boost-en-gpio",
|
||||
|
||||
[GPIO_OLED_END] = "",
|
||||
};
|
||||
|
||||
/* Store oled ssd1306 gpio pin number, will be filled by get_gpio_by_dtsname() */
|
||||
static int oled_ssd1306_gpio[GPIO_OLED_END] = {0};
|
||||
|
||||
/*******************************************************************************
|
||||
Function : get_gpio_by_dtsname
|
||||
Description : get gpio pin number by name defined in dts config file.
|
||||
Input : @node, the device node defined in dts which we get the gpio pin number form
|
||||
@gpio_name[], the string array which store the gpio name defined in dts file
|
||||
@gpio_num, we will store the gpio pin number getted from dts file in the int array gpio_num point to
|
||||
@len, the numbers of gpio we will get
|
||||
Output : gpio_num: the request gpios pin number which gpio_num point to
|
||||
Return : void
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static void get_gpio_by_dtsname(struct device_node *node, const char *gpio_name[], u32 *gpio_num, int len)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < len; ++ i)
|
||||
{
|
||||
gpio_num[i] = of_get_named_gpio(node, gpio_name[i], 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_config_gpios
|
||||
Description : request/free for specific gpio
|
||||
Input : @enable, 0: free gpios, 1: request gpios
|
||||
Output : request or free the specific gpio stored in oled_ssd1306_gpio[]
|
||||
Return : void
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static void oled_ssd1306_config_gpios(int enable)
|
||||
{
|
||||
int i, rc = 0;
|
||||
|
||||
for (i = 0; i < GPIO_OLED_END; ++ i)
|
||||
{
|
||||
if (enable) {
|
||||
rc = gpio_request(oled_ssd1306_gpio[i], dts_gpio_name[i]);
|
||||
if (rc)
|
||||
{
|
||||
pr_err("request gpio %s failed, rc=%d\n", dts_gpio_name[i], rc);
|
||||
gpio_free(oled_ssd1306_gpio[i]);
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
gpio_free(oled_ssd1306_gpio[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_power_save
|
||||
Description : power on/off the oled
|
||||
Input : @on, 0: power off, 1: power on
|
||||
Output :
|
||||
Return : None
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_power_save(int on)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (on) {
|
||||
gpio_direction_output(oled_ssd1306_gpio[GPIO_OLED_RES], 0);
|
||||
mdelay(1);
|
||||
|
||||
gpio_direction_output(oled_ssd1306_gpio[GPIO_OLED_BOOST_EN], 1);
|
||||
mdelay(1);
|
||||
|
||||
__gpio_set_value(oled_ssd1306_gpio[GPIO_OLED_RES], 1);
|
||||
mdelay(1);
|
||||
} else {
|
||||
gpio_direction_output(oled_ssd1306_gpio[GPIO_OLED_BOOST_EN], 0);
|
||||
mdelay(1);
|
||||
|
||||
gpio_direction_output(oled_ssd1306_gpio[GPIO_OLED_RES], 0);
|
||||
mdelay(1);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
/* [ZhangTao end]*/
|
||||
|
||||
static int ssd1306_i2c_txdata(const uint16_t saddr,
|
||||
uint8_t *txdata, const uint16_t length)
|
||||
{
|
||||
struct i2c_msg msg[] = {
|
||||
{
|
||||
.addr = saddr,
|
||||
.flags = 0,
|
||||
.len = length,
|
||||
.buf = txdata,
|
||||
},
|
||||
};
|
||||
|
||||
if (i2c_transfer(ssd1306_client->adapter, msg, 1) < 0) {
|
||||
printk("ssd1306_i2c_txdata faild 0x%x\n", saddr);
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_print_buffer
|
||||
Description : print the oled buffer data, hex
|
||||
Input : None
|
||||
Output : buf: Command line buffer
|
||||
Return : The number of characters will display in command
|
||||
line.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_print_buffer(char *buf)
|
||||
{
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
||||
for (i = 0; i < PAGE_NUM; i++){
|
||||
for (j = 0; j < COLUMN_NUM; j++) {
|
||||
sprintf(buf + 3 *(i * (COLUMN_NUM + 1) + j), "%02x ",
|
||||
*(oled_ssd1306_image
|
||||
+ (i << COLUMN_NUM_EXP) + j));
|
||||
}
|
||||
sprintf(buf + (i + 1) * 3 * (COLUMN_NUM + 1) - 3, " \n" );
|
||||
}
|
||||
|
||||
return (COLUMN_NUM + 1) * 3 * PAGE_NUM;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : ssd1306_i2c_write_cmd
|
||||
Description : Send command by I2C
|
||||
Input : data: Command will be send
|
||||
len: The length of Command
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int ssd1306_i2c_write_cmd(const uint8_t *data, const uint16_t len)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
#ifdef OLED_SSD1306_DEBUG
|
||||
int i = 0;
|
||||
printk("%s, data = 0x%x, len = %d\n", __func__, *data, len);
|
||||
#endif
|
||||
|
||||
if (TRUE == ssd1306_state.disp_powered_up) {
|
||||
|
||||
*frame_data = OLED_CONTROL_CMDS;
|
||||
memcpy(frame_data + 1, data, len);
|
||||
|
||||
#ifdef OLED_SSD1306_DEBUG
|
||||
for (i = 0; i < len + 1; i++){
|
||||
printk("0x%x ", *(frame_data+i));
|
||||
}
|
||||
printk("\n");
|
||||
#endif
|
||||
|
||||
rc = ssd1306_i2c_txdata(ssd1306_client->addr, frame_data, len + 1);
|
||||
|
||||
if (rc < 0) {
|
||||
printk("%s fail, data = 0x%x, len = %d\n",
|
||||
__func__, *data, len);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : ssd1306_i2c_write_data
|
||||
Description : Send data by I2C
|
||||
Input : data: Data will be send
|
||||
len: The length of data
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int ssd1306_i2c_write_data(const uint8_t *data, const uint16_t len)
|
||||
{
|
||||
int rc = -EFAULT;
|
||||
|
||||
#ifdef OLED_SSD1306_DEBUG
|
||||
printk("%s, data = 0x%x, len = %d\n", __func__, *data, len);
|
||||
#endif
|
||||
|
||||
if (TRUE == ssd1306_state.disp_powered_up) {
|
||||
|
||||
*frame_data = OLED_CONTROL_DATAS;
|
||||
memcpy(frame_data + 1, data, len);
|
||||
|
||||
rc = ssd1306_i2c_txdata((ssd1306_client->addr),
|
||||
frame_data, len + 1);
|
||||
if (rc < 0) {
|
||||
printk("%s fail, data = 0x%x, len = %d\n",
|
||||
__func__, *data, len);
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void oled_ssd1306_pin_assign(void)
|
||||
{
|
||||
/* Setting the Default GPIO's */
|
||||
oled_ssd1306_sa0 = oled_ssd1306_gpio[GPIO_OLED_A0];
|
||||
oled_ssd1306_cs = oled_ssd1306_gpio[GPIO_OLED_CS];
|
||||
}
|
||||
|
||||
static int oled_ssd1306_area_check(const uint8_t x, const uint8_t y,
|
||||
const uint8_t width, const uint8_t height)
|
||||
{
|
||||
if ((x < 0) || (y < 0) || (width <= 0) || (height <= 0)
|
||||
|| (x + width > COLUMN_NUM) || (y + height > PAGE_NUM)){
|
||||
printk("%s error, row_start=%d, col_start=%d, width=%d, height=%d",
|
||||
__func__, x, y, width, height);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* [wuzhong start] */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
|
||||
static int oled_sh1106_and_ssd1306_fill_with_pic(const uint8_t *pic, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s,width=%d, height=%d\n", __func__, width, height);
|
||||
#endif
|
||||
|
||||
if (oled_ssd1306_area_check(x, y, width, height)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (TRUE == ssd1306_state.disp_initialized) {
|
||||
mutex_lock(&flush_mutex);
|
||||
|
||||
for (i = 0; i < height; i++)
|
||||
{
|
||||
oled_sh1106_flush_cmd[1] = 0xb0 + y + i;
|
||||
oled_sh1106_flush_cmd[2] = (x + SH1106_OFFSET) & 0x0f;
|
||||
oled_sh1106_flush_cmd[3] = (((x + SH1106_OFFSET) & 0xf0) >> 4) | 0x10;
|
||||
|
||||
ssd1306_i2c_write_cmd(oled_sh1106_flush_cmd, sizeof(oled_sh1106_flush_cmd));
|
||||
ssd1306_i2c_write_data(pic + i * width, width);
|
||||
}
|
||||
|
||||
for (i = y; i < y + height; i++) {
|
||||
memcpy(oled_ssd1306_image + (i << COLUMN_NUM_EXP) + x,
|
||||
pic + width * (i - y), width);
|
||||
}
|
||||
|
||||
mutex_unlock(&flush_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#else /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_fill_with_pic
|
||||
Description : Fill and flush certain area with picture.
|
||||
Input : pic: Picture to fill
|
||||
x: Start point, x coordinate, 0 ~ COLUMN_NUM - 1
|
||||
y: Start point, y coordiante, 0 ~ PAGE_NUM - 1
|
||||
width: Area width
|
||||
height: Area height
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_fill_with_pic(const uint8_t *pic, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s,width=%d, height=%d\n", __func__, width, height);
|
||||
#endif
|
||||
|
||||
if (oled_ssd1306_area_check(x, y, width, height)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (TRUE == ssd1306_state.disp_initialized) {
|
||||
mutex_lock(&flush_mutex);
|
||||
*(oled_ssd1306_flush_cmd_config.col_addr_start) = x;
|
||||
*(oled_ssd1306_flush_cmd_config.col_addr_end) = x + width - 1;
|
||||
*(oled_ssd1306_flush_cmd_config.page_addr_start) = y;
|
||||
*(oled_ssd1306_flush_cmd_config.page_addr_end) = y + height - 1;
|
||||
|
||||
ssd1306_i2c_write_cmd(oled_ssd1306_flush_cmd, sizeof(oled_ssd1306_flush_cmd));
|
||||
|
||||
ssd1306_i2c_write_data(pic, width * height);
|
||||
|
||||
for (i = y; i < y + height; i++) {
|
||||
memcpy(oled_ssd1306_image + (i << COLUMN_NUM_EXP) + x,
|
||||
pic + width * (i - y), width);
|
||||
}
|
||||
|
||||
mutex_unlock(&flush_mutex);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#endif /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
/* [wuzhong end] */
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_fill_with_value
|
||||
Description : Fill and flush certain area with value.
|
||||
Input : value: Value to fill
|
||||
x: Start point, x coordinate, 0 ~ COLUMN_NUM - 1
|
||||
y: Start point, y coordiante, 0 ~ PAGE_NUM - 1
|
||||
width: Area width
|
||||
height: Area height
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_fill_with_value(const uint8_t value, const uint8_t x,
|
||||
const uint8_t y, const uint8_t width, const uint8_t height)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if (oled_ssd1306_area_check(x, y, width, height)) {
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(oled_ssd1306_buf, value, width * height);
|
||||
|
||||
/* [wuzhong start] */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
return oled_sh1106_and_ssd1306_fill_with_pic(oled_ssd1306_buf, x, y, width, height);
|
||||
#else
|
||||
return oled_ssd1306_fill_with_pic(oled_ssd1306_buf, x, y, width, height);
|
||||
#endif
|
||||
/* [wuzhong end] */
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_fade_blink
|
||||
Description : Fade out or blink.
|
||||
Input : mode: 0: Disable Fade Out / Blinking Mode.
|
||||
2: Enable Fade Out mode.
|
||||
3: Enable Blinking mode.
|
||||
t_interval_scroll: Set time interval for each fade step, 0~7,
|
||||
(8 * t_interval_scroll + 1))frames
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_fade_blink(const uint8_t mode, const uint8_t t_interval_scroll)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if ((mode < 0) || (t_interval_scroll < 0) || (mode > 3)
|
||||
|| (1 == mode) || (t_interval_scroll > 15)) {
|
||||
printk("%s error, mode=%d, t_interval_scroll=%d",
|
||||
__func__, mode, t_interval_scroll);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
*(oled_ssd1306_fade_blink_cmd_config.fade_blink_parameter)
|
||||
= (mode << 4) | t_interval_scroll;
|
||||
|
||||
return ssd1306_i2c_write_cmd(oled_ssd1306_fade_blink_cmd, sizeof(oled_ssd1306_fade_blink_cmd));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_scroll_stop
|
||||
Description : Stop scroll.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_scroll_stop(void)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
return ssd1306_i2c_write_cmd(oled_ssd1306_scroll_stop_cmd, sizeof(oled_ssd1306_scroll_stop_cmd));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_horizontal_scroll
|
||||
Description : Horizontal scroll.
|
||||
Input : y: Start point, y coordiante, 0 ~ PAGE_NUM - 1
|
||||
height: Scroll area height
|
||||
t_interval_scroll: 0: 5 frame, 1: 64, 2: 128, 3: 256,
|
||||
4: 3, 5: 4, 6: 25, 7: 2
|
||||
direction: 0: Left->Right, 1:Right->Left
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_horizontal_scroll(const uint8_t y, const uint8_t height,
|
||||
const uint8_t t_interval_scroll, const uint8_t direction)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if ((y < 0) || (height < 0) || (y + height > PAGE_NUM)
|
||||
|| (t_interval_scroll < 0) || (t_interval_scroll > 7)
|
||||
|| (direction < 0) || (direction > 1)) {
|
||||
printk("%s error, y=%d, height=%d, t_interval_scroll=%d, direction=%d",
|
||||
__func__, y, height, t_interval_scroll, direction);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
oled_ssd1306_scroll_stop();
|
||||
mdelay(1);
|
||||
|
||||
*(oled_ssd1306_h_scroll_cmd_config.horizontal_scroll_direction) = CMD_HORIZONTAL_SCROLL_ARRAY[direction];
|
||||
*(oled_ssd1306_h_scroll_cmd_config.page_addr_start) = y;
|
||||
*(oled_ssd1306_h_scroll_cmd_config.time_interval_scroll) = t_interval_scroll;
|
||||
*(oled_ssd1306_h_scroll_cmd_config.page_addr_end) = y + height - 1;
|
||||
|
||||
return ssd1306_i2c_write_cmd(oled_ssd1306_h_scroll_cmd, sizeof(oled_ssd1306_h_scroll_cmd));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_set_backlight
|
||||
Description : Set backlight on or off.
|
||||
Input : on: 0: off, 1: on.
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_set_backlight(const uint8_t on)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s, on =%u\n", __func__, on);
|
||||
#endif
|
||||
|
||||
if (0 == on) {
|
||||
oled_ssd1306_backlight_cmd[0] = CMD_DISPLAY_OFF_ON(0);
|
||||
} else {
|
||||
oled_ssd1306_backlight_cmd[0] = CMD_DISPLAY_OFF_ON(1);
|
||||
}
|
||||
|
||||
return ssd1306_i2c_write_cmd(oled_ssd1306_backlight_cmd, sizeof(oled_ssd1306_backlight_cmd));
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : ssd1306_disp_on
|
||||
Description : initial oled.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static void ssd1306_disp_on(void)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if (ssd1306_state.disp_powered_up && !ssd1306_state.display_on) {
|
||||
ssd1306_i2c_write_cmd(oled_ssd1306_init_cmd, sizeof(oled_ssd1306_init_cmd));
|
||||
|
||||
ssd1306_state.display_on = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : ssd1306_disp_powerup
|
||||
Description : Power and initial.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static void ssd1306_disp_powerup(void)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
|
||||
if (!ssd1306_state.disp_powered_up && !ssd1306_state.display_on) {
|
||||
/* Reset the hardware first */
|
||||
ssd1306_state.disp_powered_up = TRUE;
|
||||
if (oled_ssd1306_pdata->oled_power_save)
|
||||
oled_ssd1306_pdata->oled_power_save(1);
|
||||
|
||||
gpio_direction_output(oled_ssd1306_cs, 0);
|
||||
gpio_direction_output(oled_ssd1306_sa0, 0);
|
||||
mdelay(5);
|
||||
|
||||
/* CS will be always 0 in I2C mode */
|
||||
__gpio_set_value(oled_ssd1306_cs, 0);
|
||||
/* SA0 is used to determine the I2C address in I2C mode */
|
||||
__gpio_set_value(oled_ssd1306_sa0, 0);
|
||||
mdelay(3);
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_panel_on
|
||||
Description : Power and initial oled SSD1306.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_panel_on(void)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
mutex_lock(&oled_panel_mutex);
|
||||
if (!ssd1306_state.disp_initialized) {
|
||||
/* Configure reset GPIO that drives DAC */
|
||||
if (oled_ssd1306_pdata->oled_gpio_config)
|
||||
oled_ssd1306_pdata->oled_gpio_config(1);
|
||||
ssd1306_disp_powerup();
|
||||
ssd1306_disp_on();
|
||||
ssd1306_state.disp_initialized = TRUE;
|
||||
}
|
||||
mutex_unlock(&oled_panel_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
Function : oled_ssd1306_panel_off
|
||||
Description : Power down oled SSD1306.
|
||||
Input : None
|
||||
Output : None
|
||||
Return : 0: OK, Others: Error.
|
||||
Others : None
|
||||
*******************************************************************************/
|
||||
static int oled_ssd1306_panel_off(void)
|
||||
{
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
mutex_lock(&oled_panel_mutex);
|
||||
if (ssd1306_state.disp_powered_up && ssd1306_state.display_on) {
|
||||
/* Main panel power off (Deep standby in) */
|
||||
ssd1306_i2c_write_cmd(oled_ssd1306_panel_off_cmd,
|
||||
sizeof(oled_ssd1306_panel_off_cmd));
|
||||
mdelay(100); /* Typical 100ms */
|
||||
|
||||
if (oled_ssd1306_pdata->oled_power_save)
|
||||
oled_ssd1306_pdata->oled_power_save(0);
|
||||
|
||||
if (oled_ssd1306_pdata->oled_gpio_config)
|
||||
oled_ssd1306_pdata->oled_gpio_config(0);
|
||||
ssd1306_state.disp_powered_up = FALSE;
|
||||
ssd1306_state.display_on = FALSE;
|
||||
ssd1306_state.disp_initialized = FALSE;
|
||||
}
|
||||
mutex_unlock(&oled_panel_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devinit oled_ssd1306_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
if (!node)
|
||||
{
|
||||
dev_err(&pdev->dev, "%s: device tree information missing\n", __func__);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
printk("%s\n", __func__);
|
||||
|
||||
pdev->dev.platform_data = &oled_ssd1306_panel_data;
|
||||
oled_ssd1306_pdata = pdev->dev.platform_data;
|
||||
|
||||
/* get gpios' number by name defined in the dts config file and store them in oled_ssd1306_gpio array */
|
||||
get_gpio_by_dtsname(node, dts_gpio_name, oled_ssd1306_gpio, GPIO_OLED_END);
|
||||
|
||||
oled_ssd1306_pin_assign();
|
||||
|
||||
/* [ZhangTao start] */
|
||||
oled_ssd1306_pdata->oled_gpio_config = oled_ssd1306_config_gpios;
|
||||
oled_ssd1306_pdata->oled_power_save = oled_ssd1306_power_save;
|
||||
/* [ZhangTao end] */
|
||||
|
||||
oled_ssd1306_pdata->oled_panel_on = oled_ssd1306_panel_on;
|
||||
oled_ssd1306_pdata->oled_panel_off = oled_ssd1306_panel_off;
|
||||
oled_ssd1306_pdata->oled_horizontal_scroll = oled_ssd1306_horizontal_scroll;
|
||||
oled_ssd1306_pdata->oled_scroll_stop = oled_ssd1306_scroll_stop;
|
||||
oled_ssd1306_pdata->oled_fade_blink = oled_ssd1306_fade_blink;
|
||||
|
||||
/* [wuzhong start] */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
oled_ssd1306_pdata->oled_fill_with_pic = oled_sh1106_and_ssd1306_fill_with_pic;
|
||||
#else
|
||||
oled_ssd1306_pdata->oled_fill_with_pic = oled_ssd1306_fill_with_pic;
|
||||
#endif
|
||||
/* [wuzhong end] */
|
||||
|
||||
oled_ssd1306_pdata->oled_fill_with_value = oled_ssd1306_fill_with_value;
|
||||
oled_ssd1306_pdata->oled_print_buffer = oled_ssd1306_print_buffer;
|
||||
oled_ssd1306_pdata->oled_set_backlight = oled_ssd1306_set_backlight;
|
||||
oled_ssd1306_pdata->panel_width = COLUMN_NUM;
|
||||
oled_ssd1306_pdata->panel_height = PAGE_NUM;
|
||||
|
||||
mutex_init(&flush_mutex);
|
||||
mutex_init(&oled_panel_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit oled_ssd1306_remove(struct platform_device *pdev)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __devexit ssd1306_i2c_remove(struct i2c_client *client)
|
||||
{
|
||||
struct ssd1306_work_t *ssd1306 = i2c_get_clientdata(client);
|
||||
free_irq(client->irq, ssd1306);
|
||||
ssd1306_client = NULL;
|
||||
kfree(ssd1306);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1306_init_client(struct i2c_client *client)
|
||||
{
|
||||
/* Initialize the MSM_CAMI2C Chip */
|
||||
init_waitqueue_head(&ssd1306_wait_queue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ssd1306_i2c_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
int rc = 0;
|
||||
printk("%s called!\n", __func__);
|
||||
|
||||
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
|
||||
printk("i2c_check_functionality failed\n");
|
||||
goto probe_failure;
|
||||
}
|
||||
|
||||
ssd1306_sensorw = kzalloc(sizeof(struct ssd1306_work_t), GFP_KERNEL);
|
||||
if (!ssd1306_sensorw) {
|
||||
printk("kzalloc failed.\n");
|
||||
rc = -ENOMEM;
|
||||
goto probe_failure;
|
||||
}
|
||||
|
||||
i2c_set_clientdata(client, ssd1306_sensorw);
|
||||
ssd1306_init_client(client);
|
||||
ssd1306_client = client;
|
||||
|
||||
msleep(50);
|
||||
|
||||
printk("%s successed! rc = %d\n", __func__, rc);
|
||||
return 0;
|
||||
|
||||
probe_failure:
|
||||
printk("%s failed! rc = %d\n", __func__, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static struct of_device_id qcom_ssd1306_i2c_table[] = {
|
||||
{ .compatible = "qcom,ssd1306",},
|
||||
{ },
|
||||
};
|
||||
|
||||
static const struct i2c_device_id ssd1306_i2c_id[] = {
|
||||
{"ssd1306", 0},
|
||||
{ }
|
||||
};
|
||||
|
||||
static struct i2c_driver ssd1306_i2c_driver = {
|
||||
.id_table = ssd1306_i2c_id,
|
||||
.probe = ssd1306_i2c_probe,
|
||||
.remove = __exit_p(ssd1306_i2c_remove),
|
||||
.driver = {
|
||||
.name = "ssd1306",
|
||||
.of_match_table = qcom_ssd1306_i2c_table,
|
||||
},
|
||||
};
|
||||
|
||||
static struct of_device_id qcom_ssd1306_pt_table[] = {
|
||||
{ .compatible = "qcom,oled_ssd1306_pt",},
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct platform_driver this_driver = {
|
||||
.probe = oled_ssd1306_probe,
|
||||
.remove = __devexit_p(oled_ssd1306_remove),
|
||||
.driver = {
|
||||
.name = "oled_ssd1306_pt",
|
||||
.of_match_table = qcom_ssd1306_pt_table,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init oled_ssd1306_panel_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
#if defined(OLED_SSD1306_DEBUG)
|
||||
printk("%s\n", __func__);
|
||||
#endif
|
||||
ret = platform_driver_register(&this_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = i2c_add_driver(&ssd1306_i2c_driver);
|
||||
|
||||
if (ret < 0 || ssd1306_client == NULL) {
|
||||
ret = -ENOTSUPP;
|
||||
printk("I2C add driver failed");
|
||||
goto fail_driver;
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
fail_driver:
|
||||
platform_driver_unregister(&this_driver);
|
||||
return ret;
|
||||
}
|
||||
|
||||
device_initcall(oled_ssd1306_panel_init);
|
||||
|
||||
MODULE_AUTHOR("Lin Yunfeng");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_DESCRIPTION("OLED SSD1306 driver");
|
||||
|
@ -1,272 +0,0 @@
|
||||
/*******************************************************************************
|
||||
Copyright (C), 1996-2012, TP-LINK TECHNOLOGIES CO., LTD.
|
||||
File name : oled_ssd1306_pt.h
|
||||
Description : Driver for OLED SSD1306.
|
||||
Author : linyunfeng
|
||||
|
||||
History:
|
||||
------------------------------
|
||||
V0.1, 2011-08-16, linyunfeng create file.
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef __OLED_SSD1306_PT_H__
|
||||
#define __OLED_SSD1306_PT_H__
|
||||
|
||||
/* [wuzhong start] 2012-11-29 */
|
||||
#define __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
/* [wuzhong end] */
|
||||
|
||||
|
||||
#define PAGE_NUM 8 /* 0~7 */
|
||||
|
||||
/* [wuzhong start] 2012-11-29 */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
#define COLUMN_NUM 132
|
||||
#else
|
||||
#define COLUMN_NUM 128
|
||||
#endif
|
||||
/* [wuzhong end] */
|
||||
|
||||
#define COLUMN_NUM_EXP 7 /* 2^7 = 128 */
|
||||
|
||||
/*
|
||||
* Four Formats:
|
||||
* 1. CMD_CONTROL BYTE . CMD . CMD . CMD <20><><EFBFBD><EFBFBD>
|
||||
* 2. CMD_CONTROL BYTE . CMD . CMD_CONTROL_BYTE . CMD <20><><EFBFBD><EFBFBD>
|
||||
* 3. DAT_CONTROL BYTE . DATA . DATA . DATA <20><><EFBFBD><EFBFBD>
|
||||
* 4. DAT_CONTROL BYTE . DATA . DAT_CONTROL_BYTE . DATA <20><><EFBFBD><EFBFBD>
|
||||
*/
|
||||
#define OLED_CONTROL_CMDS 0x00
|
||||
#define OLED_CONTROL_CMD_PAIRS 0x80
|
||||
#define OLED_CONTROL_DATAS 0x40
|
||||
#define OLED_CONTROL_DATA_PAIRS 0xC0
|
||||
|
||||
/* SINGLE CMDS */
|
||||
#define CMD_DUMMY_BYTE_ZERO 0x00
|
||||
#define CMD_DUMMY_BYTE_FF 0xFF
|
||||
#define CMD_GRAM_IGNORE(bit) (0xA4|(bit)) /* 0: No, 1: Yes */
|
||||
#define CMD_DISPLAY_OFF_ON(bit) (0xAE|(bit)) /* v: 0|1 */
|
||||
#define CMD_SCAN_DIRECTION_0_TO_N 0xC0
|
||||
#define CMD_SCAN_DIRECTION_N_TO_0 0xC8
|
||||
#define CMD_LOWER_COL_ADDR(addr) (0x00|(addr)) /* addr: 0~F */
|
||||
#define CMD_HIGHER_COL_ADDR(addr) (0x10|(addr)) /* addr: 0~F */
|
||||
#define CMD_SEGMENT_REMAP(dir) (0xA0|(dir)) /* dir:0 normal direction, dir:1 reverse direction */
|
||||
#define CMD_START_LINE(line) (0x40|(line)) /* line: 0 ~ 63 */
|
||||
#define CMD_NORMAL_REV_DISPLAY(bit) (0xA6|(bit)) /* bit:0 normal display, bit:1 reverse display */
|
||||
#define CMD_HORIZONTAL_SCROLL(dir) (0x26|(dir)) /* 0: L->R, 1:R->L */
|
||||
#define CMD_SCROLL_ENABLE(ena) (0x2E|(ena)) /* 0:Disable, 1:Enable */
|
||||
|
||||
/* DOUBLE CMDS */
|
||||
#define CMD_DOUBLE_CLOCK_DIVIDE_RATIO 0xD5
|
||||
#define CMD_DOUBLE_MULTIPLEX_RATIO 0xA8
|
||||
#define CMD_DOUBLE_PRECHARGE_PERIOD 0xD9
|
||||
#define CMD_DOUBLE_PADS_HW_CONFIG 0xDA /* Sequence: 0x02; Alternative: 0x12*/
|
||||
#define CMD_DOUBLE_CONTRAST_CONTROL 0x81
|
||||
#define CMD_DOUBLE_DISPLAY_OFFSET 0xD3 /* 0x00 ~ 3f */
|
||||
#define CMD_DOUBLE_VCOM_HLEVEL 0xDB /* 0x00 ~ 0xff */
|
||||
#define CMD_DOUBLE_SET_CHARGE_PUMP 0x8D /* Enable: 0x14, Disable: 0x10*/
|
||||
#define CMD_DOUBLE_MEMORY_ADDRESSING_MODE 0x20 /* 00: Horizontal 01: Vertial 10: Page 11: Invalid*/
|
||||
#define CMD_DOUBLE_FADE_BLINK_MODE 0x23 /* Fade out or blinking mode */
|
||||
|
||||
/* TRIPLE CMDS */
|
||||
#define CMD_TRIPE_COLUMN_ADDRESS 0x21 /* 0~127, 0~127 */
|
||||
#define CMD_TRIPE_PAGE_ADDRESS 0x22 /* 0~7, 0~7 */
|
||||
|
||||
#define OLED_MATREIAL_STANDARD_CONTRAST 0xAF
|
||||
#define OLED_MATREIAL_LOW_CONTRAST 0x0F
|
||||
|
||||
uint8_t CMD_HORIZONTAL_SCROLL_ARRAY[] = {CMD_HORIZONTAL_SCROLL(0), CMD_HORIZONTAL_SCROLL(1)};
|
||||
uint8_t CMD_BACKLIGHT_ARRAY[] = {
|
||||
CMD_DISPLAY_OFF_ON(0), /* Backlight off */
|
||||
CMD_DISPLAY_OFF_ON(1) /* Backlight oN */
|
||||
};
|
||||
|
||||
|
||||
/* [wuzhong start] 2012-11-29 */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
#define CMD_DC_DC_CONTROL 0xad
|
||||
#define CMD_DC_DC_ON 0x8b /* POR */
|
||||
#define CMD_DC_DC_OFF 0x8a
|
||||
#endif
|
||||
/* [wuzhong end] */
|
||||
|
||||
|
||||
uint8_t oled_ssd1306_init_cmd[] = {
|
||||
#if 0
|
||||
CMD_DISPLAY_OFF_ON(0),
|
||||
CMD_LOWER_COL_ADDR(0),
|
||||
CMD_HIGHER_COL_ADDR(0),
|
||||
CMD_START_LINE(0),
|
||||
CMD_DOUBLE_CONTRAST_CONTROL,
|
||||
OLED_MATREIAL_STANDARD_CONTRAST,
|
||||
CMD_SEGMENT_REMAP(1), /* left-right */
|
||||
CMD_NORMAL_REV_DISPLAY(0),
|
||||
CMD_SCAN_DIRECTION_N_TO_0, /* up-down */
|
||||
CMD_DOUBLE_MULTIPLEX_RATIO, 0x3F, /* something influence */
|
||||
CMD_DOUBLE_DISPLAY_OFFSET, 0x00,
|
||||
CMD_DOUBLE_CLOCK_DIVIDE_RATIO, 0xF0, /* something influence */
|
||||
CMD_DOUBLE_PRECHARGE_PERIOD, 0x22, /* something influence */
|
||||
CMD_DOUBLE_PADS_HW_CONFIG, 0x12,
|
||||
CMD_DOUBLE_VCOM_HLEVEL, 0x40, /* something influence */
|
||||
CMD_DOUBLE_SET_CHARGE_PUMP, 0x14, /* set charge pump enable*/
|
||||
CMD_DISPLAY_OFF_ON(1) /* manual display on */
|
||||
#else /* From vendor */
|
||||
|
||||
/* [wuzhong start] */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
|
||||
CMD_DISPLAY_OFF_ON(0),
|
||||
CMD_DOUBLE_CLOCK_DIVIDE_RATIO, 0x80, /* something influence */
|
||||
CMD_DOUBLE_MULTIPLEX_RATIO, 0x3f, /* something influence */
|
||||
CMD_DOUBLE_DISPLAY_OFFSET, 0x00,
|
||||
CMD_START_LINE(0),
|
||||
//CMD_DC_DC_CONTROL, CMD_DC_DC_ON, /* same with POR in sh1106, no this command in ssd1306 */
|
||||
CMD_DOUBLE_SET_CHARGE_PUMP, 0x14, /* set charge pump enable for ssd1306, no this command in sh1106 */
|
||||
//CMD_DOUBLE_MEMORY_ADDRESSING_MODE, 0x10, /* POR in ssd1306 , no this command in sh1106 */
|
||||
CMD_SEGMENT_REMAP(1), /* left-right */
|
||||
CMD_SCAN_DIRECTION_N_TO_0,
|
||||
CMD_DOUBLE_PADS_HW_CONFIG, 0x12,
|
||||
CMD_DOUBLE_CONTRAST_CONTROL,OLED_MATREIAL_STANDARD_CONTRAST, /* 0x40 was given in sh1106 init code(0x80 is recommended in sh1106 datasheet ), while SSD1306 use 0xaf */
|
||||
CMD_DOUBLE_PRECHARGE_PERIOD, 0xF1, /* TODO: */
|
||||
CMD_DOUBLE_VCOM_HLEVEL, 0x40, /* something influence */
|
||||
CMD_GRAM_IGNORE(0),
|
||||
CMD_NORMAL_REV_DISPLAY(0),
|
||||
//CMD_DISPLAY_OFF_ON(1) /* Backlight on */
|
||||
|
||||
#else /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
|
||||
CMD_DISPLAY_OFF_ON(0),
|
||||
CMD_DOUBLE_CLOCK_DIVIDE_RATIO, 0x80, /* something influence */
|
||||
CMD_DOUBLE_MULTIPLEX_RATIO, 0x3f, /* something influence */
|
||||
CMD_DOUBLE_DISPLAY_OFFSET, 0x00,
|
||||
CMD_START_LINE(0),
|
||||
CMD_DOUBLE_SET_CHARGE_PUMP, 0x14, /* set charge pump enable*/
|
||||
CMD_DOUBLE_MEMORY_ADDRESSING_MODE, 0x00,
|
||||
CMD_SEGMENT_REMAP(1), /* left-right */
|
||||
CMD_SCAN_DIRECTION_N_TO_0,
|
||||
CMD_DOUBLE_PADS_HW_CONFIG, 0x12,
|
||||
CMD_DOUBLE_CONTRAST_CONTROL,
|
||||
OLED_MATREIAL_STANDARD_CONTRAST,
|
||||
CMD_DOUBLE_PRECHARGE_PERIOD, 0xF1, /* something influence */
|
||||
CMD_DOUBLE_VCOM_HLEVEL, 0x40, /* something influence */
|
||||
CMD_GRAM_IGNORE(0),
|
||||
CMD_NORMAL_REV_DISPLAY(0),
|
||||
//CMD_DISPLAY_OFF_ON(1) /* Backlight on */
|
||||
|
||||
#endif /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
/* [wuzhong end] */
|
||||
|
||||
#endif /* From vendor */
|
||||
};
|
||||
|
||||
uint8_t oled_ssd1306_backlight_cmd[] = {
|
||||
CMD_DISPLAY_OFF_ON(0)
|
||||
};
|
||||
|
||||
uint8_t oled_ssd1306_panel_off_cmd[] = {
|
||||
CMD_DISPLAY_OFF_ON(0), /* manual display on */
|
||||
CMD_DOUBLE_SET_CHARGE_PUMP, 0x10 /* set charge pump enable*/
|
||||
};
|
||||
|
||||
uint8_t oled_ssd1306_scroll_stop_cmd[] = {
|
||||
CMD_SCROLL_ENABLE(0)
|
||||
};
|
||||
|
||||
/* Fade out or blinking mode */
|
||||
uint8_t oled_ssd1306_fade_blink_cmd[] = {
|
||||
CMD_DOUBLE_FADE_BLINK_MODE,
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* fade_blink_parameter:
|
||||
* A[5:4] = 00b Disable Fade Out / Blinking Mode
|
||||
* A[5:4] = 10b Enable Fade Out mode
|
||||
* A[5:4] = 11b Enable Blinking mode
|
||||
* A[3:0] : Set time interval for each fade step, (8 * (A[3:0] + 1))frames
|
||||
*/
|
||||
struct oled_ssd1306_fade_blink_cmd_config_struct {
|
||||
uint8_t *fade_blink_parameter;
|
||||
};
|
||||
|
||||
static struct oled_ssd1306_fade_blink_cmd_config_struct oled_ssd1306_fade_blink_cmd_config = {
|
||||
.fade_blink_parameter = &oled_ssd1306_fade_blink_cmd[1],
|
||||
};
|
||||
|
||||
/* [wuzhong start] */
|
||||
#ifdef __ENABLE_OLED_SH1106_AND_SSD1306__
|
||||
|
||||
// sh1106 is 4 pixel widder then ssd1306
|
||||
#define SH1106_OFFSET 2
|
||||
|
||||
//struct oled_sh1106_flush_cmd {
|
||||
// uint8_t* line_start;
|
||||
// uint8_t* low_column;
|
||||
// uint8_t* high_column;
|
||||
// uint8_t* page_number;
|
||||
//};
|
||||
|
||||
// line: 0x40 as default
|
||||
// page: range 0xb0~0xb7
|
||||
// low column: range 0x00~0x0f
|
||||
// high column: range 0x10~0x1f
|
||||
uint8_t oled_sh1106_flush_cmd[] = {
|
||||
0x40, 0xb0, 0x00, 0x10
|
||||
};
|
||||
|
||||
#else /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
|
||||
/* Flush the screen */
|
||||
uint8_t oled_ssd1306_flush_cmd[] = {
|
||||
CMD_DOUBLE_MEMORY_ADDRESSING_MODE, 0,
|
||||
CMD_TRIPE_COLUMN_ADDRESS, 0, (COLUMN_NUM - 1),
|
||||
CMD_TRIPE_PAGE_ADDRESS, 0, (PAGE_NUM - 1)
|
||||
};
|
||||
|
||||
struct oled_ssd1306_flush_cmd_config_struct {
|
||||
uint8_t *col_addr_start;
|
||||
uint8_t *col_addr_end;
|
||||
uint8_t *page_addr_start;
|
||||
uint8_t *page_addr_end;
|
||||
};
|
||||
|
||||
static struct oled_ssd1306_flush_cmd_config_struct oled_ssd1306_flush_cmd_config = {
|
||||
.col_addr_start = &oled_ssd1306_flush_cmd[3], /* Start column address, 0~127 */
|
||||
.col_addr_end = &oled_ssd1306_flush_cmd[4], /* End column address, 0~127 */
|
||||
.page_addr_start = &oled_ssd1306_flush_cmd[6], /* Start page address, 0~7 */
|
||||
.page_addr_end = &oled_ssd1306_flush_cmd[7], /* End page address, 0~7 */
|
||||
};
|
||||
|
||||
#endif /* __ENABLE_OLED_SH1106_AND_SSD1306__ */
|
||||
/* [wuzhong end] */
|
||||
|
||||
/* Horizontal scroll */
|
||||
uint8_t oled_ssd1306_h_scroll_cmd[] = {
|
||||
CMD_HORIZONTAL_SCROLL(0), /* Direction, 0: L->R, 1:R->L */
|
||||
CMD_DUMMY_BYTE_ZERO,
|
||||
0, /* Start page address */
|
||||
0, /* Frames interval between each scroll,
|
||||
* 0: 5 frame, 1: 64, 2: 128, 3: 256,
|
||||
* 4: 3, 5: 4, 6: 25, 7: 2 */
|
||||
(PAGE_NUM - 1), /* End page address */
|
||||
CMD_DUMMY_BYTE_ZERO,
|
||||
CMD_DUMMY_BYTE_FF,
|
||||
CMD_SCROLL_ENABLE(1)
|
||||
};
|
||||
|
||||
struct oled_ssd1306_h_scroll_cmd_config_struct {
|
||||
uint8_t *horizontal_scroll_direction;
|
||||
uint8_t *page_addr_start;
|
||||
uint8_t *time_interval_scroll;
|
||||
uint8_t *page_addr_end;
|
||||
};
|
||||
|
||||
static struct oled_ssd1306_h_scroll_cmd_config_struct oled_ssd1306_h_scroll_cmd_config = {
|
||||
.horizontal_scroll_direction = &oled_ssd1306_h_scroll_cmd[0],
|
||||
.page_addr_start = &oled_ssd1306_h_scroll_cmd[2],
|
||||
.time_interval_scroll = &oled_ssd1306_h_scroll_cmd[3],
|
||||
.page_addr_end = &oled_ssd1306_h_scroll_cmd[4],
|
||||
};
|
||||
|
||||
#endif /* __OLED_SSD1306_PT__ */
|
||||
|
Reference in New Issue
Block a user