Thanks for the comments, will upload patch set<div>with your comments.<br><br><div class="gmail_quote">On Fri, Aug 24, 2012 at 11:20 AM, Daniel Vetter <span dir="ltr"><<a href="mailto:daniel@ffwll.ch" target="_blank">daniel@ffwll.ch</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="im">On Fri, Aug 24, 2012 at 02:56:50PM +0530, Shirish S wrote:<br>
> The current logic for probing ddc is limited to<br>
> 2 blocks (256 bytes), this patch adds support<br>
> for the 4 block (512) data.<br>
><br>
> To do this, a single 8-bit segment index is<br>
> passed to the display via the I2C address 30h.<br>
> Data from the selected segment is then immediately<br>
> read via the regular DDC2 address using a repeated<br>
> I2C 'START' signal.<br>
><br>
> Signed-off-by: Shirish S <<a href="mailto:s.shirish@samsung.com">s.shirish@samsung.com</a>><br>
> ---<br>
> drivers/gpu/drm/drm_edid.c | 83 ++++++++++++++++++++++++++++++++-----------<br>
> 1 files changed, 62 insertions(+), 21 deletions(-)<br>
><br>
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c<br>
> index a8743c3..a10a130 100644<br>
> --- a/drivers/gpu/drm/drm_edid.c<br>
> +++ b/drivers/gpu/drm/drm_edid.c<br>
> @@ -254,6 +254,8 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,<br>
> int block, int len)<br>
> {<br>
> unsigned char start = block * EDID_LENGTH;<br>
> + unsigned char segment = block >> 1;<br>
> + unsigned short segFlags = segment ? 0 : I2C_M_IGNORE_NAK;<br>
<br>
</div>You can inline segFlags to the only place it's used.<br>
<div><div class="h5"><br>
> int ret, retries = 5;<br>
><br>
> /* The core i2c driver will automatically retry the transfer if the<br>
> @@ -262,29 +264,68 @@ drm_do_probe_ddc_edid(struct i2c_adapter *adapter, unsigned char *buf,<br>
> * generate spurious NAKs and timeouts. Retrying the transfer<br>
> * of the individual block a few times seems to overcome this.<br>
> */<br>
> - do {<br>
> - struct i2c_msg msgs[] = {<br>
> - {<br>
> - .addr = DDC_ADDR,<br>
> - .flags = 0,<br>
> - .len = 1,<br>
> - .buf = &start,<br>
> - }, {<br>
> - .addr = DDC_ADDR,<br>
> - .flags = I2C_M_RD,<br>
> - .len = len,<br>
> - .buf = buf,<br>
> + switch (segment) {<br>
> + /* To reduce traffic on I2C, we request the i2c xfer<br>
> + * for segment addr only if 4 block edid data is<br>
> + * present.<br>
> + * 0 : DDC<br>
> + * 1 : E-DDC<br>
> + */<br>
<br>
</div></div>This comment is a bit misleading: We don't avoid the segment xfer to<br>
reduce i2c traffic, but to avoid upsetting any non-compliant screens.<br>
<div class="im"><br>
> + case 0:<br>
> + do {<br>
<br>
</div>Keeping the loop as the outermost would imo be clearer and avoid<br>
duplicating it (it also would make the patch a bit smaller). You could<br>
even do a trick with the msgs array like this:<br>
<br>
msgs[] = { full i2c xfer including segment addr}<br>
xfers = 3;<br>
<br>
/* Avoid sending the segment addr to not upset non-compliant ddc<br>
* monitors. */<br>
if (!segments)<br>
msgs++, len--;<br>
<br>
i2c_transefer(adapter, msgs, len);<br>
<br>
Also, I think it'd be good to set the IGNORE_NAK on the start addre<br>
transfer, too (but in a separate patch). At least I think we've seen<br>
screens out there that need this :(<br>
<br>
Yours, Daniel<br>
<div class="HOEnZb"><div class="h5"><br>
> + struct i2c_msg msgs[] = {<br>
> + {<br>
> + .addr = DDC_ADDR,<br>
> + .flags = 0,<br>
> + .len = 1,<br>
> + .buf = &start,<br>
> + }, {<br>
> + .addr = DDC_ADDR,<br>
> + .flags = I2C_M_RD,<br>
> + .len = len,<br>
> + .buf = buf,<br>
> + }<br>
> + };<br>
> + ret = i2c_transfer(adapter, msgs, 2);<br>
> + if (ret == -ENXIO) {<br>
> + DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n",<br>
> + adapter->name);<br>
> + break;<br>
> }<br>
> - };<br>
> - ret = i2c_transfer(adapter, msgs, 2);<br>
> - if (ret == -ENXIO) {<br>
> - DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n",<br>
> - adapter->name);<br>
> - break;<br>
> - }<br>
> - } while (ret != 2 && --retries);<br>
> + } while (ret != 2 && --retries);<br>
> +<br>
> + return ret == 2 ? 0 : -1;<br>
> + case 1:<br>
> + do {<br>
> + struct i2c_msg msgs[] = {<br>
> + { /*set segment pointer */<br>
> + .addr = DDC_SEGMENT_ADDR,<br>
> + .flags = segFlags,<br>
> + .len = 1,<br>
> + .buf = &segment,<br>
> + }, { /*set offset */<br>
> + .addr = DDC_ADDR,<br>
> + .flags = 0,<br>
> + .len = 1,<br>
> + .buf = &start,<br>
> + }, { /*set data */<br>
> + .addr = DDC_ADDR,<br>
> + .flags = I2C_M_RD,<br>
> + .len = len,<br>
> + .buf = buf,<br>
> + }<br>
> + };<br>
> + ret = i2c_transfer(adapter, msgs, 3);<br>
> + if (ret == -ENXIO) {<br>
> + DRM_DEBUG_KMS("drm: skipping non-existent adapter %s\n",<br>
> + adapter->name);<br>
> + break;<br>
> + }<br>
> + } while (ret != 3 && --retries);<br>
><br>
> - return ret == 2 ? 0 : -1;<br>
> + return ret == 3 ? 0 : -1;<br>
> + }<br>
> + return -1;<br>
> }<br>
><br>
> static bool drm_edid_is_zero(u8 *in_edid, int length)<br>
> --<br>
> 1.7.0.4<br>
><br>
> _______________________________________________<br>
> dri-devel mailing list<br>
> <a href="mailto:dri-devel@lists.freedesktop.org">dri-devel@lists.freedesktop.org</a><br>
> <a href="http://lists.freedesktop.org/mailman/listinfo/dri-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/dri-devel</a><br>
<br>
</div></div><span class="HOEnZb"><font color="#888888">--<br>
Daniel Vetter<br>
Mail: <a href="mailto:daniel@ffwll.ch">daniel@ffwll.ch</a><br>
Mobile: +41 (0)79 365 57 48<br>
</font></span><div class="HOEnZb"><div class="h5">_______________________________________________<br>
dri-devel mailing list<br>
<a href="mailto:dri-devel@lists.freedesktop.org">dri-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/dri-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/dri-devel</a><br>
</div></div></blockquote></div><br></div>