diff mbox

[09051_43] Siano: Add new GPIO management interface

Message ID 855967.12185.qm@web110807.mail.gq1.yahoo.com (mailing list archive)
State Accepted
Headers show

Commit Message

Uri Shkolnik May 19, 2009, 2:49 p.m. UTC
# HG changeset patch
# User Uri Shkolnik <uris@siano-ms.com>
# Date 1242744570 -10800
# Node ID 749c11a362a9fad1992809007247d5c76c35bfc9
# Parent  08e292f80f37496d8d4b43a542f518196eaa4dc0
[09051_43] Siano: Add new GPIO management interface

From: Uri Shkolnik <uris@siano-ms.com>

Add new GPIO management interface to replace old (buggy) one.
Keeping old interface intact for now.

Priority: normal

Signed-off-by: Uri Shkolnik <uris@siano-ms.com>




      
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Michael Krufky May 19, 2009, 4:13 p.m. UTC | #1
On Tue, May 19, 2009 at 10:49 AM, Uri Shkolnik <urishk@yahoo.com> wrote:
>
> # HG changeset patch
> # User Uri Shkolnik <uris@siano-ms.com>
> # Date 1242744570 -10800
> # Node ID 749c11a362a9fad1992809007247d5c76c35bfc9
> # Parent  08e292f80f37496d8d4b43a542f518196eaa4dc0
> [09051_43] Siano: Add new GPIO management interface
>
> From: Uri Shkolnik <uris@siano-ms.com>
>
> Add new GPIO management interface to replace old (buggy) one.
> Keeping old interface intact for now.
>
> Priority: normal
>
> Signed-off-by: Uri Shkolnik <uris@siano-ms.com>
>
> diff -r 08e292f80f37 -r 749c11a362a9 linux/drivers/media/dvb/siano/sms-cards.c
> --- a/linux/drivers/media/dvb/siano/sms-cards.c Tue May 19 16:30:40 2009 +0300
> +++ b/linux/drivers/media/dvb/siano/sms-cards.c Tue May 19 17:49:30 2009 +0300
> @@ -109,7 +109,7 @@ static int sms_set_gpio(struct smscore_d
>  {
>        int lvl, ret;
>        u32 gpio;
> -       struct smscore_gpio_config gpioconfig = {
> +       struct smscore_config_gpio gpioconfig = {
>                .direction            = SMS_GPIO_DIRECTION_OUTPUT,
>                .pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
>                .inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
> diff -r 08e292f80f37 -r 749c11a362a9 linux/drivers/media/dvb/siano/smscoreapi.c
> --- a/linux/drivers/media/dvb/siano/smscoreapi.c        Tue May 19 16:30:40 2009 +0300
> +++ b/linux/drivers/media/dvb/siano/smscoreapi.c        Tue May 19 17:49:30 2009 +0300
> @@ -1331,8 +1331,9 @@ static int smscore_map_common_buffer(str
>  }
>  #endif
>
> +/* old GPIO managments implementation */
>  int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
> -                          struct smscore_gpio_config *pinconfig)
> +                          struct smscore_config_gpio *pinconfig)
>  {
>        struct {
>                struct SmsMsgHdr_ST hdr;
> @@ -1399,6 +1400,238 @@ int smscore_set_gpio(struct smscore_devi
>
>        return coredev->sendrequest_handler(coredev->context,
>                                            &msg, sizeof(msg));
> +}
> +
> +/* new GPIO managment implementation */
> +static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
> +               u32 *pGroupNum, u32 *pGroupCfg) {
> +
> +       *pGroupCfg = 1;
> +
> +       if (PinNum >= 0 && PinNum <= 1) {
> +               *pTranslatedPinNum = 0;
> +               *pGroupNum = 9;
> +               *pGroupCfg = 2;
> +       } else if (PinNum >= 2 && PinNum <= 6) {
> +               *pTranslatedPinNum = 2;
> +               *pGroupNum = 0;
> +               *pGroupCfg = 2;
> +       } else if (PinNum >= 7 && PinNum <= 11) {
> +               *pTranslatedPinNum = 7;
> +               *pGroupNum = 1;
> +       } else if (PinNum >= 12 && PinNum <= 15) {
> +               *pTranslatedPinNum = 12;
> +               *pGroupNum = 2;
> +               *pGroupCfg = 3;
> +       } else if (PinNum == 16) {
> +               *pTranslatedPinNum = 16;
> +               *pGroupNum = 23;
> +       } else if (PinNum >= 17 && PinNum <= 24) {
> +               *pTranslatedPinNum = 17;
> +               *pGroupNum = 3;
> +       } else if (PinNum == 25) {
> +               *pTranslatedPinNum = 25;
> +               *pGroupNum = 6;
> +       } else if (PinNum >= 26 && PinNum <= 28) {
> +               *pTranslatedPinNum = 26;
> +               *pGroupNum = 4;
> +       } else if (PinNum == 29) {
> +               *pTranslatedPinNum = 29;
> +               *pGroupNum = 5;
> +               *pGroupCfg = 2;
> +       } else if (PinNum == 30) {
> +               *pTranslatedPinNum = 30;
> +               *pGroupNum = 8;
> +       } else if (PinNum == 31) {
> +               *pTranslatedPinNum = 31;
> +               *pGroupNum = 17;
> +       } else
> +               return -1;
> +
> +       *pGroupCfg <<= 24;
> +
> +       return 0;
> +}
> +
> +int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
> +               struct smscore_gpio_config *pGpioConfig) {
> +
> +       u32 totalLen;
> +       u32 TranslatedPinNum;
> +       u32 GroupNum;
> +       u32 ElectricChar;
> +       u32 groupCfg;
> +       void *buffer;
> +       int rc;
> +
> +       struct SetGpioMsg {
> +               struct SmsMsgHdr_ST xMsgHeader;
> +               u32 msgData[6];
> +       } *pMsg;
> +
> +
> +       if (PinNum > MAX_GPIO_PIN_NUMBER)
> +               return -EINVAL;
> +
> +       if (pGpioConfig == NULL)
> +               return -EINVAL;
> +
> +       totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
> +
> +       buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
> +                       GFP_KERNEL | GFP_DMA);
> +       if (!buffer)
> +               return -ENOMEM;
> +
> +       pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
> +
> +       pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
> +       pMsg->xMsgHeader.msgDstId = HIF_TASK;
> +       pMsg->xMsgHeader.msgFlags = 0;
> +       pMsg->xMsgHeader.msgLength = (u16) totalLen;
> +       pMsg->msgData[0] = PinNum;
> +
> +       if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
> +               pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
> +               if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
> +                               &groupCfg) != 0)
> +                       return -EINVAL;
> +
> +               pMsg->msgData[1] = TranslatedPinNum;
> +               pMsg->msgData[2] = GroupNum;
> +               ElectricChar = (pGpioConfig->PullUpDown)
> +                               | (pGpioConfig->InputCharacteristics << 2)
> +                               | (pGpioConfig->OutputSlewRate << 3)
> +                               | (pGpioConfig->OutputDriving << 4);
> +               pMsg->msgData[3] = ElectricChar;
> +               pMsg->msgData[4] = pGpioConfig->Direction;
> +               pMsg->msgData[5] = groupCfg;
> +       } else {
> +               pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
> +               pMsg->msgData[1] = pGpioConfig->PullUpDown;
> +               pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
> +               pMsg->msgData[3] = pGpioConfig->OutputDriving;
> +               pMsg->msgData[4] = pGpioConfig->Direction;
> +               pMsg->msgData[5] = 0;
> +       }
> +
> +       smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
> +       rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
> +                       &coredev->gpio_configuration_done);
> +
> +       if (rc != 0) {
> +               if (rc == -ETIME)
> +                       sms_err("smscore_gpio_configure timeout");
> +               else
> +                       sms_err("smscore_gpio_configure error");
> +       }
> +       kfree(buffer);
> +
> +       return rc;
> +}
> +
> +int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
> +               u8 NewLevel) {
> +
> +       u32 totalLen;
> +       int rc;
> +       void *buffer;
> +
> +       struct SetGpioMsg {
> +               struct SmsMsgHdr_ST xMsgHeader;
> +               u32 msgData[3]; /* keep it 3 ! */
> +       } *pMsg;
> +
> +       if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER) ||
> +                       (PinNum > MAX_GPIO_PIN_NUMBER))
> +               return -EINVAL;
> +
> +       totalLen = sizeof(struct SmsMsgHdr_ST) +
> +                       (3 * sizeof(u32)); /* keep it 3 ! */
> +
> +       buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
> +                       GFP_KERNEL | GFP_DMA);
> +       if (!buffer)
> +               return -ENOMEM;
> +
> +       pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
> +
> +       pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
> +       pMsg->xMsgHeader.msgDstId = HIF_TASK;
> +       pMsg->xMsgHeader.msgFlags = 0;
> +       pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
> +       pMsg->xMsgHeader.msgLength = (u16) totalLen;
> +       pMsg->msgData[0] = PinNum;
> +       pMsg->msgData[1] = NewLevel;
> +
> +       /* Send message to SMS */
> +       smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
> +       rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
> +                       &coredev->gpio_set_level_done);
> +
> +       if (rc != 0) {
> +               if (rc == -ETIME)
> +                       sms_err("smscore_gpio_set_level timeout");
> +               else
> +                       sms_err("smscore_gpio_set_level error");
> +       }
> +       kfree(buffer);
> +
> +       return rc;
> +}
> +
> +int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
> +               u8 *level) {
> +
> +       u32 totalLen;
> +       int rc;
> +       void *buffer;
> +
> +       struct SetGpioMsg {
> +               struct SmsMsgHdr_ST xMsgHeader;
> +               u32 msgData[2];
> +       } *pMsg;
> +
> +
> +       if (PinNum > MAX_GPIO_PIN_NUMBER)
> +               return -EINVAL;
> +
> +       totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
> +
> +       buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
> +                       GFP_KERNEL | GFP_DMA);
> +       if (!buffer)
> +               return -ENOMEM;
> +
> +       pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
> +
> +       pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
> +       pMsg->xMsgHeader.msgDstId = HIF_TASK;
> +       pMsg->xMsgHeader.msgFlags = 0;
> +       pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
> +       pMsg->xMsgHeader.msgLength = (u16) totalLen;
> +       pMsg->msgData[0] = PinNum;
> +       pMsg->msgData[1] = 0;
> +
> +       /* Send message to SMS */
> +       smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
> +       rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
> +                       &coredev->gpio_get_level_done);
> +
> +       if (rc != 0) {
> +               if (rc == -ETIME)
> +                       sms_err("smscore_gpio_get_level timeout");
> +               else
> +                       sms_err("smscore_gpio_get_level error");
> +       }
> +       kfree(buffer);
> +
> +       /* Its a race between other gpio_get_level() and the copy of the single
> +        * global 'coredev->gpio_get_res' to  the function's variable 'level'
> +        */
> +       *level = coredev->gpio_get_res;
> +
> +       return rc;
>  }
>
>  static int __init smscore_module_init(void)
> diff -r 08e292f80f37 -r 749c11a362a9 linux/drivers/media/dvb/siano/smscoreapi.h
> --- a/linux/drivers/media/dvb/siano/smscoreapi.h        Tue May 19 16:30:40 2009 +0300
> +++ b/linux/drivers/media/dvb/siano/smscoreapi.h        Tue May 19 17:49:30 2009 +0300
> @@ -550,7 +550,7 @@ struct SMSHOSTLIB_I2C_RES_ST {
>  };
>
>
> -struct smscore_gpio_config {
> +struct smscore_config_gpio {
>  #define SMS_GPIO_DIRECTION_INPUT  0
>  #define SMS_GPIO_DIRECTION_OUTPUT 1
>        u8 direction;
> @@ -574,6 +574,48 @@ struct smscore_gpio_config {
>  #define SMS_GPIO_OUTPUTDRIVING_12mA 2
>  #define SMS_GPIO_OUTPUTDRIVING_16mA 3
>        u8 outputdriving;
> +};
> +
> +struct smscore_gpio_config {
> +#define SMS_GPIO_DIRECTION_INPUT  0
> +#define SMS_GPIO_DIRECTION_OUTPUT 1
> +       u8 Direction;
> +
> +#define SMS_GPIO_PULLUPDOWN_NONE     0
> +#define SMS_GPIO_PULLUPDOWN_PULLDOWN 1
> +#define SMS_GPIO_PULLUPDOWN_PULLUP   2
> +#define SMS_GPIO_PULLUPDOWN_KEEPER   3
> +       u8 PullUpDown;
> +
> +#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL  0
> +#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1
> +       u8 InputCharacteristics;
> +
> +#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW         1 /* 10xx */
> +#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST         0 /* 10xx */
> +
> +
> +#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS    0 /* 11xx */
> +#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS     1 /* 11xx */
> +#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS     2 /* 11xx */
> +#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS     3 /* 11xx */
> +       u8 OutputSlewRate;
> +
> +#define SMS_GPIO_OUTPUT_DRIVING_S_4mA          0 /* 10xx */
> +#define SMS_GPIO_OUTPUT_DRIVING_S_8mA          1 /* 10xx */
> +#define SMS_GPIO_OUTPUT_DRIVING_S_12mA         2 /* 10xx */
> +#define SMS_GPIO_OUTPUT_DRIVING_S_16mA         3 /* 10xx */
> +
> +#define SMS_GPIO_OUTPUT_DRIVING_1_5mA          0 /* 11xx */
> +#define SMS_GPIO_OUTPUT_DRIVING_2_8mA          1 /* 11xx */
> +#define SMS_GPIO_OUTPUT_DRIVING_4mA                    2 /* 11xx */
> +#define SMS_GPIO_OUTPUT_DRIVING_7mA                    3 /* 11xx */
> +#define SMS_GPIO_OUTPUT_DRIVING_10mA                   4 /* 11xx */
> +#define SMS_GPIO_OUTPUT_DRIVING_11mA                   5 /* 11xx */
> +#define SMS_GPIO_OUTPUT_DRIVING_14mA                   6 /* 11xx */
> +#undef SMS_GPIO_OUTPUT_DRIVING_16mA
> +#define SMS_GPIO_OUTPUT_DRIVING_16mA                   7 /* 11xx */
> +       u8 OutputDriving;
>  };
>
>  extern void smscore_registry_setmode(char *devpath, int mode);
> @@ -619,9 +661,18 @@ extern void smscore_putbuffer(struct sms
>  extern void smscore_putbuffer(struct smscore_device_t *coredev,
>                              struct smscore_buffer_t *cb);
>
> +/* old GPIO managment */
>  int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
> -                          struct smscore_gpio_config *pinconfig);
> +                          struct smscore_config_gpio *pinconfig);
>  int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
> +
> +/* new GPIO managment */
> +extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
> +               struct smscore_gpio_config *pGpioConfig);
> +extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
> +               u8 NewLevel);
> +extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
> +               u8 *level);
>
>  void smscore_set_board_id(struct smscore_device_t *core, int id);
>  int smscore_get_board_id(struct smscore_device_t *core);
>
>
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-media" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>




