diff mbox

[v3,02/11] media: ov772x: allow i2c controllers without I2C_FUNC_PROTOCOL_MANGLING

Message ID 1524412577-14419-3-git-send-email-akinobu.mita@gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Akinobu Mita April 22, 2018, 3:56 p.m. UTC
The ov772x driver only works when the i2c controller have
I2C_FUNC_PROTOCOL_MANGLING.  However, many i2c controller drivers don't
support it.

The reason that the ov772x requires I2C_FUNC_PROTOCOL_MANGLING is that
it doesn't support repeated starts.

This changes the reading ov772x register method so that it doesn't
require I2C_FUNC_PROTOCOL_MANGLING by calling two separated i2c messages.

Cc: Jacopo Mondi <jacopo+renesas@jmondi.org>
Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Cc: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
Cc: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
---
* v3
- Remove I2C_CLIENT_SCCB flag set as it isn't needed anymore

 drivers/media/i2c/ov772x.c | 20 ++++++++++++++------
 1 file changed, 14 insertions(+), 6 deletions(-)

Comments

Laurent Pinchart April 23, 2018, 9:18 a.m. UTC | #1
Hi Mita-san,

On Sunday, 22 April 2018 18:56:08 EEST Akinobu Mita wrote:
> The ov772x driver only works when the i2c controller have
> I2C_FUNC_PROTOCOL_MANGLING.  However, many i2c controller drivers don't
> support it.
> 
> The reason that the ov772x requires I2C_FUNC_PROTOCOL_MANGLING is that
> it doesn't support repeated starts.
> 
> This changes the reading ov772x register method so that it doesn't
> require I2C_FUNC_PROTOCOL_MANGLING by calling two separated i2c messages.

As commented in a reply to v1, given that this implementation is in no way 
specific to the ov772x driver, I'd prefer implementing the fallback in the I2C 
core instead.

> Cc: Jacopo Mondi <jacopo+renesas@jmondi.org>
> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> Cc: Hans Verkuil <hans.verkuil@cisco.com>
> Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
> Cc: Mauro Carvalho Chehab <mchehab@s-opensource.com>
> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
> ---
> * v3
> - Remove I2C_CLIENT_SCCB flag set as it isn't needed anymore
> 
>  drivers/media/i2c/ov772x.c | 20 ++++++++++++++------
>  1 file changed, 14 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
> index b62860c..2ae730f 100644
> --- a/drivers/media/i2c/ov772x.c
> +++ b/drivers/media/i2c/ov772x.c
> @@ -542,9 +542,19 @@ static struct ov772x_priv *to_ov772x(struct v4l2_subdev
> *sd) return container_of(sd, struct ov772x_priv, subdev);
>  }
> 
> -static inline int ov772x_read(struct i2c_client *client, u8 addr)
> +static int ov772x_read(struct i2c_client *client, u8 addr)
>  {
> -	return i2c_smbus_read_byte_data(client, addr);
> +	int ret;
> +	u8 val;
> +
> +	ret = i2c_master_send(client, &addr, 1);
> +	if (ret < 0)
> +		return ret;
> +	ret = i2c_master_recv(client, &val, 1);
> +	if (ret < 0)
> +		return ret;
> +
> +	return val;
>  }
> 
>  static inline int ov772x_write(struct i2c_client *client, u8 addr, u8
> value) @@ -1255,13 +1265,11 @@ static int ov772x_probe(struct i2c_client
> *client, return -EINVAL;
>  	}
> 
> -	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
> -					      I2C_FUNC_PROTOCOL_MANGLING)) {
> +	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
>  		dev_err(&adapter->dev,
> -			"I2C-Adapter doesn't support SMBUS_BYTE_DATA or PROTOCOL_MANGLING
\n");
> +			"I2C-Adapter doesn't support SMBUS_BYTE_DATA\n");
>  		return -EIO;
>  	}
> -	client->flags |= I2C_CLIENT_SCCB;
> 
>  	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
>  	if (!priv)
Akinobu Mita April 23, 2018, 3:55 p.m. UTC | #2
2018-04-23 18:18 GMT+09:00 Laurent Pinchart <laurent.pinchart@ideasonboard.com>:
> Hi Mita-san,
>
> On Sunday, 22 April 2018 18:56:08 EEST Akinobu Mita wrote:
>> The ov772x driver only works when the i2c controller have
>> I2C_FUNC_PROTOCOL_MANGLING.  However, many i2c controller drivers don't
>> support it.
>>
>> The reason that the ov772x requires I2C_FUNC_PROTOCOL_MANGLING is that
>> it doesn't support repeated starts.
>>
>> This changes the reading ov772x register method so that it doesn't
>> require I2C_FUNC_PROTOCOL_MANGLING by calling two separated i2c messages.
>
> As commented in a reply to v1, given that this implementation is in no way
> specific to the ov772x driver, I'd prefer implementing the fallback in the I2C
> core instead.

