add rgb2mipi display drivers for tc358768 and ssd2828

This commit is contained in:
hhb
2013-02-21 15:45:14 +08:00
parent 4b955ffded
commit bb7e7b9fe4
7 changed files with 866 additions and 136 deletions

View File

@@ -11,10 +11,6 @@ config RK610_LVDS
help
Support Jetta(RK610) to output LCD1 and LVDS.
config TC358768_RGB2MIPI
bool "toshiba RGB to MIPI DSI"
help
"a chip that change RGB interface parallel signal into DSI serial signal"
config DP_ANX6345
bool "RGB to Display Port transmitter anx6345,anx9804,anx9805 support"
@@ -23,3 +19,17 @@ config DP501
bool"RGB to Display Port transmitter dp501 support"
endchoice
config MIPI_DSI
bool "RGB to MIPI DSI"
config TC358768_RGB2MIPI
bool "toshiba TC358768 RGB to MIPI DSI"
depends on MIPI_DSI
help
"a chip that change RGB interface parallel signal into DSI serial signal"
config SSD2828_RGB2MIPI
bool "solomon SSD2828 RGB to MIPI DSI"
depends on MIPI_DSI
help
"a chip that change RGB interface parallel signal into DSI serial signal"

View File

@@ -2,6 +2,8 @@
# Makefile for display transmitter like lvds edp mipi
#
obj-$(CONFIG_RK610_LVDS) += rk610_lcd.o
obj-$(CONFIG_MIPI_DSI) += mipi_dsi.o
obj-$(CONFIG_TC358768_RGB2MIPI) += tc358768.o
obj-$(CONFIG_SSD2828_RGB2MIPI) += ssd2828.o
obj-$(CONFIG_DP_ANX6345) += dp_anx6345.o
obj-$(CONFIG_DP501) += dp501.o

View File

