HDMI: support show edid status.
authorZheng Yang <zhengyang@rock-chips.com>
Thu, 21 May 2015 05:45:22 +0000 (13:45 +0800)
committerZheng Yang <zhengyang@rock-chips.com>
Thu, 21 May 2015 05:45:22 +0000 (13:45 +0800)
Use /sys/class/display/HDMI/debug node to
show sink EDID status and raw status.

Signed-off-by: Zheng Yang <zhengyang@rock-chips.com>
drivers/video/rockchip/hdmi/rockchip-hdmi-core.c
drivers/video/rockchip/hdmi/rockchip-hdmi-lcdc.c
drivers/video/rockchip/hdmi/rockchip-hdmi-sysfs.c
drivers/video/rockchip/hdmi/rockchip-hdmi.h

index 98fdeaee7b613cc0d639141e78f5ef38caacc1c2..4c65868f83977048231e011984079710ae3403cd 100644 (file)
@@ -123,7 +123,7 @@ static void hdmi_wq_set_video(struct hdmi *hdmi)
 static void hdmi_wq_parse_edid(struct hdmi *hdmi)
 {
        struct hdmi_edid *pedid;
-       unsigned char *buff = NULL;
+
        int rc = HDMI_ERROR_SUCESS, extendblock = 0, i, trytimes;
 
        if (hdmi == NULL)
@@ -136,8 +136,8 @@ static void hdmi_wq_parse_edid(struct hdmi *hdmi)
        memset(pedid, 0, sizeof(struct hdmi_edid));
        INIT_LIST_HEAD(&pedid->modelist);
 
-       buff = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
-       if (buff == NULL) {
+       pedid->raw[0] = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
+       if (pedid->raw[0] == NULL) {
                dev_err(hdmi->dev,
                        "[%s] can not allocate memory for edid buff.\n",
                        __func__);
@@ -154,15 +154,15 @@ static void hdmi_wq_parse_edid(struct hdmi *hdmi)
        for (trytimes = 0; trytimes < 3; trytimes++) {
                if (trytimes)
                        msleep(50);
-               memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
-               rc = hdmi->ops->getedid(hdmi, 0, buff);
+               memset(pedid->raw[0], 0 , HDMI_EDID_BLOCK_SIZE);
+               rc = hdmi->ops->getedid(hdmi, 0, pedid->raw[0]);
                if (rc) {
                        dev_err(hdmi->dev,
                                "[HDMI] read edid base block error\n");
                        continue;
                }
 
-               rc = hdmi_edid_parse_base(buff, &extendblock, pedid);
+               rc = hdmi_edid_parse_base(pedid->raw[0], &extendblock, pedid);
                if (rc) {
                        dev_err(hdmi->dev,
                                "[HDMI] parse edid base block error\n");
@@ -174,12 +174,20 @@ static void hdmi_wq_parse_edid(struct hdmi *hdmi)
        if (rc)
                goto out;
 
-       for (i = 1; i < extendblock + 1; i++) {
+       for (i = 1; (i < extendblock + 1) && (i < HDMI_MAX_EDID_BLOCK); i++) {
+               pedid->raw[i] = kmalloc(HDMI_EDID_BLOCK_SIZE, GFP_KERNEL);
+               if (pedid->raw[i] == NULL) {
+                       dev_err(hdmi->dev,
+                               "[%s] can not allocate memory for edid buff.\n",
+                               __func__);
+                       rc = HDMI_ERROR_FALSE;
+                       goto out;
+               }
                for (trytimes = 0; trytimes < 3; trytimes++) {
                        if (trytimes)
                                msleep(20);
-                       memset(buff, 0 , HDMI_EDID_BLOCK_SIZE);
-                       rc = hdmi->ops->getedid(hdmi, i, buff);
+                       memset(pedid->raw[i], 0 , HDMI_EDID_BLOCK_SIZE);
+                       rc = hdmi->ops->getedid(hdmi, i, pedid->raw[i]);
                        if (rc) {
                                dev_err(hdmi->dev,
                                        "[HDMI] read edid block %d error\n",
@@ -187,7 +195,7 @@ static void hdmi_wq_parse_edid(struct hdmi *hdmi)
                                continue;
                        }
 
-                       rc = hdmi_edid_parse_extensions(buff, pedid);
+                       rc = hdmi_edid_parse_extensions(pedid->raw[i], pedid);
                        if (rc) {
                                dev_err(hdmi->dev,
                                        "[HDMI] parse edid block %d error\n",
@@ -200,7 +208,6 @@ static void hdmi_wq_parse_edid(struct hdmi *hdmi)
                }
        }
 out:
-       kfree(buff);
        rc = hdmi_ouputmode_select(hdmi, rc);
 }
 
@@ -234,6 +241,7 @@ static void hdmi_wq_remove(struct hdmi *hdmi)
 {
        struct list_head *pos, *n;
        struct rk_screen screen;
+       int i;
 
        DBG("%s", __func__);
        if (hdmi->ops->remove)
@@ -249,6 +257,8 @@ static void hdmi_wq_remove(struct hdmi *hdmi)
                list_del(pos);
                kfree(pos);
        }
+       for (i = 0; i < HDMI_MAX_EDID_BLOCK; i++)
+               kfree(hdmi->edid.raw[i]);
        kfree(hdmi->edid.audio);
        if (hdmi->edid.specs) {
                kfree(hdmi->edid.specs->modedb);
index 25f938f0c4b03594206b4be97b2bac07699915ff..af86044b315fae159ad5c1cc151bd6abbfe14bd3 100644 (file)
@@ -532,6 +532,7 @@ int hdmi_ouputmode_select(struct hdmi *hdmi, int edid_ok)
 
        if (edid_ok != HDMI_ERROR_SUCESS) {
                dev_err(hdmi->dev, "warning: EDID error, assume sink as HDMI !!!!");
+               hdmi->edid.status = -1;
                hdmi->edid.sink_hdmi = 1;
                hdmi->edid.baseaudio_support = 1;
                hdmi->edid.ycbcr444 = 0;
index 95d60eb18ded0477c100b259301d19f717762d0a..3d9d5c0cc2c362f8760b3ed68c7f8c92cf02481e 100644 (file)
@@ -304,6 +304,33 @@ static int hdmi_get_monspecs(struct rk_display_device *device,
        return 0;
 }
 
+static int hdmi_get_debug(struct rk_display_device *device, char *buf)
+{
+       struct hdmi *hdmi = device->priv_data;
+       char *buff;
+       int i, j, len = 0;
+
+       if (!hdmi)
+               return 0;
+       len += snprintf(buf+len, PAGE_SIZE, "EDID status:%s\n",
+                       hdmi->edid.status ? "False" : "Okay");
+       len += snprintf(buf+len, PAGE_SIZE, "Raw Data:");
+       mutex_lock(&hdmi->lock);
+       for (i = 0; i < HDMI_MAX_EDID_BLOCK; i++) {
+               if (!hdmi->edid.raw[i])
+                       break;
+               buff = hdmi->edid.raw[i];
+               for (j = 0; j < HDMI_EDID_BLOCK_SIZE; j++) {
+                       if (j % 16 == 0)
+                               len += snprintf(buf+len, PAGE_SIZE, "\n");
+                       len += snprintf(buf+len, PAGE_SIZE, "0x%02x, ",
+                                       buff[j]);
+               }
+       }
+       mutex_unlock(&hdmi->lock);
+       return len;
+}
+
 static struct rk_display_ops hdmi_display_ops = {
        .setenable = hdmi_set_enable,
        .getenable = hdmi_get_enable,
@@ -319,6 +346,7 @@ static struct rk_display_ops hdmi_display_ops = {
        .getmonspecs = hdmi_get_monspecs,
        .setscale = hdmi_set_scale,
        .getscale = hdmi_get_scale,
+       .getdebug = hdmi_get_debug,
 };
 
 static int hdmi_display_probe(struct rk_display_device *device, void *devdata)
index 33b8598554eeb6ed5f4e9b25b9be1f102ce89a8c..a47c38a9676b238f722f214a06d6001d84badb76 100644 (file)
@@ -263,6 +263,7 @@ struct hdmi_audio {
        u32     word_length;            /*Audio data word length*/
 };
 
+#define HDMI_MAX_EDID_BLOCK            8
 /* HDMI EDID Information */
 struct hdmi_edid {
        unsigned char sink_hdmi;        /*HDMI display device flag*/
@@ -294,6 +295,9 @@ struct hdmi_edid {
        unsigned char baseaudio_support;
        struct hdmi_audio *audio;       /*Device supported audio info*/
        unsigned int  audio_num;        /*Device supported audio type number*/
+
+       unsigned int status;            /*EDID read status, success or failed*/
+       char *raw[HDMI_MAX_EDID_BLOCK]; /*Raw EDID Data*/
 };
 
 struct hdmi;