Do you have any ideas how to implement in the I2C core?
I wonder if I can modify i2c_smbus_read_byte_data() or i2c_transfer()
for I2C_CLIENT_SCCB.

>> Cc: Jacopo Mondi <jacopo+renesas@jmondi.org>
>> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
>> Cc: Hans Verkuil <hans.verkuil@cisco.com>
>> Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
>> Cc: Mauro Carvalho Chehab <mchehab@s-opensource.com>
>> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
>> ---
>> * v3
>> - Remove I2C_CLIENT_SCCB flag set as it isn't needed anymore
>>
>>  drivers/media/i2c/ov772x.c | 20 ++++++++++++++------
>>  1 file changed, 14 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
>> index b62860c..2ae730f 100644
>> --- a/drivers/media/i2c/ov772x.c
>> +++ b/drivers/media/i2c/ov772x.c
>> @@ -542,9 +542,19 @@ static struct ov772x_priv *to_ov772x(struct v4l2_subdev
>> *sd) return container_of(sd, struct ov772x_priv, subdev);
>>  }
>>
>> -static inline int ov772x_read(struct i2c_client *client, u8 addr)
>> +static int ov772x_read(struct i2c_client *client, u8 addr)
>>  {
>> -     return i2c_smbus_read_byte_data(client, addr);
>> +     int ret;
>> +     u8 val;
>> +
>> +     ret = i2c_master_send(client, &addr, 1);
>> +     if (ret < 0)
>> +             return ret;
>> +     ret = i2c_master_recv(client, &val, 1);
>> +     if (ret < 0)
>> +             return ret;
>> +
>> +     return val;
>>  }
>>
>>  static inline int ov772x_write(struct i2c_client *client, u8 addr, u8
>> value) @@ -1255,13 +1265,11 @@ static int ov772x_probe(struct i2c_client
>> *client, return -EINVAL;
>>       }
>>
>> -     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
>> -                                           I2C_FUNC_PROTOCOL_MANGLING)) {
>> +     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
>>               dev_err(&adapter->dev,
>> -                     "I2C-Adapter doesn't support SMBUS_BYTE_DATA or PROTOCOL_MANGLING
> \n");
>> +                     "I2C-Adapter doesn't support SMBUS_BYTE_DATA\n");
>>               return -EIO;
>>       }
>> -     client->flags |= I2C_CLIENT_SCCB;
>>
>>       priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
>>       if (!priv)
>
>
> --
> Regards,
>
> Laurent Pinchart
>
>
>
Laurent Pinchart April 23, 2018, 7:41 p.m. UTC | #3
Hi Mita-san,

(CC'ing Wolfram Sang)

On Monday, 23 April 2018 18:55:20 EEST Akinobu Mita wrote:
> 2018-04-23 18:18 GMT+09:00 Laurent Pinchart:
> > On Sunday, 22 April 2018 18:56:08 EEST Akinobu Mita wrote:
> >> The ov772x driver only works when the i2c controller have
> >> I2C_FUNC_PROTOCOL_MANGLING.  However, many i2c controller drivers don't
> >> support it.
> >> 
> >> The reason that the ov772x requires I2C_FUNC_PROTOCOL_MANGLING is that
> >> it doesn't support repeated starts.
> >> 
> >> This changes the reading ov772x register method so that it doesn't
> >> require I2C_FUNC_PROTOCOL_MANGLING by calling two separated i2c messages.
> > 
> > As commented in a reply to v1, given that this implementation is in no way
> > specific to the ov772x driver, I'd prefer implementing the fallback in the
> > I2C core instead.
> 
> Do you have any ideas how to implement in the I2C core?
> I wonder if I can modify i2c_smbus_read_byte_data() or i2c_transfer()
> for I2C_CLIENT_SCCB.

How about i2c_smbus_xfer_emulated() ? The tricky part will be to handle the 
I2C adapters that implement .smbus_xfer(), as those won't go through 
i2c_smbus_xfer_emulated(). i2c_smbus_xfer_emulated() relies on i2c_transfer(), 
which itself relies on the I2C adapter's .master_xfer() operation. We're thus 
only concerned about the drivers that implement both .smbus_xfer() and 
master_xfer(), and there's only 4 of them (i2c-opal, i2c-pasemi, i2c-powermac 
and i2c-zx2967). Maybe the simplest solution would be to force the emulation 
path if I2C_CLIENT_SCCB && !I2C_FUNC_PROTOCOL_MANGLING && ->master_xfer != 
NULL ?