@@ -0,0 +1,162 @@
/*
* Copyright (C) 2012 ROCKCHIP, Inc.
*
* author: hhb@rock-chips.com
* create date: 2013-01-17
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "mipi_dsi.h"
#include <linux/module.h>
#include <linux/init.h>
#include <asm/system.h>
#define MAX_DSI_CHIPS 5
static struct mipi_dsi_ops *dsi_ops[MAX_DSI_CHIPS] = {NULL};
static struct mipi_dsi_ops *cur_dsi_ops;
int register_dsi_ops(struct mipi_dsi_ops *ops) {
int i = 0;
for(i = 0; i < MAX_DSI_CHIPS; i++) {
if(!dsi_ops[i]) {
dsi_ops[i] = ops;
break;
}
}
if(i == MAX_DSI_CHIPS) {
printk("dsi ops support 5 chips at most\n");
return -1;
}
return 0;
}
EXPORT_SYMBOL(register_dsi_ops);
int del_dsi_ops(struct mipi_dsi_ops *ops) {
int i = 0;
for(i = 0; i < MAX_DSI_CHIPS; i++) {
if(dsi_ops[i] == ops) {
dsi_ops[i] = NULL;
break;
}
}
if(cur_dsi_ops == ops)
cur_dsi_ops = NULL;
if(i == MAX_DSI_CHIPS) {
printk("dsi ops not found\n");
return -1;
}
return 0;
}
EXPORT_SYMBOL(del_dsi_ops);
int dsi_probe_current_chip(void) {
int i = 0, id;
struct mipi_dsi_ops *ops = NULL;
for(i = 0; i < MAX_DSI_CHIPS; i++) {
if(dsi_ops[i]) {
ops = dsi_ops[i];
id = ops->get_id();
if(id == ops->id) {
cur_dsi_ops = ops;
printk("load mipi dsi chip:%s id:%04x\n", ops->name, ops->id);
break;
} else {
printk("mipi dsi chip is not found, read id:%04x, but %04x is correct\n", id, ops->id);
dsi_ops[i] = NULL;
cur_dsi_ops = NULL;
}
}
}
if(i == MAX_DSI_CHIPS)
printk("no mipi dsi chip\n");
return 0;
}
EXPORT_SYMBOL(dsi_probe_current_chip);
int dsi_power_up(void) {
if(!cur_dsi_ops)
return -1;
if(cur_dsi_ops->power_up)
cur_dsi_ops->power_up();
return 0;
}
EXPORT_SYMBOL(dsi_power_up);
int dsi_power_off(void) {
if(!cur_dsi_ops)
return -1;
if(cur_dsi_ops->power_down)
cur_dsi_ops->power_down();
return 0;
}
EXPORT_SYMBOL(dsi_power_off);
int dsi_set_regs(void *array, int n) {
if(!cur_dsi_ops)
return -1;
if(cur_dsi_ops->dsi_set_regs)
cur_dsi_ops->dsi_set_regs(array, n);
return 0;
}
EXPORT_SYMBOL(dsi_set_regs);
int dsi_init(void *array, int n) {
if(!cur_dsi_ops)
return -1;
if(cur_dsi_ops->dsi_init)
cur_dsi_ops->dsi_init(array, n);
return 0;
}
EXPORT_SYMBOL(dsi_init);
int dsi_send_dcs_packet(unsigned char *packet, int n) {
if(!cur_dsi_ops)
return -1;
if(cur_dsi_ops->dsi_send_dcs_packet)
cur_dsi_ops->dsi_send_dcs_packet(packet, n);
return 0;
}
EXPORT_SYMBOL(dsi_send_dcs_packet);
int dsi_read_dcs_packet(unsigned char *packet, int n) {
if(!cur_dsi_ops)
return -1;
if(cur_dsi_ops->dsi_read_dcs_packet)
cur_dsi_ops->dsi_read_dcs_packet(packet, n);
return 0;
}
EXPORT_SYMBOL(dsi_read_dcs_packet);
int dsi_send_packet(void *packet, int n) {
if(!cur_dsi_ops)
return -1;
if(cur_dsi_ops->dsi_send_packet)
cur_dsi_ops->dsi_send_packet(packet, n);
return 0;
}
EXPORT_SYMBOL(dsi_send_packet);

View File

@@ -0,0 +1,107 @@
#ifndef MIPI_DSI_H_
#define MIPI_DSI_H_
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/rk_fb.h>
#include <linux/rk_screen.h>
#include <linux/ktime.h>
//DSI DATA TYPE
#define DTYPE_DCS_SWRITE_0P 0X05
#define DTYPE_DCS_SWRITE_1P 0X15
#define DTYPE_DCS_LWRITE 0X39
#define DTYPE_GEN_LWRITE 0X29
#define DTYPE_GEN_SWRITE_2P 0X23
#define DTYPE_GEN_SWRITE_1P 0X13
#define DTYPE_GEN_SWRITE_0P 0X03
struct spi_t {
int cs;
char* cs_mux_name;
int sck;
char* sck_mux_name;
int miso;
char* miso_mux_name;
int mosi;
char* mosi_mux_name;
};
struct power_t {
int enable_pin; //gpio that control power
char* mux_name;
u32 mux_mode;
u32 effect_value;
u32 min_voltage;
u32 max_voltage;
int (*enable)(void *);
int (*disable)(void *);
};
struct reset_t {
int reset_pin; //gpio that control reset
char* mux_name;
u32 mux_mode;
u32 effect_value;
u32 time_before_reset; //ms
u32 time_after_reset;
int (*do_reset)(void *);
};
struct tc358768_t {
u32 id;
struct reset_t reset;
struct power_t vddc;
struct power_t vddio;
struct power_t vdd_mipi;
struct i2c_client *client;
int (*gpio_init)(void *);
int (*gpio_deinit)(void *);
int (*power_up)(void);
int (*power_down)(void);
};
struct ssd2828_t {
u32 id;
struct reset_t reset;
struct power_t vddio;
struct power_t vdd_mipi;
struct spi_t spi;
int (*gpio_init)(void *);
int (*gpio_deinit)(void *);
int (*power_up)(void);
int (*power_down)(void);
};
struct mipi_dsi_ops {
u32 id;
char *name;
int (*get_id)(void);
int (*dsi_init)(void *, int n);
int (*dsi_set_regs)(void *, int n);
int (*dsi_send_dcs_packet)(unsigned char *, int n);
int (*dsi_read_dcs_packet)(unsigned char *, int n);
int (*dsi_send_packet)(void *, int n);
int (*power_up)(void);
int (*power_down)(void);
};
int register_dsi_ops(struct mipi_dsi_ops *ops);
int del_dsi_ops(struct mipi_dsi_ops *ops);
int dsi_power_up(void);
int dsi_power_off(void);
int dsi_probe_current_chip(void);
int dsi_init(void *array, int n);
int dsi_set_regs(void *array, int n);
int dsi_send_dcs_packet(unsigned char *packet, int n);
int dsi_read_dcs_packet(unsigned char *packet, int n);
int dsi_send_packet(void *packet, int n);
#endif /* end of MIPI_DSI_H_ */

