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>