Wolfram, what do you think ?

> >> Cc: Jacopo Mondi <jacopo+renesas@jmondi.org>
> >> Cc: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> >> Cc: Hans Verkuil <hans.verkuil@cisco.com>
> >> Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
> >> Cc: Mauro Carvalho Chehab <mchehab@s-opensource.com>
> >> Signed-off-by: Akinobu Mita <akinobu.mita@gmail.com>
> >> ---
> >> * v3
> >> - Remove I2C_CLIENT_SCCB flag set as it isn't needed anymore
> >> 
> >>  drivers/media/i2c/ov772x.c | 20 ++++++++++++++------
> >>  1 file changed, 14 insertions(+), 6 deletions(-)
> >> 
> >> diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
> >> index b62860c..2ae730f 100644
> >> --- a/drivers/media/i2c/ov772x.c
> >> +++ b/drivers/media/i2c/ov772x.c
> >> @@ -542,9 +542,19 @@ static struct ov772x_priv *to_ov772x(struct
> >> v4l2_subdev *sd)
> >>  	return container_of(sd, struct ov772x_priv, subdev);
> >>  }
> >> 
> >> -static inline int ov772x_read(struct i2c_client *client, u8 addr)
> >> +static int ov772x_read(struct i2c_client *client, u8 addr)
> >>  {
> >> -     return i2c_smbus_read_byte_data(client, addr);
> >> +     int ret;
> >> +     u8 val;
> >> +
> >> +     ret = i2c_master_send(client, &addr, 1);
> >> +     if (ret < 0)
> >> +             return ret;
> >> +     ret = i2c_master_recv(client, &val, 1);
> >> +     if (ret < 0)
> >> +             return ret;
> >> +
> >> +     return val;
> >>  }
> >>  
> >>  static inline int ov772x_write(struct i2c_client *client, u8 addr, u8
> >> value)
> >> @@ -1255,13 +1265,11 @@ static int ov772x_probe(struct i2c_client
> >> *client,
> >>  			return -EINVAL;
> >>       }
> >> 
> >> -     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
> >> -                                           I2C_FUNC_PROTOCOL_MANGLING))
> >> {
> >> +     if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
> >>               dev_err(&adapter->dev,
> >> -                     "I2C-Adapter doesn't support SMBUS_BYTE_DATA or
> >> PROTOCOL_MANGLING\n");
> >> +                     "I2C-Adapter doesn't support SMBUS_BYTE_DATA\n");
> >>               return -EIO;
> >>       }
> >> 
> >> -     client->flags |= I2C_CLIENT_SCCB;
> >> 
> >>       priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
> >>       if (!priv)
Wolfram Sang April 23, 2018, 8:11 p.m. UTC | #4
> How about i2c_smbus_xfer_emulated() ? The tricky part will be to handle the 
> I2C adapters that implement .smbus_xfer(), as those won't go through 
> i2c_smbus_xfer_emulated(). i2c_smbus_xfer_emulated() relies on i2c_transfer(), 
> which itself relies on the I2C adapter's .master_xfer() operation. We're thus 
> only concerned about the drivers that implement both .smbus_xfer() and 
> master_xfer(), and there's only 4 of them (i2c-opal, i2c-pasemi, i2c-powermac 
> and i2c-zx2967). Maybe the simplest solution would be to force the emulation 
> path if I2C_CLIENT_SCCB && !I2C_FUNC_PROTOCOL_MANGLING && ->master_xfer != 
> NULL ?
> 
> Wolfram, what do you think ?

I think it is a mess :)

Further: I don't think we will ever see an SMBus controller which allows
mangling. SMBus is way more precisely defined than I2C, so HW can then
do much more things automatically. They will always do a REP_START, so I
don't think you can connect SCCB devices to SMBus.