View File

@@ -0,0 +1,503 @@
/*
* Copyright (C) 2012 ROCKCHIP, Inc.
*
* author: hhb@rock-chips.com
* create date: 2013-01-17
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation, and
* may be copied, distributed, and modified under those terms.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/rk_fb.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#include <mach/board.h>
#include <linux/rk_screen.h>
#include "mipi_dsi.h"
/* define spi gpio*/
#define TXD_PORT ssd2828->spi.mosi
#define CLK_PORT ssd2828->spi.sck
#define CS_PORT ssd2828->spi.cs
#define RXD_PORT ssd2828->spi.miso
#define CS_OUT() gpio_direction_output(CS_PORT, 0)
#define CS_SET() gpio_set_value(CS_PORT, GPIO_HIGH)
#define CS_CLR() gpio_set_value(CS_PORT, GPIO_LOW)
#define CLK_OUT() gpio_direction_output(CLK_PORT, 0)
#define CLK_SET() gpio_set_value(CLK_PORT, GPIO_HIGH)
#define CLK_CLR() gpio_set_value(CLK_PORT, GPIO_LOW)
#define TXD_OUT() gpio_direction_output(TXD_PORT, 0)
#define TXD_SET() gpio_set_value(TXD_PORT, GPIO_HIGH)
#define TXD_CLR() gpio_set_value(TXD_PORT, GPIO_LOW)
#define RXD_INPUT() gpio_direction_input(RXD_PORT)
#define RXD_GET() gpio_get_value(RXD_PORT)
struct ssd2828_t *ssd2828 = NULL;
int ssd2828_gpio_init(void *data) {
int ret = 0;
struct reset_t *reset = &ssd2828->reset;
struct power_t *vdd = &ssd2828->vddio;
struct spi_t *spi = &ssd2828->spi;
if(reset->reset_pin > INVALID_GPIO) {
ret = gpio_request(reset->reset_pin, "ssd2828_reset");
if (ret != 0) {
//gpio_free(reset->reset_pin);
printk("%s: request ssd2828_RST_PIN error\n", __func__);
} else {
if(reset->mux_name)
rk30_mux_api_set(reset->mux_name, 0);
gpio_direction_output(reset->reset_pin, reset->effect_value);
}
}
if(vdd->enable_pin > INVALID_GPIO) {
ret = gpio_request(vdd->enable_pin, "ssd2828_vddio");
if (ret != 0) {
//gpio_free(vdd->enable_pin);
printk("%s: request ssd2828_vddio_PIN error\n", __func__);
} else {
if(vdd->mux_name)
rk30_mux_api_set(vdd->mux_name, 0);
gpio_direction_output(vdd->enable_pin, !vdd->effect_value);
}
}
vdd = &ssd2828->vdd_mipi;
if(vdd->enable_pin > INVALID_GPIO) {
ret = gpio_request(vdd->enable_pin, "ssd2828_vdd_mipi");
if (ret != 0) {
//gpio_free(vdd->enable_pin);
printk("%s: request ssd2828_vdd_mipi_PIN error\n", __func__);
} else {
if(vdd->mux_name)
rk30_mux_api_set(vdd->mux_name, 0);
gpio_direction_output(vdd->enable_pin, !vdd->effect_value);
}
}
if(spi->cs > INVALID_GPIO) {
ret = gpio_request(spi->cs, "ssd2828_spi_cs");
if (ret != 0) {
//gpio_free(spi->cs);
printk("%s: request ssd2828_spi->cs_PIN error\n", __func__);
} else {
if(spi->cs_mux_name)
rk30_mux_api_set(spi->cs_mux_name, 0);
gpio_direction_output(spi->cs, GPIO_HIGH);
}
}
if(spi->sck > INVALID_GPIO) {
ret = gpio_request(spi->sck, "ssd2828_spi_sck");
if (ret != 0) {
//gpio_free(spi->sck);
printk("%s: request ssd2828_spi->sck_PIN error\n", __func__);
} else {
if(spi->sck_mux_name)
rk30_mux_api_set(spi->sck_mux_name, 0);
gpio_direction_output(spi->sck, GPIO_HIGH);
}
}
if(spi->mosi > INVALID_GPIO) {
ret = gpio_request(spi->mosi, "ssd2828_spi_mosi");
if (ret != 0) {
//gpio_free(spi->mosi);
printk("%s: request ssd2828_spi->mosi_PIN error\n", __func__);
} else {
if(spi->mosi_mux_name)
rk30_mux_api_set(spi->mosi_mux_name, 0);
gpio_direction_output(spi->mosi, GPIO_HIGH);
}
}
if(spi->miso > INVALID_GPIO) {
ret = gpio_request(spi->miso, "ssd2828_spi_miso");
if (ret != 0) {
//gpio_free(spi->miso);
printk("%s: request ssd2828_spi->miso_PIN error\n", __func__);
} else {
if(spi->miso_mux_name)
rk30_mux_api_set(spi->miso_mux_name, 0);
gpio_direction_input(spi->miso);
}
}
return 0;
}
int ssd2828_gpio_deinit(void *data) {
struct reset_t *reset = &ssd2828->reset;
struct power_t *vdd = &ssd2828->vddio;
struct spi_t *spi = &ssd2828->spi;
gpio_direction_input(reset->reset_pin);
gpio_free(reset->reset_pin);
gpio_direction_input(vdd->enable_pin);
gpio_free(vdd->enable_pin);
vdd = &ssd2828->vdd_mipi;
gpio_direction_input(vdd->enable_pin);
gpio_free(vdd->enable_pin);
gpio_direction_input(spi->cs);
gpio_free(spi->cs);
gpio_direction_input(spi->sck);
gpio_free(spi->sck);
gpio_direction_input(spi->mosi);
gpio_free(spi->mosi);
gpio_free(spi->miso);
return 0;
}
int ssd2828_reset(void *data) {
int ret = 0;
struct reset_t *reset = &ssd2828->reset;
if(reset->reset_pin <= INVALID_GPIO)
return -1;
gpio_set_value(reset->reset_pin, reset->effect_value);
if(reset->time_before_reset <= 0)
msleep(1);
else
msleep(reset->time_before_reset);
gpio_set_value(reset->reset_pin, !reset->effect_value);
if(reset->time_after_reset <= 0)
msleep(5);
else
msleep(reset->time_after_reset);
return ret;
}
int ssd2828_vdd_enable(void *data) {
int ret = 0;
struct power_t *vdd = (struct power_t *)data;
if(vdd->enable_pin > INVALID_GPIO) {
gpio_set_value(vdd->enable_pin, vdd->effect_value);
} else {
//for other control
}
return ret;
}
int ssd2828_vdd_disable(void *data) {
int ret = 0;
struct power_t *vdd = (struct power_t *)data;
if(vdd->enable_pin > INVALID_GPIO) {
gpio_set_value(vdd->enable_pin, !vdd->effect_value);
} else {
//for other control
}
return ret;
}
int ssd2828_power_up(void) {
int ret = 0;
struct ssd2828_t *ssd = (struct ssd2828_t *)ssd2828;
ssd2828_gpio_init(NULL);
ssd->vdd_mipi.enable(&ssd->vdd_mipi);
ssd->vddio.enable(&ssd->vddio);
ssd->reset.do_reset(&ssd->reset);
return ret;
}
int ssd2828_power_down(void) {
int ret = 0;
struct ssd2828_t *ssd = (struct ssd2828_t *)ssd2828;
ssd->vddio.disable(&ssd->vddio);
ssd->vdd_mipi.disable(&ssd->vdd_mipi);
ssd2828_gpio_deinit(NULL);
return ret;
}
/* spi write a data frame,type mean command or data
3 wire 24 bit SPI interface
*/
static void spi_send_data(unsigned int data)
{
unsigned int i;
CS_SET();
udelay(1);
CLK_SET();
TXD_SET();
CS_CLR();
udelay(1);
for (i = 0; i < 24; i++)
{
//udelay(1);
CLK_CLR();
udelay(1);
if (data & 0x00800000) {
TXD_SET();
} else {
TXD_CLR();
}
udelay(1);
CLK_SET();
udelay(1);
data <<= 1;
}
TXD_SET();
CS_SET();
}
static void spi_recv_data(unsigned int* data)
{
unsigned int i = 0, temp = 0x73; //read data
CS_SET();
udelay(1);
CLK_SET();
TXD_SET();
CS_CLR();
udelay(1);
for(i = 0; i < 8; i++) // 8 bits Data
{
udelay(1);
CLK_CLR();
if (temp & 0x80)
TXD_SET();
else
TXD_CLR();
temp <<= 1;
udelay(1);
CLK_SET();
udelay(1);
}
udelay(1);
temp = 0;
for(i = 0; i < 16; i++) // 16 bits Data
{
udelay(1);
CLK_CLR();
udelay(1);
CLK_SET();
udelay(1);
temp <<= 1;
if(RXD_GET() == GPIO_HIGH)
temp |= 0x01;
}
TXD_SET();
CS_SET();
*data = temp;
}
#define DEVIE_ID (0x70 << 16)
void send_ctrl_cmd(unsigned int cmd)
{
unsigned int out = (DEVIE_ID | cmd );
spi_send_data(out);
}
static void send_data_cmd(unsigned int data)
{
unsigned int out = (DEVIE_ID | (0x2 << 16) | data );
spi_send_data(out);
}
unsigned int ssd_read_register(unsigned int reg) {
unsigned int data = 0;
send_ctrl_cmd(reg);
spi_recv_data(&data);
return data;
}
void ssd_set_register(unsigned int reg_and_value)
{
send_ctrl_cmd(reg_and_value >> 16);
send_data_cmd(reg_and_value & 0x0000ffff);
}
int ssd_set_registers(unsigned int reg_array[], int n) {
int i = 0;
for(i = 0; i < n; i++) {
if(reg_array[i] < 0x00b00000) { //the lowest address is 0xb0 of ssd2828
if(reg_array[i] < 20000)
udelay(reg_array[i]);
else {
mdelay(reg_array[i]/1000);
}
} else {
ssd_set_register(reg_array[i]);
}
}
return 0;
}
int ssd_mipi_dsi_send_dcs_packet(unsigned char regs[], int n) {
//unsigned int data = 0, i = 0;
ssd_set_register(0x00B70363);
ssd_set_register(0x00B80000);
ssd_set_register(0x00Bc0001);
ssd_set_register(0x00Bf0000 | regs[0]);
msleep(1);
return 0;
}
int _ssd2828_send_packet(unsigned char type, unsigned char regs[], int n) {
return 0;
}
int ssd2828_send_packet(unsigned char type, unsigned char regs[], int n) {
return _ssd2828_send_packet(type, regs, n);
}
int ssd_mipi_dsi_read_dcs_packet(unsigned char *data, int n) {
//DCS READ
unsigned int i = 0;
i = ssd_read_register(0xc6);
printk("read mipi slave error:%04x\n", i);
ssd_set_register(0x00B70382);
ssd_set_register(0x00BB0008);
ssd_set_register(0x00C1000A);
ssd_set_register(0x00C00001);
ssd_set_register(0x00Bc0001);
ssd_set_register(0x00Bf0000 | *data);
msleep(10);
i = ssd_read_register(0xc6);
printk("read mipi slave error:%04x\n", i);
if(i & 1) {
i = ssd_read_register(0xff);
printk("read %02x:%04x\n", *data, i);
i = ssd_read_register(0xff);
printk("read %02x:%04x\n", *data, i);
i = ssd_read_register(0xff);
printk("read %02x:%04x\n", *data, i);
}
return 0;
}
int ssd2828_get_id(void) {
int id = -1;
ssd2828_power_up();
id = ssd_read_register(0xb0);
return id;
}
static struct mipi_dsi_ops ssd2828_ops = {
.id = 0x2828,
.name = "ssd2828",
.get_id = ssd2828_get_id,
.dsi_set_regs = ssd_set_registers,
.dsi_send_dcs_packet = ssd_mipi_dsi_send_dcs_packet,
.dsi_read_dcs_packet = ssd_mipi_dsi_read_dcs_packet,
.power_up = ssd2828_power_up,
.power_down = ssd2828_power_down,
};
static int ssd2828_probe(struct platform_device *pdev) {
if(pdev->dev.platform_data)
ssd2828 = pdev->dev.platform_data;
if(!ssd2828->gpio_init)
ssd2828->gpio_init = ssd2828_gpio_init;
if(!ssd2828->gpio_deinit)
ssd2828->gpio_deinit = ssd2828_gpio_deinit;
if(!ssd2828->power_up)
ssd2828->power_up = ssd2828_power_up;
if(!ssd2828->power_down)
ssd2828->power_down = ssd2828_power_down;
if(!ssd2828->reset.do_reset)
ssd2828->reset.do_reset = ssd2828_reset;
if(!ssd2828->vddio.enable)
ssd2828->vddio.enable = ssd2828_vdd_enable;
if(!ssd2828->vddio.disable)
ssd2828->vddio.disable = ssd2828_vdd_disable;
if(!ssd2828->vdd_mipi.enable)
ssd2828->vdd_mipi.enable = ssd2828_vdd_enable;
if(!ssd2828->vdd_mipi.disable)
ssd2828->vdd_mipi.disable = ssd2828_vdd_disable;
return 0;
}
static int ssd2828_remove(struct platform_device *pdev) {
if(!ssd2828)
ssd2828 = NULL;
return 0;
}
static struct platform_driver ssd2828_driver = {
.probe = ssd2828_probe,
.remove = ssd2828_remove,
//.suspend = mipi_dsi_suspend,
//.resume = mipi_dsi_resume,
.driver = {
.name = "ssd2828",
.owner = THIS_MODULE,
}
};
static int __init ssd2828_init(void)
{
platform_driver_register(&ssd2828_driver);
if(!ssd2828)
return -1;
register_dsi_ops(&ssd2828_ops);
if(ssd2828->id > 0)
ssd2828_ops.id = ssd2828->id;
return 0;
}
static void __exit ssd2828_exit(void)
{
platform_driver_unregister(&ssd2828_driver);
del_dsi_ops(&ssd2828_ops);
}
subsys_initcall_sync(ssd2828_init);
module_exit(ssd2828_exit);

