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.

SN65DSI86: SN65DSI86 sinal problem

Part Number: SN65DSI86

Dear TI,

Customer are using SN65DSI86ZQER edp converter chip SN65DSI86ZQER in their project. Now they encount that the icon didn't display(the backlight is turned on).When the icon didn't display, customer used oscilloscope to measure mipi data-input pin of SN65DSI86, they found the pin signal was normal.Output pin of SN65DSI86, LANE1_N, had data output, but customer couln't diagnose that it was normal(the normal and abnormal chip had the same electrical timing).

In view of this phenomenon, R&D engineer made an initialization of the chip again in kernel stage, the logo could be displayed normally.
Therefore, we want to know why there exists no icon in the Uboot(XBL) stage? 

Please review the schematic and log from customer.

Thanks for your reply. Urgently.MC509_MB_V1.00_SCH_20191011-1550(2)(1).pdfMC509_edp_panel(1).txt

  • Hi

    I don't see an issue with the schematic.

    1. Please check the DSI86 power up sequence and make sure the power up sequence meets the requirement in Fig 1 of the DSI86 datasheet.

    2. When there is no logo, please dump out registers 0xF0 to 0xF8. These registers would tell us the DSI86 error status.

    3. In Register 0x96, could you please enable TPS1 in ML_TX_MODE first before starting the semi-auto link training?

    Thanks

    David

  • Dear David,

    Please see the reg info. below:

    Normal

    Innormal

    Thank you.

  • Dear David,

    Please review the driver and give some advice for us, Thank you.

    /*
    *author :Meige team
    *version:1.0
    *data:2016.9.9
    *function description : an i2c interface for mipi bridge or others i2c slave
    */
    #include <linux/module.h>
    #include <linux/init.h>
    #include <linux/interrupt.h>
    #include <linux/irq.h>
    #include <linux/workqueue.h>
    #include <linux/errno.h>
    #include <linux/pm.h>
    #include <linux/platform_device.h>
    #include <linux/input.h>
    #include <linux/i2c.h>
    #include <linux/gpio.h>
    #include <linux/slab.h>
    #include <linux/wait.h>
    #include <linux/time.h>
    #include <linux/delay.h>
    #include <linux/of_gpio.h>
    #include <linux/pinctrl/consumer.h>
    #include <linux/leds.h>
    #include <linux/regulator/consumer.h>
    #include <linux/notifier.h>
    #include <linux/fb.h>
    
    #include "mdss_i2c_dsi0_edp.h"
    extern char *saved_command_line;
    struct edp_i2c_interface {
    	struct i2c_client *edp_client;
    	int gpio_rstn;  //sn65dsi84 电源复位脚
    	int gpio_edp_3v3_en; //sn65dsi84 电源使能脚
    	int gpio_bkl_en; //背光使能脚
    	int gpio_lcd_12v_en; //lcd 电源使能脚
    	int gpio_lcd_dvdd_en; //lcd 电源使能脚
    	atomic_t video_status;
    	struct notifier_block fb_notif;
    	struct workqueue_struct *workq;
    	struct delayed_work delay_work_id;
    	struct delayed_work led_work_id;
    	int led_bright_lvl;
    	int led_set_done;
    };
    
    #define BRIGHTNESS__MAX 255
    static struct led_classdev backlight_pwm = {
    	.name           = "seclcd-backlight",
    	.brightness     = BRIGHTNESS__MAX / 2,
    	.max_brightness = BRIGHTNESS__MAX,
    	.default_trigger = "bkl-trigger",
    	.flags           = SET_BRIGHTNESS_ASYNC,
    };
    
    static struct edp_i2c_interface *edp_mipi_i2c ;
    
    int edp_mipi_i2c_init_ok(void);
    
    static int edp_write_reg(int reg, int val)
    {
    	int rc = 0;
    	rc = i2c_smbus_write_byte_data(edp_mipi_i2c->edp_client,reg,val);
    	if (rc < 0) {
    		pr_err("%s: edp_write_reg fail \n", __func__);
            return rc;
    	}
    	return rc ;
    }
    
    void edp_video_set(int on)
    {
    	pr_err("%s, on:%d\n", __func__, on);
    	atomic_set(&edp_mipi_i2c->video_status, on);
    	queue_delayed_work(edp_mipi_i2c->workq, &edp_mipi_i2c->delay_work_id, 0);
    }
    
    int sn65dsi86_dump_regs(void)
    {
    	int value = 0;
    	int index;
    
    	if (!edp_mipi_i2c){
    		pr_err("failed to dump regs cause of null pointer\n");
    		return -1;
    	}
    	for(index=0xf0;index<0xf9;index++){
    		value = i2c_smbus_read_byte_data(edp_mipi_i2c->edp_client,index);
    		pr_err("addr(0x%x) = 0x%x\n",index,value);
    	}
    	return 0;
    }
    
    int edp_mipi_i2c_init(struct mdss_dsi_ctrl_pdata *ctrl, int from_mdp)
    {
    	if (!edp_mipi_i2c)
    		return -1;
    
    	pr_err("%s\n", __func__);
    	pr_info("MEIG:%s config start!\n", __func__);
    	gpio_direction_output(edp_mipi_i2c->gpio_rstn, 0);
    	mdelay(10);
    	gpio_direction_output(edp_mipi_i2c->gpio_rstn, 1);
    	mdelay(20);
    	edp_mipi_i2c_init_ok();
    	mdelay(20);
    	//gpio_direction_output(edp_mipi_i2c->gpio_bkl_en, 1);
    	edp_video_set(1);
    	return 0;
    }
    EXPORT_SYMBOL_GPL(edp_mipi_i2c_init);
    
    /*This function para Get from FAE*/
    int edp_mipi_i2c_init_ok(void)
    {
    	if (!edp_mipi_i2c)
    		return -1;
    
    	edp_write_reg(0x09,0x00);
    	edp_write_reg(0x0A,0x09);
    	edp_write_reg(0x0D,0x00);
    	edp_write_reg(0x10,0x26);
    	edp_write_reg(0x11,0x00);
    	edp_write_reg(0x12,0x5c);
    	edp_write_reg(0x13,0x5c);
    	edp_write_reg(0x20,0x80);
    	edp_write_reg(0x21,0x07);
    	edp_write_reg(0x22,0x00);
    	edp_write_reg(0x23,0x00);
    	edp_write_reg(0x24,0x38);
    	edp_write_reg(0x25,0x04);
    	edp_write_reg(0x2C,0x20);
    	edp_write_reg(0x2D,0x00);
    	edp_write_reg(0x30,0x05);
    	edp_write_reg(0x31,0x00);
    	edp_write_reg(0x34,0xc8);
    	edp_write_reg(0x36,0x20);
    	edp_write_reg(0x38,0x30);
    	edp_write_reg(0x3A,0x03);
    	edp_write_reg(0x3C,0x00);//normal
    	edp_write_reg(0x3D,0x00);
    	edp_write_reg(0x3E,0x00);
    	edp_write_reg(0x5B,0x01);
    	edp_write_reg(0x93,0x20);
    	edp_write_reg(0x94,0x80);
    
    	//edp_write_reg(0x3C,0x10);//test
    	edp_write_reg(0x5C,0x01);//rm hpd
    	edp_write_reg(0x5A,0x05);
    	edp_write_reg(0x0d,0x01);
    	mdelay(20);
    	edp_write_reg(0x64,0x01);
    	edp_write_reg(0x74,0x00);
    	edp_write_reg(0x75,0x01);
    	edp_write_reg(0x76,0x0A);
    	edp_write_reg(0x77,0x01);
    	edp_write_reg(0x78,0x81);
    	edp_write_reg(0x96,0x01);
    	edp_write_reg(0x5A,0x0D);
    	mdelay(20);
    	return 0 ;
    }
    
    void edp_mipi_i2c_disable(void)
    {
    	if (!edp_mipi_i2c)
    		return;
    
    	pr_err("%s\n", __func__);
    	gpio_direction_output(edp_mipi_i2c->gpio_bkl_en, 0);
    	edp_write_reg(0xA5,0x00);
    	mdelay(20);
    
    	edp_write_reg(0x96,0x0);
    	edp_write_reg(0x93,0x04);
    	edp_write_reg(0x0d,0x0);
    
    	mdelay(20);
    	gpio_direction_output(edp_mipi_i2c->gpio_rstn, 0);
    	mdelay(20);
    }
    
    static void edp_video_work(struct work_struct *work)
    {
    	if (!edp_mipi_i2c)
    		return;
    
    	pr_err("%s\n", __func__);
    	if (atomic_read(&edp_mipi_i2c->video_status)) {
    		mdelay(500);
    		gpio_direction_output(edp_mipi_i2c->gpio_bkl_en, 1);
    	} else {
    		//edp_mipi_i2c_disable();
    	}
    }
    
    static void gpio_to_pwm(struct led_classdev *led_cdev,
                        enum led_brightness value)
    {
    	if (!edp_mipi_i2c)
    		return;
    
    	edp_mipi_i2c->led_bright_lvl = value;
    	//edp_mipi_i2c->led_set_done = 0;
    	queue_delayed_work(edp_mipi_i2c->workq, &edp_mipi_i2c->led_work_id, 0);
    	//while (!edp_mipi_i2c->led_set_done);
    }
    
    static void edp_led_work(struct work_struct *work)
    {
    	struct i2c_client *client = NULL;
    	static int led_init = 0;
    	int value;
    
    	if (!edp_mipi_i2c)
    		return;
    
    	value = edp_mipi_i2c->led_bright_lvl;
    	if (!led_init) {
    		pr_err("%s leg_trigger set\n", __func__);
    		client = edp_mipi_i2c->edp_client;
    		backlight_pwm.brightness_set = gpio_to_pwm;
    		backlight_pwm.dev = &client->dev;
    		led_trigger_set_default(&backlight_pwm);
    		led_init = 1;
    		return;
    	}
    
    	if(value > BRIGHTNESS__MAX)
    		value = BRIGHTNESS__MAX;
    	value = 255 - value;
    	pr_info("MEIG: :gpio_to_pwm start value = %d\n", value);
    	if((value < 0) || (value > BRIGHTNESS__MAX )){
    		edp_write_reg(0xA3,BRIGHTNESS__MAX);
    		//edp_write_reg(0xA5,0x00);
    	}
    	else{
    		edp_write_reg(0xA5,0x02);
    		edp_write_reg(0x5F,0x80);
    		edp_write_reg(0xA0,0x64);
    		edp_write_reg(0xA1,0xFF);
    		edp_write_reg(0xA2,0x00);
    		edp_write_reg(0xA3,value);
    		edp_write_reg(0xA4,0x00);
    		if (!gpio_get_value(edp_mipi_i2c->gpio_bkl_en)){
    			gpio_direction_output(edp_mipi_i2c->gpio_bkl_en, 1);
    		}
    	}
    	edp_mipi_i2c->led_set_done = 1;
    }
    
    #if defined(CONFIG_FB__)
    static int _fb_notifier_callback_(struct notifier_block *self,
    				 unsigned long event, void *data)
    {
    	struct fb_event *evdata = data;
    	int *blank;
    
    	if (!edp_mipi_i2c)
    		return -1;
    
    	if (evdata && evdata->data && event == FB_EVENT_BLANK &&
    			edp_mipi_i2c && edp_mipi_i2c->edp_client) {
    		blank = evdata->data;
    		pr_err("%s blank:%d\n", __func__, blank);
    		if (*blank == FB_BLANK_UNBLANK){
    			pr_debug("%s :_fb_notifier_callback_ 1 \n", __func__);
    			//edp_mipi_i2c_init(NULL, 0);
    		}
    		else if (*blank == FB_BLANK_NORMAL){
    			pr_debug("%s :_fb_notifier_callback_ 2  \n", __func__);
    			//edp_mipi_i2c_disable();
    			//gpio_direction_output(edp_mipi_i2c->gpio_bkl_en, 0);
    		}
    	}
    
    	return 0;
    }
    #endif
    
    static void mdss_edp_gpio_init(void)
    {
    	int ret;
    
    	ret = of_get_named_gpio(edp_mipi_i2c->edp_client->dev.of_node,
                                 "edp,vcc12v_en", 0);
    	if (ret < 0) {
    		pr_err("%s get edp,vcc12v_en error!\n", __func__);
    		edp_mipi_i2c->gpio_lcd_12v_en = -1;
    	}
    	else {
    		edp_mipi_i2c->gpio_lcd_12v_en = ret;
    		if (gpio_request(edp_mipi_i2c->gpio_lcd_12v_en, "gpio_lcd_12v_en"))
    			pr_err("%s request gpio_lcd_12v_en error!\n", __func__);
    		else
    			gpio_direction_output(edp_mipi_i2c->gpio_lcd_12v_en, 1);
    	}
    
    	ret = of_get_named_gpio(edp_mipi_i2c->edp_client->dev.of_node,
                                 "lcd,3_3v_en", 0);
    	if (ret < 0) {
    		pr_err("%s get lcd,3_3v_en error!\n", __func__);
    		edp_mipi_i2c->gpio_edp_3v3_en = -1;
    	}
    	else {
    		edp_mipi_i2c->gpio_edp_3v3_en = ret; 
    		if (gpio_request(edp_mipi_i2c->gpio_edp_3v3_en, "sn,gpio_edp_3v3_en") < 0)
    			pr_err("%s request gpio_edp_3v3_en error!\n", __func__);
    		else
    			gpio_direction_output(edp_mipi_i2c->gpio_edp_3v3_en, 1);
    	}
    
    	ret = of_get_named_gpio(edp_mipi_i2c->edp_client->dev.of_node,
                                 "edp,dvdd_en", 0);
    	if (ret < 0) {
    		pr_err("%s get edp,dvdd_en error!\n", __func__);
    		edp_mipi_i2c->gpio_lcd_dvdd_en = -1;
    	}
    	else {
    		edp_mipi_i2c->gpio_lcd_dvdd_en = ret;
    		if (gpio_request(edp_mipi_i2c->gpio_lcd_dvdd_en, "gpio_lcd_dvdd_en"))
    			pr_err("%s request gpio_lcd_dvdd_en error!", __func__);
    		else
    			gpio_direction_output(edp_mipi_i2c->gpio_lcd_dvdd_en, 1);
    	}
    
    	ret = of_get_named_gpio(edp_mipi_i2c->edp_client->dev.of_node, 
                                 "edp,gpio_rstn", 0);
    	if (ret < 0) {
    		pr_err("%s get edp,gpio_rstn gpio error!\n", __func__);
    		edp_mipi_i2c->gpio_rstn = -1;
    	}
    	else {
    		edp_mipi_i2c->gpio_rstn  = ret;
    		if (gpio_request(edp_mipi_i2c->gpio_rstn, "sn,gpio_rstn"))
    			pr_err("%s request gpio_rstn error!\n", __func__);
    		else {
    			gpio_direction_output(edp_mipi_i2c->gpio_rstn, 1);
    			mdelay(10);
    		}
    	}
    
    	ret = of_get_named_gpio(edp_mipi_i2c->edp_client->dev.of_node,
                                 "bkl,en", 0);
    	if(ret < 0) {
    		pr_err("%s get bkl,en gpio error!\n", __func__);
    		edp_mipi_i2c->gpio_bkl_en = -1;
    	}
    	else {
    		edp_mipi_i2c->gpio_bkl_en = ret;
    		if (gpio_request(edp_mipi_i2c->gpio_bkl_en, "gpio_bkl_en") < 0)
    			pr_err("%s request gpio_bkl_en error!\n", __func__);
    		else
    			gpio_direction_output(edp_mipi_i2c->gpio_bkl_en, 1);
    	}
    }
    
    static int mipi_i2c_probe(struct i2c_client *client,
            const struct i2c_device_id *id)
    {
    	int err;
    	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
    		dev_err(&client->dev, "%s: check_functionality failed.", __func__);
    		err = -ENODEV;
    		goto exit0;
    	}
    
    	/* Allocate memory for driver data */
    	edp_mipi_i2c = kzalloc(sizeof(struct edp_i2c_interface), GFP_KERNEL);
    	if (!edp_mipi_i2c) {
    		pr_err("%s: memory allocation failed.", __func__);
    		err = -ENOMEM;
    		goto exit0;
    	}
    
    	/***** I2C initialization *****/
    	edp_mipi_i2c->edp_client = client;
    
    	mdss_edp_gpio_init();
    
    	/* set client data */
    	i2c_set_clientdata(client, edp_mipi_i2c);
    
    	err = i2c_smbus_read_byte_data(client, 0x5B);
    	if (err < 0) {
    		pr_err("%s: i2c test Failed ret = %d\n", __func__, err);
    		goto exit1;
    	}
    	pr_info("%s 1111 sn65dsi84 i2c test ok .id = %d\n", __func__, err);
    #if defined(CONFIG_FB__)
    	edp_mipi_i2c->fb_notif.notifier_call = _fb_notifier_callback_;
    	err = fb_register_client(&edp_mipi_i2c->fb_notif);
    	if (err) {
    		pr_err("%s:_fb_notifier_callback_err!", __func__);
    	}
    #endif
    
    	edp_mipi_i2c->workq = create_workqueue("video_workq");
    	if (!edp_mipi_i2c->workq) {
    		pr_err("%s, create workqueue fail\n", __func__);
    		goto exit1;
    	}
    	sn65dsi86_dump_regs();
    	INIT_DELAYED_WORK(&edp_mipi_i2c->delay_work_id, edp_video_work);
    	INIT_DELAYED_WORK(&edp_mipi_i2c->led_work_id, edp_led_work);
    	queue_delayed_work(edp_mipi_i2c->workq, &edp_mipi_i2c->led_work_id, 1*HZ);
    	return 0;
    
    exit1:
    	kfree(edp_mipi_i2c);
    	edp_mipi_i2c = NULL;
    exit0:
    	return err;
    }
    
    static const struct of_device_id mipi_i2c_of_match[] = {
        { .compatible = "ti,sn65dsi86",},
        {},
    };
    
    static const struct i2c_device_id mipi_i2c_id[] = {
        {"ti,sn65dsi86", 0},
        {},
    };
    
    static int mipi_i2c_remove(struct i2c_client *client) {
    
        return 0;
    }
    
    static struct i2c_driver mipi_i2c_driver = {
        .driver = {
            .name = "ti,sn65dsi86",
            .owner    = THIS_MODULE,
            .of_match_table = mipi_i2c_of_match,
            //.pm = &mipi_i2c_pm_ops,
        },
        .probe    = mipi_i2c_probe,
        .remove   = mipi_i2c_remove,
        .id_table = mipi_i2c_id,
    };
    
    module_i2c_driver(mipi_i2c_driver);
    
    MODULE_LICENSE("GPL");
    

  • Hi

    When do you start the semi-auto link training in your driver code? 

    From the register dump 0xF8, I don't see link training to be successful, are you doing the link training?

    For register 0xF0 to 0xF8, can you please write 0xFF to these registers first to clear them, and then read again to make sure these errors are real?

    Thanks

    David

  • Dear David,

    Could you please check the reg for us, if possible, please contact me by mail: derek.zhong@arrow.com. My KMM customer need our support. Thank you.

  • Derek

    Please see my email response.

    Thanks

    David