As a result, we shouldn't do SMBus calls for SCCB. Maybe we should
introduce sccb_byte_read? SCCB didn't specify much more than byte read
IIRC, or? The implementation here with two seperate messages makes much
sense to me then.

I could argue that the sccb_* helpers should live in drivers/media since
it is probably only Omnivision trying to work around I2C licensing here?

But if it is not too heavy, maybe we could take it into i2c as well.

Makes sense or did I miss something?
Laurent Pinchart April 23, 2018, 8:21 p.m. UTC | #5
Hi Wolfram,

On Monday, 23 April 2018 23:11:21 EEST Wolfram Sang wrote:
> > How about i2c_smbus_xfer_emulated() ? The tricky part will be to handle
> > the I2C adapters that implement .smbus_xfer(), as those won't go through
> > i2c_smbus_xfer_emulated(). i2c_smbus_xfer_emulated() relies on
> > i2c_transfer(), which itself relies on the I2C adapter's .master_xfer()
> > operation. We're thus only concerned about the drivers that implement
> > both .smbus_xfer() and master_xfer(), and there's only 4 of them
> > (i2c-opal, i2c-pasemi, i2c-powermac and i2c-zx2967). Maybe the simplest
> > solution would be to force the emulation path if I2C_CLIENT_SCCB &&
> > !I2C_FUNC_PROTOCOL_MANGLING && ->master_xfer != NULL ?
> > 
> > Wolfram, what do you think ?
> 
> I think it is a mess :)
> 
> Further: I don't think we will ever see an SMBus controller which allows
> mangling. SMBus is way more precisely defined than I2C, so HW can then
> do much more things automatically. They will always do a REP_START, so I
> don't think you can connect SCCB devices to SMBus.
> 
> As a result, we shouldn't do SMBus calls for SCCB. Maybe we should
> introduce sccb_byte_read? SCCB didn't specify much more than byte read
> IIRC, or? The implementation here with two seperate messages makes much
> sense to me then.
> 
> I could argue that the sccb_* helpers should live in drivers/media since
> it is probably only Omnivision trying to work around I2C licensing here?
> 
> But if it is not too heavy, maybe we could take it into i2c as well.
> 
> Makes sense or did I miss something?

SCCB helpers would work too. It would be easy to just move the functions 
defined in this patch to helpers and be done with it. However, there are I2C 
adapters that have native SCCB support, so to take advantage of that feature 
we need to forward native SCCB calls all the way down the stack in that case. 
That's why I thought an implementation in the I2C subsystem would be better. 
Furthermore, as SCCB is really a slightly mangled version of I2C, I think the 
I2C subsystem would be a natural location for the implementation. It shouldn't 
be too much work, it's just a matter of deciding what the call stacks should 
be for the native vs. emulated cases.
Wolfram Sang April 23, 2018, 8:36 p.m. UTC | #6
> SCCB helpers would work too. It would be easy to just move the functions 
> defined in this patch to helpers and be done with it. However, there are I2C 
> adapters that have native SCCB support, so to take advantage of that feature 

Ah, didn't notice that so far. Can't find it in drivers/i2c/busses.
Where are those?

> we need to forward native SCCB calls all the way down the stack in that case. 

And how is it done currently?

> That's why I thought an implementation in the I2C subsystem would be better. 
> Furthermore, as SCCB is really a slightly mangled version of I2C, I think the 
> I2C subsystem would be a natural location for the implementation. It shouldn't 

Can be argued. But it can also be argues that it sits on top of I2C and
doesn't need to live in i2c-folders itself (like PMBus). The
implementation given in this patch looks a bit like the latter. However,
this is not the main question currently.

> be too much work, it's just a matter of deciding what the call stacks should 
> be for the native vs. emulated cases.

I don't like it. We shouldn't use SMBus calls for SCCB because SMBus
will very likely never support it. Or do you know of such a case? I
think I really want sccb helpers. So, people immediately see that SCCB
is used and not SMBus or I2C. And there, we can handle native support
vs. I2C-SCCB-emulation. And maybe SMBus-SCCB emulation but I doubt we
will ever need it.
Laurent Pinchart April 23, 2018, 8:51 p.m. UTC | #7
Hi Wolfram,