View File

@@ -12,8 +12,19 @@
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "tc358768.h"
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/rk_fb.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#include <mach/board.h>
#include <linux/rk_screen.h>
#include <linux/ktime.h>
#include "mipi_dsi.h"
#define CONFIG_TC358768_I2C 1
#define CONFIG_TC358768_I2C_CLK 400*1000
#if 0
#define dsi_debug printk
@@ -22,9 +33,9 @@
#endif
#ifdef CONFIG_TC358768_I2C
struct tc358768_t *tc358768 = NULL;
struct i2c_client *tc358768_client = NULL;
struct mipi_dsi_t *dsi;
static struct tc358768_t *tc358768 = NULL;
static struct i2c_client *tc358768_client = NULL;
static struct mipi_dsi_ops tc358768_ops;
u32 i2c_write_32bits(u32 value)
@@ -89,7 +100,7 @@ int tc358768_gpio_init(void *data) {
if(reset->reset_pin > INVALID_GPIO) {
ret = gpio_request(reset->reset_pin, "tc358768_reset");
if (ret != 0) {
gpio_free(reset->reset_pin);
//gpio_free(reset->reset_pin);
printk("%s: request TC358768_RST_PIN error\n", __func__);
} else {
if(reset->mux_name)
@@ -101,7 +112,7 @@ int tc358768_gpio_init(void *data) {
if(vdd->enable_pin > INVALID_GPIO) {
ret = gpio_request(vdd->enable_pin, "tc358768_vddc");
if (ret != 0) {
gpio_free(vdd->enable_pin);
//gpio_free(vdd->enable_pin);
printk("%s: request TC358768_vddc_PIN error\n", __func__);
} else {
if(vdd->mux_name)
@@ -114,7 +125,7 @@ int tc358768_gpio_init(void *data) {
if(vdd->enable_pin > INVALID_GPIO) {
ret = gpio_request(vdd->enable_pin, "tc358768_vddio");
if (ret != 0) {
gpio_free(vdd->enable_pin);
//gpio_free(vdd->enable_pin);
printk("%s: request TC358768_vddio_PIN error\n", __func__);
} else {
if(vdd->mux_name)
@@ -127,7 +138,7 @@ int tc358768_gpio_init(void *data) {
if(vdd->enable_pin > INVALID_GPIO) {
ret = gpio_request(vdd->enable_pin, "tc358768_vdd_mipi");
if (ret != 0) {
gpio_free(vdd->enable_pin);
//gpio_free(vdd->enable_pin);
printk("%s: request TC358768_vdd_mipi_PIN error\n", __func__);
} else {
if(vdd->mux_name)
@@ -142,12 +153,18 @@ int tc358768_gpio_init(void *data) {
int tc358768_gpio_deinit(void *data) {
struct reset_t *reset = &tc358768->reset;
struct power_t *vdd = &tc358768->vddc;
gpio_direction_input(reset->reset_pin);
gpio_free(reset->reset_pin);
gpio_direction_input(vdd->enable_pin);
gpio_free(vdd->enable_pin);
vdd = &tc358768->vddio;
gpio_direction_input(vdd->enable_pin);
gpio_free(vdd->enable_pin);
vdd = &tc358768->vdd_mipi;
gpio_direction_input(vdd->enable_pin);
gpio_free(vdd->enable_pin);
return 0;
}
@@ -195,10 +212,12 @@ int tc358768_vdd_disable(void *data) {
}
int tc358768_power_up(void *data) {
int tc358768_power_up(void) {
int ret = 0;
struct tc358768_t *tc = (struct tc358768_t *)tc358768;
tc358768_gpio_init(NULL);
tc->vddc.enable(&tc->vddc);
tc->vdd_mipi.enable(&tc->vdd_mipi);
tc->vddio.enable(&tc->vddio);
@@ -207,13 +226,15 @@ int tc358768_power_up(void *data) {
return ret;
}
int tc358768_power_down(void *data) {
int tc358768_power_down(void) {
int ret = 0;
struct tc358768_t *tc = (struct tc358768_t *)tc358768;
tc->vddio.disable(&tc->vddio);
tc->vdd_mipi.disable(&tc->vdd_mipi);
tc->vddc.disable(&tc->vddc);
tc358768_gpio_deinit(NULL);
return ret;
}
@@ -222,7 +243,6 @@ static int tc358768_probe(struct i2c_client *client,
const struct i2c_device_id *did)
{
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
int ret = 0;
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C)) {
@@ -230,13 +250,14 @@ static int tc358768_probe(struct i2c_client *client,
"I2C-Adapter doesn't support I2C_FUNC_I2C\n");
return -EIO;
}
tc358768 = (struct tc358768_t *)client->dev.platform_data;
if(!tc358768) {
ret = -1;
printk("%s:%d tc358768 is null\n", __func__, __LINE__);
return ret;
}
tc358768_client = client;
if(!tc358768_client) {
ret = -1;
@@ -272,9 +293,7 @@ static int tc358768_probe(struct i2c_client *client,
tc358768->vdd_mipi.enable = tc358768_vdd_enable;
if(!tc358768->vdd_mipi.disable)
tc358768->vdd_mipi.disable = tc358768_vdd_disable;
dsi->chip = tc358768;
return ret;
}
static int tc358768_remove(struct i2c_client *client)
@@ -666,24 +685,50 @@ int mipi_dsi_read_dcs_packet(unsigned char *data, int n) {
return 0;
}
int tc358768_get_id(void) {
int id = -1;
tc358768_power_up();
id = tc358768_rd_reg_32bits(0);
return id;
}
int tc358768_init(struct mipi_dsi_t *pram) {
int ret = 0;
dsi = pram;
if(!dsi)
return -1;
dsi->id = 0x4401;
dsi->dsi_init = _tc358768_wr_regs_32bits;
dsi->dsi_hs_start = _tc358768_wr_regs_32bits;
dsi->dsi_send_dcs_packet = mipi_dsi_send_dcs_packet;
dsi->dsi_read_dcs_packet = mipi_dsi_read_dcs_packet;
static struct mipi_dsi_ops tc358768_ops = {
.id = 0x4401,
.name = "tc358768a",
.get_id = tc358768_get_id,
.dsi_set_regs = _tc358768_wr_regs_32bits,
.dsi_send_dcs_packet = mipi_dsi_send_dcs_packet,
.dsi_read_dcs_packet = mipi_dsi_read_dcs_packet,
.power_up = tc358768_power_up,
.power_down = tc358768_power_down,
};
static int __init tc358768_module_init(void)
{
#ifdef CONFIG_TC358768_I2C
i2c_add_driver(&tc358768_driver);
#endif
tc358768_gpio_init(NULL);
return 0;
exit_init:
//tc358768_power_down(NULL);
tc358768_gpio_deinit(NULL);
return -1;
if(!tc358768 || !tc358768_client)
return -1;
#endif
register_dsi_ops(&tc358768_ops);
if(tc358768->id > 0)
tc358768_ops.id = tc358768->id;
return 0;
}
static void __exit tc358768_module_exit(void)
{
del_dsi_ops(&tc358768_ops);
#ifdef CONFIG_TC358768_I2C
i2c_del_driver(&tc358768_driver);
#endif
}
subsys_initcall_sync(tc358768_module_init);
//module_exit(tc358768_module_init);
module_exit(tc358768_module_exit);

View File

@@ -1,99 +0,0 @@
#ifndef TC358768_H_
#define TC358768_H_
#include <linux/fb.h>
#include <linux/delay.h>
#include <linux/rk_fb.h>
#include <mach/gpio.h>
#include <mach/iomux.h>
#include <mach/board.h>
#include <linux/rk_screen.h>
#include <linux/ktime.h>
//DSI DATA TYPE
#define DTYPE_DCS_SWRITE_0P 0X05
#define DTYPE_DCS_SWRITE_1P 0X15
#define DTYPE_DCS_LWRITE 0X39
#define DTYPE_GEN_LWRITE 0X29
#define DTYPE_GEN_SWRITE_2P 0X23
#define DTYPE_GEN_SWRITE_1P 0X13
#define DTYPE_GEN_SWRITE_0P 0X03
#define CONFIG_TC358768_I2C 1
#define CONFIG_TC358768_I2C_CLK 400*1000
#if !CONFIG_TC358768_I2C
/* define spi write command and data interface function */
#define TXD_PORT gLcd_info->txd_pin
#define CLK_PORT gLcd_info->clk_pin
#define CS_PORT gLcd_info->cs_pin
#define LCD_RST_PORT gLcd_info->reset_pin
#define CS_OUT() gpio_direction_output(CS_PORT, 0)
#define CS_SET() gpio_set_value(CS_PORT, GPIO_HIGH)
#define CS_CLR() gpio_set_value(CS_PORT, GPIO_LOW)
#define CLK_OUT() gpio_direction_output(CLK_PORT, 0)
#define CLK_SET() gpio_set_value(CLK_PORT, GPIO_HIGH)
#define CLK_CLR() gpio_set_value(CLK_PORT, GPIO_LOW)
#define TXD_OUT() gpio_direction_output(TXD_PORT, 0)
#define TXD_SET() gpio_set_value(TXD_PORT, GPIO_HIGH)
#define TXD_CLR() gpio_set_value(TXD_PORT, GPIO_LOW)
#define LCD_RST_OUT(i) gpio_direction_output(LCD_RST_PORT, i)
#define LCD_RST(i) gpio_set_value(LCD_RST_PORT, i)
#endif
struct mipi_dsi_t {
u32 id;
int (*dsi_init)(void *, int n);
int (*dsi_hs_start)(void *, int n);
int (*dsi_send_dcs_packet)(unsigned char *, int n);
int (*dsi_read_dcs_packet)(unsigned char *, int n);
int (*dsi_send_packet)(void *, int n);
void *chip;
};
struct power_t {
int enable_pin; //gpio that control power
char* mux_name;
u32 mux_mode;
u32 effect_value;
u32 min_voltage;
u32 max_voltage;
int (*enable)(void *);
int (*disable)(void *);
};
struct reset_t {
int reset_pin; //gpio that control reset
char* mux_name;
u32 mux_mode;
u32 effect_value;
u32 time_before_reset; //ms
u32 time_after_reset;
int (*do_reset)(void *);
};
struct tc358768_t {
struct reset_t reset;
struct power_t vddc;
struct power_t vddio;
struct power_t vdd_mipi;
struct i2c_client *client;
int (*gpio_init)(void *);
int (*gpio_deinit)(void *);
int (*power_up)(void *);
int (*power_down)(void *);
};
int tc358768_init(struct mipi_dsi_t *pram);
u32 tc358768_wr_reg_32bits_delay(u32 delay, u32 data);
#endif /* end of TC358768_H_ */