From fb3f41eb38af691d7e867ab8ebedfe0a4167527d Mon Sep 17 00:00:00 2001 From: hhb Date: Mon, 20 May 2013 15:54:52 +0800 Subject: [PATCH] mipi_dsi: update ssd2828 driver --- drivers/video/display/transmitter/ssd2828.c | 221 +++++++++++++++++--- 1 file changed, 196 insertions(+), 25 deletions(-) diff --git a/drivers/video/display/transmitter/ssd2828.c b/drivers/video/display/transmitter/ssd2828.c index 77518bddd47e..74bb6b3876d2 100644 --- a/drivers/video/display/transmitter/ssd2828.c +++ b/drivers/video/display/transmitter/ssd2828.c @@ -19,7 +19,12 @@ #include #include #include +#include #include "mipi_dsi.h" +#include +#include +#include + /* define spi gpio*/ #define TXD_PORT ssd2828->spi.mosi @@ -41,7 +46,7 @@ struct ssd2828_t *ssd2828 = NULL; - +void ssd_set_register(unsigned int reg_and_value); int ssd2828_gpio_init(void *data) { int ret = 0; @@ -92,6 +97,21 @@ int ssd2828_gpio_init(void *data) { } } + vdd = &ssd2828->shut; + if(vdd->enable_pin > INVALID_GPIO) { + ret = gpio_request(vdd->enable_pin, "ssd2828_shut"); + if (ret != 0) { + //gpio_free(vdd->enable_pin); + printk("%s: request ssd2828_shut_PIN error\n", __func__); + } else { +#if OLD_RK_IOMUX + if(vdd->mux_name) + rk30_mux_api_set(vdd->mux_name, 0); +#endif + 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) { @@ -154,24 +174,39 @@ int ssd2828_gpio_deinit(void *data) { 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); - + if(reset->reset_pin > INVALID_GPIO) { + gpio_direction_input(reset->reset_pin); + gpio_free(reset->reset_pin); + } + if(vdd->enable_pin > INVALID_GPIO) { + 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); - + if(vdd->enable_pin > INVALID_GPIO) { + gpio_direction_input(vdd->enable_pin); + gpio_free(vdd->enable_pin); + } + vdd = &ssd2828->shut; + if(vdd->enable_pin > INVALID_GPIO) { + gpio_direction_input(vdd->enable_pin); + gpio_free(vdd->enable_pin); + } + if(spi->cs > INVALID_GPIO) { + gpio_direction_input(spi->cs); + gpio_free(spi->cs); + } + if(spi->sck > INVALID_GPIO) { + gpio_direction_input(spi->sck); + gpio_free(spi->sck); + } + if(spi->mosi > INVALID_GPIO) { + gpio_direction_input(spi->mosi); + gpio_free(spi->mosi); + } + if(spi->miso > INVALID_GPIO) { + gpio_free(spi->miso); + } return 0; } @@ -182,7 +217,7 @@ int ssd2828_reset(void *data) { return -1; gpio_set_value(reset->reset_pin, reset->effect_value); if(reset->time_before_reset <= 0) - msleep(1); + msleep(10); else msleep(reset->time_before_reset); @@ -199,8 +234,17 @@ int ssd2828_vdd_enable(void *data) { 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 + } else if(vdd->name) { + struct regulator *ldo = regulator_get(NULL, vdd->name); + if (ldo == NULL || IS_ERR(ldo) ){ + printk("%s: get %s ldo failed!\n", __func__, vdd->name); + ret = -1; + return ret; + } + regulator_set_voltage(ldo, vdd->voltage, vdd->voltage); + regulator_enable(ldo); + printk(" %s set %s=%dmV end\n", __func__, vdd->name, regulator_get_voltage(ldo)); + regulator_put(ldo); } return ret; } @@ -211,8 +255,17 @@ int ssd2828_vdd_disable(void *data) { if(vdd->enable_pin > INVALID_GPIO) { gpio_set_value(vdd->enable_pin, !vdd->effect_value); - } else { - //for other control + } else if(vdd->name) { + struct regulator *ldo = regulator_get(NULL, vdd->name); + if (ldo == NULL || IS_ERR(ldo) ){ + printk("%s: get %s ldo failed!\n", __func__, vdd->name); + ret = -1; + return ret; + } + while(regulator_is_enabled(ldo) > 0){ + regulator_disable(ldo); + } + regulator_put(ldo); } return ret; } @@ -222,10 +275,16 @@ int ssd2828_power_up(void) { int ret = 0; struct ssd2828_t *ssd = (struct ssd2828_t *)ssd2828; - + struct spi_t *spi = &ssd2828->spi; ssd->vdd_mipi.enable(&ssd->vdd_mipi); ssd->vddio.enable(&ssd->vddio); ssd->reset.do_reset(&ssd->reset); + ssd->shut.enable(&ssd->shut); + + gpio_direction_output(spi->cs, GPIO_HIGH); + gpio_direction_output(spi->sck, GPIO_LOW); + gpio_direction_input(spi->miso); + gpio_direction_output(spi->mosi, GPIO_LOW); return ret; } @@ -234,9 +293,28 @@ int ssd2828_power_down(void) { int ret = 0; struct ssd2828_t *ssd = (struct ssd2828_t *)ssd2828; + struct spi_t *spi = &ssd2828->spi; + ssd->shut.disable(&ssd->shut); + msleep(10); + + ssd_set_register(0x00b70300); + msleep(1); + ssd_set_register(0x00b70304); + msleep(1); + ssd_set_register(0x00b90000); + msleep(10); + + //set all gpio to low to avoid current leakage + gpio_direction_output(spi->cs, GPIO_LOW); + gpio_direction_output(spi->sck, GPIO_LOW); + gpio_direction_output(spi->miso, GPIO_LOW); + gpio_direction_output(spi->mosi, GPIO_LOW); + gpio_direction_output(ssd->reset.reset_pin, GPIO_LOW); + ssd->vddio.disable(&ssd->vddio); ssd->vdd_mipi.disable(&ssd->vdd_mipi); + ssd->shut.enable(&ssd->shut); return ret; } @@ -441,6 +519,93 @@ static struct mipi_dsi_ops ssd2828_ops = { }; +static struct proc_dir_entry *reg_proc_entry; + +int reg_proc_write(struct file *file, const char __user *buff, size_t count, loff_t *offp) +{ + int ret = -1; + char *buf = kmalloc(count, GFP_KERNEL); + char *data = buf; + unsigned int regs_val = 0, read_val = 0; + ret = copy_from_user((void*)buf, buff, count); + + while(1) { + data = strstr(data, "0x"); + if(data == NULL) + goto reg_proc_write_exit; + sscanf(data, "0x%x", ®s_val); + ssd_set_register(regs_val); + read_val = ssd_read_register(regs_val >> 16); + regs_val &= 0xffff; + if(read_val != regs_val) + printk("%s fail:0x%04x\n", __func__, read_val); + data += 3; + } + +reg_proc_write_exit: + kfree(buf); + msleep(10); + return count; +} + +int reg_proc_read(struct file *file, char __user *buff, size_t count, loff_t *offp) +{ +#if 0 + int ret = -1; + const char buf[32] = {0}; + unsigned int regs_val = 0; + ret = copy_from_user((void*)buf, buff, count); + sscanf(buf, "0x%x", ®s_val); + regs_val = ssd_read_register(regs_val); + sprintf(buf, "0x%04x\n", regs_val); + copy_to_user(buff, buf, 4); + + printk("%s:%04x\n", __func__, regs_val); + msleep(10); +#endif + return count; +} + +int reg_proc_open(struct inode *inode, struct file *file) +{ + //printk("%s\n", __func__); + //msleep(10); + return 0; +} + +int reg_proc_close(struct inode *inode, struct file *file) +{ + //printk("%s\n", __func__); + //msleep(10); + return 0; +} + +struct file_operations reg_proc_fops = { + .owner = THIS_MODULE, + .open = reg_proc_open, + .release = reg_proc_close, + .write = reg_proc_write, + .read = reg_proc_read, +}; + +static int reg_proc_init(char *name) +{ + int ret = 0; + reg_proc_entry = create_proc_entry(name, 0666, NULL); + if(reg_proc_entry == NULL) { + printk("Couldn't create proc entry : %s!\n", name); + ret = -ENOMEM; + return ret ; + } + else { + printk("Create proc entry:%s success!\n", name); + reg_proc_entry->proc_fops = ®_proc_fops; + } + + return 0; +} + + static int ssd2828_probe(struct platform_device *pdev) { if(pdev->dev.platform_data) @@ -470,8 +635,14 @@ static int ssd2828_probe(struct platform_device *pdev) { if(!ssd2828->vdd_mipi.disable) ssd2828->vdd_mipi.disable = ssd2828_vdd_disable; + if(!ssd2828->shut.enable) + ssd2828->shut.enable = ssd2828_vdd_enable; + if(!ssd2828->shut.disable) + ssd2828->shut.disable = ssd2828_vdd_disable; + + ssd2828_gpio_init(NULL); - + reg_proc_init(ssd2828_ops.name); return 0; } -- 2.34.1