On Monday, 23 April 2018 23:36:16 EEST Wolfram Sang wrote:
> > SCCB helpers would work too. It would be easy to just move the functions
> > defined in this patch to helpers and be done with it. However, there are
> > I2C adapters that have native SCCB support, so to take advantage of that
> > feature
> 
> Ah, didn't notice that so far. Can't find it in drivers/i2c/busses.
> Where are those?

IIRC the OMAP I2C adapter supports SCCB natively. I'm not sure the driver 
implements that though.

> > we need to forward native SCCB calls all the way down the stack in that
> > case.
> 
> And how is it done currently?

Currently we go down to .master_xfer(), and adapters can then decide to use 
the hardware SCCB support. Again, it might not be implemented :-)

> > That's why I thought an implementation in the I2C subsystem would be
> > better. Furthermore, as SCCB is really a slightly mangled version of I2C,
> > I think the I2C subsystem would be a natural location for the
> > implementation. It shouldn't
> 
> Can be argued. But it can also be argues that it sits on top of I2C and
> doesn't need to live in i2c-folders itself (like PMBus). The
> implementation given in this patch looks a bit like the latter. However,
> this is not the main question currently.
> 
> > be too much work, it's just a matter of deciding what the call stacks
> > should be for the native vs. emulated cases.
> 
> I don't like it. We shouldn't use SMBus calls for SCCB because SMBus
> will very likely never support it. Or do you know of such a case? I
> think I really want sccb helpers. So, people immediately see that SCCB
> is used and not SMBus or I2C. And there, we can handle native support
> vs. I2C-SCCB-emulation. And maybe SMBus-SCCB emulation but I doubt we
> will ever need it.

I'm fine with SCCB helpers. Please note, however, that SCCB differs from SMBus 
in two ways: NACKs shall be ignored by the master (even though most SCCB 
devices generate an ack, so we could likely ignore this), and write-read 
sequences shouldn't use a repeated start. Apart from that register reads and 
register writes are identical to SMBus, which prompted the reuse (or abuse) of 
the SMBus API. If we end up implementing SCCB helpers, they will likely look 
very, very similar to the SMBus implementation, including the SMBus emulated 
transfer helper.
Sakari Ailus April 24, 2018, 10:04 a.m. UTC | #8
Hi guys,

On Mon, Apr 23, 2018 at 11:51:30PM +0300, Laurent Pinchart wrote:
> Hi Wolfram,
> 
> On Monday, 23 April 2018 23:36:16 EEST Wolfram Sang wrote:
> > > SCCB helpers would work too. It would be easy to just move the functions
> > > defined in this patch to helpers and be done with it. However, there are
> > > I2C adapters that have native SCCB support, so to take advantage of that
> > > feature
> > 
> > Ah, didn't notice that so far. Can't find it in drivers/i2c/busses.
> > Where are those?
> 
> IIRC the OMAP I2C adapter supports SCCB natively. I'm not sure the driver 
> implements that though.
> 
> > > we need to forward native SCCB calls all the way down the stack in that
> > > case.
> > 
> > And how is it done currently?
> 
> Currently we go down to .master_xfer(), and adapters can then decide to use 
> the hardware SCCB support. Again, it might not be implemented :-)
> 
> > > That's why I thought an implementation in the I2C subsystem would be
> > > better. Furthermore, as SCCB is really a slightly mangled version of I2C,
> > > I think the I2C subsystem would be a natural location for the
> > > implementation. It shouldn't
> > 
> > Can be argued. But it can also be argues that it sits on top of I2C and
> > doesn't need to live in i2c-folders itself (like PMBus). The
> > implementation given in this patch looks a bit like the latter. However,
> > this is not the main question currently.
> > 
> > > be too much work, it's just a matter of deciding what the call stacks
> > > should be for the native vs. emulated cases.
> > 
> > I don't like it. We shouldn't use SMBus calls for SCCB because SMBus
> > will very likely never support it. Or do you know of such a case? I
> > think I really want sccb helpers. So, people immediately see that SCCB
> > is used and not SMBus or I2C. And there, we can handle native support
> > vs. I2C-SCCB-emulation. And maybe SMBus-SCCB emulation but I doubt we
> > will ever need it.
> 
> I'm fine with SCCB helpers. Please note, however, that SCCB differs from SMBus 
> in two ways: NACKs shall be ignored by the master (even though most SCCB 
> devices generate an ack, so we could likely ignore this), and write-read 
> sequences shouldn't use a repeated start. Apart from that register reads and 
> register writes are identical to SMBus, which prompted the reuse (or abuse) of 
> the SMBus API. If we end up implementing SCCB helpers, they will likely look 
> very, very similar to the SMBus implementation, including the SMBus emulated 
> transfer helper.

Sounds like that there would be a bit of work to do here but AFAIU the
patchset should be fine to go in (with the other comments addressed) and
this could be addressed separately. Let me know if you have concerns.

Thanks.
Wolfram Sang April 26, 2018, 12:32 p.m. UTC | #9
> > Ah, didn't notice that so far. Can't find it in drivers/i2c/busses.
> > Where are those?
> 
> IIRC the OMAP I2C adapter supports SCCB natively. I'm not sure the driver 
> implements that though.

It doesn't currently. And seeing how long it sits in HW without a driver
for it, I don't have much expectations.

> > > we need to forward native SCCB calls all the way down the stack in that
> > > case.
> > 
> > And how is it done currently?
> 
> Currently we go down to .master_xfer(), and adapters can then decide to use 
> the hardware SCCB support. Again, it might not be implemented :-)

To sum it up: hardware-driven SCCB support is a very rare exception not
implemented anywhere in all those years. From a pragmatic point of view,
I'd say: we should be open for it, but we don't need to design around
it.

> I'm fine with SCCB helpers. Please note, however, that SCCB differs from SMBus 
> in two ways: NACKs shall be ignored by the master (even though most SCCB 
> devices generate an ack, so we could likely ignore this), and write-read 
> sequences shouldn't use a repeated start. Apart from that register reads and 

Especially the latter is a huge difference to SMBus, and so I think it
will be much safer to not abuse SMBus calls for SCCB.

> register writes are identical to SMBus, which prompted the reuse (or abuse) of 
> the SMBus API. If we end up implementing SCCB helpers, they will likely look 
> very, very similar to the SMBus implementation, including the SMBus emulated 
> transfer helper.

I don't think so. SCCB has much less transaction types than SMBus. Also, the
fallback as sketched in this patch (one master write, then a master
read) would be impossible on SMBus.

I have an idea in my mind. Maybe it is better to implement an RFC first,
so we can talk over code (even if only in prototype stage). I already
found this in ov7670.c, so I am proven wrong on this one already:

 472  * Note that there are two versions of these.  On the XO 1, the
 473  * i2c controller only does SMBUS, so that's what we use.  The
 474  * ov7670 is not really an SMBUS device, though, so the communication
 475  * is not always entirely reliable.

Sigh...
diff mbox

Patch

diff --git a/drivers/media/i2c/ov772x.c b/drivers/media/i2c/ov772x.c
index b62860c..2ae730f 100644
--- a/drivers/media/i2c/ov772x.c
+++ b/drivers/media/i2c/ov772x.c
@@ -542,9 +542,19 @@  static struct ov772x_priv *to_ov772x(struct v4l2_subdev *sd)
 	return container_of(sd, struct ov772x_priv, subdev);
 }
 
-static inline int ov772x_read(struct i2c_client *client, u8 addr)
+static int ov772x_read(struct i2c_client *client, u8 addr)
 {
-	return i2c_smbus_read_byte_data(client, addr);
+	int ret;
+	u8 val;
+
+	ret = i2c_master_send(client, &addr, 1);
+	if (ret < 0)
+		return ret;
+	ret = i2c_master_recv(client, &val, 1);
+	if (ret < 0)
+		return ret;
+
+	return val;
 }
 
 static inline int ov772x_write(struct i2c_client *client, u8 addr, u8 value)
@@ -1255,13 +1265,11 @@  static int ov772x_probe(struct i2c_client *client,
 		return -EINVAL;
 	}
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
-					      I2C_FUNC_PROTOCOL_MANGLING)) {
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
 		dev_err(&adapter->dev,
-			"I2C-Adapter doesn't support SMBUS_BYTE_DATA or PROTOCOL_MANGLING\n");
+			"I2C-Adapter doesn't support SMBUS_BYTE_DATA\n");
 		return -EIO;
 	}
-	client->flags |= I2C_CLIENT_SCCB;
 
 	priv = devm_kzalloc(&client->dev, sizeof(*priv), GFP_KERNEL);
 	if (!priv)