lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Thu, 6 Oct 2016 11:16:38 +0530
From:   Saurabh Rawat <saurabh.rawat@...com>
To:     <rpurdie@...ys.net>, <j.anaszewski@...sung.com>,
        <linux-leds@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
        <saurabh.rawat@...com>
Subject: [PATCH] Added Support for STMicroelectronics 16 channels LED7708 LED Driver

---
 .../devicetree/bindings/leds/leds-st.txt           |  105 ++
 KERNEL/Documentation/leds/leds-st7708.txt          |  167 +++
 KERNEL/drivers/leds/leds-st.c                      | 1210 ++++++++++++++++++++
 KERNEL/include/linux/platform_data/leds-st.h       |  170 +++
 patches/defconfig                                  |    3 +-
 5 files changed, 1654 insertions(+), 1 deletion(-)
 create mode 100644 KERNEL/Documentation/devicetree/bindings/leds/leds-st.txt
 create mode 100644 KERNEL/Documentation/leds/leds-st7708.txt
 create mode 100644 KERNEL/drivers/leds/leds-st.c
 create mode 100644 KERNEL/include/linux/platform_data/leds-st.h

diff --git a/KERNEL/Documentation/devicetree/bindings/leds/leds-st.txt b/KERNEL/Documentation/devicetree/bindings/leds/leds-st.txt
new file mode 100644
index 0000000..dde53f9
--- /dev/null
+++ b/KERNEL/Documentation/devicetree/bindings/leds/leds-st.txt
@@ -0,0 +1,105 @@
+STMicroelectronics LED7708 Driver connected to BeagleboneBlack.This can be customized for any other
+hardware platform running linux depending on available free GPIOS
+
+Required properties:
+- compatible : should be : "st,st-leds".
+- sdo-gpio :contains a single GPIO specifier for the GPIO which is used for master to slave data OUT data.
+- sdi-gpio: contains a single GPIO specifier for the GPIO which is used for master to slave data IN data.
+- le-gpios: contains a single GPIO specifier for the GPIO which is used for Latch Enable data.
+- lren-gpios: contains a single GPIO specifier for the GPIO which is used for Lren data.This has to be High for Device to Operate.
+- sck-gpio: contains a single GPIO specifier for the GPIO which is used for the clock pin.
+- chanx :For controlling each LED channel Independently 
+- chan-common: For controlling all the 16 channels in a single shot.
+
+Optional properties:
+ - None
+
+Example:
+
+st-leds {
+        compatible = "st,st-leds";
+        sdo-gpio = <&gpio1 16 1>;
+        sdi-gpio = <&gpio1 28 1>;
+        le-gpio = <&gpio3 21 1>;
+        lren-gpio = <&gpio1 19 1>;
+        sck-gpio = <&gpio1 17 1>;
+
+        chan1 {
+
+                chan-name = "led7708-chan1";
+        };
+
+        chan2 {
+
+                chan-name = "led7708-chan2";
+        };
+        chan3 {
+
+                chan-name = "led7708-chan3";
+        };
+
+        chan4 {
+
+                chan-name = "led7708-chan4";
+        };
+        chan5 {
+
+                chan-name = "led7708-chan5";
+        };
+
+        chan6 {
+
+                chan-name = "led7708-chan6";
+        };
+        chan7 {
+
+                chan-name = "led7708-chan7";
+                };
+
+        chan8 {
+
+                chan-name = "led7708-chan8";
+        };
+
+        chan9 {
+
+                chan-name = "led7708-chan9";
+	};
+		
+	chan10 {
+		
+	        chan-name = "led7708-chan10";
+	};
+	chan11 {
+	
+	        chan-name = "led7708-chan11";
+	};
+		
+	chan12 {
+		
+	        chan-name = "led7708-chan12";
+	};
+	chan13 {
+		
+	        chan-name = "led7708-chan13";
+	};
+		
+	chan14 {
+		
+	        chan-name = "led7708-chan14";
+	};
+	chan15 {
+		
+	        chan-name = "led7708-chan15";
+	};
+		
+	chan16 {
+		
+	        chan-name = "led7708-chan16";
+	};
+		
+	chan-common {
+		
+	        chan-name = "led7708-chan-comm";
+	};
+};
diff --git a/KERNEL/Documentation/leds/leds-st7708.txt b/KERNEL/Documentation/leds/leds-st7708.txt
new file mode 100644
index 0000000..c1725ab
--- /dev/null
+++ b/KERNEL/Documentation/leds/leds-st7708.txt
@@ -0,0 +1,167 @@
+Kernel driver for led7708
+===========================
+
+* STMicroelectronics LED7708 Driver
+* Datasheet: www.st.com/resource/en/datasheet/led7708.pdf
+
+Authors: Saurabh Rawat
+Contact: Saurabh Rawat (saurabh.rawat-at-st.com)
+
+Description
+----------------------------------------------------------------------------------------------------------------
+LED7708 is a simple 16 channels LED driver hardware from STMicroelectronics. Leds can be controlled directly via
+the led class control interface.
+Each channel can be controlled independently in two modes - group-dimming mode or gray-scale dimming mode.
+In group dimming mode writing brightness to any one channel will configure the brightness of all the channels 
+with the same brightness.This mode is enabled by default in the driver.
+In gray scale dimming mode each channel can be configured to have different brightness values and all the channels
+can be controlled in one shot.
+
+Follow these steps to configure the LED7708 channels in goup-dimming mode
+- Either select the channels from the sysfs by channel mask  e.g ff00 -> echo ff00 > led_7708_select_channel for 9-16 channels 
+                                 or
+- go to any channel's sysfs as described below, and write the brightness value to it , echo 122 > brightness .
+  All the seleted channels will get configured with this brightness value.
+
+Follow these steps to configure the channels of LED7708 in gray-scale mode
+- Select the mode - echo 1 > led_7708_dimming_mode
+- Select the data format - echo 3 or echo 2 or echo 1 > led_7708_data_fmt
+- Write brightness values to each channels , go to any channel sysfs and write brightness value to it , echo 213 > brightness
+- Enable sync - This will write the brightness for all the channels , echo 1 > led_7708_sync_brightness
+
+
+Scripts
+----------------------------------------------------------------------------------------------------------------
+----------------------------------------------------------------------------------------------------------------
+
+
+Follow these steps to use the direct commands.Custom scripts can be made using them with/without them using the debug interface - led_7708_dbg_rw
+echo "(0X,YY,ZZZZ)" > led_7708_dbg_rw
+0X --> Registers Identifier
+ W_BRT_DL    1
+ W_BRT_GL    2
+ W_CHSEL     4
+ R_CHSTA     7
+ W_DEVCFGx   8
+ R_DEVCFGx   11
+ W_GSLAT     13
+
+YY --> Number of Nibbles to be written
+ZZZZ --> Data to be written
+
+
+#script1 - Same brighntess on All channels (Group Dimming)
+$echo "(08,04,2130)" > led_7708_dbg_rw
+$echo "(08,04,8440)" > led_7708_dbg_rw
+$echo "(04,04,FFFF)" > led_7708_dbg_rw
+$echo "(08,04,2131)" > led_7708_dbg_rw
+$echo "(02,04,FFFF)" > led_7708_dbg_rw
+$echo "(02,04,0000)" > led_7708_dbg_rw
+
+#script2 - Different brighntess on All channels in one shot - 1X192 format (Gray Scale)
+$echo "(08,04,2530)" > led_7708_dbg_rw
+$echo "(08,04,C240)" > led_7708_dbg_rw
+$echo "(04,04,FFFF)" > led_7708_dbg_rw
+$echo "(08,04,2531)" > led_7708_dbg_rw
+$echo "(02,48,020111222333444555666777888999AAABBBCCCDDDEEEFFF)" > led_7708_dbg_rw
+$echo "(02,48,000000000000000000000000000000000000000000000000)" > led_7708_dbg_rw
+
+ 
+#script3 - Different brighntess on All channels in one shot - 1X256 format (Gray Scale)
+$echo "(08,04,2530)" > led_7708_dbg_rw
+$echo "(08,04,C640)" > led_7708_dbg_rw
+$echo "(08,04,2530)" > led_7708_dbg_rw
+$echo "(04,04,FFFF)" > led_7708_dbg_rw
+$echo "(08,04,2531)" > led_7708_dbg_rw
+$echo "(02,64,FFFFEEEEDDDDCCCCBBBBAAAA9900000000000000000000003333222211110000)" > led_7708_dbg_rw
+$echo "(02,64,0000000000000000000000000000000000000000000000000000000000000000)" > led_7708_dbg_rw
+
+
+#script4 - Different brighntess on All channels in one shot - 16X16 format (Gray Scale)
+$echo "(08,04,2500)" > led_7708_dbg_rw
+$echo "(08,04,8440)" > led_7708_dbg_rw 
+$echo "(04,04,FFFF)" > led_7708_dbg_rw 
+$echo "(08,04,2501)" > led_7708_dbg_rw 
+$echo "(01,04,1111)" > led_7708_dbg_rw 
+$echo "(01,04,2222)" > led_7708_dbg_rw 
+$echo "(01,04,3333)" > led_7708_dbg_rw 
+$echo "(01,04,4444)" > led_7708_dbg_rw 
+$echo "(01,04,5555)" > led_7708_dbg_rw 
+$echo "(01,04,6666)" > led_7708_dbg_rw
+$echo "(01,04,7777)" > led_7708_dbg_rw 
+$echo "(01,04,8888)" > led_7708_dbg_rw 
+$echo "(01,04,9999)" > led_7708_dbg_rw 
+$echo "(01,04,AAAA)" > led_7708_dbg_rw 
+$echo "(01,04,BBBB)" > led_7708_dbg_rw 
+$echo "(01,04,CCCC)" > led_7708_dbg_rw 
+$echo "(01,04,DDDD)" > led_7708_dbg_rw 
+$echo "(01,04,EEEE)" > led_7708_dbg_rw 
+$echo "(01,04,FFFF)" > led_7708_dbg_rw 
+$echo "(02,04,AAAA)" > led_7708_dbg_rw
+
+#script5 - Independent Brightness Control (Group Dimming)
+e.g.1 => set 145 brightness value to 8 to 16 channels
+$lc
+$sdm
+$echo ff00 > led_7708_select_channel
+$l1
+$chb
+$echo 145 > brightness 
+
+e.g.2=> set 250 brightness value to 1-4 ,7,8,9,10,14 and 16 channels
+$lc
+$sdm
+$echo a3cf > led_7708_select_channel
+$l1
+$chb
+$echo 250 > brightness 
+
+
+#script6 - Gray-Scale Brightness Control for 1,7 and 15th channels
+$lc
+$sdm
+$echo 3 > led_7708_data_fmt
+$echo 1 > led_7708_dimming_mode
+$l1
+$chb
+$echo 213 > brightness
+$l7
+$chb
+$echo 123 > brightness
+$l15
+$chb
+$echo 213 > brightness
+$lc
+$echo 1 > led_7708_sync_brightness
+
+
+
+#lc,lx,sdm,chb are the aliases created as below in the ~/.bash_aliases : 
+
+alias l<x>='cd /sys/class/leds/led7708-chan<x>'
+e.g.
+
+alias l1='cd /sys/class/leds/led7708-chan1'
+alias l2='cd /sys/class/leds/led7708-chan2'
+alias l3='cd /sys/class/leds/led7708-chan3'
+alias l4='cd /sys/class/leds/led7708-chan4'
+..
+and so on 
+alias lc='cd /sys/class/leds/led7708-chan-comm'
+alias chb='sudo chmod 666 brightness'
+alias sdm='sudo chmod 666 led_*'
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/KERNEL/drivers/leds/leds-st.c b/KERNEL/drivers/leds/leds-st.c
new file mode 100644
index 0000000..1dd9c5e
--- /dev/null
+++ b/KERNEL/drivers/leds/leds-st.c
@@ -0,0 +1,1210 @@
+/*
+ * Driver for STMicroelectronics LED7708 driver
+ *
+ * Copyright 2016 STMicroelectronics <saurabh.rawat@...com>
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include "leds.h"
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/platform_data/leds-st.h>
+
+
+
+u16 channel_mask;
+char data_buff[Max_Packet_Length];
+struct device *dev_global;
+char data[Max_Packet_Length];
+/*default group dimming data for 16 bit resolution */
+char brightness_data_grp_dim_16[MAX_LENGTH] = "0000000000000000000000000000000000000000000000000000000000000000";
+/*default group dimming data for 12 bit resolution */
+char brightness_data_grp_dim_12[MAX_LENGTH] = "000000000000000000000000000000000000000000000000";
+struct led7708_chip *chip;
+static struct st7708_led *
+cdev_to_led7708_led(struct led_classdev *cdev)
+{
+return container_of(cdev, struct st7708_led, cdev);
+}
+
+/* Takes one character and returns it's hex value*/
+u16
+chartohex(char c)
+{
+int i;
+int d = 'a' - 'A';
+i = c - 'A';
+if (i > 0)
+   return ((i % d) % 6) + 10;
+  i = c - '0';
+  if (i > 0)
+    return i % 10;
+  return 0;
+}
+
+
+int
+inttochar(int x, char *res)
+{
+  if (x <= 0xFFFF) {
+      res[0] = TO_HEX(((x & 0xF000) >> 12));
+      res[1] = TO_HEX(((x & 0x0F00) >> 8));
+      res[2] = TO_HEX(((x & 0x00F0) >> 4));
+      res[3] = TO_HEX((x & 0x000F));
+      res[4] = '\0';
+    }
+  return 0;
+}
+
+void
+clock_out(struct led7708_platform_data *pdata)
+{
+  gpio_set_value(pdata->sck_gpio, 1);
+  msleep(MS50);
+  gpio_set_value(pdata->sck_gpio, 0);
+  msleep(MS50);
+
+
+}
+
+void
+led7708_create_brightness_data(struct led7708_platform_data *pdata,
+				u16 BrightnessData, char *brt_data_grp_dim)
+{
+
+  if (pdata->led_config->data_fmt == LED7708_1X256) {
+
+      inttochar(BrightnessData, &data[0]);
+      brt_data_grp_dim[0] = data[0];
+      brt_data_grp_dim[1] = data[1];
+      brt_data_grp_dim[2] = data[2];
+      brt_data_grp_dim[3] = data[3];
+    }
+  else if (pdata->led_config->data_fmt == LED7708_1X192) {
+      inttochar(BrightnessData, &data[0]);
+      brt_data_grp_dim[0] = data[0];
+      brt_data_grp_dim[1] = data[1];
+      brt_data_grp_dim[2] = data[2];
+      /* brt_data_grp_dim[3] = data[3]; */
+
+    }
+
+  return;
+
+}
+
+static int
+convert_to_hex(char x)
+{
+  int d;
+  if (x == 'F')
+    d = 15;
+  else if (x == 'E')
+    d = 14;
+  else if (x == 'D')
+    d = 13;
+  else if (x == 'C')
+    d = 12;
+  else if (x == 'B')
+    d = 11;
+  else if (x == 'A')
+    d = 10;
+  else
+    d = x;
+
+  return d;
+
+}
+
+static int
+write_led7708(struct led7708_platform_data *pdata, u8 pulse, char nbytes,
+	       char *data_to_send)
+{
+
+  int pulses_before_lren = 0, i, j, flag, temp, mask;
+  u8 received_stream[Max_Packet_Length], mode = 2;
+
+
+  for (i = 0; i < nbytes; i++) {
+      temp = convert_to_hex(data_to_send[i]);
+      mask = 8;
+      received_stream[i] = 0;
+
+      for (j = 0; j <= 3; j++) {
+	  flag = temp & mask;
+
+	  if (flag) {
+
+	      gpio_set_value(pdata->sdo_gpio, 1);
+	      msleep(MS50);
+	      gpio_set_value(pdata->sck_gpio, 1);
+	      msleep(MS50);
+	      gpio_set_value(pdata->sck_gpio, 0);
+	      msleep(MS50);
+	      if (gpio_get_value(pdata->sdi_gpio))	{
+		  received_stream[i] = received_stream[i] | mask;
+		}
+	    }
+	  else {
+
+	      gpio_set_value(pdata->sdo_gpio, 0);
+	      msleep(MS50);
+	      gpio_set_value(pdata->sck_gpio, 1);
+	      msleep(MS50);
+	      gpio_set_value(pdata->sck_gpio, 0);
+	      msleep(MS50);
+	      if (gpio_get_value(pdata->sdi_gpio)) {
+		  received_stream[i] = received_stream[i] | mask;
+		}
+
+	    }
+
+	  pulses_before_lren++;
+
+	  if (pulse != 0) {
+	      if (pulses_before_lren == ((nbytes * 4) - pulse)) {
+		  gpio_set_value(pdata->le_gpio, 1);
+		  msleep(MS50);
+
+		}
+	      if (pulses_before_lren == nbytes * 4) {
+		  gpio_set_value(pdata->le_gpio, 0);
+		  msleep(MS50);
+
+		}
+	    }
+	  mask = mask / 2;
+	}
+    }
+  if (pdata->led_config->mode == LED7708_R)  {
+      for (i = 0; i < nbytes; i++)	{
+	  if ((received_stream[i] >= 0) && (received_stream[i] <= 9)) {
+	      received_stream[i] = received_stream[i] + 48;
+	    }
+	  else if ((received_stream[i] >= 10) && (received_stream[i] <= 15)) {
+	      received_stream[i] = received_stream[i] + 55;
+	    }
+
+	}
+      dev_info(dev_global, "Continuous Brightness Reading = %s \n",
+		received_stream);
+    }
+  return 0;
+}
+
+
+static void
+led7708_led_brightness(struct st7708_led *led)
+{
+  struct led7708_chip *chip = led->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+
+  mutex_lock(&chip->lock);
+  if (led->chan_nr <= LED7708_MAX_CHANNELS) {
+      channel_mask = channel_mask | ((1 << (led->chan_nr)) & (0xFFFF));
+    }
+
+  /*Map the brightness to the LED7708 brightness value [0=255] - [0 - 65536] */
+  led->brightness =
+    led->brightness * (MAX_BRIGHTNESS) / (MAX_LED_SUBSYS_BRIGHTNESS);
+
+
+  /*Group Dimming mode Disabled by default */
+  if (!pdata->led_config->dimming_mode) {
+      inttochar(channel_mask, &data[0]);
+      write_led7708(chip->pdata, W_CHSEL, 4, data);
+      /*enable the device */
+      inttochar(0x2131, &data[0]);
+      write_led7708(chip->pdata, W_DEVCFGx, 4, data);
+      /*Write the common channel Brightness to the selected channels */
+      inttochar(led->brightness, &data[0]);
+      write_led7708(chip->pdata, W_BRT_GL, 4, data);
+    }
+  else {
+
+/*Select All channels
+ *inttochar(0xFFFF,&data[0]);
+ *write_led7708(chip->pdata,W_CHSEL,4,data);
+ *enable the device in GSME = 1 , group dimming mode
+ *inttochar(0x2501,&data[0]);
+ *write_led7708(chip->pdata,W_DEVCFGx,4,data);
+*/
+      if (pdata->led_config->data_fmt == LED7708_1X256) {
+	  led7708_create_brightness_data(pdata, led->brightness,
+					  &brightness_data_grp_dim_16[4 *
+								      (15 -
+								       led->
+								       chan_nr)]);
+	  dev_info(&chip->pd->dev,
+		    "Current Brightness string = %s  strlen = %x \n",
+		    brightness_data_grp_dim_16,
+		    strlen (brightness_data_grp_dim_16));
+	  dev_info(&chip->pd->dev, "Channel_mask = %x \n", channel_mask);
+
+	}
+      else if (pdata->led_config->data_fmt == LED7708_1X192) {
+	  led7708_create_brightness_data(pdata, led->brightness,
+					  &brightness_data_grp_dim_12[3 *
+								      (15 -
+								       led->
+								       chan_nr)]);
+	  dev_info (&chip->pd->dev,
+		    "Current Brightness string = %s  strlen = %x \n",
+		    brightness_data_grp_dim_12,
+		    strlen (brightness_data_grp_dim_12));
+	  dev_info (&chip->pd->dev, "Channel_mask = %x \n", channel_mask);
+
+	}
+      else if (pdata->led_config->data_fmt == LED7708_16X16) {
+	  inttochar (led->brightness, &data[0]);
+	  /* data Latch */
+	  write_led7708 (chip->pdata, W_BRT_DL, 4, data);
+	}
+      else	{
+	  dev_info (&chip->pd->dev, "Incorrect Value for data format");
+
+	}
+    }
+
+  mutex_unlock (&chip->lock);
+}
+
+
+static char
+demodecodewriteCmd (struct led7708_platform_data *led_dat, char mode,
+		    char buffer[Max_Packet_Length])
+{
+
+  char n_bytes = 0;
+  char le_pulses = 0;
+  char usb_received_bytes = strlen (buffer) - 1;
+  int i;
+
+  if ((buffer[0] == '(') && (buffer[3] == ',') && (buffer[6] == ',') &&
+      (buffer[usb_received_bytes - 1] == ')') && (buffer[1] >= '0') &&
+      (buffer[1] <= '9') && (buffer[2] >= '0') && (buffer[2] <= '9') &&
+      (buffer[4] >= '0') && (buffer[4] <= '9') && (buffer[5] >= '0')
+      && (buffer[5] <= '9')) {
+
+      le_pulses = (buffer[2] - 48) + 10 * (buffer[1] - 48);
+      n_bytes = (buffer[5] - 48) + 10 * (buffer[4] - 48);
+
+      if (n_bytes == (usb_received_bytes - 8))	{
+
+	  /* Convert received data characters into ASCII value if nibble mode: */
+	  if (mode != 0)
+	    for (i = 7; i <= usb_received_bytes - 2; i++) {
+		if (buffer[i] >= 'A' && buffer[i] <= 'F')
+		  buffer[i] = buffer[i] - 55;
+		else if (buffer[i] >= '0' && buffer[i] <= '9')
+		  buffer[i] = buffer[i] - 48;
+		else
+		  buffer[i] = 0;
+	      }
+	  write_led7708 (led_dat, le_pulses, n_bytes, &buffer[7]);
+
+	}
+      else {
+	  return ERR;
+	}
+
+    }
+  else {
+      return ERR;
+    }
+
+
+  return NOERR;
+
+}
+
+
+static ssize_t
+led_7708_data_fmt_store (struct device *dev,
+			 struct device_attribute *attr,
+			 const char *buff, size_t count)
+{
+  /* struct st7708_led *led_dat =    container_of(dev_get_drvdata (dev), struct st7708_led, cdev); */
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+  u16 data_fmt_reg_value = 0;
+  /*BDFS , BRLS
+   * 0       0  -> 0 => 16x16, 12-bit , (the 4 most significant bits are not used)
+   * 0       1  -> 1 => 16x16, 16-bit (default)
+   * 1       0  -> 2 => 192x1, 12-bit
+   * 1       1  -> 3 => 256x1, 16-bit
+   */
+
+  mutex_lock (&chip->lock);
+
+  if (!strncmp (buff, "0", 1)) {
+      pdata->led_config->data_fmt = LED7708_12X16;
+      data_fmt_reg_value = 0x8440;
+      dev_info (&chip->pd->dev,
+		" Current Brightness Data Format Set is = %d \n",
+		pdata->led_config->data_fmt);
+    }
+  else if (!strncmp (buff, "1", 1)) {
+      pdata->led_config->data_fmt = LED7708_16X16;
+      data_fmt_reg_value = 0x8440;
+      dev_info (&chip->pd->dev,
+		" Current Brightness Data Format Set is = %d \n",
+		pdata->led_config->data_fmt);
+    }
+  else if (!strncmp (buff, "2", 1)) {
+      pdata->led_config->data_fmt = LED7708_1X192;
+      data_fmt_reg_value = 0xC240;
+      dev_info (&chip->pd->dev,
+		" Current Brightness Data Format Set is = %d \n",
+		pdata->led_config->data_fmt);
+    }
+  else if (!strncmp (buff, "3", 1)) {
+      pdata->led_config->data_fmt = LED7708_1X256;
+      data_fmt_reg_value = 0xC640;
+      dev_info (&chip->pd->dev,
+		" Current Brightness Data Format Set is = %d \n",
+		pdata->led_config->data_fmt);
+    }
+  else
+    dev_info (&chip->pd->dev,
+	      " Wrong value Set, [0-3] accepted only.Previous Value Retained = %d \n",
+	      pdata->led_config->data_fmt);
+
+
+
+  if (pdata->led_config->data_fmt == LED7708_12X16) {
+      inttochar (0x2500, &data[0]);
+      dev_info (&chip->pd->dev, "16X16 : %s written \n", data);
+      write_led7708 (chip->pdata, W_DEVCFGx, 4, data);
+    }
+/*16 bit resolution*/
+  inttochar (data_fmt_reg_value, &data[0]);
+  dev_info (&chip->pd->dev, "data FMT : %s written \n", data);
+  write_led7708 (chip->pdata, W_DEVCFGx, 4, data);
+
+  mutex_unlock (&chip->lock);
+
+  return count;
+}
+
+static ssize_t
+led_7708_dimming_mode_store (struct device *dev,
+			     struct device_attribute *attr,
+			     const char *buff, size_t count)
+{
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+  /*GSME
+   * 0       GSME => Group Dimming mode Enabled
+   * 1       GSME => Group Dimming mode Disabled
+   */
+
+  mutex_lock (&chip->lock);
+
+  if (!strncmp (buff, "0", 1)) {
+      pdata->led_config->dimming_mode = LED7708_GREY_SCALE_MODE_GRP_DIM;
+      dev_info (&chip->pd->dev,
+		" Current Brightness Data Format Set is = %d \n",
+		pdata->led_config->dimming_mode);
+      inttochar (0x2130, &data[0]);
+    }
+  else if (!strncmp (buff, "1", 1)) {
+      pdata->led_config->dimming_mode = LED7708_GREY_SCALE_MODE_GRY_DIM;
+      dev_info (&chip->pd->dev,
+		" Current Brightness Data Format Set is = %d \n",
+		pdata->led_config->dimming_mode);
+      inttochar (0x2530, &data[0]);
+    }
+  else
+    dev_info (&chip->pd->dev,
+	      " Wrong value Set, [0-1] accepted only.Previous Value Retained = %d \n",
+	      pdata->led_config->dimming_mode);
+
+  dev_info (&chip->pd->dev, "Dimming mode : %s written \n", data);
+  write_led7708 (pdata, W_DEVCFGx, 4, data);
+  mutex_unlock (&chip->lock);
+
+
+  return count;
+}
+
+
+static ssize_t
+led_7708_sync_brightness_store (struct device *dev,
+				struct device_attribute *attr,
+				const char *buff, size_t count)
+{
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+
+  struct st7708_led *led =
+    container_of (dev_get_drvdata (dev), struct st7708_led, cdev);
+  mutex_lock (&chip->lock);
+
+  if (!strncmp (buff, "0", 1)) {
+      pdata->led_config->sync_brightness = 0;
+    }
+  else if (!strncmp (buff, "1", 1))  {
+      pdata->led_config->sync_brightness = 1;
+    }
+  else
+    dev_info (&chip->pd->dev,
+	      " Wrong value Set, [0-1] accepted only.Previous Value Retained = %d \n",
+	      pdata->led_config->sync_brightness);
+
+/* if Sync received then write both the channel mask and the Brightness string accumulated ar*/
+  if (pdata->led_config->sync_brightness) {
+
+      inttochar (channel_mask, &data[0]);
+      dev_info (&chip->pd->dev, "Channel Mask 0x: %s written \n", data);
+      write_led7708 (chip->pdata, W_CHSEL, 4, data);
+      dev_info (&chip->pd->dev, "Device Enabled 0x : %s written \n", data);
+
+      /*Device Enabled */
+      if (pdata->led_config->data_fmt == LED7708_16X16)  {
+
+	  inttochar (0x2501, &data[0]);
+	}
+      else	{
+	  inttochar (0x2531, &data[0]);
+	}
+
+      write_led7708 (chip->pdata, W_DEVCFGx, 4, data);
+
+      /*write the brightness data now
+       *dev_info(&chip->pd->dev, "Current Brightness Data value = %s \n",brightness_data_grp_dim);
+       *        brightness_data_grp_dim[64] = '\n';
+       */
+      if (pdata->led_config->data_fmt == LED7708_1X256)	{
+	  dev_info (&chip->pd->dev,
+		    "Final Brightness Data value = %s  strlen = %d \n",
+		    brightness_data_grp_dim_16,
+		    strlen (brightness_data_grp_dim_16));
+	  write_led7708 (chip->pdata, W_BRT_GL, 64,
+			 brightness_data_grp_dim_16);
+
+	}
+      else if (pdata->led_config->data_fmt == LED7708_1X192) {
+	  dev_info (&chip->pd->dev,
+		    "Final Brightness Data value = %s  strlen = %d \n",
+		    brightness_data_grp_dim_12,
+		    strlen (brightness_data_grp_dim_12));
+	  write_led7708 (chip->pdata, W_BRT_GL, 48,
+			 brightness_data_grp_dim_12);
+
+	}
+      else if (pdata->led_config->data_fmt == LED7708_16X16) {
+	  inttochar (led->brightness, &data[0]);
+	  /* Global Latch */
+	  write_led7708 (chip->pdata, W_BRT_GL, 4, data);
+
+	}
+
+    }
+  else  {
+      /*deselect all the channels */
+      write_led7708 (chip->pdata, W_CHSEL, 4, "0000");
+
+    }
+
+  mutex_unlock (&chip->lock);
+
+
+  return count;
+}
+
+
+static ssize_t
+led_7708_dbg_rw_store (struct device *dev,
+		       struct device_attribute *attr,
+		       const char *buff, size_t count)
+{
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+  mutex_lock (&chip->lock);
+
+  demodecodewriteCmd (pdata, 2, buff);
+
+  mutex_unlock (&chip->lock);
+
+
+  return count;
+}
+
+
+static ssize_t
+led_7708_enable_csrd_store (struct device *dev,
+			    struct device_attribute *attr,
+			    const char *buff, size_t count)
+{
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+  /*
+   * 0       W => Continuous Brightness Reading mode Enabled
+   * 1       R => Continuous Brightness Reding mode Disabled
+   */
+
+  mutex_lock (&chip->lock);
+  if (pdata->led_config->data_fmt == LED7708_1X192
+      || pdata->led_config->data_fmt == LED7708_1X256)  {
+
+      if (!strncmp (buff, "0", 1)) {
+	  pdata->led_config->mode = 0;
+	  dev_info (&chip->pd->dev, " Current csrd mode  is = %d \n",
+		    pdata->led_config->mode);
+	}
+      else if (!strncmp (buff, "1", 1))	{
+	  pdata->led_config->mode = 1;
+	  dev_info (&chip->pd->dev, " Current csrd mode  is = %d \n",
+		    pdata->led_config->mode);
+	}
+    }  else   {
+
+      dev_err (&chip->pd->dev,
+	       " CSRD not Available Only in 1X256 and 1X192 mode ,Current mode value remains = %d \n",
+	       pdata->led_config->mode);
+
+    }
+
+  mutex_unlock (&chip->lock);
+
+
+  return count;
+}
+
+
+static ssize_t
+led_7708_select_channel_store (struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buff, size_t count)
+{
+  int i, m = 1;
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+
+  mutex_lock (&chip->lock);
+  channel_mask = 0;
+  for (i = sizeof (buff) - 1; i > -1; i--, m *= 16)
+    channel_mask += m * chartohex (buff[i]);
+
+  inttochar (channel_mask, &data[0]);
+  /*write select the channels */
+  write_led7708 (chip->pdata, W_CHSEL, 4, data);
+
+
+  mutex_unlock (&chip->lock);
+
+
+  return count;
+}
+
+
+static ssize_t
+led_7708_data_fmt_show (struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+  char bufc[2] = "0";
+  dev_info (&chip->pd->dev, "current Dimming mode %d \n",
+	 pdata->led_config->data_fmt);
+	switch (pdata->led_config->data_fmt) {
+	case 0:
+	strcpy (bufc, "0");
+	break;
+
+	case 1:
+	strcpy (bufc, "1");
+	break;
+
+	case 2:
+	strcpy (bufc, "2");
+	break;
+
+	case 3:
+	strcpy (bufc, "3");
+	break;
+
+	default:
+	break;
+
+    }
+  return sprintf (buf, "%s\n", bufc);
+
+}
+
+
+static ssize_t
+led_7708_dimming_mode_show (struct device *dev, struct device_attribute *attr,
+			    char *buf)
+{
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+  char bufc[2] = "0";
+  dev_info (&chip->pd->dev, "current Dimming mode %d \n",
+	    pdata->led_config->dimming_mode);
+	switch (pdata->led_config->dimming_mode) {
+	case 0:
+	strcpy (bufc, "0");
+	break;
+	case 1:
+	strcpy (bufc, "1");
+	break;
+	default:
+	break;
+
+	 }
+  return sprintf (buf, "%s\n", bufc);
+
+}
+
+static ssize_t
+led_7708_sync_brightness_show (struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+  char bufc[2] = "0";
+  dev_info (&chip->pd->dev, "current sync_brightness Enable %d \n",
+	    pdata->led_config->sync_brightness);
+	switch (pdata->led_config->sync_brightness)  {
+	case 0:
+	strcpy (bufc, "0");
+	break;
+
+	case 1:
+	strcpy (bufc, "1");
+	break;
+
+	default:
+	break;
+
+	}
+  return sprintf (buf, "%s\n", bufc);
+}
+
+static ssize_t
+led_7708_dbg_rw_show (struct device *dev, struct device_attribute *attr,
+		      char *buf)
+{
+  /*struct led_classdev *led_cdev = dev_get_drvdata (dev);
+   * struct st7708_led *led_dat =  container_of (led_cdev, struct st7708_led, cdev);
+   */
+  return sprintf (buf, "%d\n", 1);;
+}
+
+static ssize_t
+led_7708_enable_csrd_show (struct device *dev, struct device_attribute *attr,
+			   char *buf)
+{
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+  char bufc[2] = "0";
+  dev_info (&chip->pd->dev, "current csrd mode %d \n",
+	    pdata->led_config->mode);
+	switch (pdata->led_config->mode) {
+	case 0:
+	strcpy (bufc, "0");
+	break;
+
+	case 1:
+	strcpy (bufc, "1");
+	break;
+
+	default:
+	break;
+
+    }
+  return sprintf (buf, "%s\n", bufc);
+}
+
+
+static ssize_t
+led_7708_select_channel_show (struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+  struct led7708_chip *chip =
+    (container_of (dev_get_drvdata (dev), struct st7708_led, cdev))->chip;
+  struct led7708_platform_data *pdata = chip->pdata;
+
+  return sprintf (buf, "Channel Select Mask %x\n", channel_mask);
+}
+
+/*common device attribute for controlling all the 16 channels*/
+static DEVICE_ATTR (led_7708_dimming_mode, 0644, led_7708_dimming_mode_show,
+		    led_7708_dimming_mode_store);
+static DEVICE_ATTR (led_7708_data_fmt, 0644, led_7708_data_fmt_show,
+		    led_7708_data_fmt_store);
+static DEVICE_ATTR (led_7708_sync_brightness, 0644,
+		    led_7708_sync_brightness_show,
+		    led_7708_sync_brightness_store);
+static DEVICE_ATTR (led_7708_dbg_rw, 0644, led_7708_dbg_rw_show,
+		    led_7708_dbg_rw_store);
+static DEVICE_ATTR (led_7708_enable_csrd, 0644, led_7708_enable_csrd_show,
+		    led_7708_enable_csrd_store);
+static DEVICE_ATTR (led_7708_select_channel, 0644,
+		    led_7708_select_channel_show,
+		    led_7708_select_channel_store);
+
+
+static struct attribute *st7708_led_common_attrs[] = {
+  &dev_attr_led_7708_dimming_mode.attr,
+  &dev_attr_led_7708_data_fmt.attr,
+  &dev_attr_led_7708_sync_brightness.attr,
+  &dev_attr_led_7708_dbg_rw.attr,
+  &dev_attr_led_7708_enable_csrd.attr,
+  &dev_attr_led_7708_select_channel.attr,
+  NULL
+};
+
+ATTRIBUTE_GROUPS (st7708_led_common);
+
+
+/* Chip specific configurations */
+static struct led7708_device_config led_cfg = {
+
+/*Extra Channel is for Common Channel Configuration */
+  .max_channel = LED7708_MAX_CHANNELS + 1,
+  .brightness_fn = led7708_led_brightness,
+};
+
+
+static struct led7708_platform_data *
+led7708_of_populate_pdata (struct device *dev, struct device_node *np)
+{
+  struct device_node *child;
+  struct led7708_platform_data *pdata;
+  struct led7708_config *cfg;
+  int ret;
+  int num_channels;
+  int i = 0;
+
+  pdata = devm_kzalloc (dev, sizeof (*pdata), GFP_KERNEL);
+  if (!pdata)
+    return ERR_PTR (-ENOMEM);
+
+  num_channels = of_get_child_count (np);
+  if (num_channels == 0)  {
+      dev_err (dev, "no LED channels\n");
+      return ERR_PTR (-EINVAL);
+    }
+
+  cfg = devm_kzalloc (dev, sizeof (*cfg) * num_channels, GFP_KERNEL);
+  if (!cfg)
+    return ERR_PTR (-ENOMEM);
+
+  pdata->led_config = &cfg[0];
+  pdata->num_channels = num_channels;
+
+  for_each_child_of_node (np, child)  {
+    cfg[i].chan_nr = i;
+
+    of_property_read_string (child, "chan-name", &cfg[i].name);
+    cfg[i].default_trigger =
+      of_get_property (child, "linux,default-trigger", NULL);
+
+    i++;
+  }
+
+  of_property_read_string (np, "label", &pdata->label);
+
+  /*Parse all the GPIOs from the Device Tree */
+    ret = of_get_named_gpio (np, "sdo-gpio", 0);
+	if (ret > 0)
+	pdata->sdo_gpio = ret;
+	else
+    goto gpio_error;
+
+    ret = of_get_named_gpio (np, "sdi-gpio", 0);
+    if (ret > 0)
+    pdata->sdi_gpio = ret;
+    else
+    goto gpio_error;
+
+
+	ret = of_get_named_gpio (np, "le-gpio", 0);
+	if (ret > 0)
+	pdata->le_gpio = ret;
+	else
+	goto gpio_error;
+
+	ret = of_get_named_gpio (np, "lren-gpio", 0);
+	if (ret > 0)
+	pdata->lren_gpio = ret;
+	else
+	goto gpio_error;
+
+
+	ret = of_get_named_gpio (np, "sck-gpio", 0);
+	if (ret > 0)
+	pdata->sck_gpio = ret;
+	else
+	 goto gpio_error;
+
+  return pdata;
+
+gpio_error:
+  return ret;
+
+}
+
+static int
+led7708_init_device (struct led7708_chip *chip)
+{
+  struct led7708_platform_data *pdata;
+  struct led7708_device_config *cfg;
+  struct device *dev = &chip->pd->dev;
+  int ret = 0;
+
+  pdata = chip->pdata;
+  cfg = chip->cfg;
+
+  if (!pdata || !cfg)
+    return -EINVAL;
+
+
+  if (gpio_is_valid (pdata->sdi_gpio))  {
+      ret =
+	devm_gpio_request_one (dev, pdata->sdi_gpio, GPIOF_DIR_IN,
+			       "sdi-gpio");
+      if (ret < 0) {
+	  dev_err (dev, "could not acquire sdi_gpio (err=%d)\n", ret);
+	  goto err;
+	}
+
+    }
+
+  if (gpio_is_valid (pdata->sck_gpio))  {
+      ret =
+	devm_gpio_request_one (dev, pdata->sck_gpio, GPIOF_DIR_OUT,
+			       "sck-gpio");
+      if (ret < 0) {
+	  dev_err (dev, "could not acquire sck_gpio (err=%d)\n", ret);
+	  goto err;
+	}
+
+    }
+
+
+  if (gpio_is_valid (pdata->lren_gpio))  {
+      ret =
+	devm_gpio_request_one (dev, pdata->lren_gpio, GPIOF_DIR_OUT,
+			       "lren-gpio");
+      if (ret < 0) {
+	  dev_err (dev, "could not acquire lren_gpio (err=%d)\n", ret);
+	  goto err;
+	}
+
+    }
+
+  if (gpio_is_valid (pdata->le_gpio))  {
+      ret =
+	devm_gpio_request_one (dev, pdata->le_gpio, GPIOF_DIR_OUT, "le-gpio");
+      if (ret < 0)	{
+	  dev_err (dev, "could not acquire le_gpio (err=%d)\n", ret);
+	  goto err;
+	}
+
+    }
+
+
+  if (gpio_is_valid (pdata->sdo_gpio))  {
+      ret =
+	devm_gpio_request_one (dev, pdata->sdo_gpio, GPIOF_DIR_OUT,
+			       "sdo_gpio");
+      if (ret < 0)	{
+	  dev_err (dev, "could not acquire sdo_gpio (err=%d)\n", ret);
+	  goto err;
+	}
+
+    }
+
+  gpio_set_value(pdata->lren_gpio, 0);
+  msleep(MS50);
+  gpio_set_value(pdata->lren_gpio, 1);
+  msleep(MS50);
+
+
+  return 0;
+
+err:
+  return ret;
+}
+
+
+static void
+led7708_set_brightness (struct led_classdev *cdev,
+			enum led_brightness brightness)
+{
+  struct st7708_led *led = cdev_to_led7708_led (cdev);
+  struct led7708_device_config *cfg = led->chip->cfg;
+  led->brightness = (u8) brightness;
+  return cfg->brightness_fn(led);
+}
+
+static int
+led7708_init_led (struct st7708_led *led, struct led7708_chip *chip, int chan)
+{
+  struct led7708_platform_data *pdata = chip->pdata;
+  struct led7708_device_config *cfg = chip->cfg;
+  struct device *dev = &chip->pd->dev;
+  char name[32];
+  int ret;
+  int max_channel = cfg->max_channel;
+
+
+
+  if (chan >= max_channel)  {
+      dev_err (dev, "invalid channel: %d / %d\n", chan, max_channel);
+      return -EINVAL;
+    }
+
+  led->chan_nr = pdata->led_config[chan].chan_nr;
+  led->cdev.default_trigger = pdata->led_config[chan].default_trigger;
+
+  if (led->chan_nr >= max_channel)  {
+      dev_err (dev, "Use channel numbers between 0 and %d\n",
+	       max_channel - 1);
+      return -EINVAL;
+    }
+
+  led->cdev.brightness_set = led7708_set_brightness;
+
+  if (pdata->led_config[chan].name)  {
+      led->cdev.name = pdata->led_config[chan].name;
+    }
+  else  {
+      snprintf (name, sizeof (name), "%s:channel%d",
+		pdata->label ? : chip->pd->name, chan);
+      led->cdev.name = name;
+    }
+
+  if (!strcmp (led->cdev.name, "led7708-chan-comm"))  {
+      led->cdev.groups = st7708_led_common_groups;
+
+
+    }
+
+  ret = led_classdev_register (dev, &led->cdev);
+  if (ret)  {
+      dev_err (dev, "led register err: %d\n", ret);
+      return ret;
+    }
+  else {
+
+
+    }
+
+  return 0;
+}
+
+static void
+led7708_unregister_leds (struct st7708_led *led, struct led7708_chip *chip)
+{
+  int i;
+  struct st7708_led *each;
+
+  for (i = 0; i < chip->num_leds; i++)  {
+      each = led + i;
+      led_classdev_unregister (&each->cdev);
+    }
+}
+
+static int
+led7708_register_leds (struct st7708_led *led, struct led7708_chip *chip)
+{
+  struct led7708_platform_data *pdata = chip->pdata;
+  struct led7708_device_config *cfg = chip->cfg;
+  int num_channels = pdata->num_channels;
+  struct st7708_led *each;
+  int ret;
+  int i;
+
+  if (!cfg->brightness_fn)  {
+      dev_err (&chip->pd->dev, "empty brightness configuration\n");
+      return -EINVAL;
+    }
+
+  for (i = 0; i < num_channels; i++) {
+
+      each = led + i;
+      ret = led7708_init_led(each, chip, i);
+      if (ret)	{
+	  goto err_init_led;
+	}
+      else{
+
+	}
+
+      chip->num_leds++;
+      each->chip = chip;
+
+    }
+
+
+  return 0;
+
+err_init_led:
+  led7708_unregister_leds(led, chip);
+  return ret;
+}
+
+void
+led7708_deinit_device (struct led7708_chip *chip)
+{
+  struct led7708_platform_data *pdata = chip->pdata;
+  if (gpio_is_valid(pdata->lren_gpio))
+    /*Disables the device */
+    gpio_set_value(pdata->lren_gpio, 0);
+
+}
+
+static void
+st_led_7708_init (struct led7708_chip *chip)
+{
+  struct led7708_platform_data *pdata = chip->pdata;
+
+  mutex_lock(&chip->lock);
+  /*defautl configure in the 16 Bit resolution 1X256 bit data format mode , enable gray scale mode */
+  write_led7708(pdata, W_DEVCFGx, 4, "2530");
+  write_led7708(pdata, W_DEVCFGx, 4, "C640");
+  msleep(MS50);
+
+  mutex_unlock(&chip->lock);
+
+}
+
+
+static int
+st_led_7708_probe (struct platform_device *pdev)
+{
+  int ret;
+  struct led7708_chip *chip;
+  struct st7708_led *led;
+  struct led7708_platform_data *pdata = dev_get_platdata(&pdev->dev);
+  struct device_node *np = pdev->dev.of_node;
+
+  if (!pdata)  {
+      if (np) {
+	  pdata = led7708_of_populate_pdata(&pdev->dev, np);
+	  if (IS_ERR(pdata))
+	    return PTR_ERR(pdata);
+	}
+      else	{
+	  dev_err(&pdev->dev, "no platform data\n");
+	  return -EINVAL;
+	}
+    }
+
+  chip = devm_kzalloc(&pdev->dev, sizeof(*chip), GFP_KERNEL);
+  if (!chip)
+    return -ENOMEM;
+
+  led = devm_kzalloc(&pdev->dev,
+		      sizeof(*led) * pdata->num_channels, GFP_KERNEL);
+  if (!led)
+    return -ENOMEM;
+
+  chip->pd = pdev;
+  chip->pdata = pdata;
+  chip->cfg = &led_cfg;
+
+
+  mutex_init(&chip->lock);
+
+  platform_set_drvdata(pdev, led);
+
+
+  ret = led7708_init_device(chip);
+  if (ret)
+    goto err_init;
+
+  ret = led7708_register_leds(led, chip);
+
+  if (ret)
+    goto err_register_leds;
+
+  if (ret) {
+      dev_err(&pdev->dev, "registering sysfs failed\n");
+      goto err_register_sysfs;
+    }
+  else {
+
+    }
+
+  /*Initialize the led7708 with gsme =1 , 16 bit resolution and all channels de-selected */
+  st_led_7708_init(chip);
+
+  dev_global = &chip->pd->dev;
+
+
+  return 0;
+
+err_register_sysfs:
+  led7708_unregister_leds(led, chip);
+err_register_leds:
+  led7708_deinit_device(chip);
+err_init:
+  return ret;
+}
+
+
+
+static int
+st_led_7708_remove (struct platform_device *pdev)
+{
+  struct st7708_led *led = platform_get_drvdata(pdev);
+  struct led7708_chip *chip = led->chip;
+  chip->pdata->led_config->sync_brightness = 0;
+
+  led7708_unregister_leds(led, chip);
+  led7708_deinit_device(chip);
+
+  dev_info(&pdev->dev, "ST LED7708 Driver removed Successfully \n");
+
+
+  return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id of_st_leds_match[] = {
+{.compatible = "st,st-leds",},
+{},
+};
+
+MODULE_DEVICE_TABLE(of, of_st_leds_match);
+#endif
+
+static struct platform_driver st_led_7708_driver = {
+.driver = {
+	     .name = "leds-st",
+	     .of_match_table = of_match_ptr(of_st_leds_match),
+	     },
+.probe = st_led_7708_probe,
+.remove = st_led_7708_remove,
+};
+
+module_platform_driver(st_led_7708_driver);
+
+MODULE_AUTHOR("Saurabh Rawat <saurabh.rawat@...com>");
+MODULE_DESCRIPTION("ST LED7708 Driver");
+MODULE_LICENSE("GPL");
diff --git a/KERNEL/include/linux/platform_data/leds-st.h b/KERNEL/include/linux/platform_data/leds-st.h
new file mode 100644
index 0000000..4a5a31f
--- /dev/null
+++ b/KERNEL/include/linux/platform_data/leds-st.h
@@ -0,0 +1,170 @@
+/*
+ * Platform data structure for ST LED7708 driver
+ *
+ * This file is licensed under the terms of the GNU General Public
+ * License version 2.  This program is licensed "as is" without any
+ * warranty of any kind, whether express or implied.
+ */
+
+#ifndef __LEDS_7708_ST_H
+#define __LEDS_7708_ST_H
+
+#define W_BRT_DL    1
+#define W_BRT_GL    2
+#define W_CHSEL     4
+#define R_CHSTA     7
+#define W_DEVCFGx   8
+#define R_DEVCFGx   11
+#define W_GSLAT     13
+
+/* DEVCFG0 register bits */
+#define DEVCFG0_DEN		(1 << 0) /* Device Enable */
+#define DEVCFG0_EDMI		(1 << 1) /* Error Detection Mode Indctr  */
+#define DEVCFG0_OVFW		(1 << 2) /* Regulation DAC Overflow */
+#define DEVCFG0_OTAF		(1 << 3) /* Over-Temperature Alert Flag  */
+#define DEVCFG0_OCAD		(1 << 4) /* Open Channels Auto Disconnect*/
+#define DEVCFG0_SCAD		(1 << 5) /* Shorted Channels Auto Disconn*/
+#define DEVCFG0_CFP		(1 << 6) /* Critical Fault Protection    */
+#define DEVCFG0_RWAS		(1 << 7) /* Regulation Wndw Amplitude Sel*/
+#define DEVCFG0_DTS_DIS		(0 << 8) /* Regulation Wndw Amplitude Sel*/
+#define DEVCFG0_DTS_3_4		(1 << 8) /* Regulation Wndw Amplitude Sel*/
+#define DEVCFG0_DTS_6_8		(2 << 8) /* Regulation Wndw Amplitude Sel*/
+#define DEVCFG0_DTS_8_4		(3 << 8) /* Regulation Wndw Amplitude Sel*/
+#define DEVCFG0_GSME		(1 << 10) /* Gray-Scale Mode Enable       */
+#define DEVCFG0_CRS		(1 << 11) /* Current Range Selector       */
+#define DEVCFG0_OVRS		(1 << 12) /* Output Volt Regulation Stat  */
+#define DEVCFG0_OVRE		(1 << 13) /* Output Volt Regulation Enbl  */
+#define DEVCFG0_SDMS		(1 << 14) /* Slave Device Mode Selection  */
+#define DEVCFG0_DEST_CFG0	(0 << 15) /* FIFO loaded into DEVCFG0     */
+
+/* DEVCFG1 register bits */
+#define DEVCFG1_ADJ_SET(_val)	(((_val) & 0x3f) << 0)
+/* Current Gain Adjust          */
+#define DEVCFG1_CGRS		(1 << 6) /* Current Gain Range Selector  */
+#define DEVCFG1_LAT16		(1 << 7) /* Bits #16 of dimming latency  */
+#define DEVCFG1_LAT17		(1 << 8) /* Bits #17 of dimming latency  */
+#define DEVCFG1_BDFS		(1 << 9) /* Brightness Data Format Sel   */
+#define DEVCFG1_BRLS		(1 << 10) /* Brightness Registers Len Sel */
+#define DEVCFG1_DTIN		(1 << 11) /* Dimming Timing Inversion sel */
+#define DEVCFG1_DASS		(1 << 12) /* Data Synchronization Selector*/
+#define DEVCFG1_DSYS		(1 << 13) /* Dimming Synch Selector       */
+#define DEVCFG1_CSRD		(1 << 14) /* Continuous Status Reading    */
+#define DEVCFG1_DEST_CFG1	(1 << 15) /* FIFO loaded into DEVCFG1     */
+
+#define TO_HEX(i) (i <= 9 ? '0' + i : 'A' - 10 + i)
+
+#define LED7708_MAX_CHANNELS		16
+#define MAX_BRIGHTNESS			0xffff
+#define MAX_LED_SUBSYS_BRIGHTNESS	0xff
+#define MAX_LENGTH			100
+#define Max_Packet_Length		100
+#define ERR 1
+#define NOERR 0
+
+
+#define MS50 0
+#define MS100 0
+
+enum st_led_modes {
+LED7708_W = 0,
+LED7708_R = 1,
+};
+
+enum st_led_datafmt {
+LED7708_12X16 = 0,
+LED7708_16X16 = 1,
+LED7708_1X192 = 2,
+LED7708_1X256 = 3,
+};
+
+enum st_led_gsme_mode {
+LED7708_GREY_SCALE_MODE_GRP_DIM = 0,
+LED7708_GREY_SCALE_MODE_GRY_DIM = 1,
+};
+
+
+struct st_led {
+const char *name;
+const char *default_trigger;
+unsigned le;
+unsigned lren;
+unsigned sdo;
+unsigned sck;
+unsigned sdi;
+};
+
+struct st_led_platform_data {
+int num_leds;
+struct st_led *leds;
+};
+
+/*
+ * struct led7708_chip
+ * @pdata      : Platform specific data
+ * @lock       : Lock for user-space interface
+ * @num_leds   : Number of registered LEDs
+ * @cfg        : Device specific configuration data
+ */
+struct led7708_chip {
+struct platform_device *pd;
+struct led7708_platform_data *pdata;
+struct mutex lock;		/* lock for user-space interface */
+int num_leds;
+struct led7708_device_config *cfg;
+};
+
+
+/*
+ * struct st7708_led
+ * @chan_nr         : Channel number
+ * @cdev            : LED class device
+ * @brightness      : Brightness value
+ * @chip            : The led7708 chip data
+ */
+struct st7708_led {
+int chan_nr;
+struct led_classdev cdev;
+u16 brightness;
+struct led7708_chip *chip;
+};
+
+ /*
+  * struct led7708_platform_data
+  * @led_config        : Configurable led class device
+  * @num_channels      : Number of LED channels
+  * @label             : Used for naming LEDs
+  */
+struct led7708_platform_data {
+
+  /* LED channel configuration */
+struct led7708_config *led_config;
+u8 num_channels;
+const char *label;
+int sdo_gpio;
+int sdi_gpio;
+int sck_gpio;
+int lren_gpio;
+int le_gpio;
+
+};
+
+struct led7708_config {
+const char *name;
+const char *default_trigger;
+u8 chan_nr;
+u8 dimming_mode;
+u8 data_fmt;
+u8 sync_brightness;
+u8 mode;
+};
+
+struct led7708_device_config {
+const int max_channel;
+
+/* access brightness register */
+void (*brightness_fn)(struct st7708_led *led);
+
+};
+
+
+#endif /* __LEDS_7708_ST_H */
diff --git a/patches/defconfig b/patches/defconfig
index 4c7f16f..856c245 100644
--- a/patches/defconfig
+++ b/patches/defconfig
@@ -1,6 +1,6 @@
 #
 # Automatically generated file; DO NOT EDIT.
-# Linux/arm 4.7.0 Kernel Configuration
+# Linux/arm 4.7.6 Kernel Configuration
 #
 CONFIG_ARM=y
 CONFIG_ARM_HAS_SG_CHAIN=y
@@ -4693,6 +4693,7 @@ CONFIG_LEDS_PCA9532=m
 CONFIG_LEDS_PCA9532_GPIO=y
 CONFIG_LEDS_GPIO=m
 CONFIG_LEDS_LP3944=m
+CONFIG_LEDS_STLED7708=y
 CONFIG_LEDS_LP55XX_COMMON=m
 CONFIG_LEDS_LP5521=m
 CONFIG_LEDS_LP5523=m
-- 
2.1.4

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