Mauro,

I am OK with this changeset, since the old GPIO functions were left
intact.  I haven't actually TESTED this patch, but I will do so after
it's merged.

After Uri is done with his changes, I will cleanup the Hauppauge code
for GPIO handling, to remove the duplicated functionality.

It would have been cleaner to simply add the "wait" flag to the new
gpio function, but I cant tell Uri what to do -- this is OK for now.

Acked-by: Michael Krufky <mkrufky@linuxtv.org>
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff -r 08e292f80f37 -r 749c11a362a9 linux/drivers/media/dvb/siano/sms-cards.c
--- a/linux/drivers/media/dvb/siano/sms-cards.c	Tue May 19 16:30:40 2009 +0300
+++ b/linux/drivers/media/dvb/siano/sms-cards.c	Tue May 19 17:49:30 2009 +0300
@@ -109,7 +109,7 @@  static int sms_set_gpio(struct smscore_d
 {
 	int lvl, ret;
 	u32 gpio;
-	struct smscore_gpio_config gpioconfig = {
+	struct smscore_config_gpio gpioconfig = {
 		.direction            = SMS_GPIO_DIRECTION_OUTPUT,
 		.pullupdown           = SMS_GPIO_PULLUPDOWN_NONE,
 		.inputcharacteristics = SMS_GPIO_INPUTCHARACTERISTICS_NORMAL,
diff -r 08e292f80f37 -r 749c11a362a9 linux/drivers/media/dvb/siano/smscoreapi.c
--- a/linux/drivers/media/dvb/siano/smscoreapi.c	Tue May 19 16:30:40 2009 +0300
+++ b/linux/drivers/media/dvb/siano/smscoreapi.c	Tue May 19 17:49:30 2009 +0300
@@ -1331,8 +1331,9 @@  static int smscore_map_common_buffer(str
 }
 #endif
 
+/* old GPIO managments implementation */
 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
-			   struct smscore_gpio_config *pinconfig)
+			   struct smscore_config_gpio *pinconfig)
 {
 	struct {
 		struct SmsMsgHdr_ST hdr;
@@ -1399,6 +1400,238 @@  int smscore_set_gpio(struct smscore_devi
 
 	return coredev->sendrequest_handler(coredev->context,
 					    &msg, sizeof(msg));
+}
+
+/* new GPIO managment implementation */
+static int GetGpioPinParams(u32 PinNum, u32 *pTranslatedPinNum,
+		u32 *pGroupNum, u32 *pGroupCfg) {
+
+	*pGroupCfg = 1;
+
+	if (PinNum >= 0 && PinNum <= 1)	{
+		*pTranslatedPinNum = 0;
+		*pGroupNum = 9;
+		*pGroupCfg = 2;
+	} else if (PinNum >= 2 && PinNum <= 6) {
+		*pTranslatedPinNum = 2;
+		*pGroupNum = 0;
+		*pGroupCfg = 2;
+	} else if (PinNum >= 7 && PinNum <= 11) {
+		*pTranslatedPinNum = 7;
+		*pGroupNum = 1;
+	} else if (PinNum >= 12 && PinNum <= 15) {
+		*pTranslatedPinNum = 12;
+		*pGroupNum = 2;
+		*pGroupCfg = 3;
+	} else if (PinNum == 16) {
+		*pTranslatedPinNum = 16;
+		*pGroupNum = 23;
+	} else if (PinNum >= 17 && PinNum <= 24) {
+		*pTranslatedPinNum = 17;
+		*pGroupNum = 3;
+	} else if (PinNum == 25) {
+		*pTranslatedPinNum = 25;
+		*pGroupNum = 6;
+	} else if (PinNum >= 26 && PinNum <= 28) {
+		*pTranslatedPinNum = 26;
+		*pGroupNum = 4;
+	} else if (PinNum == 29) {
+		*pTranslatedPinNum = 29;
+		*pGroupNum = 5;
+		*pGroupCfg = 2;
+	} else if (PinNum == 30) {
+		*pTranslatedPinNum = 30;
+		*pGroupNum = 8;
+	} else if (PinNum == 31) {
+		*pTranslatedPinNum = 31;
+		*pGroupNum = 17;
+	} else
+		return -1;
+
+	*pGroupCfg <<= 24;
+
+	return 0;
+}
+
+int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+		struct smscore_gpio_config *pGpioConfig) {
+
+	u32 totalLen;
+	u32 TranslatedPinNum;
+	u32 GroupNum;
+	u32 ElectricChar;
+	u32 groupCfg;
+	void *buffer;
+	int rc;
+
+	struct SetGpioMsg {
+		struct SmsMsgHdr_ST xMsgHeader;
+		u32 msgData[6];
+	} *pMsg;
+
+
+	if (PinNum > MAX_GPIO_PIN_NUMBER)
+		return -EINVAL;
+
+	if (pGpioConfig == NULL)
+		return -EINVAL;
+
+	totalLen = sizeof(struct SmsMsgHdr_ST) + (sizeof(u32) * 6);
+
+	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+			GFP_KERNEL | GFP_DMA);
+	if (!buffer)
+		return -ENOMEM;
+
+	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	pMsg->xMsgHeader.msgDstId = HIF_TASK;
+	pMsg->xMsgHeader.msgFlags = 0;
+	pMsg->xMsgHeader.msgLength = (u16) totalLen;
+	pMsg->msgData[0] = PinNum;
+
+	if (!(coredev->device_flags & SMS_DEVICE_FAMILY2)) {
+		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_REQ;
+		if (GetGpioPinParams(PinNum, &TranslatedPinNum, &GroupNum,
+				&groupCfg) != 0)
+			return -EINVAL;
+
+		pMsg->msgData[1] = TranslatedPinNum;
+		pMsg->msgData[2] = GroupNum;
+		ElectricChar = (pGpioConfig->PullUpDown)
+				| (pGpioConfig->InputCharacteristics << 2)
+				| (pGpioConfig->OutputSlewRate << 3)
+				| (pGpioConfig->OutputDriving << 4);
+		pMsg->msgData[3] = ElectricChar;
+		pMsg->msgData[4] = pGpioConfig->Direction;
+		pMsg->msgData[5] = groupCfg;
+	} else {
+		pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_CONFIG_EX_REQ;
+		pMsg->msgData[1] = pGpioConfig->PullUpDown;
+		pMsg->msgData[2] = pGpioConfig->OutputSlewRate;
+		pMsg->msgData[3] = pGpioConfig->OutputDriving;
+		pMsg->msgData[4] = pGpioConfig->Direction;
+		pMsg->msgData[5] = 0;
+	}
+
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+			&coredev->gpio_configuration_done);
+
+	if (rc != 0) {
+		if (rc == -ETIME)
+			sms_err("smscore_gpio_configure timeout");
+		else
+			sms_err("smscore_gpio_configure error");
+	}
+	kfree(buffer);
+
+	return rc;
+}
+
+int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 NewLevel) {
+
+	u32 totalLen;
+	int rc;
+	void *buffer;
+
+	struct SetGpioMsg {
+		struct SmsMsgHdr_ST xMsgHeader;
+		u32 msgData[3]; /* keep it 3 ! */
+	} *pMsg;
+
+	if ((NewLevel > 1) || (PinNum > MAX_GPIO_PIN_NUMBER) ||
+			(PinNum > MAX_GPIO_PIN_NUMBER))
+		return -EINVAL;
+
+	totalLen = sizeof(struct SmsMsgHdr_ST) +
+			(3 * sizeof(u32)); /* keep it 3 ! */
+
+	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+			GFP_KERNEL | GFP_DMA);
+	if (!buffer)
+		return -ENOMEM;
+
+	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	pMsg->xMsgHeader.msgDstId = HIF_TASK;
+	pMsg->xMsgHeader.msgFlags = 0;
+	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_SET_LEVEL_REQ;
+	pMsg->xMsgHeader.msgLength = (u16) totalLen;
+	pMsg->msgData[0] = PinNum;
+	pMsg->msgData[1] = NewLevel;
+
+	/* Send message to SMS */
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+			&coredev->gpio_set_level_done);
+
+	if (rc != 0) {
+		if (rc == -ETIME)
+			sms_err("smscore_gpio_set_level timeout");
+		else
+			sms_err("smscore_gpio_set_level error");
+	}
+	kfree(buffer);
+
+	return rc;
+}
+
+int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 *level) {
+
+	u32 totalLen;
+	int rc;
+	void *buffer;
+
+	struct SetGpioMsg {
+		struct SmsMsgHdr_ST xMsgHeader;
+		u32 msgData[2];
+	} *pMsg;
+
+
+	if (PinNum > MAX_GPIO_PIN_NUMBER)
+		return -EINVAL;
+
+	totalLen = sizeof(struct SmsMsgHdr_ST) + (2 * sizeof(u32));
+
+	buffer = kmalloc(totalLen + SMS_DMA_ALIGNMENT,
+			GFP_KERNEL | GFP_DMA);
+	if (!buffer)
+		return -ENOMEM;
+
+	pMsg = (struct SetGpioMsg *) SMS_ALIGN_ADDRESS(buffer);
+
+	pMsg->xMsgHeader.msgSrcId = DVBT_BDA_CONTROL_MSG_ID;
+	pMsg->xMsgHeader.msgDstId = HIF_TASK;
+	pMsg->xMsgHeader.msgFlags = 0;
+	pMsg->xMsgHeader.msgType = MSG_SMS_GPIO_GET_LEVEL_REQ;
+	pMsg->xMsgHeader.msgLength = (u16) totalLen;
+	pMsg->msgData[0] = PinNum;
+	pMsg->msgData[1] = 0;
+
+	/* Send message to SMS */
+	smsendian_handle_tx_message((struct SmsMsgHdr_ST *)pMsg);
+	rc = smscore_sendrequest_and_wait(coredev, pMsg, totalLen,
+			&coredev->gpio_get_level_done);
+
+	if (rc != 0) {
+		if (rc == -ETIME)
+			sms_err("smscore_gpio_get_level timeout");
+		else
+			sms_err("smscore_gpio_get_level error");
+	}
+	kfree(buffer);
+
+	/* Its a race between other gpio_get_level() and the copy of the single
+	 * global 'coredev->gpio_get_res' to  the function's variable 'level'
+	 */
+	*level = coredev->gpio_get_res;
+
+	return rc;
 }
 
 static int __init smscore_module_init(void)
