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.

DS90UB921-Q1: SOC could not configure 948 because of I2C error

Part Number: DS90UB921-Q1

Hi Team,

My customer now use 921 and 948. The video could display normally. However the I2C communication has problem.

  • SOC could configure 921 register successfully.
  • SOC could not configure 948 register and has error. As the following log shows that SDA and SCL have been pull down to low...

The following is the signal chain and SOC has 2 device connected.

SOC  -------   DS90UB921(0x0c)    ---FPD-LINK---     ----------- DS90UB948(0x34)   --------- Touch(0x20)

          -------   PCA 9654(0x24,GPIO expand)

The following is 921 and 948 configuration.

static const unsigned int fpd3_921_ser_init[] = {
/* digital reset0, digital reset1 */
FPD3_SER_RESET, 0x00,
/* RX CRC check, i2c passthrough */
FPD3_SER_CONFIG, 0xDA,
/* DES Device ID ds90ub948q*/
FPD3_SER_DES_ID, 0x68,
FPD3_SER_SLAVE_ID0, (0x20<<1),
FPD3_SER_SLAVE_AL0, (0x20<<1),
};

static const unsigned int fpd3_921to948_des_init[] = {
//digital reset0, digital reset1
FPD3_DES_RESET, 0x07,
//RX CRC check, i2c passthrough
FPD3_DES_CONFIG1, 0x78,
//Prevention of I2C Errors During Abrupt System Faults
FPD3_DES_BCC_WDG_CTL,0x02,
// FPD3_DES_I2C_CTRL, 0x8E},
//SER Device ID ds90ub921q
FPD3_DES_SER_ID, 0x18,
FPD3_DES_SLAVE_ID0, (0x20<<1),
FPD3_DES_SLAVE_AL0, (0x20<<1),

Are there any error about the configuration?

  • Hi Amelie,

    I dont see anything wrong currently, at what point are you seeing the error in the code? Can you send the addresses of the registers that you are writing in your code?Have you probed the I2C lines on the display?

    Regards,

    Michael W.

  • Hi Michael,

    Please see my feedback about these three question. Could you please kindly help? it is quite urgent in customer side.

    1. At what point are you seeing the error in the code? 

    When visit 948, it has I2C error.

    Here is Linux kernel log:

    [    2.022134] i2c-rcar e6508000.i2c:  error -110 : 1

    [    2.026932] fpd3_serdes 1-0034: Failed to read 0x00, Error = -110

    [    2.037269] i2c i2c-1: SCL is stuck low, exit recovery

    [    2.042413] i2c-rcar e6508000.i2c:  error -16 : 1

    [    2.047123] fpd3_serdes 1-0034: Failed to read 0x00, Error = -16

    [    2.057369] i2c i2c-1: SCL is stuck low, exit recovery

    [    2.062512] i2c-rcar e6508000.i2c:  error -16 : 1

    [    2.067222] fpd3_serdes 1-0034: Failed to read 0x00, Error = -16

    [    2.278128] i2c-rcar e6508000.i2c:  error -110 : 1

    [    2.282922] fpd3_serdes 1-0034: Failed to read 0x00, Error = -110

    [    2.293255] i2c i2c-1: SCL is stuck low, exit recovery

    [    2.298398] i2c-rcar e6508000.i2c:  error -16 : 1

    [    2.303106] fpd3_serdes 1-0034: Failed to read 0x00, Error = -16

    [    2.313352] i2c i2c-1: SCL is stuck low, exit recovery

    [    2.318495] i2c-rcar e6508000.i2c:  error -16 : 1

    [    2.323204] fpd3_serdes 1-0034: Failed to read 0x00, Error = -16

    [    2.534128] i2c-rcar e6508000.i2c:  error -110 : 1

    [    2.538922] fpd3_serdes 1-0034: Failed to read 0x00, Error = -110

    [    2.549255] i2c i2c-1: SCL is stuck low, exit recovery

    [    2.554398] i2c-rcar e6508000.i2c:  error -16 : 1

    [    2.559107] fpd3_serdes 1-0034: Failed to read 0x00, Error = -16

    [    2.569352] i2c i2c-1: SCL is stuck low, exit recovery

    [    2.574495] i2c-rcar e6508000.i2c:  error -16 : 1

    [    2.579204] fpd3_serdes 1-0034: Failed to read 0x00, Error = -16

    [    2.790126] i2c-rcar e6508000.i2c:  error -110 : 1

    [    2.794920] fpd3_serdes 1-0034: Failed to read 0x00, Error = -110

    [    2.804017] fpd3_serdes 1-0034: Not a fpd3_921to948_des chip

    [    2.809680] kfree memory fpd3_serdes_probe -- 618

    [    2.814405] i2c device fpd3_921to948_des : 0x34 disconnect.

    2. Can you send the addresses of the registers that you are writing in your code?

    Please see fpd3_serdes.h about the address definition.

    3. Have you probed the I2C lines on the display?

    When customer visit other device, such as 921, it is normal. However, when they visit 948, has error.

    fpd3_serdes.h

    2705.fpd3_serdes.c
    /*
     * fpd3_serdes.c
     *
     * lvds based serial link interface for onboard communication.
     */
    
    /*
     * Datasheets:-
     * DS90UB913aq/DS90UB914aq http://www.ti.com/lit/ds/snls443a/snls443a.pdf
     * DS90UH925Q http://www.ti.com/lit/ds/symlink/ds90uh925q-q1.pdf
     * DS90UH928Q http://www.ti.com/lit/ds/snls440a/snls440a.pdf
     * DS90UB924Q http://www.ti.com/lit/ds/snls512/snls512.pdf
     * DS90UB921Q http://www.ti.com/lit/ds/symlink/ds90ub921-q1.pdf
     *
     * Documentation:-
     * -> Documentation/video-serdes.txt
     * -> Documentation/devicetree/bindings/video/fpd3-serdes.txt
     */
    
    #include <linux/kernel.h>
    #include <linux/module.h>
    #include <linux/slab.h>
    #include <linux/i2c.h>
    #include <linux/gpio.h>
    #include <linux/delay.h>
    #include <linux/of_gpio.h>
    #include <linux/of_device.h>
    #include "fpd3_serdes.h"
    
    //#define TI_FPD3_DEBUG(...)
    #define TI_FPD3_DEBUG  printk
    
    
    static const unsigned int fpd3_949_ser_init[] = {
    	/* digital reset0, digital reset1 */
        FPD3_SER_RESET,      0x00,
        /* RX CRC check, i2c passthrough */
        FPD3_SER_CONFIG,     0xDA,
        /* DES Device ID ds90ub948q*/
        FPD3_SER_DES_ID,     0x68,
        FPD3_SER_SLAVE_ID0,  (0x20<<1),
        FPD3_SER_SLAVE_AL0,  (0x20<<1),
    
    //  FPD3_SER_I2C_CTRL,   0x9E,
        FPD3_SER_ICR,        0x21,
    };
    
    
    
    static const unsigned int fpd3_947_ser_init[] = {
    	//After power up write the following to the device:
    	FPD3_SER_947_ANA_IA_CNTL,		0x10,// select OLDI register
    	FPD3_SER_947_ANA_IA_ADDR,		0x49,// force PLL controller in PPM reset state
    	FPD3_SER_947_ANA_IA_DATA,		0x16,
    	FPD3_SER_947_ANA_IA_ADDR,		0x47,// force PLL LOCK Low
    	FPD3_SER_947_ANA_IA_DATA,		0x20,
    	FPD3_SER_947_ANA_IA_DATA,		0xA0,// reset PLL divider
    	FPD3_SER_947_ANA_IA_DATA,		0x20,
    	FPD3_SER_947_ANA_IA_DATA,		0x00,// release PLL LOCK control
    	FPD3_SER_947_ANA_IA_ADDR,		0x49,// release PLL state control
    	FPD3_SER_947_ANA_IA_DATA,		0x00,
    
    	/* digital reset0, digital reset1 */
    	FPD3_SER_RESET,      0x00,
    	/* RX CRC check, i2c passthrough */
    	FPD3_SER_CONFIG,     0xDA,
    	/* DES Device ID ds90ub948q*/
    	FPD3_SER_DES_ID,     0x68,
    	FPD3_SER_SLAVE_ID0,  (0x20<<1),
    	FPD3_SER_SLAVE_AL0,  (0x20<<1),
    };
    
    static const unsigned int fpd3_921_ser_init[] = {
    	/* digital reset0, digital reset1 */
    	FPD3_SER_RESET,				0x00,
    	/* RX CRC check, i2c passthrough */
    	FPD3_SER_CONFIG,			0xDA,
    	/* DES Device ID ds90ub948q*/
    	FPD3_SER_DES_ID,     0x68,
    	FPD3_SER_SLAVE_ID0,  (0x20<<1),
    	FPD3_SER_SLAVE_AL0,  (0x20<<1),
    };
    
    static const unsigned int fpd3_949to948_des_init[] = {
    	//digital reset0, digital reset1
    	FPD3_DES_RESET,		0x07,
    	//RX CRC check, i2c passthrough
    	FPD3_DES_CONFIG1,	0x78,
    	//Prevention of I2C Errors During Abrupt System Faults
    	FPD3_DES_BCC_WDG_CTL,0x02,
    //	FPD3_DES_I2C_CTRL,	0x8E,
    	//SER Device ID ds90ub949q
    	FPD3_DES_SER_ID,	0x18,
    	FPD3_DES_SLAVE_ID0,	(0x20<<1),
    	FPD3_DES_SLAVE_AL0,	(0x20<<1),
    
    	//GPIO1 for lighten - remote gpio control
    	FPD3_DES_GPIO_12,	0x99,
    
    	FPD3_DES_GPIO_78,	0x01,
    
    	FPD3_DES_GPIO_78,	0x09,
    };
    
    static const unsigned int fpd3_947to948_des_init[] = {
    	//digital reset0, digital reset1
    	FPD3_DES_RESET,		0x07,
    	//RX CRC check, i2c passthrough
    	FPD3_DES_CONFIG1,	0x78,
    	//Prevention of I2C Errors During Abrupt System Faults
    	FPD3_DES_BCC_WDG_CTL,0x02,
    //	FPD3_DES_I2C_CTRL,	0x8E},
    	//SER Device ID ds90ub947q
    	FPD3_DES_SER_ID, 	0x34,
    	FPD3_DES_SLAVE_ID0,	(0x20<<1),
    	FPD3_DES_SLAVE_AL0,	(0x20<<1),
    
    	//GPIO1 for lighten - remote gpio control
    	FPD3_DES_GPIO_12,	0x99,
    
    	FPD3_DES_GPIO_78,	0x01,
    
    	FPD3_DES_GPIO_78,	0x09,
    };
    
    
    static const unsigned int fpd3_921to948_des_init[] = {
    	//digital reset0, digital reset1
    	FPD3_DES_RESET,		0x07,
    	//RX CRC check, i2c passthrough
    	FPD3_DES_CONFIG1,	0x78,
    	//Prevention of I2C Errors During Abrupt System Faults
    	FPD3_DES_BCC_WDG_CTL,0x02,
    //	FPD3_DES_I2C_CTRL,	0x8E},
    	//SER Device ID ds90ub921q
    	FPD3_DES_SER_ID,	0x18,
    	FPD3_DES_SLAVE_ID0,	(0x20<<1),
    	FPD3_DES_SLAVE_AL0,	(0x20<<1),
    
    	//GPIO1 for lighten - remote gpio control
    	FPD3_DES_GPIO_12,	0x99,
    
    	FPD3_DES_GPIO_78,	0x01,
    
    	FPD3_DES_GPIO_78,	0x09,
    };
    
    int fpd3_serdes_initialize(struct i2c_client *client)
    {
    	struct fpd3_serdes_data *data = i2c_get_clientdata(client);
    	const struct fpd3_serdes_platform_data *pdata = data->pdata;
    	const unsigned int *seq;
    	int i, len, reg, ret = 0, count = 0;
    
    	if(!client)
    		return -ENODEV;
    
    	/* Wait for the device to initialize and show up device ID */
    	if((pdata->dev_type >= FPD3_SER_DEV)&&(pdata->dev_type < FPD3_DES_DEV))
    	{
    		reg = FPD3_SER_DEV_ID;
    	}
    	else if(pdata->dev_type >= FPD3_DES_DEV)
    	{
    		reg = FPD3_DES_DEV_ID;
    	}
    	//读取设备ID,判断设备是否连接  (默认读取10次)
    	while (ret != pdata->device_id && count < FPD3_MAX_POLL_COUNT) {
    		ret = i2c_read_le8(client, reg);
    		count++;
    		mdelay(3);
    	}
    	if (count == FPD3_MAX_POLL_COUNT) {
    		dev_err(&client->dev, "Not a %s chip", pdata->name);
    		return -ENODEV;
    	}
    	
    	//调用 fpd3_921_ser_init 之类数组初始化寄存器
    	len = pdata->init_len;
    	seq = pdata->init_seq;
    	for (i = 0; i < len; i += 2) {
    		ret = i2c_write_le8(client, seq[i], seq[i+1]);
    		if (ret)
    			i2c_write_le8(client, seq[i], seq[i+1]);
    		if (seq[i] == 0x01)
    			udelay(1000);
    		else
    			udelay(10);
    	}
    
    	return ret;
    }
    EXPORT_SYMBOL(fpd3_serdes_initialize);
    
    
    
    
    
    static int fpd3_serdes_probe(struct i2c_client *client,
    			 const struct i2c_device_id *id)
    {
    	const struct of_device_id *of_dev_id;
    	const struct fpd3_serdes_platform_data *pdata;
    	struct fpd3_serdes_data *data;
    	int status;
    
    	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
    	if (!data)
    		return -ENOMEM;
    
    	data->client = client;
    	i2c_set_clientdata(client, data);
    
    	fpd3_serdes_remove_conflict(client);
    
    	of_dev_id = of_match_device(fpd3_serdes_dt_ids, &client->dev);
    	if (!of_dev_id) {
    		dev_err(&client->dev, "Unable to match device");
    		return -EINVAL;
    	}
    	pdata = of_dev_id->data;
    	data->pdata = pdata;
    
    
    	status = fpd3_serdes_initialize(client);
    	if(status)
    	{
    		if((pdata->dev_type >= FPD3_SER_DEV)&&(pdata->dev_type < FPD3_DES_DEV))
    			goto free_gpio;
    		else if(pdata->dev_type >= FPD3_DES_DEV)
    			goto fail;
    	}
    
    	dev_err(&client->dev, "%s %s ready", pdata->dev_type == FPD3_SER_DEV ?
    		"Serializer" : "Deserializer", data->pdata->name);
    	
    	return 0;
    free_gpio:
    	fpd3_of_gpio_free(data);
    fail:
    	TI_FPD3_DEBUG(KERN_INFO"kfree memory %s -- %d\n",__func__,__LINE__);
    	TI_FPD3_DEBUG(KERN_INFO"i2c device %s : 0x%2x disconnect.\n",data->pdata->name,client->addr);
    	devm_kfree(&client->dev,data);
    	return status;
    }
    
    static int fpd3_serdes_remove(struct i2c_client *client)
    {
    	struct fpd3_serdes_data	*data = i2c_get_clientdata(client);
    
    	fpd3_of_gpio_free(data);
    	devm_kfree(&client->dev,data);
    
    	return 0;
    }
    
    static struct i2c_driver fpd3_serdes_driver = {
    	.driver = {
    		.name = "fpd3_serdes",
    		.owner = THIS_MODULE,
    		.of_match_table	= fpd3_serdes_dt_ids,
    	},
    	.probe = fpd3_serdes_probe,
    	.remove = fpd3_serdes_remove,
    	.id_table = fpd3_serdes_i2c_ids
    };
    
    static int __init fpd3_i2c_init(void)
    {
    	return i2c_add_driver(&fpd3_serdes_driver);
    }
    
    static void __exit fpd3_i2c_exit(void)
    {
    	i2c_del_driver(&fpd3_serdes_driver);
    }
    
    fs_initcall(fpd3_i2c_init);
    module_exit(fpd3_i2c_exit);
    
    MODULE_LICENSE("GPL");
    MODULE_AUTHOR("Nikhil Devshatwar");
    

  • Hi Team,

    One more comment, I saw the 921 datasheet P43 that,

    when 921+926, it uses Figure 28. Typical STP System Diagram;

    when 921+948, it uses Figure 29. Typical Coax Applications Diagram.

    does it mean when use 921+948, only support Coax? Customer now use STP...

  • Hi Amelie,

    Can you send me a register dump of the 921 configured? also can you get local I2C access to 948 and get a reg dump?

    What are the MODE_SEL set to on the 948?

    The 921 can be linked to the 948 through a STP cable.

    Regards,

    Michael W.

  • Hi Michael,

    Please see the feedback from customer side:

    • Can you send me a register dump of the 921 configured?

         0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef

    00: 18 00 00 fa 80 00 68 40 40 00 00 00 00 00 00 00    ?..??.h@@.......

    10: 00 00 00 10 00 00 fe 5e a1 a5 00 00 00 00 00 00    ...?..?^??......

    20: 00 00 25 00 00 00 00 00 00 24 00 a0 00 00 00 00    ..%......$.?....

    30: 03 10 00 00 00 00 08 34 00 0a 20 21 00 00 f0 00    ??....?4.? !..?.

    40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

    50: 20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00     ...............

    60: 00 00 00 00 10 00 00 00 00 00 00 00 00 00 00 00    ....?...........

    70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

    80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

    90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    .....

    • also can you get local I2C access to 948 and get a reg dump?

    Customer doesn't change the value in 948 so all of register is default value in 948.

    • What are the MODE_SEL set to on the 948?

  • Hi Michael,

    Could you please kindly help about this?

  • Hi Amelie,

    I didnt find anything wrong with your 921 configuration.

    Have you tried using commands like:

    I2cget -y 0 0x34 0x00

    Regards,

    Michael W.

  • Hi Michael,

    I saw customer code. They haven't used I2cget -y 0 0x34 0x00.

    Do we have other way to check whether the I2C communication between 921 and 948 is ok or not?

  • Hi Amelie,

    Can you have them try:

    I2cget -y 0 0x34 0x00

    and 

    can they probe the I2C lines on the 948 side when they send I2C commands to see if the 948 is outputting them?

    Regards,

    Michael W.

  • Hi Michael.

    I will ask customer to try.

    May I consult that what does "I2cget -y 0 0x34 0x00" mean?

    Why suggest use this command?

    Thanks!

  • AS for the second point, the SCL and SDA is low in 948 side.

    It is quite strange. Because when customer use 949+948, they could configure 948 normally by I2C; but when use 921+948, it has error and I2C is low.

  • Hi Amelie,

    I suggest the I2C command be cause it is the 7 bit address of the 948 and will get the contents of register 0x00.

    That is very strange. Is it the same 948 board that is connected to the 949 as the 921?

    Regards,

    Michael W.

  • Yes. They are the same..

  • Hello Amelie,

    Thanks for providing the additional details. We will continue the evaluation and respond back on Monday 

    Best Regards,

    Casey 

  • Hi Amelie,

    Can you capture a register dump of the 948 connected to the 921? and when connected to the 949?

    Regards,

    Michael W.

  • HI Michael,

    When connected to 921, it can't visit 948 register because meet the I2C error. But when connected to 949, it could work.

    The following I2C command have already used in customer system and all of them met I2C error.

             I2cdetect –l

             I2cdetect –y –r 1

             I2cdump –f –y 1 0x34

             I2cget –f –y 1 0x34 0x00

             I2cset –f –y 1 0x34 0x01 0x3f

  • Hi Amelie,

    Can you get local access to the 948's I2C and get a register dump?

    Regards,

    Michael W.

  • Hi Michael,

    Display is not designed by customer side. So they can't configure in 948 side...

  • Hi Amelie,

    Can you Check the lock pinon the 948? and can you run BIST on the 948-921 link?

    Regards,

    Michael W.

  • Hi Michael,

    I will ask customer to check.

    May I ask:

    Compared with 949 and 948, is there some special configuration need to change or Register need to setup when use 921 and 948?

    I am worried whether there are some difference I2C configuration between 92x/94x and 94x/94x. 

  • Hi Amelie,

    No there is no special configuration between the two.

    Regards,

    Michael W.

  • Hi Amelie,

    Also can you verify that the 921 is following the power up requirements stated in section:  "9.1 Power Up Requirements and PDB Pin" of the datasheet.

    Regards,

    Michael W.