Commit f4742e1d authored by Sean Young's avatar Sean Young Committed by Mauro Carvalho Chehab

[media] winbond-cir: use sysfs wakeup filter

Now that we can select the exact variant of the protocol for wakeup
filter, the winbond-cir can use the wakeup filter rather than module
parameters.
Signed-off-by: default avatarSean Young <sean@mess.org>
Cc: David Härdeman <david@hardeman.nu>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@s-opensource.com>
parent 6eae57e9
...@@ -190,7 +190,6 @@ enum wbcir_txstate { ...@@ -190,7 +190,6 @@ enum wbcir_txstate {
#define WBCIR_NAME "Winbond CIR" #define WBCIR_NAME "Winbond CIR"
#define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */ #define WBCIR_ID_FAMILY 0xF1 /* Family ID for the WPCD376I */
#define WBCIR_ID_CHIP 0x04 /* Chip ID for the WPCD376I */ #define WBCIR_ID_CHIP 0x04 /* Chip ID for the WPCD376I */
#define INVALID_SCANCODE 0x7FFFFFFF /* Invalid with all protos */
#define WAKEUP_IOMEM_LEN 0x10 /* Wake-Up I/O Reg Len */ #define WAKEUP_IOMEM_LEN 0x10 /* Wake-Up I/O Reg Len */
#define EHFUNC_IOMEM_LEN 0x10 /* Enhanced Func I/O Reg Len */ #define EHFUNC_IOMEM_LEN 0x10 /* Enhanced Func I/O Reg Len */
#define SP_IOMEM_LEN 0x08 /* Serial Port 3 (IR) Reg Len */ #define SP_IOMEM_LEN 0x08 /* Serial Port 3 (IR) Reg Len */
...@@ -221,10 +220,6 @@ struct wbcir_data { ...@@ -221,10 +220,6 @@ struct wbcir_data {
u32 txcarrier; u32 txcarrier;
}; };
static enum wbcir_protocol protocol = IR_PROTOCOL_RC6;
module_param(protocol, uint, 0444);
MODULE_PARM_DESC(protocol, "IR protocol to use for the power-on command (0 = RC5, 1 = NEC, 2 = RC6A, default)");
static bool invert; /* default = 0 */ static bool invert; /* default = 0 */
module_param(invert, bool, 0444); module_param(invert, bool, 0444);
MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver"); MODULE_PARM_DESC(invert, "Invert the signal from the IR receiver");
...@@ -233,15 +228,6 @@ static bool txandrx; /* default = 0 */ ...@@ -233,15 +228,6 @@ static bool txandrx; /* default = 0 */
module_param(txandrx, bool, 0444); module_param(txandrx, bool, 0444);
MODULE_PARM_DESC(txandrx, "Allow simultaneous TX and RX"); MODULE_PARM_DESC(txandrx, "Allow simultaneous TX and RX");
static unsigned int wake_sc = 0x800F040C;
module_param(wake_sc, uint, 0644);
MODULE_PARM_DESC(wake_sc, "Scancode of the power-on IR command");
static unsigned int wake_rc6mode = 6;
module_param(wake_rc6mode, uint, 0644);
MODULE_PARM_DESC(wake_rc6mode, "RC6 mode for the power-on command (0 = 0, 6 = 6A, default)");
/***************************************************************************** /*****************************************************************************
* *
...@@ -692,80 +678,96 @@ wbcir_shutdown(struct pnp_dev *device) ...@@ -692,80 +678,96 @@ wbcir_shutdown(struct pnp_dev *device)
{ {
struct device *dev = &device->dev; struct device *dev = &device->dev;
struct wbcir_data *data = pnp_get_drvdata(device); struct wbcir_data *data = pnp_get_drvdata(device);
struct rc_dev *rc = data->dev;
bool do_wake = true; bool do_wake = true;
u8 match[11]; u8 match[11];
u8 mask[11]; u8 mask[11];
u8 rc6_csl = 0; u8 rc6_csl = 0;
u8 proto;
u32 wake_sc = rc->scancode_wakeup_filter.data;
u32 mask_sc = rc->scancode_wakeup_filter.mask;
int i; int i;
memset(match, 0, sizeof(match)); memset(match, 0, sizeof(match));
memset(mask, 0, sizeof(mask)); memset(mask, 0, sizeof(mask));
if (wake_sc == INVALID_SCANCODE || !device_may_wakeup(dev)) { if (!mask_sc || !device_may_wakeup(dev)) {
do_wake = false; do_wake = false;
goto finish; goto finish;
} }
switch (protocol) { switch (rc->wakeup_protocol) {
case IR_PROTOCOL_RC5: case RC_TYPE_RC5:
if (wake_sc > 0xFFF) {
do_wake = false;
dev_err(dev, "RC5 - Invalid wake scancode\n");
break;
}
/* Mask = 13 bits, ex toggle */ /* Mask = 13 bits, ex toggle */
mask[0] = 0xFF; mask[0] = (mask_sc & 0x003f);
mask[1] = 0x17; mask[0] |= (mask_sc & 0x0300) >> 2;
mask[1] = (mask_sc & 0x1c00) >> 10;
if (mask_sc & 0x0040) /* 2nd start bit */
match[1] |= 0x10;
match[0] = (wake_sc & 0x003F); /* 6 command bits */ match[0] = (wake_sc & 0x003F); /* 6 command bits */
match[0] |= (wake_sc & 0x0180) >> 1; /* 2 address bits */ match[0] |= (wake_sc & 0x0300) >> 2; /* 2 address bits */
match[1] = (wake_sc & 0x0E00) >> 9; /* 3 address bits */ match[1] = (wake_sc & 0x1c00) >> 10; /* 3 address bits */
if (!(wake_sc & 0x0040)) /* 2nd start bit */ if (!(wake_sc & 0x0040)) /* 2nd start bit */
match[1] |= 0x10; match[1] |= 0x10;
proto = IR_PROTOCOL_RC5;
break; break;
case IR_PROTOCOL_NEC: case RC_TYPE_NEC:
if (wake_sc > 0xFFFFFF) { mask[1] = bitrev8(mask_sc);
do_wake = false; mask[0] = mask[1];
dev_err(dev, "NEC - Invalid wake scancode\n"); mask[3] = bitrev8(mask_sc >> 8);
mask[2] = mask[3];
match[1] = bitrev8(wake_sc);
match[0] = ~match[1];
match[3] = bitrev8(wake_sc >> 8);
match[2] = ~match[3];
proto = IR_PROTOCOL_NEC;
break; break;
}
mask[0] = mask[1] = mask[2] = mask[3] = 0xFF; case RC_TYPE_NECX:
mask[1] = bitrev8(mask_sc);
mask[0] = mask[1];
mask[2] = bitrev8(mask_sc >> 8);
mask[3] = bitrev8(mask_sc >> 16);
match[1] = bitrev8((wake_sc & 0xFF)); match[1] = bitrev8(wake_sc);
match[0] = ~match[1]; match[0] = ~match[1];
match[2] = bitrev8(wake_sc >> 8);
match[3] = bitrev8(wake_sc >> 16);
match[3] = bitrev8((wake_sc & 0xFF00) >> 8); proto = IR_PROTOCOL_NEC;
if (wake_sc > 0xFFFF)
match[2] = bitrev8((wake_sc & 0xFF0000) >> 16);
else
match[2] = ~match[3];
break; break;
case IR_PROTOCOL_RC6: case RC_TYPE_NEC32:
mask[0] = bitrev8(mask_sc);
mask[1] = bitrev8(mask_sc >> 8);
mask[2] = bitrev8(mask_sc >> 16);
mask[3] = bitrev8(mask_sc >> 24);
if (wake_rc6mode == 0) { match[0] = bitrev8(wake_sc);
if (wake_sc > 0xFFFF) { match[1] = bitrev8(wake_sc >> 8);
do_wake = false; match[2] = bitrev8(wake_sc >> 16);
dev_err(dev, "RC6 - Invalid wake scancode\n"); match[3] = bitrev8(wake_sc >> 24);
proto = IR_PROTOCOL_NEC;
break; break;
}
case RC_TYPE_RC6_0:
/* Command */ /* Command */
match[0] = wbcir_to_rc6cells(wake_sc >> 0); match[0] = wbcir_to_rc6cells(wake_sc >> 0);
mask[0] = 0xFF; mask[0] = wbcir_to_rc6cells(mask_sc >> 0);
match[1] = wbcir_to_rc6cells(wake_sc >> 4); match[1] = wbcir_to_rc6cells(wake_sc >> 4);
mask[1] = 0xFF; mask[1] = wbcir_to_rc6cells(mask_sc >> 4);
/* Address */ /* Address */
match[2] = wbcir_to_rc6cells(wake_sc >> 8); match[2] = wbcir_to_rc6cells(wake_sc >> 8);
mask[2] = 0xFF; mask[2] = wbcir_to_rc6cells(mask_sc >> 8);
match[3] = wbcir_to_rc6cells(wake_sc >> 12); match[3] = wbcir_to_rc6cells(wake_sc >> 12);
mask[3] = 0xFF; mask[3] = wbcir_to_rc6cells(mask_sc >> 12);
/* Header */ /* Header */
match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */ match[4] = 0x50; /* mode1 = mode0 = 0, ignore toggle */
...@@ -774,41 +776,46 @@ wbcir_shutdown(struct pnp_dev *device) ...@@ -774,41 +776,46 @@ wbcir_shutdown(struct pnp_dev *device)
mask[5] = 0x0F; mask[5] = 0x0F;
rc6_csl = 44; rc6_csl = 44;
proto = IR_PROTOCOL_RC6;
break;
} else if (wake_rc6mode == 6) { case RC_TYPE_RC6_6A_24:
case RC_TYPE_RC6_6A_32:
case RC_TYPE_RC6_MCE:
i = 0; i = 0;
/* Command */ /* Command */
match[i] = wbcir_to_rc6cells(wake_sc >> 0); match[i] = wbcir_to_rc6cells(wake_sc >> 0);
mask[i++] = 0xFF; mask[i++] = wbcir_to_rc6cells(mask_sc >> 0);
match[i] = wbcir_to_rc6cells(wake_sc >> 4); match[i] = wbcir_to_rc6cells(wake_sc >> 4);
mask[i++] = 0xFF; mask[i++] = wbcir_to_rc6cells(mask_sc >> 4);
/* Address + Toggle */ /* Address + Toggle */
match[i] = wbcir_to_rc6cells(wake_sc >> 8); match[i] = wbcir_to_rc6cells(wake_sc >> 8);
mask[i++] = 0xFF; mask[i++] = wbcir_to_rc6cells(mask_sc >> 8);
match[i] = wbcir_to_rc6cells(wake_sc >> 12); match[i] = wbcir_to_rc6cells(wake_sc >> 12);
mask[i++] = 0x3F; mask[i++] = wbcir_to_rc6cells(mask_sc >> 12);
/* Customer bits 7 - 0 */ /* Customer bits 7 - 0 */
match[i] = wbcir_to_rc6cells(wake_sc >> 16); match[i] = wbcir_to_rc6cells(wake_sc >> 16);
mask[i++] = 0xFF; mask[i++] = wbcir_to_rc6cells(mask_sc >> 16);
if (rc->wakeup_protocol == RC_TYPE_RC6_6A_20) {
rc6_csl = 52;
} else {
match[i] = wbcir_to_rc6cells(wake_sc >> 20); match[i] = wbcir_to_rc6cells(wake_sc >> 20);
mask[i++] = 0xFF; mask[i++] = wbcir_to_rc6cells(mask_sc >> 20);
if (wake_sc & 0x80000000) { if (rc->wakeup_protocol == RC_TYPE_RC6_6A_24) {
rc6_csl = 60;
} else {
/* Customer range bit and bits 15 - 8 */ /* Customer range bit and bits 15 - 8 */
match[i] = wbcir_to_rc6cells(wake_sc >> 24); match[i] = wbcir_to_rc6cells(wake_sc >> 24);
mask[i++] = 0xFF; mask[i++] = wbcir_to_rc6cells(mask_sc >> 24);
match[i] = wbcir_to_rc6cells(wake_sc >> 28); match[i] = wbcir_to_rc6cells(wake_sc >> 28);
mask[i++] = 0xFF; mask[i++] = wbcir_to_rc6cells(mask_sc >> 28);
rc6_csl = 76; rc6_csl = 76;
} else if (wake_sc <= 0x007FFFFF) { }
rc6_csl = 60;
} else {
do_wake = false;
dev_err(dev, "RC6 - Invalid wake scancode\n");
break;
} }
/* Header */ /* Header */
...@@ -816,14 +823,8 @@ wbcir_shutdown(struct pnp_dev *device) ...@@ -816,14 +823,8 @@ wbcir_shutdown(struct pnp_dev *device)
mask[i++] = 0xFF; mask[i++] = 0xFF;
match[i] = 0x0A; /* start bit = 1, mode2 = 1 */ match[i] = 0x0A; /* start bit = 1, mode2 = 1 */
mask[i++] = 0x0F; mask[i++] = 0x0F;
proto = IR_PROTOCOL_RC6;
} else {
do_wake = false;
dev_err(dev, "RC6 - Invalid wake mode\n");
}
break; break;
default: default:
do_wake = false; do_wake = false;
break; break;
...@@ -851,7 +852,8 @@ wbcir_shutdown(struct pnp_dev *device) ...@@ -851,7 +852,8 @@ wbcir_shutdown(struct pnp_dev *device)
wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07); wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_EV_EN, 0x01, 0x07);
/* Set CEIR_EN */ /* Set CEIR_EN */
wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, 0x01, 0x01); wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL,
(proto << 4) | 0x01, 0x31);
} else { } else {
/* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */ /* Clear BUFF_EN, Clear END_EN, Clear MATCH_EN */
...@@ -871,6 +873,15 @@ wbcir_shutdown(struct pnp_dev *device) ...@@ -871,6 +873,15 @@ wbcir_shutdown(struct pnp_dev *device)
disable_irq(data->irq); disable_irq(data->irq);
} }
/*
* Wakeup handling is done on shutdown.
*/
static int
wbcir_set_wakeup_filter(struct rc_dev *rc, struct rc_scancode_filter *filter)
{
return 0;
}
static int static int
wbcir_suspend(struct pnp_dev *device, pm_message_t state) wbcir_suspend(struct pnp_dev *device, pm_message_t state)
{ {
...@@ -883,16 +894,11 @@ wbcir_suspend(struct pnp_dev *device, pm_message_t state) ...@@ -883,16 +894,11 @@ wbcir_suspend(struct pnp_dev *device, pm_message_t state)
static void static void
wbcir_init_hw(struct wbcir_data *data) wbcir_init_hw(struct wbcir_data *data)
{ {
u8 tmp;
/* Disable interrupts */ /* Disable interrupts */
wbcir_set_irqmask(data, WBCIR_IRQ_NONE); wbcir_set_irqmask(data, WBCIR_IRQ_NONE);
/* Set PROT_SEL, RX_INV, Clear CEIR_EN (needed for the led) */ /* Set RX_INV, Clear CEIR_EN (needed for the led) */
tmp = protocol << 4; wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_CTL, invert ? 8 : 0, 0x09);
if (invert)
tmp |= 0x08;
outb(tmp, data->wbase + WBCIR_REG_WCEIR_CTL);
/* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */ /* Clear status bits NEC_REP, BUFF, MSG_END, MATCH */
wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17); wbcir_set_bits(data->wbase + WBCIR_REG_WCEIR_STS, 0x17, 0x17);
...@@ -1080,6 +1086,14 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id) ...@@ -1080,6 +1086,14 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
data->dev->timeout = MS_TO_NS(100); data->dev->timeout = MS_TO_NS(100);
data->dev->rx_resolution = US_TO_NS(2); data->dev->rx_resolution = US_TO_NS(2);
data->dev->allowed_protocols = RC_BIT_ALL; data->dev->allowed_protocols = RC_BIT_ALL;
data->dev->allowed_wakeup_protocols = RC_BIT_NEC | RC_BIT_NECX |
RC_BIT_NEC32 | RC_BIT_RC5 | RC_BIT_RC6_0 |
RC_BIT_RC6_6A_20 | RC_BIT_RC6_6A_24 |
RC_BIT_RC6_6A_32 | RC_BIT_RC6_MCE;
data->dev->wakeup_protocol = RC_TYPE_RC6_MCE;
data->dev->scancode_wakeup_filter.data = 0x800f040c;
data->dev->scancode_wakeup_filter.mask = 0xffff7fff;
data->dev->s_wakeup_filter = wbcir_set_wakeup_filter;
err = rc_register_device(data->dev); err = rc_register_device(data->dev);
if (err) if (err)
...@@ -1195,15 +1209,6 @@ wbcir_init(void) ...@@ -1195,15 +1209,6 @@ wbcir_init(void)
{ {
int ret; int ret;
switch (protocol) {
case IR_PROTOCOL_RC5:
case IR_PROTOCOL_NEC:
case IR_PROTOCOL_RC6:
break;
default:
pr_err("Invalid power-on protocol\n");
}
ret = pnp_register_driver(&wbcir_driver); ret = pnp_register_driver(&wbcir_driver);
if (ret) if (ret)
pr_err("Unable to register driver\n"); pr_err("Unable to register driver\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment