On Fri, 2009-03-20 at 14:09 +0800, Ma Ling wrote:
> Usually drm read basic EDID, that is enough for us, but because digital 
> display in introduced
> i.e. HDMI monitor, sometime we need to interact with monitor by EDID 
> extension information,
> including audio/video data block, speaker allocation and vendor specific data 
> block...
> This patch intends to read EDID extensions(max 4) from digital monitor for 
> user.
> 
> Signed-off-by: Ma Ling <ling...@intel.com>

This looks fine to me.  airlied, you want to pick this up for next, or
should I?

> ---
> In this version drm will read max number if the number of edid extensions is 
> over max number.
> 
>  drivers/gpu/drm/drm_edid.c |  121 +++++++++++++++++++++++++++++++++----------
>  include/drm/drm_crtc.h     |    3 +-
>  2 files changed, 95 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
> index a839a28..fab2bdf 100644
> --- a/drivers/gpu/drm/drm_edid.c
> +++ b/drivers/gpu/drm/drm_edid.c
> @@ -550,11 +550,20 @@ static int add_detailed_info(struct drm_connector 
> *connector,
>  }
>  
>  #define DDC_ADDR 0x50
> -
> -unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter)
> +/**
> + * Get EDID information via I2C.
> + *
> + * \param adapter : i2c device adaptor
> + * \param buf     : EDID data buffer to be filled
> + * \param len     : EDID data buffer length
> + * \return 0 on success or -1 on failure.
> + *
> + * Try to fetch EDID information by calling i2c driver function.
> + */
> +int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
> +                       unsigned char *buf, int len)
>  {
>       unsigned char start = 0x0;
> -     unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
>       struct i2c_msg msgs[] = {
>               {
>                       .addr   = DDC_ADDR,
> @@ -564,31 +573,36 @@ unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter 
> *adapter)
>               }, {
>                       .addr   = DDC_ADDR,
>                       .flags  = I2C_M_RD,
> -                     .len    = EDID_LENGTH,
> +                     .len    = len,
>                       .buf    = buf,
>               }
>       };
>  
> -     if (!buf) {
> -             dev_warn(&adapter->dev, "unable to allocate memory for EDID "
> -                      "block.\n");
> -             return NULL;
> -     }
> -
>       if (i2c_transfer(adapter, msgs, 2) == 2)
> -             return buf;
> +             return 0;
>  
>       dev_info(&adapter->dev, "unable to read EDID block.\n");
> -     kfree(buf);
> -     return NULL;
> +     return -1;
>  }
>  EXPORT_SYMBOL(drm_do_probe_ddc_edid);
>  
> -static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
> +/**
> + * Get EDID information.
> + *
> + * \param adapter : i2c device adaptor.
> + * \param buf     : EDID data buffer to be filled
> + * \param len     : EDID data buffer length
> + * \return 0 on success or -1 on failure.
> + *
> + * Initialize DDC, then fetch EDID information
> + * by calling drm_do_probe_ddc_edid function.
> + */
> +static int drm_ddc_read(struct i2c_adapter *adapter,
> +                     unsigned char *buf, int len)
>  {
>       struct i2c_algo_bit_data *algo_data = adapter->algo_data;
> -     unsigned char *edid = NULL;
>       int i, j;
> +     int ret = -1;
>  
>       algo_data->setscl(algo_data->data, 1);
>  
> @@ -616,7 +630,7 @@ static unsigned char *drm_ddc_read(struct i2c_adapter 
> *adapter)
>               msleep(15);
>  
>               /* Do the real work */
> -             edid = drm_do_probe_ddc_edid(adapter);
> +             ret = drm_do_probe_ddc_edid(adapter, buf, len);
>               algo_data->setsda(algo_data->data, 0);
>               algo_data->setscl(algo_data->data, 0);
>               msleep(15);
> @@ -632,7 +646,7 @@ static unsigned char *drm_ddc_read(struct i2c_adapter 
> *adapter)
>               msleep(15);
>               algo_data->setscl(algo_data->data, 0);
>               algo_data->setsda(algo_data->data, 0);
> -             if (edid)
> +             if (ret == 0)
>                       break;
>       }
>       /* Release the DDC lines when done or the Apple Cinema HD display
> @@ -641,9 +655,31 @@ static unsigned char *drm_ddc_read(struct i2c_adapter 
> *adapter)
>       algo_data->setsda(algo_data->data, 1);
>       algo_data->setscl(algo_data->data, 1);
>  
> -     return edid;
> +     return ret;
> +}
> +
> +static int drm_ddc_read_edid(struct drm_connector *connector,
> +                          struct i2c_adapter *adapter,
> +                          char *buf, int len)
> +{
> +     int ret;
> +
> +     ret = drm_ddc_read(adapter, buf, len);
> +     if (ret != 0) {
> +             dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
> +                      drm_get_connector_name(connector));
> +             goto end;
> +     }
> +     if (!edid_is_valid((struct edid *)buf)) {
> +             dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
> +                      drm_get_connector_name(connector));
> +             ret = -1;
> +     }
> +end:
> +     return ret;
>  }
>  
> +#define MAX_EDID_EXT_NUM 4
>  /**
>   * drm_get_edid - get EDID data, if available
>   * @connector: connector we're probing
> @@ -656,24 +692,53 @@ static unsigned char *drm_ddc_read(struct i2c_adapter 
> *adapter)
>  struct edid *drm_get_edid(struct drm_connector *connector,
>                         struct i2c_adapter *adapter)
>  {
> +     int ret;
>       struct edid *edid;
>  
> -     edid = (struct edid *)drm_ddc_read(adapter);
> -     if (!edid) {
> -             dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
> -                      drm_get_connector_name(connector));
> -             return NULL;
> +     edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1),
> +                    GFP_KERNEL);
> +     if (edid == NULL) {
> +             dev_warn(&connector->dev->pdev->dev,
> +                      "Failed to allocate EDID\n");
> +             goto end;
>       }
> -     if (!edid_is_valid(edid)) {
> -             dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
> -                      drm_get_connector_name(connector));
> -             kfree(edid);
> -             return NULL;
> +
> +     /* Read first EDID block */
> +     ret = drm_ddc_read_edid(connector, adapter,
> +                             (unsigned char *)edid, EDID_LENGTH);
> +     if (ret != 0)
> +             goto clean_up;
> +
> +     /* There are EDID extensions to be read */
> +     if (edid->extensions != 0) {
> +             int edid_ext_num = edid->extensions;
> +
> +             if (edid_ext_num > MAX_EDID_EXT_NUM) {
> +                     dev_warn(&connector->dev->pdev->dev,
> +                              "The number of extension(%d) is "
> +                              "over max (%d), actually read number (%d)\n",
> +                              edid_ext_num, MAX_EDID_EXT_NUM,
> +                              MAX_EDID_EXT_NUM);
> +                     /* Reset EDID extension number to be read */
> +                     edid_ext_num = MAX_EDID_EXT_NUM;
> +             }
> +             /* Read EDID including extensions too */
> +             ret = drm_ddc_read_edid(connector, adapter, (char *)edid,
> +                                     EDID_LENGTH * (edid_ext_num + 1));
> +             if (ret != 0)
> +                     goto clean_up;
> +
>       }
>  
>       connector->display_info.raw_edid = (char *)edid;
> +     goto end;
>  
> +clean_up:
> +     kfree(edid);
> +     edid = NULL;
> +end:
>       return edid;
> +
>  }
>  EXPORT_SYMBOL(drm_get_edid);
>  
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 5ded1ac..5d73adb 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -613,7 +613,8 @@ extern void drm_fb_release(struct drm_file *file_priv);
>  extern int drm_mode_group_init_legacy_group(struct drm_device *dev, struct 
> drm_mode_group *group);
>  extern struct edid *drm_get_edid(struct drm_connector *connector,
>                                struct i2c_adapter *adapter);
> -extern unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter);
> +extern int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
> +                              unsigned char *buf, int len);
>  extern int drm_add_edid_modes(struct drm_connector *connector, struct edid 
> *edid);
>  extern void drm_mode_probed_add(struct drm_connector *connector, struct 
> drm_display_mode *mode);
>  extern void drm_mode_remove(struct drm_connector *connector, struct 
> drm_display_mode *mode);
-- 
Eric Anholt
e...@anholt.net                         eric.anh...@intel.com


Attachment: signature.asc
Description: This is a digitally signed message part

------------------------------------------------------------------------------
Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are
powering Web 2.0 with engaging, cross-platform capabilities. Quickly and
easily build your RIAs with Flex Builder, the Eclipse(TM)based development
software that enables intelligent coding and step-through debugging.
Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com
--
_______________________________________________
Dri-devel mailing list
Dri-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/dri-devel

Reply via email to