[02/12] cx231xx: use own i2c_client for eeprom access

Message ID 1411621684-8295-2-git-send-email-zzam@gentoo.org (mailing list archive)
State Superseded, archived
Headers

Commit Message

Matthias Schwarzott Sept. 25, 2014, 5:07 a.m. UTC
  Signed-off-by: Matthias Schwarzott <zzam@gentoo.org>
---
 drivers/media/usb/cx231xx/cx231xx-cards.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)
  

Comments

Antti Palosaari Sept. 25, 2014, 2:58 p.m. UTC | #1
Reviewed-by: Antti Palosaari <crope@iki.fi>

Please add commit description (why and how).

Some notes for further development:
It sends single messages, so you could (or even should) use 
i2c_master_send/i2c_master_recv (i2c_transfer is aimed for sending 
multiple messages using REPEATED START condition).

I am not sure though if these eeprom chips uses REPEATED START condition 
for reads (means it could be broken even now).

regards
Antti

On 09/25/2014 08:07 AM, Matthias Schwarzott wrote:
> Signed-off-by: Matthias Schwarzott <zzam@gentoo.org>
> ---
>   drivers/media/usb/cx231xx/cx231xx-cards.c | 24 +++++++++++++-----------
>   1 file changed, 13 insertions(+), 11 deletions(-)
>
> diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
> index 791f00c..092fb85 100644
> --- a/drivers/media/usb/cx231xx/cx231xx-cards.c
> +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
> @@ -980,23 +980,20 @@ static void cx231xx_config_tuner(struct cx231xx *dev)
>
>   }
>
> -static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
> +static int read_eeprom(struct cx231xx *dev, struct i2c_client *client,
> +		       u8 *eedata, int len)
>   {
>   	int ret = 0;
> -	u8 addr = 0xa0 >> 1;
>   	u8 start_offset = 0;
>   	int len_todo = len;
>   	u8 *eedata_cur = eedata;
>   	int i;
> -	struct i2c_msg msg_write = { .addr = addr, .flags = 0,
> +	struct i2c_msg msg_write = { .addr = client->addr, .flags = 0,
>   		.buf = &start_offset, .len = 1 };
> -	struct i2c_msg msg_read = { .addr = addr, .flags = I2C_M_RD };
> -
> -	/* mutex_lock(&dev->i2c_lock); */
> -	cx231xx_enable_i2c_port_3(dev, false);
> +	struct i2c_msg msg_read = { .addr = client->addr, .flags = I2C_M_RD };
>
>   	/* start reading at offset 0 */
> -	ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_write, 1);
> +	ret = i2c_transfer(client->adapter, &msg_write, 1);
>   	if (ret < 0) {
>   		cx231xx_err("Can't read eeprom\n");
>   		return ret;
> @@ -1006,7 +1003,7 @@ static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
>   		msg_read.len = (len_todo > 64) ? 64 : len_todo;
>   		msg_read.buf = eedata_cur;
>
> -		ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_read, 1);
> +		ret = i2c_transfer(client->adapter, &msg_read, 1);
>   		if (ret < 0) {
>   			cx231xx_err("Can't read eeprom\n");
>   			return ret;
> @@ -1062,9 +1059,14 @@ void cx231xx_card_setup(struct cx231xx *dev)
>   		{
>   			struct tveeprom tvee;
>   			static u8 eeprom[256];
> +			struct i2c_client client;
> +
> +			memset(&client, 0, sizeof(client));
> +			client.adapter = &dev->i2c_bus[1].i2c_adap;
> +			client.addr = 0xa0 >> 1;
>
> -			read_eeprom(dev, eeprom, sizeof(eeprom));
> -			tveeprom_hauppauge_analog(&dev->i2c_bus[1].i2c_client,
> +			read_eeprom(dev, &client, eeprom, sizeof(eeprom));
> +			tveeprom_hauppauge_analog(&client,
>   						&tvee, eeprom + 0xc0);
>   			break;
>   		}
>
  
Matthias Schwarzott Sept. 26, 2014, 4:30 a.m. UTC | #2
Hi Antti,

I think that i2c_transfer sens no repeated start when sending only one
message per call.

At least the received eeprom content looks correct.

Regards
Matthias

On 25.09.2014 16:58, Antti Palosaari wrote:
> Reviewed-by: Antti Palosaari <crope@iki.fi>
> 
> Please add commit description (why and how).
> 
> Some notes for further development:
> It sends single messages, so you could (or even should) use
> i2c_master_send/i2c_master_recv (i2c_transfer is aimed for sending
> multiple messages using REPEATED START condition).
> 
> I am not sure though if these eeprom chips uses REPEATED START condition
> for reads (means it could be broken even now).
> 
> regards
> Antti
> 
> On 09/25/2014 08:07 AM, Matthias Schwarzott wrote:
>> Signed-off-by: Matthias Schwarzott <zzam@gentoo.org>
>> ---
>>   drivers/media/usb/cx231xx/cx231xx-cards.c | 24 +++++++++++++-----------
>>   1 file changed, 13 insertions(+), 11 deletions(-)
>>
>> diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c
>> b/drivers/media/usb/cx231xx/cx231xx-cards.c
>> index 791f00c..092fb85 100644
>> --- a/drivers/media/usb/cx231xx/cx231xx-cards.c
>> +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
>> @@ -980,23 +980,20 @@ static void cx231xx_config_tuner(struct cx231xx
>> *dev)
>>
>>   }
>>
>> -static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
>> +static int read_eeprom(struct cx231xx *dev, struct i2c_client *client,
>> +               u8 *eedata, int len)
>>   {
>>       int ret = 0;
>> -    u8 addr = 0xa0 >> 1;
>>       u8 start_offset = 0;
>>       int len_todo = len;
>>       u8 *eedata_cur = eedata;
>>       int i;
>> -    struct i2c_msg msg_write = { .addr = addr, .flags = 0,
>> +    struct i2c_msg msg_write = { .addr = client->addr, .flags = 0,
>>           .buf = &start_offset, .len = 1 };
>> -    struct i2c_msg msg_read = { .addr = addr, .flags = I2C_M_RD };
>> -
>> -    /* mutex_lock(&dev->i2c_lock); */
>> -    cx231xx_enable_i2c_port_3(dev, false);
>> +    struct i2c_msg msg_read = { .addr = client->addr, .flags =
>> I2C_M_RD };
>>
>>       /* start reading at offset 0 */
>> -    ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_write, 1);
>> +    ret = i2c_transfer(client->adapter, &msg_write, 1);
>>       if (ret < 0) {
>>           cx231xx_err("Can't read eeprom\n");
>>           return ret;
>> @@ -1006,7 +1003,7 @@ static int read_eeprom(struct cx231xx *dev, u8
>> *eedata, int len)
>>           msg_read.len = (len_todo > 64) ? 64 : len_todo;
>>           msg_read.buf = eedata_cur;
>>
>> -        ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_read, 1);
>> +        ret = i2c_transfer(client->adapter, &msg_read, 1);
>>           if (ret < 0) {
>>               cx231xx_err("Can't read eeprom\n");
>>               return ret;
>> @@ -1062,9 +1059,14 @@ void cx231xx_card_setup(struct cx231xx *dev)
>>           {
>>               struct tveeprom tvee;
>>               static u8 eeprom[256];
>> +            struct i2c_client client;
>> +
>> +            memset(&client, 0, sizeof(client));
>> +            client.adapter = &dev->i2c_bus[1].i2c_adap;
>> +            client.addr = 0xa0 >> 1;
>>
>> -            read_eeprom(dev, eeprom, sizeof(eeprom));
>> -            tveeprom_hauppauge_analog(&dev->i2c_bus[1].i2c_client,
>> +            read_eeprom(dev, &client, eeprom, sizeof(eeprom));
>> +            tveeprom_hauppauge_analog(&client,
>>                           &tvee, eeprom + 0xc0);
>>               break;
>>           }
>>
> 

--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
  
Antti Palosaari Sept. 26, 2014, 12:31 p.m. UTC | #3
yes, of course :) If you has only one message, there is nothing to start 
again. Sending one message using i2c_transfer() means same than using 
i2c_master_send(), but the later one is just aimed to send single 
message and it cannot be used to send multiple messages at once.

Code is correct, but it triggered my sensors when reading it and I have 
to check it many times whats going there.

regards
Antti

On 09/26/2014 07:30 AM, Matthias Schwarzott wrote:
> Hi Antti,
>
> I think that i2c_transfer sens no repeated start when sending only one
> message per call.
>
> At least the received eeprom content looks correct.
>
> Regards
> Matthias
>
> On 25.09.2014 16:58, Antti Palosaari wrote:
>> Reviewed-by: Antti Palosaari <crope@iki.fi>
>>
>> Please add commit description (why and how).
>>
>> Some notes for further development:
>> It sends single messages, so you could (or even should) use
>> i2c_master_send/i2c_master_recv (i2c_transfer is aimed for sending
>> multiple messages using REPEATED START condition).
>>
>> I am not sure though if these eeprom chips uses REPEATED START condition
>> for reads (means it could be broken even now).
>>
>> regards
>> Antti
>>
>> On 09/25/2014 08:07 AM, Matthias Schwarzott wrote:
>>> Signed-off-by: Matthias Schwarzott <zzam@gentoo.org>
>>> ---
>>>    drivers/media/usb/cx231xx/cx231xx-cards.c | 24 +++++++++++++-----------
>>>    1 file changed, 13 insertions(+), 11 deletions(-)
>>>
>>> diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c
>>> b/drivers/media/usb/cx231xx/cx231xx-cards.c
>>> index 791f00c..092fb85 100644
>>> --- a/drivers/media/usb/cx231xx/cx231xx-cards.c
>>> +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
>>> @@ -980,23 +980,20 @@ static void cx231xx_config_tuner(struct cx231xx
>>> *dev)
>>>
>>>    }
>>>
>>> -static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
>>> +static int read_eeprom(struct cx231xx *dev, struct i2c_client *client,
>>> +               u8 *eedata, int len)
>>>    {
>>>        int ret = 0;
>>> -    u8 addr = 0xa0 >> 1;
>>>        u8 start_offset = 0;
>>>        int len_todo = len;
>>>        u8 *eedata_cur = eedata;
>>>        int i;
>>> -    struct i2c_msg msg_write = { .addr = addr, .flags = 0,
>>> +    struct i2c_msg msg_write = { .addr = client->addr, .flags = 0,
>>>            .buf = &start_offset, .len = 1 };
>>> -    struct i2c_msg msg_read = { .addr = addr, .flags = I2C_M_RD };
>>> -
>>> -    /* mutex_lock(&dev->i2c_lock); */
>>> -    cx231xx_enable_i2c_port_3(dev, false);
>>> +    struct i2c_msg msg_read = { .addr = client->addr, .flags =
>>> I2C_M_RD };
>>>
>>>        /* start reading at offset 0 */
>>> -    ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_write, 1);
>>> +    ret = i2c_transfer(client->adapter, &msg_write, 1);
>>>        if (ret < 0) {
>>>            cx231xx_err("Can't read eeprom\n");
>>>            return ret;
>>> @@ -1006,7 +1003,7 @@ static int read_eeprom(struct cx231xx *dev, u8
>>> *eedata, int len)
>>>            msg_read.len = (len_todo > 64) ? 64 : len_todo;
>>>            msg_read.buf = eedata_cur;
>>>
>>> -        ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_read, 1);
>>> +        ret = i2c_transfer(client->adapter, &msg_read, 1);
>>>            if (ret < 0) {
>>>                cx231xx_err("Can't read eeprom\n");
>>>                return ret;
>>> @@ -1062,9 +1059,14 @@ void cx231xx_card_setup(struct cx231xx *dev)
>>>            {
>>>                struct tveeprom tvee;
>>>                static u8 eeprom[256];
>>> +            struct i2c_client client;
>>> +
>>> +            memset(&client, 0, sizeof(client));
>>> +            client.adapter = &dev->i2c_bus[1].i2c_adap;
>>> +            client.addr = 0xa0 >> 1;
>>>
>>> -            read_eeprom(dev, eeprom, sizeof(eeprom));
>>> -            tveeprom_hauppauge_analog(&dev->i2c_bus[1].i2c_client,
>>> +            read_eeprom(dev, &client, eeprom, sizeof(eeprom));
>>> +            tveeprom_hauppauge_analog(&client,
>>>                            &tvee, eeprom + 0xc0);
>>>                break;
>>>            }
>>>
>>
>
  
Antti Palosaari Sept. 26, 2014, 1 p.m. UTC | #4
I decided to check how eeprom I2C interface works from datasheet. Chip 
keeps internally current address value and read operations are done for 
that. Basically both reads works, as chip keeps count of current read 
address internally.

That datasheet has nice figures from use cases:
http://www.atmel.com/Images/doc8700.pdf

Figure 9-1. Byte Write
Figure 9-2. Page Write
Figure 9-3. Current Address Read
Figure 9-4. Random Read
Figure 9-5. Sequential Read

regards
Antti

On 09/26/2014 03:31 PM, Antti Palosaari wrote:
> yes, of course :) If you has only one message, there is nothing to start
> again. Sending one message using i2c_transfer() means same than using
> i2c_master_send(), but the later one is just aimed to send single
> message and it cannot be used to send multiple messages at once.
>
> Code is correct, but it triggered my sensors when reading it and I have
> to check it many times whats going there.
>
> regards
> Antti
>
> On 09/26/2014 07:30 AM, Matthias Schwarzott wrote:
>> Hi Antti,
>>
>> I think that i2c_transfer sens no repeated start when sending only one
>> message per call.
>>
>> At least the received eeprom content looks correct.
>>
>> Regards
>> Matthias
>>
>> On 25.09.2014 16:58, Antti Palosaari wrote:
>>> Reviewed-by: Antti Palosaari <crope@iki.fi>
>>>
>>> Please add commit description (why and how).
>>>
>>> Some notes for further development:
>>> It sends single messages, so you could (or even should) use
>>> i2c_master_send/i2c_master_recv (i2c_transfer is aimed for sending
>>> multiple messages using REPEATED START condition).
>>>
>>> I am not sure though if these eeprom chips uses REPEATED START condition
>>> for reads (means it could be broken even now).
>>>
>>> regards
>>> Antti
>>>
>>> On 09/25/2014 08:07 AM, Matthias Schwarzott wrote:
>>>> Signed-off-by: Matthias Schwarzott <zzam@gentoo.org>
>>>> ---
>>>>    drivers/media/usb/cx231xx/cx231xx-cards.c | 24
>>>> +++++++++++++-----------
>>>>    1 file changed, 13 insertions(+), 11 deletions(-)
>>>>
>>>> diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c
>>>> b/drivers/media/usb/cx231xx/cx231xx-cards.c
>>>> index 791f00c..092fb85 100644
>>>> --- a/drivers/media/usb/cx231xx/cx231xx-cards.c
>>>> +++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
>>>> @@ -980,23 +980,20 @@ static void cx231xx_config_tuner(struct cx231xx
>>>> *dev)
>>>>
>>>>    }
>>>>
>>>> -static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
>>>> +static int read_eeprom(struct cx231xx *dev, struct i2c_client *client,
>>>> +               u8 *eedata, int len)
>>>>    {
>>>>        int ret = 0;
>>>> -    u8 addr = 0xa0 >> 1;
>>>>        u8 start_offset = 0;
>>>>        int len_todo = len;
>>>>        u8 *eedata_cur = eedata;
>>>>        int i;
>>>> -    struct i2c_msg msg_write = { .addr = addr, .flags = 0,
>>>> +    struct i2c_msg msg_write = { .addr = client->addr, .flags = 0,
>>>>            .buf = &start_offset, .len = 1 };
>>>> -    struct i2c_msg msg_read = { .addr = addr, .flags = I2C_M_RD };
>>>> -
>>>> -    /* mutex_lock(&dev->i2c_lock); */
>>>> -    cx231xx_enable_i2c_port_3(dev, false);
>>>> +    struct i2c_msg msg_read = { .addr = client->addr, .flags =
>>>> I2C_M_RD };
>>>>
>>>>        /* start reading at offset 0 */
>>>> -    ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_write, 1);
>>>> +    ret = i2c_transfer(client->adapter, &msg_write, 1);
>>>>        if (ret < 0) {
>>>>            cx231xx_err("Can't read eeprom\n");
>>>>            return ret;
>>>> @@ -1006,7 +1003,7 @@ static int read_eeprom(struct cx231xx *dev, u8
>>>> *eedata, int len)
>>>>            msg_read.len = (len_todo > 64) ? 64 : len_todo;
>>>>            msg_read.buf = eedata_cur;
>>>>
>>>> -        ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_read, 1);
>>>> +        ret = i2c_transfer(client->adapter, &msg_read, 1);
>>>>            if (ret < 0) {
>>>>                cx231xx_err("Can't read eeprom\n");
>>>>                return ret;
>>>> @@ -1062,9 +1059,14 @@ void cx231xx_card_setup(struct cx231xx *dev)
>>>>            {
>>>>                struct tveeprom tvee;
>>>>                static u8 eeprom[256];
>>>> +            struct i2c_client client;
>>>> +
>>>> +            memset(&client, 0, sizeof(client));
>>>> +            client.adapter = &dev->i2c_bus[1].i2c_adap;
>>>> +            client.addr = 0xa0 >> 1;
>>>>
>>>> -            read_eeprom(dev, eeprom, sizeof(eeprom));
>>>> -            tveeprom_hauppauge_analog(&dev->i2c_bus[1].i2c_client,
>>>> +            read_eeprom(dev, &client, eeprom, sizeof(eeprom));
>>>> +            tveeprom_hauppauge_analog(&client,
>>>>                            &tvee, eeprom + 0xc0);
>>>>                break;
>>>>            }
>>>>
>>>
>>
>
  

Patch

diff --git a/drivers/media/usb/cx231xx/cx231xx-cards.c b/drivers/media/usb/cx231xx/cx231xx-cards.c
index 791f00c..092fb85 100644
--- a/drivers/media/usb/cx231xx/cx231xx-cards.c
+++ b/drivers/media/usb/cx231xx/cx231xx-cards.c
@@ -980,23 +980,20 @@  static void cx231xx_config_tuner(struct cx231xx *dev)
 
 }
 
-static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
+static int read_eeprom(struct cx231xx *dev, struct i2c_client *client,
+		       u8 *eedata, int len)
 {
 	int ret = 0;
-	u8 addr = 0xa0 >> 1;
 	u8 start_offset = 0;
 	int len_todo = len;
 	u8 *eedata_cur = eedata;
 	int i;
-	struct i2c_msg msg_write = { .addr = addr, .flags = 0,
+	struct i2c_msg msg_write = { .addr = client->addr, .flags = 0,
 		.buf = &start_offset, .len = 1 };
-	struct i2c_msg msg_read = { .addr = addr, .flags = I2C_M_RD };
-
-	/* mutex_lock(&dev->i2c_lock); */
-	cx231xx_enable_i2c_port_3(dev, false);
+	struct i2c_msg msg_read = { .addr = client->addr, .flags = I2C_M_RD };
 
 	/* start reading at offset 0 */
-	ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_write, 1);
+	ret = i2c_transfer(client->adapter, &msg_write, 1);
 	if (ret < 0) {
 		cx231xx_err("Can't read eeprom\n");
 		return ret;
@@ -1006,7 +1003,7 @@  static int read_eeprom(struct cx231xx *dev, u8 *eedata, int len)
 		msg_read.len = (len_todo > 64) ? 64 : len_todo;
 		msg_read.buf = eedata_cur;
 
-		ret = i2c_transfer(&dev->i2c_bus[1].i2c_adap, &msg_read, 1);
+		ret = i2c_transfer(client->adapter, &msg_read, 1);
 		if (ret < 0) {
 			cx231xx_err("Can't read eeprom\n");
 			return ret;
@@ -1062,9 +1059,14 @@  void cx231xx_card_setup(struct cx231xx *dev)
 		{
 			struct tveeprom tvee;
 			static u8 eeprom[256];
+			struct i2c_client client;
+
+			memset(&client, 0, sizeof(client));
+			client.adapter = &dev->i2c_bus[1].i2c_adap;
+			client.addr = 0xa0 >> 1;
 
-			read_eeprom(dev, eeprom, sizeof(eeprom));
-			tveeprom_hauppauge_analog(&dev->i2c_bus[1].i2c_client,
+			read_eeprom(dev, &client, eeprom, sizeof(eeprom));
+			tveeprom_hauppauge_analog(&client,
 						&tvee, eeprom + 0xc0);
 			break;
 		}