initial import of dsi85 driver
this driver is based on the omap dss dsi85 driver
This commit is contained in:
commit
4aef94c064
11
Makefile
Normal file
11
Makefile
Normal file
|
@ -0,0 +1,11 @@
|
|||
ifneq ($(KERNELRELEASE),)
|
||||
# kbuild part of makefile
|
||||
include Kbuild
|
||||
else
|
||||
# normal makefile
|
||||
KDIR ?= /lib/modules/`uname -r`/build
|
||||
|
||||
default:
|
||||
$(MAKE) -C $(KDIR) M=$$PWD
|
||||
|
||||
endif
|
787
dsi85_main.c
Executable file
787
dsi85_main.c
Executable file
|
@ -0,0 +1,787 @@
|
|||
/*
|
||||
*
|
||||
* Copyright 2011 Texas Instruments, Inc.
|
||||
* Author: Archit Taneja <archit@ti.com>
|
||||
*
|
||||
* based on d2l panel driver by Jerry Alexander <x0135174@ti.com>
|
||||
*
|
||||
* This program iss free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 as published by
|
||||
* the Free Software Foundation.
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with
|
||||
* this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/err.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/seq_file.h>
|
||||
#include <linux/backlight.h>
|
||||
#include <linux/fb.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include "dsi85.h"
|
||||
|
||||
#define DSI85DEBUG
|
||||
|
||||
static struct i2c_board_info dsi85_i2c_board_info =
|
||||
{
|
||||
I2C_BOARD_INFO("dsi85_i2c_driver", 0x2d /*0x2c*/),
|
||||
};
|
||||
|
||||
struct dsi85_i2c_data
|
||||
{
|
||||
struct mutex xfer_lock;
|
||||
};
|
||||
|
||||
|
||||
|
||||
static struct omap_video_timings dsi85_timings =
|
||||
{
|
||||
.x_res = 1024,
|
||||
.y_res = 600,
|
||||
.pixel_clock = 50000,
|
||||
.hfp = 36, //42 128 38 - 100 1 107 chido es 36 128 45
|
||||
.hsw = 128,
|
||||
.hbp = 45,
|
||||
.vfp = 1,
|
||||
.vsw = 4,
|
||||
.vbp = 9,
|
||||
};
|
||||
|
||||
static const struct omap_dss_dsi_videomode_data vm_data =
|
||||
{
|
||||
.hsa = 1,
|
||||
.hfp = 20, // Set to 4/3 of the DISPC porch value.
|
||||
.hbp = 20, // Set to 4/3 of the DISPC porch value.
|
||||
.vsa = 4,
|
||||
.vfp = 6,
|
||||
.vbp = 4,
|
||||
|
||||
.blanking_mode = 1,
|
||||
.hsa_blanking_mode = 1,
|
||||
.hbp_blanking_mode = 1,
|
||||
.hfp_blanking_mode = 1,
|
||||
|
||||
.vp_de_pol = true,
|
||||
.vp_vsync_pol = false,
|
||||
.vp_hsync_pol = false,
|
||||
.vp_hsync_end = false,
|
||||
.vp_vsync_end = false,
|
||||
|
||||
.window_sync = 4,
|
||||
.ddr_clk_always_on = true,
|
||||
};
|
||||
|
||||
struct dsi85_data
|
||||
{
|
||||
struct mutex lock;
|
||||
|
||||
struct omap_dss_device* dssdev;
|
||||
struct backlight_device* bldev;
|
||||
struct dentry* debug_dir;
|
||||
bool enabled;
|
||||
u8 rotate;
|
||||
bool mirror;
|
||||
bool use_dsi_bl;
|
||||
unsigned int bl;
|
||||
unsigned long hw_guard_end; /* next value of jiffies when we can
|
||||
* issue the next sleep in/out command
|
||||
*/
|
||||
unsigned long hw_guard_wait; /* max guard time in jiffies */
|
||||
|
||||
int config_channel;
|
||||
int pixel_channel;
|
||||
|
||||
struct omap_video_timings* timings;
|
||||
|
||||
struct panel_dsi85_data* pdata;
|
||||
struct i2c_client* dsi85_i2c_client;
|
||||
};
|
||||
|
||||
struct dsi85_reg
|
||||
{
|
||||
/* Address and register value */
|
||||
u8 data[10];
|
||||
int len;
|
||||
};
|
||||
|
||||
|
||||
static void dsi85_get_timings(struct omap_dss_device* dssdev,
|
||||
struct omap_video_timings* timings)
|
||||
{
|
||||
*timings = dssdev->panel.timings;
|
||||
}
|
||||
|
||||
static void dsi85_set_timings(struct omap_dss_device* dssdev,
|
||||
struct omap_video_timings* timings)
|
||||
{
|
||||
dssdev->panel.timings.x_res = timings->x_res;
|
||||
dssdev->panel.timings.y_res = timings->y_res;
|
||||
dssdev->panel.timings.pixel_clock = timings->pixel_clock;
|
||||
dssdev->panel.timings.hsw = timings->hsw;
|
||||
dssdev->panel.timings.hfp = timings->hfp;
|
||||
dssdev->panel.timings.hbp = timings->hbp;
|
||||
dssdev->panel.timings.vsw = timings->vsw;
|
||||
dssdev->panel.timings.vfp = timings->vfp;
|
||||
dssdev->panel.timings.vbp = timings->vbp;
|
||||
}
|
||||
|
||||
static int dsi85_check_timings(struct omap_dss_device* dssdev,
|
||||
struct omap_video_timings* timings)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dsi85_get_resolution(struct omap_dss_device* dssdev,
|
||||
u16* xres, u16* yres)
|
||||
{
|
||||
struct dsi85_data* dsi85_d = dev_get_drvdata(&dssdev->dev);
|
||||
|
||||
if (dsi85_d->rotate == 0 || dsi85_d->rotate == 2)
|
||||
{
|
||||
*xres = dssdev->panel.timings.x_res;
|
||||
*yres = dssdev->panel.timings.y_res;
|
||||
}
|
||||
else
|
||||
{
|
||||
*yres = dssdev->panel.timings.x_res;
|
||||
*xres = dssdev->panel.timings.y_res;
|
||||
}
|
||||
}
|
||||
|
||||
static int dsi85_probe(struct omap_dss_device* dssdev)
|
||||
{
|
||||
struct i2c_adapter* adapter;
|
||||
struct i2c_client* dsi85_i2c_client;
|
||||
int ret = 0;
|
||||
struct dsi85_data* dsi85_d = NULL;
|
||||
dev_dbg(&dssdev->dev, "dsi85_probe\n");
|
||||
|
||||
if (dssdev->data == NULL)
|
||||
{
|
||||
dev_err(&dssdev->dev, "no platform data!\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dssdev->panel.config = OMAP_DSS_LCD_TFT;
|
||||
dssdev->panel.timings = dsi85_timings;
|
||||
dssdev->panel.dsi_vm_data = vm_data;
|
||||
dssdev->ctrl.pixel_size = 24;
|
||||
dssdev->panel.acbi = 0;
|
||||
dssdev->panel.acb = 40;
|
||||
dsi85_d = kzalloc(sizeof(*dsi85_d), GFP_KERNEL);
|
||||
|
||||
if (!dsi85_d)
|
||||
{
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
dsi85_d->dssdev = dssdev;
|
||||
dsi85_d->pdata = dssdev->data;
|
||||
|
||||
if (!dsi85_d->pdata)
|
||||
{
|
||||
dev_err(&dssdev->dev, "Invalid platform data\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
mutex_init(&dsi85_d->lock);
|
||||
dev_set_drvdata(&dssdev->dev, dsi85_d);
|
||||
dsi85_d->debug_dir = debugfs_create_dir("dsi85", NULL);
|
||||
|
||||
if (!dsi85_d->debug_dir)
|
||||
{
|
||||
dev_err(&dssdev->dev, "failed to create debug dir\n");
|
||||
goto err_debugfs;
|
||||
}
|
||||
|
||||
ret = omap_dsi_request_vc(dssdev, &dsi85_d->pixel_channel);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
dev_err(&dssdev->dev, "failed to request pixel update "
|
||||
"channel\n");
|
||||
goto err_debugfs;
|
||||
}
|
||||
else
|
||||
printk(KERN_INFO "pixel channel setup for %d\n", \
|
||||
dsi85_d->pixel_channel);
|
||||
|
||||
printk(KERN_INFO "pixel channel %d\n", dsi85_d->pixel_channel);
|
||||
ret = omap_dsi_set_vc_id(dssdev, dsi85_d->pixel_channel, 0);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
dev_err(&dssdev->dev, "failed to set VC_ID for pixel data"
|
||||
" virtual channel\n");
|
||||
goto err_pixel_vc;
|
||||
}
|
||||
|
||||
adapter = i2c_get_adapter(2);
|
||||
|
||||
if (!adapter)
|
||||
{
|
||||
printk(KERN_INFO "DSI85-I2C: can't get i2c adapter 2\n");
|
||||
// ret = -ENODEV;
|
||||
// goto err_pixel_vc;
|
||||
}
|
||||
|
||||
dsi85_i2c_client = i2c_new_device(adapter, &dsi85_i2c_board_info);
|
||||
|
||||
if (!dsi85_i2c_client)
|
||||
{
|
||||
printk(KERN_INFO "DSI85-I2C: can't add i2c device\n");
|
||||
// ret = -ENODEV;
|
||||
// goto err_pixel_vc;
|
||||
}
|
||||
|
||||
dsi85_d->dsi85_i2c_client = dsi85_i2c_client;
|
||||
ret = i2c_smbus_read_byte_data(dsi85_i2c_client, 0x00);
|
||||
printk(KERN_INFO "DSI85-I2C: reading 0x00 returned - 0x%x\n", ret);
|
||||
dev_dbg(&dssdev->dev, "dsi85_probe\n");
|
||||
return 0;
|
||||
err_pixel_vc:
|
||||
omap_dsi_release_vc(dssdev, dsi85_d->pixel_channel);
|
||||
err_debugfs:
|
||||
mutex_destroy(&dsi85_d->lock);
|
||||
gpio_free(dsi85_d->pdata->reset_gpio);
|
||||
err:
|
||||
kfree(dsi85_d);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dsi85_remove(struct omap_dss_device* dssdev)
|
||||
{
|
||||
struct dsi85_data* dsi85_d = dev_get_drvdata(&dssdev->dev);
|
||||
debugfs_remove_recursive(dsi85_d->debug_dir);
|
||||
mutex_destroy(&dsi85_d->lock);
|
||||
gpio_free(dsi85_d->pdata->reset_gpio);
|
||||
kfree(dsi85_d);
|
||||
}
|
||||
|
||||
#ifdef DSI85DEBUG
|
||||
static void dsi85_dumpconfig(struct omap_dss_device* dssdev)
|
||||
{
|
||||
struct dsi85_data* dsi85_d = dev_get_drvdata(&dssdev->dev);
|
||||
struct i2c_client* dsi85_i2c_client = dsi85_d->dsi85_i2c_client;
|
||||
printk(KERN_INFO "luis' message");
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x00, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x00));
|
||||
/*
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x01, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x01));
|
||||
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x02, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x02));
|
||||
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x03, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x03));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x04, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x04));
|
||||
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x05, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x05));
|
||||
*/
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x0D, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x0D));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x0A, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x0A));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x0B, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x0B));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x10, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x10));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x18, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x18));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x1A, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x1A));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x20, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x20));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x21, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x21));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x22, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x22));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x23, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x23));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x24, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x24));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x25, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x25));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x26, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x26));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x27, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x27));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x28, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x28));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x29, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x29));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x2A, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x2A));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x2B, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x2B));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x2C, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x2C));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x2D, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x2D));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x2E, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x2E));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x2F, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x2F));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x30, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x30));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x31, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x31));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x32, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x32));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x33, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x33));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x34, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x34));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x35, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x35));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x36, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x32));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x37, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x33));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x38, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x34));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x39, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x35));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x3A, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x35));
|
||||
printk(KERN_INFO "DSI85-I2C: read 0x%02x - 0x%02x\n", 0x3B, \
|
||||
i2c_smbus_read_byte_data(dsi85_i2c_client, 0x3B));
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
/* DSI85 registers */
|
||||
#define DSI85_SOFT_RESET 0x09
|
||||
#define DSI85_CORE_PLL 0x0A
|
||||
#define DSI85_PLL_DIV 0x0B
|
||||
#define DSI85_PLL_EN 0x0D
|
||||
#define DSI85_DSI_CFG 0x10
|
||||
#define DSI85_DSI_EQ 0x11
|
||||
#define DSI85_CHA_DSI_CLK_RNG 0x12
|
||||
#define DSI85_CHB_DSI_CLK_RNG 0x13
|
||||
#define DSI85_LVDS_MODE 0x18
|
||||
#define DSI85_LVDS_SIGN 0x19
|
||||
#define DSI85_LVDS_TERM 0x1A
|
||||
#define DSI85_CHA_LINE_LEN_LO 0x20
|
||||
#define DSI85_CHA_LINE_LEN_HI 0x21
|
||||
#define DSI85_CHB_LINE_LEN_LO 0x22
|
||||
#define DSI85_CHB_LINE_LEN_HI 0x23
|
||||
#define DSI85_CHA_VERT_LINES_LO 0x24
|
||||
#define DSI85_CHA_VERT_LINES_HI 0x25
|
||||
#define DSI85_CHB_VERT_LINES_LO 0x26
|
||||
#define DSI85_CHB_VERT_LINES_HI 0x27
|
||||
#define DSI85_CHA_SYNC_DELAY_LO 0x28
|
||||
#define DSI85_CHA_SYNC_DELAY_HI 0x29
|
||||
#define DSI85_CHB_SYNC_DELAY_LO 0x2A
|
||||
#define DSI85_CHB_SYNC_DELAY_HI 0x2B
|
||||
#define DSI85_CHA_HSYNC_WIDTH_LO 0x2C
|
||||
#define DSI85_CHA_HSYNC_WIDTH_HI 0x2D
|
||||
#define DSI85_CHB_HSYNC_WIDTH_LO 0x2E
|
||||
#define DSI85_CHB_HSYNC_WIDTH_HI 0x2F
|
||||
#define DSI85_CHA_VSYNC_WIDTH_LO 0x30
|
||||
#define DSI85_CHA_VSYNC_WIDTH_HI 0x31
|
||||
#define DSI85_CHB_VSYNC_WIDTH_LO 0x32
|
||||
#define DSI85_CHB_VSYNC_WIDTH_HI 0x33
|
||||
#define DSI85_CHA_HORZ_BACKPORCH 0x34
|
||||
#define DSI85_CHB_HORZ_BACKPORCH 0x35
|
||||
#define DSI85_CHA_VERT_BACKPORCH 0x36
|
||||
#define DSI85_CHB_VERT_BACKPORCH 0x37
|
||||
#define DSI85_CHA_HORZ_FRONTPORCH 0x38
|
||||
#define DSI85_CHB_HORZ_FRONTPORCH 0x39
|
||||
#define DSI85_CHA_VERT_FRONTPORCH 0x3A
|
||||
#define DSI85_CHB_VERT_FRONTPORCH 0x3B
|
||||
|
||||
#define LVDS_CLK_FROM_DSI_CLK 1
|
||||
|
||||
struct dsi85_lvds_timings
|
||||
{
|
||||
u16 hfp;
|
||||
u16 hsw;
|
||||
u16 hbp;
|
||||
u16 vfp;
|
||||
u16 vsw;
|
||||
u16 vbp;
|
||||
};
|
||||
|
||||
static struct dsi85_lvds_timings lvds_timings =
|
||||
{
|
||||
.hfp = 40,
|
||||
.hsw = 128,
|
||||
.hbp = 40,
|
||||
.vfp = 1,
|
||||
.vsw = 4,
|
||||
.vbp = 9,
|
||||
};
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* dsi85_config - Configure dsi85
|
||||
*
|
||||
* Initial configuration for dsi85 configuration registers
|
||||
*/
|
||||
static void dsi85_config(struct dsi85_data* dsi85_d)
|
||||
{
|
||||
printk(KERN_INFO "Now Configuring\n");
|
||||
struct i2c_client* dsi85_i2c_client = dsi85_d->dsi85_i2c_client;
|
||||
u8 val = 0;
|
||||
/* Soft reset and disable PLL */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_SOFT_RESET, 0x01);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_PLL_EN, 0x00);
|
||||
#if LVDS_CLK_FROM_DSI_CLK
|
||||
val = 0x1;
|
||||
#endif
|
||||
|
||||
/* user external clock reference with no muliplier */
|
||||
if (dssdev->panel.timings.pixel_clock <= 37500)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
else if (dssdev->panel.timings.pixel_clock <= 62500)
|
||||
{
|
||||
val |= (0x01 << 1);
|
||||
}
|
||||
else if (dssdev->panel.timings.pixel_clock <= 87500)
|
||||
{
|
||||
val |= (0x02 << 1);
|
||||
}
|
||||
else if (dssdev->panel.timings.pixel_clock <= 112500)
|
||||
{
|
||||
val |= (0x03 << 1);
|
||||
}
|
||||
else if (dssdev->panel.timings.pixel_clock <= 137500)
|
||||
{
|
||||
val |= (0x04 << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
val |= (0x05 << 1);
|
||||
}
|
||||
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CORE_PLL, val);
|
||||
#if LVDS_CLK_FROM_DSI_CLK
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_PLL_DIV, 0x10); // Divide DSI_CLK by 3.
|
||||
#else
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_PLL_DIV, 0x00); // Multiply REFCLK by 1.
|
||||
#endif
|
||||
/* four DSI lanes with single channel*/
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_DSI_CFG, 0x20);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_DSI_EQ, 0x00);
|
||||
/* set DSI clock range */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_DSI_CLK_RNG, (dssdev->panel.timings.pixel_clock * 3 / 5000));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_DSI_CLK_RNG, (dssdev->panel.timings.pixel_clock * 3 / 5000));
|
||||
/* set LVDS for single channel, 24 bit mode, HS/VS low, DE high */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_LVDS_MODE, 0x7F);
|
||||
/* set LVDS 200 Ohm termination and max differential swing voltage */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_LVDS_SIGN, 0x00);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_LVDS_TERM, 0x00);
|
||||
/* x resolution high/low for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_LINE_LEN_LO, \
|
||||
((dssdev->panel.timings.x_res) & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_LINE_LEN_HI, \
|
||||
((dssdev->panel.timings.x_res) & 0xFF00) >> 8);
|
||||
/* x resolution high/low for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_LINE_LEN_LO, \
|
||||
(dssdev->panel.timings.x_res & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_LINE_LEN_HI, \
|
||||
(dssdev->panel.timings.x_res & 0xFF00) >> 8);
|
||||
/* y resolution high/low for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VERT_LINES_LO, \
|
||||
(dssdev->panel.timings.y_res & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VERT_LINES_HI, \
|
||||
(dssdev->panel.timings.y_res & 0xFF00) >> 8);
|
||||
/* y resolution high/low for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VERT_LINES_LO, \
|
||||
(dssdev->panel.timings.y_res & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VERT_LINES_HI, \
|
||||
(dssdev->panel.timings.y_res & 0xFF00) >> 8);
|
||||
/* SYNC delay high/low for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, \
|
||||
DSI85_CHA_SYNC_DELAY_LO, 0x00);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, \
|
||||
DSI85_CHA_SYNC_DELAY_HI, 0x02);
|
||||
/* SYNC delay high/low for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, \
|
||||
DSI85_CHB_SYNC_DELAY_LO, 0x00);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, \
|
||||
DSI85_CHB_SYNC_DELAY_HI, 0x02);
|
||||
/* HSYNC width high/low for channel A */
|
||||
/* i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_HSYNC_WIDTH_LO, \
|
||||
(dssdev->panel.timings.hsw & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_HSYNC_WIDTH_HI, \
|
||||
(dssdev->panel.timings.hsw & 0xFF00)>>8); */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_HSYNC_WIDTH_LO, \
|
||||
(lvds_timings.hsw & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_HSYNC_WIDTH_HI, \
|
||||
(lvds_timings.hsw & 0xFF00) >> 8);
|
||||
/* HSYNC width high/low for channel B */
|
||||
/* i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_HSYNC_WIDTH_LO, \
|
||||
(dssdev->panel.timings.hsw & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_HSYNC_WIDTH_HI, \
|
||||
(dssdev->panel.timings.hsw & 0xFF00)>>8); */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_HSYNC_WIDTH_LO, \
|
||||
(lvds_timings.hsw & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_HSYNC_WIDTH_HI, \
|
||||
(lvds_timings.hsw & 0xFF00) >> 8);
|
||||
/* VSYNC width high/low for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VSYNC_WIDTH_LO, \
|
||||
(lvds_timings.vsw & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VSYNC_WIDTH_HI, \
|
||||
(lvds_timings.vsw & 0xFF00) >> 8);
|
||||
/* VSYNC width high/low for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VSYNC_WIDTH_LO, \
|
||||
(lvds_timings.vsw & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VSYNC_WIDTH_HI, \
|
||||
(lvds_timings.vsw & 0xFF00) >> 8);
|
||||
/* Horizontal BackPorch for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_HORZ_BACKPORCH, \
|
||||
(lvds_timings.hbp & 0x00FF));
|
||||
/* Horizontal BackPorch for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_HORZ_BACKPORCH, \
|
||||
(lvds_timings.hbp & 0x00FF));
|
||||
/* Vertical BackPorch for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VERT_BACKPORCH, \
|
||||
(lvds_timings.vbp & 0x00FF));
|
||||
/* Vertical BackPorch for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VERT_BACKPORCH, \
|
||||
(lvds_timings.vbp & 0x00FF));
|
||||
/* Horizontal FrontPorch for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_HORZ_FRONTPORCH, \
|
||||
(lvds_timings.hfp & 0x00FF));
|
||||
/* Horizontal FrontPorch for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_HORZ_FRONTPORCH, \
|
||||
(lvds_timings.hfp & 0x00FF));
|
||||
/* Vertical FrontPorch for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VERT_FRONTPORCH, \
|
||||
(lvds_timings.vbp & 0x00FF));
|
||||
/* Vertical FrontPorch for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VERT_FRONTPORCH, \
|
||||
(lvds_timings.vbp & 0x00FF));
|
||||
/* Soft reset and enable PLL */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_SOFT_RESET, 0x01);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_PLL_EN, 0x01);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void dsi85_test(struct i2c_client* dsi85_i2c_client, u32 pixel_clock, u16 x_res, u16 y_res)
|
||||
{
|
||||
u8 val = 0;
|
||||
printk(KERN_INFO "Now Configuring Test Pattern\n");
|
||||
/* Soft reset and disable PLL */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_SOFT_RESET, 0x01);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_PLL_EN, 0x00);
|
||||
#if LVDS_CLK_FROM_DSI_CLK
|
||||
val = 0x1;
|
||||
#endif
|
||||
|
||||
/* user external clock reference with no muliplier */
|
||||
if (pixel_clock <= 37500)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
else if (pixel_clock <= 62500)
|
||||
{
|
||||
val |= (0x01 << 1);
|
||||
}
|
||||
else if (pixel_clock <= 87500)
|
||||
{
|
||||
val |= (0x02 << 1);
|
||||
}
|
||||
else if (pixel_clock <= 112500)
|
||||
{
|
||||
val |= (0x03 << 1);
|
||||
}
|
||||
else if (pixel_clock <= 137500)
|
||||
{
|
||||
val |= (0x04 << 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
val |= (0x05 << 1);
|
||||
}
|
||||
|
||||
//LADLDL
|
||||
printk(KERN_INFO "Pixel CLK value was %d\n", val);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CORE_PLL, val);
|
||||
#if LVDS_CLK_FROM_DSI_CLK
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_PLL_DIV, 0x10); // Divide DSI_CLK by 3.
|
||||
#else
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_PLL_DIV, 0x00); // Multiply REFCLK by 1.
|
||||
#endif
|
||||
//LADLDL PLL enable after address A and B configured
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_PLL_EN, 0x01);
|
||||
/* four DSI lanes with single channel*/
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_DSI_CFG, 0x20);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_DSI_EQ, 0x00);
|
||||
/* set DSI clock range */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_DSI_CLK_RNG, (pixel_clock * 3 / 5000));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_DSI_CLK_RNG, (pixel_clock * 3 / 5000));
|
||||
/* set LVDS for single channel, 24 bit mode, HS/VS low, DE high */
|
||||
//i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_LVDS_MODE, 0x7F);
|
||||
/*LADLD set LVDS for single channel, 24 bit mode, HS/VS low, DE high */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_LVDS_MODE, 0x60);
|
||||
/* set LVDS 200 Ohm termination and max differential swing voltage */
|
||||
//LADLDL
|
||||
//i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_LVDS_SIGN, 0x00);
|
||||
//i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_LVDS_TERM, 0x00);
|
||||
/* x resolution high/low for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_LINE_LEN_LO, \
|
||||
((x_res) & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_LINE_LEN_HI, \
|
||||
((x_res) & 0xFF00) >> 8);
|
||||
/* x resolution high/low for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_LINE_LEN_LO, \
|
||||
(x_res & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_LINE_LEN_HI, \
|
||||
(x_res & 0xFF00) >> 8);
|
||||
/* y resolution high/low for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VERT_LINES_LO, \
|
||||
(y_res & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VERT_LINES_HI, \
|
||||
(y_res & 0xFF00) >> 8);
|
||||
/* y resolution high/low for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VERT_LINES_LO, \
|
||||
(y_res & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VERT_LINES_HI, \
|
||||
(y_res & 0xFF00) >> 8);
|
||||
/* SYNC delay high/low for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, \
|
||||
DSI85_CHA_SYNC_DELAY_LO, 0x00);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, \
|
||||
DSI85_CHA_SYNC_DELAY_HI, 0x02);
|
||||
/* SYNC delay high/low for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, \
|
||||
DSI85_CHB_SYNC_DELAY_LO, 0x00);
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, \
|
||||
DSI85_CHB_SYNC_DELAY_HI, 0x02);
|
||||
/* HSYNC width high/low for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_HSYNC_WIDTH_LO, \
|
||||
(lvds_timings.hsw & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_HSYNC_WIDTH_HI, \
|
||||
(lvds_timings.hsw & 0xFF00) >> 8);
|
||||
/* HSYNC width high/low for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_HSYNC_WIDTH_LO, \
|
||||
(lvds_timings.hsw & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_HSYNC_WIDTH_HI, \
|
||||
(lvds_timings.hsw & 0xFF00) >> 8);
|
||||
/* VSYNC width high/low for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VSYNC_WIDTH_LO, \
|
||||
(lvds_timings.vsw & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VSYNC_WIDTH_HI, \
|
||||
(lvds_timings.vsw & 0xFF00) >> 8);
|
||||
/* VSYNC width high/low for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VSYNC_WIDTH_LO, \
|
||||
(lvds_timings.vsw & 0x00FF));
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VSYNC_WIDTH_HI, \
|
||||
(lvds_timings.vsw & 0xFF00) >> 8);
|
||||
/* Horizontal BackPorch for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_HORZ_BACKPORCH, \
|
||||
(lvds_timings.hbp & 0x00FF));
|
||||
/* Horizontal BackPorch for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_HORZ_BACKPORCH, \
|
||||
(lvds_timings.hbp & 0x00FF));
|
||||
/* Vertical BackPorch for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VERT_BACKPORCH, \
|
||||
(lvds_timings.vbp & 0x00FF));
|
||||
/* Vertical BackPorch for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VERT_BACKPORCH, \
|
||||
(lvds_timings.vbp & 0x00FF));
|
||||
/* Horizontal FrontPorch for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_HORZ_FRONTPORCH, \
|
||||
(lvds_timings.hfp & 0x00FF));
|
||||
/* Horizontal FrontPorch for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_HORZ_FRONTPORCH, \
|
||||
(lvds_timings.hfp & 0x00FF));
|
||||
/* Vertical FrontPorch for channel A */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHA_VERT_FRONTPORCH, \
|
||||
(lvds_timings.vbp & 0x00FF));
|
||||
/* Vertical FrontPorch for channel B */
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_CHB_VERT_FRONTPORCH, \
|
||||
(lvds_timings.vbp & 0x00FF));
|
||||
//Test Pattern
|
||||
i2c_smbus_write_byte_data(dsi85_i2c_client, 0x3C, 0x11);
|
||||
//LADLDL
|
||||
/* Soft reset and enable PLL */
|
||||
//i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_SOFT_RESET, 0x01);
|
||||
//i2c_smbus_write_byte_data(dsi85_i2c_client, DSI85_PLL_EN, 0x01);
|
||||
return;
|
||||
}
|
||||
|
||||
static int dsi85_probe(struct i2c_client* client, const struct i2c_device_id* id)
|
||||
{
|
||||
dsi85_test(client, 137500, 1920, 1080);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dsi85_remove(struct i2c_client* client)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct i2c_device_id dsi85_id[] =
|
||||
{
|
||||
{ "dsi85", 0 },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(i2c, dsi85_id);
|
||||
|
||||
#ifdef CONFIG_OF
|
||||
static const struct of_device_id of_dsi85_match[] =
|
||||
{
|
||||
{ .compatible = "ti,dsi85", },
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, of_dsi85_match);
|
||||
#endif
|
||||
|
||||
static struct i2c_driver dsi85_driver =
|
||||
{
|
||||
.driver = {
|
||||
.name = "dsi85_i2c_driver",
|
||||
#ifdef CONFIG_OF
|
||||
.of_match_table = of_match_ptr(of_dsi85_match),
|
||||
#endif
|
||||
},
|
||||
.probe = dsi85_probe,
|
||||
.remove = dsi85_remove,
|
||||
.id_table = dsi85_id,
|
||||
};
|
||||
|
||||
module_i2c_driver(dsi85_driver);
|
||||
|
||||
MODULE_DESCRIPTION("Texas DSI85 dsi to lvds driver");
|
||||
MODULE_AUTHOR("Moritz Bitsch");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
Loading…
Reference in a new issue