sdm: Add SPD information for HDMI

- Send SPI(source product information) to HDMI driver
- Vendor name and product descrpition information is passed to
  the HDMI device, which will be used by the TV to show the
  source information instead of INPUT1. INPUT2, etc.,

Change-Id: I2658ec39f95793e25f1fe36525cdc3701f9c64b3
diff --git a/sdm/include/core/debug_interface.h b/sdm/include/core/debug_interface.h
index bd2b5dd..67a38be 100644
--- a/sdm/include/core/debug_interface.h
+++ b/sdm/include/core/debug_interface.h
@@ -118,6 +118,15 @@
   */
   virtual DisplayError GetProperty(const char *property_name, int *value) = 0;
 
+  /*! @brief Method to get property value corresponding to give string.
+
+   @param[in] property_name name of the property
+   @param[out] string value corresponding to the property name
+
+   @return \link DisplayError \endlink
+  */
+  virtual DisplayError GetProperty(const char *property_name, char *value) = 0;
+
  protected:
   virtual ~DebugHandler() { }
 };
diff --git a/sdm/include/utils/debug.h b/sdm/include/utils/debug.h
index c8a3a98..b4a286a 100644
--- a/sdm/include/utils/debug.h
+++ b/sdm/include/utils/debug.h
@@ -72,6 +72,7 @@
   static bool IsRotatorSplitDisabled();
   static bool IsScalarDisabled();
   static bool IsUbwcTiledFrameBuffer();
+  static bool GetProperty(const char *property_name, char *value);
 
  private:
   Debug();
@@ -91,6 +92,9 @@
     virtual DisplayError GetProperty(const char */*property_name*/, int */*value*/) {
       return kErrorNotSupported;
     }
+    virtual DisplayError GetProperty(const char */*property_name*/, char */*value*/) {
+      return kErrorNotSupported;
+    }
   };
 
   DefaultDebugHandler default_debug_handler_;
diff --git a/sdm/libs/core/fb/hw_device.cpp b/sdm/libs/core/fb/hw_device.cpp
index 50e686a..590c23c 100644
--- a/sdm/libs/core/fb/hw_device.cpp
+++ b/sdm/libs/core/fb/hw_device.cpp
@@ -852,7 +852,6 @@
 }
 
 bool HWDevice::EnableHotPlugDetection(int enable) {
-  bool ret_value = true;
   char hpdpath[kMaxStringLength];
   int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
   if (hdmi_node_index < 0) {
@@ -860,22 +859,14 @@
   }
 
   snprintf(hpdpath , sizeof(hpdpath), "%s%d/hpd", fb_path_, hdmi_node_index);
-  int hpdfd = Sys::open_(hpdpath, O_RDWR, 0);
-  if (hpdfd < 0) {
-    DLOGW("Open failed = %s", hpdpath);
+
+  char value = enable ? '1' : '0';
+  ssize_t length = SysFsWrite(hpdpath, &value, sizeof(value));
+  if (length <= 0) {
     return false;
   }
 
-  char value = enable ? '1' : '0';
-  ssize_t length = Sys::pwrite_(hpdfd, &value, 1, 0);
-  if (length <= 0) {
-    DLOGE("Write failed 'hpd' = %d", enable);
-    ret_value = false;
-  }
-
-  Sys::close_(hpdfd);
-
-  return ret_value;
+  return true;
 }
 
 void HWDevice::ResetDisplayParams() {
@@ -1012,5 +1003,20 @@
   return kErrorNotSupported;
 }
 
+ssize_t HWDevice::SysFsWrite(char* file_node, char* value, ssize_t length) {
+  int fd = Sys::open_(file_node, O_RDWR, 0);
+  if (fd < 0) {
+    DLOGW("Open failed = %s", file_node);
+    return -1;
+  }
+  ssize_t len = Sys::pwrite_(fd, value, length, 0);
+  if (length <= 0) {
+    DLOGE("Write failed for path %s with value %s", file_node, value);
+  }
+  Sys::close_(fd);
+
+  return len;
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/fb/hw_device.h b/sdm/libs/core/fb/hw_device.h
index cde3efa..138dbda 100644
--- a/sdm/libs/core/fb/hw_device.h
+++ b/sdm/libs/core/fb/hw_device.h
@@ -111,6 +111,7 @@
   void SetColorSpace(LayerColorSpace source, mdp_color_space *color_space);
 
   bool EnableHotPlugDetection(int enable);
+  ssize_t SysFsWrite(char* file_node, char* value, ssize_t length);
 
   // Store the Device EventHandler - used for callback
   HWEventHandler *event_handler_;
diff --git a/sdm/libs/core/fb/hw_hdmi.cpp b/sdm/libs/core/fb/hw_hdmi.cpp
index c47a0bd..a5fff54 100644
--- a/sdm/libs/core/fb/hw_hdmi.cpp
+++ b/sdm/libs/core/fb/hw_hdmi.cpp
@@ -107,6 +107,9 @@
 DisplayError HWHDMI::Init(HWEventHandler *eventhandler) {
   DisplayError error = kErrorNone;
 
+  SetSourceProductInformation("vendor_name", "ro.product.manufacturer");
+  SetSourceProductInformation("product_description", "ro.product.name");
+
   error = HWDevice::Init(eventhandler);
   if (error != kErrorNone) {
     return error;
@@ -530,5 +533,26 @@
   return is_file_present;
 }
 
+void HWHDMI::SetSourceProductInformation(const char *node, const char *name) {
+  char property_value[kMaxStringLength];
+  char sys_fs_path[kMaxStringLength];
+  int hdmi_node_index = GetFBNodeIndex(kDeviceHDMI);
+  if (hdmi_node_index < 0) {
+    return;
+  }
+
+  ssize_t length = 0;
+  bool prop_read_success = Debug::GetProperty(name, property_value);
+  if (!prop_read_success) {
+    return;
+  }
+
+  snprintf(sys_fs_path , sizeof(sys_fs_path), "%s%d/%s", fb_path_, hdmi_node_index, node);
+  length = HWDevice::SysFsWrite(sys_fs_path, property_value, strlen(property_value));
+  if (length <= 0) {
+    DLOGW("Failed to write %s = %s", node, property_value);
+  }
+}
+
 }  // namespace sdm
 
diff --git a/sdm/libs/core/fb/hw_hdmi.h b/sdm/libs/core/fb/hw_hdmi.h
index 3f18b28..c216b8f 100644
--- a/sdm/libs/core/fb/hw_hdmi.h
+++ b/sdm/libs/core/fb/hw_hdmi.h
@@ -62,6 +62,7 @@
   DisplayError ReadTimingInfo();
   bool ReadResolutionFile(char *config_buffer);
   bool IsResolutionFilePresent();
+  void SetSourceProductInformation(const char *node, const char *name);
 
   uint32_t hdmi_mode_count_;
   uint32_t hdmi_modes_[256];
diff --git a/sdm/libs/utils/debug.cpp b/sdm/libs/utils/debug.cpp
index 33f94b9..003be5a 100644
--- a/sdm/libs/utils/debug.cpp
+++ b/sdm/libs/utils/debug.cpp
@@ -133,5 +133,13 @@
   return (ubwc_framebuffer == 1);
 }
 
+bool Debug::GetProperty(const char* property_name, char* value) {
+  if (debug_.debug_handler_->GetProperty(property_name, value) != kErrorNone) {
+    return false;
+  }
+
+  return true;
+}
+
 }  // namespace sdm