From d1c8b6180aea75bf2b25d4b1bb6c574edb36c635 Mon Sep 17 00:00:00 2001
From: hjc <hjc@rock-chips.com>
Date: Mon, 22 Sep 2014 11:13:11 +0800
Subject: [PATCH] rk hdmi: add node to get TV audio&video info

---
 drivers/video/rockchip/display-sys.c        | 37 ++++++++++++
 drivers/video/rockchip/hdmi/rk_hdmi.h       |  1 +
 drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c | 64 +++++++++++++++++++++
 drivers/video/rockchip/hdmi/rk_hdmi_task.c  |  1 +
 include/linux/display-sys.h                 |  2 +
 5 files changed, 105 insertions(+)

diff --git a/drivers/video/rockchip/display-sys.c b/drivers/video/rockchip/display-sys.c
index 3f8e6b85bb6b..3097ace6ea75 100755
--- a/drivers/video/rockchip/display-sys.c
+++ b/drivers/video/rockchip/display-sys.c
@@ -210,6 +210,41 @@ static ssize_t display_store_debug(struct device *dev,
 	return -EINVAL;
 }
 
+static ssize_t display_show_sinkaudioinfo(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct rk_display_device *dsp = dev_get_drvdata(dev);
+	char audioinfo[200];
+	int ret=0;
+
+	if(dsp->ops && dsp->ops->getedidaudioinfo) {
+		ret = dsp->ops->getedidaudioinfo(dsp, audioinfo, 200);
+		if(!ret){
+			return snprintf(buf, PAGE_SIZE, "%s\n", audioinfo);
+		}
+	}
+	return -EINVAL;
+}
+
+
+
+static ssize_t display_show_monspecs(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct rk_display_device *dsp = dev_get_drvdata(dev);
+	struct fb_monspecs monspecs;
+	int ret = 0;
+	if(dsp->ops && dsp->ops->getmonspecs) {
+		ret = dsp->ops->getmonspecs(dsp,&monspecs);
+		if(!ret) {
+			memcpy(buf, &monspecs, sizeof(struct fb_monspecs));
+			return sizeof(struct fb_monspecs);//snprintf(buf, PAGE_SIZE, "%s\n", monspecs.monitor);
+		}
+	}
+	return -EINVAL;
+}
+
+
 static struct device_attribute display_attrs[] = {
 	__ATTR(name, S_IRUGO, display_show_name, NULL),
 	__ATTR(type, S_IRUGO, display_show_type, NULL),
@@ -219,6 +254,8 @@ static struct device_attribute display_attrs[] = {
 	__ATTR(mode, 0664, display_show_mode, display_store_mode),
 	__ATTR(scale, 0664, display_show_scale, display_store_scale),
 	__ATTR(debug, 0664, display_show_debug, display_store_debug),
+	__ATTR(audioinfo, S_IRUGO, display_show_sinkaudioinfo, NULL),
+	__ATTR(monspecs, S_IRUGO, display_show_monspecs, NULL),
 	__ATTR_NULL
 };
 
diff --git a/drivers/video/rockchip/hdmi/rk_hdmi.h b/drivers/video/rockchip/hdmi/rk_hdmi.h
index b8c15be41892..d962ff83f33d 100755
--- a/drivers/video/rockchip/hdmi/rk_hdmi.h
+++ b/drivers/video/rockchip/hdmi/rk_hdmi.h
@@ -331,6 +331,7 @@ struct hdmi {
 	struct switch_dev switch_hdmi;
 #endif
 
+	struct mutex lock;
 	struct workqueue_struct *workqueue;
 	struct delayed_work delay_work;
 
diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c b/drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c
index 767490d900dc..9ab7a1a96437 100755
--- a/drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c
+++ b/drivers/video/rockchip/hdmi/rk_hdmi_sysfs.c
@@ -152,8 +152,70 @@ static int hdmi_set_debug(struct rk_display_device *device, int cmd)
 
 	return 0;
 }
+//CEA 861-E: Audio Coding Type
+//sync width enum hdmi_audio_type
+static const char* const sAudioFormatStr[] = {
+	"",
+	"LPCM",		//HDMI_AUDIO_LPCM = 1,
+	"AC3",		//HDMI_AUDIO_AC3,
+	"MPEG1",	//HDMI_AUDIO_MPEG1,
+	"MP3",		//HDMI_AUDIO_MP3,
+	"MPEG2",	//HDMI_AUDIO_MPEG2,
+	"AAC-LC",	//HDMI_AUDIO_AAC_LC,		//AAC
+	"DTS",		//HDMI_AUDIO_DTS,
+	"ATARC",	//HDMI_AUDIO_ATARC,
+	"DSD",		//HDMI_AUDIO_DSD,			//One bit Audio
+	"E-AC3",	//HDMI_AUDIO_E_AC3,
+	"DTS-HD",	//HDMI_AUDIO_DTS_HD,
+	"MLP",		//HDMI_AUDIO_MLP,
+	"DST",		//HDMI_AUDIO_DST,
+	"WMA-PRO",	//HDMI_AUDIO_WMA_PRO
+};
+
+static int hdmi_get_edidaudioinfo(struct rk_display_device *device, char *audioinfo, int len)
+{
+	struct hdmi *hdmi = device->priv_data;
+	int i=0;
+	int size=0;
+	struct hdmi_audio *audio;
+	if(!hdmi)
+		return -1;
+
+	memset(audioinfo, 0x00, len);
+	mutex_lock(&hdmi->lock);
+	//printk("hdmi:edid: audio_num: %d\n", hdmi->edid.audio_num);
+	for(i = 0; i < hdmi->edid.audio_num; i++)
+	{
+		audio = &(hdmi->edid.audio[i]);
+		if(audio->type<1 || audio->type>HDMI_AUDIO_WMA_PRO){
+			printk("audio type: unsupported.");
+			continue;
+		}
+		size = strlen(sAudioFormatStr[audio->type]);
+		//printk("size: %d, type: %s\n", size, sAudioFormatStr[audio->type]);
+		memcpy(audioinfo, sAudioFormatStr[audio->type], size);
+		audioinfo[size]=',';
+		audioinfo += (size+1);
+	}
+	mutex_unlock(&hdmi->lock);
+	return 0;
+}
 
 
+static int hdmi_get_monspecs(struct rk_display_device *device, struct fb_monspecs *monspecs)
+{
+	struct hdmi *hdmi = device->priv_data;
+
+	if (!hdmi)
+		return -1;
+
+	mutex_lock(&hdmi->lock);
+	if(hdmi->edid.specs)
+		*monspecs = *(hdmi->edid.specs);
+	mutex_unlock(&hdmi->lock);
+	return 0;
+}
+
 struct rk_display_ops hdmi_display_ops = {
 	.setenable = hdmi_set_enable,
 	.getenable = hdmi_get_enable,
@@ -164,6 +226,8 @@ struct rk_display_ops hdmi_display_ops = {
 	.setscale = hdmi_set_scale,
 	.getscale = hdmi_get_scale,
 	.setdebug = hdmi_set_debug,
+	.getedidaudioinfo = hdmi_get_edidaudioinfo,
+	.getmonspecs = hdmi_get_monspecs,
 };
 
 #if 1
diff --git a/drivers/video/rockchip/hdmi/rk_hdmi_task.c b/drivers/video/rockchip/hdmi/rk_hdmi_task.c
index 26fffd439910..0728b04125b0 100755
--- a/drivers/video/rockchip/hdmi/rk_hdmi_task.c
+++ b/drivers/video/rockchip/hdmi/rk_hdmi_task.c
@@ -61,6 +61,7 @@ int hdmi_sys_init(struct hdmi *hdmi)
 
 	memset(&hdmi->edid, 0, sizeof(struct hdmi_edid));
 	INIT_LIST_HEAD(&hdmi->edid.modelist);
+	mutex_init(&hdmi->lock);
 	return 0;
 }
 
diff --git a/include/linux/display-sys.h b/include/linux/display-sys.h
index 8edee472a5e5..ce89ff7adedc 100755
--- a/include/linux/display-sys.h
+++ b/include/linux/display-sys.h
@@ -38,6 +38,8 @@ struct rk_display_ops {
 	int (*setscale)(struct rk_display_device *, int, int);
 	int (*getscale)(struct rk_display_device *, int);
 	int (*setdebug)(struct rk_display_device *, int);
+	int (*getedidaudioinfo)(struct rk_display_device *, char *audioinfo, int len);
+	int (*getmonspecs)(struct rk_display_device *, struct fb_monspecs *monspecs);
 };
 
 struct rk_display_device {
-- 
2.34.1