This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

DSI83 Driver

Dear Sir,

We use DSI83 in MT8735 platform.

Do you have  DSI83 kernel Driver?

  • We can provide a sample code that we use in Linux for OMAP to configure the DSI8x, this code executes the initial setup for the DSI8x device,  we use a function to configure the DSI8x registers, this routine creates a I2C_ client structure to configure the device registers from OMAP processor (this is only a sample code, the customer needs to modify the values in the code to match the required resolution, video format, etc… ).

    This sample code can be used to configure the DSi8x devices from Linux and you also can explain to the customer that the DSI interface is fully supported on the OMAP mainline Linux kernel in the following address:

    7080.panel-dsi85.c
    /*
     *
     * 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/>.
     */
    
    #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 <video/omapdss.h>
    #include <video/mipi_display.h>
    #include <video/omap-panel-dsi85.h>
    
    #include "panel-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 i2c_device_id dsi85_i2c_id[] = {
    	{ "dsi85_i2c_driver", 0 },
    };
    
    #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,    
    };
    
    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 int dsi85_i2c_probe(struct i2c_client *client,
    		const struct i2c_device_id *id)
    {
    	struct dsi85_i2c_data *dsi85_i2c_data;
    
    	printk(KERN_INFO "DSI85-I2C: Probe called!\n");
    	dsi85_i2c_data = kzalloc(sizeof(struct dsi85_i2c_data), GFP_KERNEL);
    
    	if (!dsi85_i2c_data) {
    		printk(KERN_ERR "DSI85-I2C: memory allocation failed!\n");
    		return -ENOMEM;
    	}
    
    	mutex_init(&dsi85_i2c_data->xfer_lock);
    	i2c_set_clientdata(client, dsi85_i2c_data);
    
    	return 0;
    }
    
    static int dsi85_i2c_remove(struct i2c_client *client)
    {
    	struct dsi85_i2c_data *dsi85_i2c_data =
    					i2c_get_clientdata(client);
    	kfree(dsi85_i2c_data);
    	return 0;
    }
    
    static struct i2c_driver dsi85_i2c_driver = {
    	.driver = {
    		.name	= "dsi85_i2c_driver",
    	},
    	.probe		= dsi85_i2c_probe,
    	.remove		= dsi85_i2c_remove,
    	.id_table	= dsi85_i2c_id,
    };
    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
    
    
    
    /**
     * dsi85_config - Configure dsi85
     *
     * Initial configuration for dsi85 configuration registers
     */
    static void dsi85_config(struct omap_dss_device *dssdev)
    {
    	printk(KERN_INFO "Now Configuring\n");
    	
    	struct dsi85_data *dsi85_d = dev_get_drvdata(&dssdev->dev);
    	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, \
    //		(dssdev->panel.timings.hbp & 0x00FF));
    	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, \
    //  	(dssdev->panel.timings.hbp & 0x00FF));
    	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, \
    //		(dssdev->panel.timings.hfp & 0x00FF));
    	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, \
    //		(dssdev->panel.timings.hfp & 0x00FF));
    	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;
    }
    
    static void dsi85_test(struct omap_dss_device *dssdev)
    {
    	printk(KERN_INFO "Now Configuring Test Pattern\n");
    	
    	struct dsi85_data *dsi85_d = dev_get_drvdata(&dssdev->dev);
    	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);
        }
        
        //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, (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);
    	/*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, \
    		((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, \
    //		(dssdev->panel.timings.hbp & 0x00FF));
    	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, \
    //  	(dssdev->panel.timings.hbp & 0x00FF));
    	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, \
    //		(dssdev->panel.timings.hfp & 0x00FF));
    	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, \
    //		(dssdev->panel.timings.hfp & 0x00FF));
    	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_power_on(struct omap_dss_device *dssdev)
    {
    	struct dsi85_data *dsi85_d = dev_get_drvdata(&dssdev->dev);
    	int ret = 0;
    
    	if (dsi85_d->enabled != 1) {
    		if (dsi85_d->pdata->set_power)
    			dsi85_d->pdata->set_power(true);
    
    		ret = omapdss_dsi_display_enable(dssdev);
    		if (ret) {
    			dev_err(&dssdev->dev, "failed to enable DSI\n");
    			goto err;
    		}
    
    		omapdss_dsi_vc_enable_hs(dssdev, dsi85_d->pixel_channel, true);
    
    		dsi_videomode_panel_preinit(dssdev, dsi85_d->pixel_channel);
    
    		msleep(100);
    
    		//LADLDL
    		dsi85_config(dssdev);
    		//dsi85_test(dssdev);
    #ifdef DSI85DEBUG
    		dsi85_dumpconfig(dssdev);
    #endif
    		dsi_video_mode_enable(dssdev, dsi85_d->pixel_channel);
    
    		dsi85_d->enabled = 1;
    	}
    
    err:
    	return ret;
    }
    
    static void dsi85_power_off(struct omap_dss_device *dssdev)
    {
    	struct dsi85_data *dsi85_d = dev_get_drvdata(&dssdev->dev);
    
    	gpio_set_value(dsi85_d->pdata->reset_gpio, 0);
    	msleep(20);
    
    	dsi85_d->enabled = 0;
    	omapdss_dsi_display_disable(dssdev, 0, 0);
    
    	if (dsi85_d->pdata->set_power)
    		dsi85_d->pdata->set_power(false);
    
    }
    
    static int dsi85_start(struct omap_dss_device *dssdev)
    {
    	struct dsi85_data *dsi85_d = dev_get_drvdata(&dssdev->dev);
    	int r = 0;
    
    	mutex_lock(&dsi85_d->lock);
    
    	dsi_bus_lock(dssdev);
    
    	r = dsi85_power_on(dssdev);
    
    	dsi_bus_unlock(dssdev);
    
    	if (r) {
    		dev_dbg(&dssdev->dev, "enable failed\n");
    		dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
    	} else {
    		dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
    		dssdev->manager->enable(dssdev->manager);
    	}
    
    	mutex_unlock(&dsi85_d->lock);
    
    	return r;
    }
    
    static void dsi85_stop(struct omap_dss_device *dssdev)
    {
    	struct dsi85_data *dsi85_d = dev_get_drvdata(&dssdev->dev);
    
    	mutex_lock(&dsi85_d->lock);
    
    	dssdev->manager->disable(dssdev->manager);
    
    	dsi_bus_lock(dssdev);
    
    	dsi85_power_off(dssdev);
    
    	dsi_bus_unlock(dssdev);
    
    	mutex_unlock(&dsi85_d->lock);
    }
    
    static void dsi85_disable(struct omap_dss_device *dssdev)
    {
    	dev_dbg(&dssdev->dev, "disable\n");
    
    	if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
    		dsi85_stop(dssdev);
    
    	dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
    }
    
    static int dsi85_enable(struct omap_dss_device *dssdev)
    {
    	dev_dbg(&dssdev->dev, "enable\n");
    
    	if (dssdev->state != OMAP_DSS_DISPLAY_DISABLED)
    		return -EINVAL;
    
    	return dsi85_start(dssdev);
    }
    
    static int dsi85_sync(struct omap_dss_device *dssdev)
    {
    	return 0;
    }
    
    static int dsi85_resume(struct omap_dss_device *dssdev)
    {
    	dev_dbg(&dssdev->dev, "resume\n");
    
    	if (dssdev->state != OMAP_DSS_DISPLAY_SUSPENDED)
    		return -EINVAL;
    
    	return dsi85_start(dssdev);
    }
    
    static int dsi85_suspend(struct omap_dss_device *dssdev)
    {
    	dev_dbg(&dssdev->dev, "suspend\n");
    
    	if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
    		return -EINVAL;
    
    	dsi85_stop(dssdev);
    
    	dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
    
    	return 0;
    }
    
    static struct omap_dss_driver dsi85_driver = {
    	.probe = dsi85_probe,
    	.remove = dsi85_remove,
    
    	.enable = dsi85_enable,
    	.enable = dsi85_enable,
    	.disable = dsi85_disable,
    	.suspend = dsi85_suspend,
    	.resume = dsi85_resume,
    
    	.sync = dsi85_sync,
    
    	.get_resolution = dsi85_get_resolution,
    	.get_recommended_bpp = omapdss_default_get_recommended_bpp,
    
    	.get_timings = dsi85_get_timings,
    	.set_timings = dsi85_set_timings,
    	.check_timings = dsi85_check_timings,
    
    	.driver = {
    		.name = "dsi85",
    		.owner = THIS_MODULE,
    	},
    };
    
    static int __init dsi85_init(void)
    {
    	int r = 0;
    
    	r = i2c_add_driver(&dsi85_i2c_driver);
    	if (r) {
    		printk(KERN_WARNING "dsi85_i2c_driver" \
    			" registration failed\n");
    		return r;
    	} else
    		printk("DSI85-I2C: registered!\n");
    
    	
    	r = omap_dss_register_driver(&dsi85_driver);
    	if (r){
    		i2c_del_driver(&dsi85_i2c_driver);
    		printk("DSI85-DSS: failed!\n");
    	}else
    		printk("DSI85-DSS: registered!\n");
    
    	return 0;
    }
    
    static void __exit dsi85_exit(void)
    {
    	i2c_del_driver(&dsi85_i2c_driver);
    	omap_dss_unregister_driver(&dsi85_driver);
    }
    
    module_init(dsi85_init);
    module_exit(dsi85_exit);
    

    1614.panel-dsi85.h

    Regards