From ad84c75d1423da5c5d0b9166b29c66622697ef37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Th=C3=A9baudeau?= Date: Thu, 9 Nov 2017 15:58:43 +0100 Subject: [PATCH] amlogic: remote: Add support for Sony SIRC 12/15/20 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Contrary to most IR RC protocols, the Sony SIRC frames end with a data bit, not with a trailer pulse, which triggers the following bugs in the hardware IR decoder because it relies on pulse intervals instead of pulse widths: - The last data bit (msb) cannot be read properly. It can only be dropped, in which case it is always returned as 0, or forcibly read by using an abnormally long maximum frame duration and ignoring the logic 1 timings, in which case it is stuck to 1. This implementation chooses to drop the msb because it is part of the device ID, so this limitation is very unlikely to cause any trouble. - The repeat maximum frame interval in AO_MF_IR_DEC_REG3 is ignored. Consequently, if the same RC key is pressed twice in a row, the decoder reports the second key press as a repeat event, even if there is a very long time between the key presses. This implementation works around this bug by considering reported repeat events as actual normal events if they occur more than a given time after the previous event. In order to support the SIRC protocol without any limitation, a software decoder would have to be used with the general time measurement mode. To this end, an equivalent of drivers/amlogic/input/remote/remote_decoder_xmp.c for SIRC could be derived from drivers/media/rc/ir-sony-decoder.c. Signed-off-by: Benoît Thébaudeau --- drivers/amlogic/input/remote/remote_meson.h | 1 + drivers/amlogic/input/remote/remote_regmap.c | 144 +++++++++++++++++++ include/dt-bindings/input/meson_rc.h | 3 + 3 files changed, 148 insertions(+) diff --git a/drivers/amlogic/input/remote/remote_meson.h b/drivers/amlogic/input/remote/remote_meson.h index a91e5d6ca1203..c56e11de76aea 100644 --- a/drivers/amlogic/input/remote/remote_meson.h +++ b/drivers/amlogic/input/remote/remote_meson.h @@ -119,6 +119,7 @@ struct remote_chip { struct ir_map_tab_list *cur_tab; int custom_num; struct key_number key_num; + unsigned long repeat_max_jiffies; int decode_status; int sys_custom_code; const char *keymap_name; diff --git a/drivers/amlogic/input/remote/remote_regmap.c b/drivers/amlogic/input/remote/remote_regmap.c index 17a7c623b390e..f62b1d1b745cc 100644 --- a/drivers/amlogic/input/remote/remote_regmap.c +++ b/drivers/amlogic/input/remote/remote_regmap.c @@ -145,6 +145,84 @@ static struct remote_reg_map regs_default_toshiba[] = { { REG_DURATN3 , 0x00} }; +static struct remote_reg_map regs_default_sony_sirc12[] = { + /* (4 +/- .5) * 600 us */ + { REG_LDR_ACTIVE, 135 << 16 | 105 << 0 }, + /* (1 +/- .5) * 600 us */ + { REG_LDR_IDLE, 45 << 16 | 15 << 0 }, + /* No repeat code */ + { REG_LDR_REPEAT, 0 }, + /* (2 +/- .5) * 600 us */ + { REG_BIT_0, 75 << 16 | 45 << 0 }, + /* + * Filter: 140 us, max frame time: (4.5 + 1.5 + 12 * 3.5) * 600 us, + * base time: 20 us + */ + { REG_REG0, 7 << 28 | 1440 << 12 | (20 - 1) }, + /* Logic "1": (3 +/- .5) * 600 us */ + { REG_STATUS, 1 << 30 | 105 << 20 | 75 << 10 }, + /* Decoder, frame body limited to 11 bits because of IP erratum */ + { REG_REG1, 1 << 15 | (11 - 1) << 8 }, + /* Check repeat time, compare frames for repeat, lsb first, Sony SIRC */ + { REG_REG2, 1 << 12 | 1 << 11 | 0 << 8 | 0x6 }, + { REG_DURATN2, 0 }, + { REG_DURATN3, 0 }, + /* Repeat max frame interval: 50 ms */ + { REG_REG3, 500 }, +}; + +static struct remote_reg_map regs_default_sony_sirc15[] = { + /* (4 +/- .5) * 600 us */ + { REG_LDR_ACTIVE, 135 << 16 | 105 << 0 }, + /* (1 +/- .5) * 600 us */ + { REG_LDR_IDLE, 45 << 16 | 15 << 0 }, + /* No repeat code */ + { REG_LDR_REPEAT, 0 }, + /* (2 +/- .5) * 600 us */ + { REG_BIT_0, 75 << 16 | 45 << 0 }, + /* + * Filter: 140 us, max frame time: (4.5 + 1.5 + 15 * 3.5) * 600 us, + * base time: 20 us + */ + { REG_REG0, 7 << 28 | 1755 << 12 | (20 - 1) }, + /* Logic "1": (3 +/- .5) * 600 us */ + { REG_STATUS, 1 << 30 | 105 << 20 | 75 << 10 }, + /* Decoder, frame body limited to 14 bits because of IP erratum */ + { REG_REG1, 1 << 15 | (14 - 1) << 8 }, + /* Check repeat time, compare frames for repeat, lsb first, Sony SIRC */ + { REG_REG2, 1 << 12 | 1 << 11 | 0 << 8 | 0x6 }, + { REG_DURATN2, 0 }, + { REG_DURATN3, 0 }, + /* Repeat max frame interval: 50 ms */ + { REG_REG3, 500 }, +}; + +static struct remote_reg_map regs_default_sony_sirc20[] = { + /* (4 +/- .5) * 600 us */ + { REG_LDR_ACTIVE, 135 << 16 | 105 << 0 }, + /* (1 +/- .5) * 600 us */ + { REG_LDR_IDLE, 45 << 16 | 15 << 0 }, + /* No repeat code */ + { REG_LDR_REPEAT, 0 }, + /* (2 +/- .5) * 600 us */ + { REG_BIT_0, 75 << 16 | 45 << 0 }, + /* + * Filter: 140 us, max frame time: (4.5 + 1.5 + 20 * 3.5) * 600 us, + * base time: 20 us + */ + { REG_REG0, 7 << 28 | 2280 << 12 | (20 - 1) }, + /* Logic "1": (3 +/- .5) * 600 us */ + { REG_STATUS, 1 << 30 | 105 << 20 | 75 << 10 }, + /* Decoder, frame body limited to 19 bits because of IP erratum */ + { REG_REG1, 1 << 15 | (19 - 1) << 8 }, + /* Check repeat time, compare frames for repeat, lsb first, Sony SIRC */ + { REG_REG2, 1 << 12 | 1 << 11 | 0 << 8 | 0x6 }, + { REG_DURATN2, 0 }, + { REG_DURATN3, 0 }, + /* Repeat max frame interval: 50 ms */ + { REG_REG3, 500 }, +}; + void set_hardcode(struct remote_chip *chip, int code) { remote_dbg(chip->dev, "framecode=0x%x\n", code); @@ -462,6 +540,39 @@ static u32 ir_toshiba_get_custom_code(struct remote_chip *chip) return custom_code; } +static int ir_sony_sirc_get_scancode(struct remote_chip *chip) +{ + int code = 0; + int decode_status = 0; + int status = 0; + + remote_reg_read(chip, MULTI_IR_ID, REG_STATUS, &decode_status); + if (decode_status & 0x01 && + !time_is_before_eq_jiffies(chip->repeat_max_jiffies)) + status |= REMOTE_REPEAT; + /* + * Workaround for IP erratum causing the repeat max frame interval in + * REG3 to be ignored for SIRC + */ + chip->repeat_max_jiffies = jiffies + msecs_to_jiffies(60); + chip->decode_status = status; /*set decode status*/ + remote_reg_read(chip, MULTI_IR_ID, REG_FRAME, &code); + remote_dbg(chip->dev, "framecode=0x%x\n", code); + chip->r_dev->cur_hardcode = code; + code &= 0x7f; + return code; +} + +static int ir_sony_sirc_get_decode_status(struct remote_chip *chip) +{ + return chip->decode_status; +} + +static u32 ir_sony_sirc_get_custom_code(struct remote_chip *chip) +{ + return chip->r_dev->cur_hardcode >> 7; +} + /*legacy IR controller support protocols*/ static struct aml_remote_reg_proto reg_legacy_nec = { @@ -555,6 +666,36 @@ static struct aml_remote_reg_proto reg_toshiba = { .get_custom_code = ir_toshiba_get_custom_code, }; +static struct aml_remote_reg_proto reg_sony_sirc12 = { + .protocol = REMOTE_TYPE_SONY_SIRC12, + .name = "SONY_SIRC12", + .reg_map = regs_default_sony_sirc12, + .reg_map_size = ARRAY_SIZE(regs_default_sony_sirc12), + .get_scancode = ir_sony_sirc_get_scancode, + .get_decode_status = ir_sony_sirc_get_decode_status, + .get_custom_code = ir_sony_sirc_get_custom_code, +}; + +static struct aml_remote_reg_proto reg_sony_sirc15 = { + .protocol = REMOTE_TYPE_SONY_SIRC15, + .name = "SONY_SIRC15", + .reg_map = regs_default_sony_sirc15, + .reg_map_size = ARRAY_SIZE(regs_default_sony_sirc15), + .get_scancode = ir_sony_sirc_get_scancode, + .get_decode_status = ir_sony_sirc_get_decode_status, + .get_custom_code = ir_sony_sirc_get_custom_code, +}; + +static struct aml_remote_reg_proto reg_sony_sirc20 = { + .protocol = REMOTE_TYPE_SONY_SIRC20, + .name = "SONY_SIRC20", + .reg_map = regs_default_sony_sirc20, + .reg_map_size = ARRAY_SIZE(regs_default_sony_sirc20), + .get_scancode = ir_sony_sirc_get_scancode, + .get_decode_status = ir_sony_sirc_get_decode_status, + .get_custom_code = ir_sony_sirc_get_custom_code, +}; + const struct aml_remote_reg_proto *remote_reg_proto[] = { ®_nec, @@ -566,6 +707,9 @@ const struct aml_remote_reg_proto *remote_reg_proto[] = { ®_rc6, ®_legacy_nec, ®_toshiba, + ®_sony_sirc12, + ®_sony_sirc15, + ®_sony_sirc20, NULL }; diff --git a/include/dt-bindings/input/meson_rc.h b/include/dt-bindings/input/meson_rc.h index 32cb61961f6aa..7cba3f7fd7b92 100644 --- a/include/dt-bindings/input/meson_rc.h +++ b/include/dt-bindings/input/meson_rc.h @@ -22,6 +22,9 @@ #define REMOTE_TYPE_RC5 0x04 #define REMOTE_TYPE_RC6 0x05 #define REMOTE_TYPE_TOSHIBA 0x06 +#define REMOTE_TYPE_SONY_SIRC12 0x07 +#define REMOTE_TYPE_SONY_SIRC15 0x08 +#define REMOTE_TYPE_SONY_SIRC20 0x09 /*hardware decode one protocol by using legacy IR controller*/ #define REMOTE_TYPE_LEGACY_NEC 0xff