diff -r 08e292f80f37 -r 749c11a362a9 linux/drivers/media/dvb/siano/smscoreapi.h
--- a/linux/drivers/media/dvb/siano/smscoreapi.h	Tue May 19 16:30:40 2009 +0300
+++ b/linux/drivers/media/dvb/siano/smscoreapi.h	Tue May 19 17:49:30 2009 +0300
@@ -550,7 +550,7 @@  struct SMSHOSTLIB_I2C_RES_ST {
 };
 
 
-struct smscore_gpio_config {
+struct smscore_config_gpio {
 #define SMS_GPIO_DIRECTION_INPUT  0
 #define SMS_GPIO_DIRECTION_OUTPUT 1
 	u8 direction;
@@ -574,6 +574,48 @@  struct smscore_gpio_config {
 #define SMS_GPIO_OUTPUTDRIVING_12mA 2
 #define SMS_GPIO_OUTPUTDRIVING_16mA 3
 	u8 outputdriving;
+};
+
+struct smscore_gpio_config {
+#define SMS_GPIO_DIRECTION_INPUT  0
+#define SMS_GPIO_DIRECTION_OUTPUT 1
+	u8 Direction;
+
+#define SMS_GPIO_PULLUPDOWN_NONE     0
+#define SMS_GPIO_PULLUPDOWN_PULLDOWN 1
+#define SMS_GPIO_PULLUPDOWN_PULLUP   2
+#define SMS_GPIO_PULLUPDOWN_KEEPER   3
+	u8 PullUpDown;
+
+#define SMS_GPIO_INPUT_CHARACTERISTICS_NORMAL  0
+#define SMS_GPIO_INPUT_CHARACTERISTICS_SCHMITT 1
+	u8 InputCharacteristics;
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_SLOW		1 /* 10xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_FAST		0 /* 10xx */
+
+
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_45_V_NS	0 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_0_9_V_NS	1 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_1_7_V_NS	2 /* 11xx */
+#define SMS_GPIO_OUTPUT_SLEW_RATE_3_3_V_NS	3 /* 11xx */
+	u8 OutputSlewRate;
+
+#define SMS_GPIO_OUTPUT_DRIVING_S_4mA		0 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_8mA		1 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_12mA		2 /* 10xx */
+#define SMS_GPIO_OUTPUT_DRIVING_S_16mA		3 /* 10xx */
+
+#define SMS_GPIO_OUTPUT_DRIVING_1_5mA		0 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_2_8mA		1 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_4mA			2 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_7mA			3 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_10mA			4 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_11mA			5 /* 11xx */
+#define SMS_GPIO_OUTPUT_DRIVING_14mA			6 /* 11xx */
+#undef SMS_GPIO_OUTPUT_DRIVING_16mA
+#define SMS_GPIO_OUTPUT_DRIVING_16mA			7 /* 11xx */
+	u8 OutputDriving;
 };
 
 extern void smscore_registry_setmode(char *devpath, int mode);
@@ -619,9 +661,18 @@  extern void smscore_putbuffer(struct sms
 extern void smscore_putbuffer(struct smscore_device_t *coredev,
 			      struct smscore_buffer_t *cb);
 
+/* old GPIO managment */
 int smscore_configure_gpio(struct smscore_device_t *coredev, u32 pin,
-			   struct smscore_gpio_config *pinconfig);
+			   struct smscore_config_gpio *pinconfig);
 int smscore_set_gpio(struct smscore_device_t *coredev, u32 pin, int level);
+
+/* new GPIO managment */
+extern int smscore_gpio_configure(struct smscore_device_t *coredev, u8 PinNum,
+		struct smscore_gpio_config *pGpioConfig);
+extern int smscore_gpio_set_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 NewLevel);
+extern int smscore_gpio_get_level(struct smscore_device_t *coredev, u8 PinNum,
+		u8 *level);
 
 void smscore_set_board_id(struct smscore_device_t *core, int id);
 int smscore_get_board_id(struct smscore_device_t *core);