#define REMOTE_IOC_SET_KEY_MAPPING_TAB _IOW('I', 4, __u32)
#define REMOTE_IOC_SET_SW_DECODE_PARA _IOW('I', 5, __u32)
#define REMOTE_IOC_GET_DATA_VERSION _IOR('I', 121, __u32)
+#define REMOTE_IOC_SET_IR_LEARNING _IOW('I', 6, __u32)
+#define REMOTE_IOC_GET_IR_LEARNING _IOR('I', 7, __u32)
+#define REMOTE_IOC_GET_RAW_DATA _IOR('I', 8, __u32)
+#define REMOTE_IOC_GET_SUM_CNT0 _IOR('I', 9, __u32)
+#define REMOTE_IOC_GET_SUM_CNT1 _IOR('I', 10, __u32)
#endif
void __user *parg = (void __user *)arg;
unsigned long flags;
u32 value;
+ u8 val;
int retval = 0;
if (!parg) {
}
chip->r_dev->max_frame_time = sw_data.max_frame_time;
break;
+ case REMOTE_IOC_GET_IR_LEARNING:
+ if (copy_to_user(parg, &chip->r_dev->ir_learning_on,
+ sizeof(u8))) {
+ retval = -EFAULT;
+ goto err;
+ }
+ break;
+
+ case REMOTE_IOC_SET_IR_LEARNING:
+ /*reset demudolation and carrier detect*/
+ if (chip->r_dev->demod_enable)
+ demod_reset(chip);
+
+ if (copy_from_user(&val, parg, sizeof(u8))) {
+ retval = -EFAULT;
+ goto err;
+ }
+
+ chip->r_dev->ir_learning_on = !!val;
+ if (!!val) {
+ if (remote_pulses_malloc(chip) < 0) {
+ retval = -ENOMEM;
+ goto err;
+ }
+ chip->set_register_config(chip, REMOTE_TYPE_RAW_NEC);
+ /*backup protocol*/
+ chip->r_dev->protocol = chip->protocol;
+ chip->protocol = REMOTE_TYPE_RAW_NEC;
+ } else {
+ chip->protocol = chip->r_dev->protocol;
+ chip->set_register_config(chip, chip->protocol);
+ remote_pulses_free(chip);
+ chip->r_dev->ir_learning_done = false;
+ }
+ break;
+
+ case REMOTE_IOC_GET_RAW_DATA:
+ if (copy_to_user(parg, chip->r_dev->pulses,
+ sizeof(struct pulse_group) +
+ chip->r_dev->max_learned_pulse *
+ sizeof(unsigned int))) {
+ retval = -EFAULT;
+ goto err;
+ }
+ /*clear to prepear next frame*/
+ memset(chip->r_dev->pulses, 0, sizeof(struct pulse_group) +
+ chip->r_dev->max_learned_pulse *
+ sizeof(unsigned int));
+
+ if (chip->r_dev->demod_enable)
+ demod_reset(chip);
+
+ /*finish reading data ,enable state machine */
+ remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15),
+ BIT(15));
+
+ chip->r_dev->ir_learning_done = false;
+
+ break;
+
+ case REMOTE_IOC_GET_SUM_CNT0:
+ if (chip->r_dev->demod_enable) {
+ remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT0,
+ &value);
+ if (copy_to_user(parg, &value, sizeof(u32))) {
+ retval = -EFAULT;
+ goto err;
+ }
+ } else {
+ retval = -EFAULT;
+ goto err;
+ }
+ break;
+
+ case REMOTE_IOC_GET_SUM_CNT1:
+ if (chip->r_dev->demod_enable) {
+ remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT1,
+ &value);
+ if (copy_to_user(parg, &value, sizeof(u32))) {
+ retval = -EFAULT;
+ goto err;
+ }
+ } else {
+ retval = -EFAULT;
+ goto err;
+ }
+ break;
default:
retval = -ENOTTY;
RAW_STOP_EVENT = (1 << 3),
};
-
+struct pulse_group {
+ int len;
+ /*bit 0-30 durations, bit31: level*/
+ unsigned int pulse[0];
+};
struct remote_raw_handle;
struct remote_dev {
unsigned long delay_off;
int led_blink;
+ /*for ir learnning feature*/
+#define MAX_LEARNED_PULSE 256
+ /*ir learnning switch*/
+ u8 ir_learning_on;
+ u8 ir_learning_done;
+ u8 demod_enable;
+ u8 use_fifo;
+ u8 auto_report;
+ int max_learned_pulse;
+ int protocol;
+ struct timer_list learning_done;
+ struct pulse_group *pulses;
+
struct timer_list timer_keyup;
unsigned long keyup_jiffies;
unsigned long keyup_delay;
#include <linux/pm_wakeirq.h>
static void amlremote_tasklet(unsigned long data);
-
+static void learning_done_workqueue(struct work_struct *work);
+static void get_fifo_data_work(struct work_struct *work);
DECLARE_TASKLET_DISABLED(tasklet, amlremote_tasklet, 0);
+static void learning_done_workqueue(struct work_struct *work)
+{
+ struct delayed_work *w = container_of(work, struct delayed_work, work);
+ struct remote_chip *chip =
+ container_of(w, struct remote_chip, ir_workqueue);
+ char *envp[2] = { "LEARN_DONE", NULL};
+
+ kobject_uevent_env(&chip->dev->kobj, KOBJ_CHANGE, envp);
+}
+
+int remote_pulses_malloc(struct remote_chip *chip)
+{
+ struct remote_dev *r_dev = chip->r_dev;
+ int len = r_dev->max_learned_pulse;
+ int ret = 0;
+
+ if (r_dev->pulses) {
+ dev_info(chip->dev, "ir learning pulse already exists\n");
+ return -EEXIST;
+ }
+
+ r_dev->pulses = kzalloc(sizeof(struct pulse_group) +
+ len * sizeof(unsigned int), GFP_KERNEL);
+
+ if (!r_dev->pulses) {
+ dev_err(chip->dev, "ir learning pulse alloc err\n");
+ ret = -ENOMEM;
+ }
+
+ return ret;
+}
+
+void remote_pulses_free(struct remote_chip *chip)
+{
+ struct remote_dev *r_dev = chip->r_dev;
+
+ kfree(r_dev->pulses);
+ r_dev->pulses = NULL;
+}
+
int remote_reg_read(struct remote_chip *chip, unsigned char id,
unsigned int reg, unsigned int *val)
{
return 0;
}
+int remote_reg_update_bits(struct remote_chip *chip, unsigned char id,
+ unsigned int reg, unsigned int mask, unsigned int val)
+{
+ int orig = 0;
+
+ remote_reg_read(chip, id, reg, &orig);
+ orig &= ~mask;
+ orig |= val & mask;
+ remote_reg_write(chip, id, reg, orig);
+
+ return 0;
+}
+
int ir_scancode_sort(struct ir_map_tab *ir_map)
{
bool is_sorted;
}
+static void get_fifo_data_work(struct work_struct *work)
+{
+ struct remote_chip *chip =
+ container_of(work, struct remote_chip, fifo_work);
+ struct remote_dev *r_dev = chip->r_dev;
+ int val = 0;
+ int is_fifo_pending = 0;
+ int is_fifo_timeout = 0;
+ int is_fifo_empty = 0;
+ u32 duration = 0;
+
+ remote_reg_read(chip, MULTI_IR_ID, REG_FIFO, &val);
+ is_fifo_pending = (val >> 30) & 0x01;
+ is_fifo_timeout = (val >> 29) & 0x01;
+ is_fifo_empty = (val >> 27) & 0x01;
+
+ /*disable interrupt*/
+ remote_reg_update_bits(chip, MULTI_IR_ID, REG_FIFO, GENMASK(22, 23), 0);
+
+ if (is_fifo_pending || is_fifo_timeout) {
+ /*clear state*/
+ remote_reg_update_bits(chip, MULTI_IR_ID, REG_FIFO,
+ GENMASK(29, 30), GENMASK(29, 30));
+
+ for (; !is_fifo_empty; ) {
+
+ remote_reg_read(chip, MULTI_IR_ID, REG_WITH, &val);
+ val = val & GENMASK(12, 0);
+
+ duration = val;
+ r_dev->pulses->pulse[r_dev->pulses->len] = duration;
+
+ if (r_dev->pulses->len % 2 == 1)
+ r_dev->pulses->pulse[r_dev->pulses->len]
+ |= BIT(31);
+
+ r_dev->pulses->len++;
+
+ remote_reg_read(chip, MULTI_IR_ID, REG_FIFO, &val);
+ is_fifo_empty = (val >> 27) & 0x01;
+
+ }
+ }
+
+ /*enable interrupt*/
+ remote_reg_update_bits(chip, MULTI_IR_ID, REG_FIFO, GENMASK(22, 23),
+ GENMASK(22, 23));
+
+ if (r_dev->auto_report)
+ mod_timer(&r_dev->learning_done,
+ jiffies + msecs_to_jiffies(50));
+}
+
static irqreturn_t ir_interrupt(int irq, void *dev_id)
{
struct remote_chip *rc = (struct remote_chip *)dev_id;
+ struct remote_dev *r_dev = rc->r_dev;
+ struct pulse_group *pgs;
int contr_status = 0;
int val = 0;
u32 duration;
remote_reg_read(rc, MULTI_IR_ID, REG_REG1, &val);
val = (val & 0x1FFF0000) >> 16;
- sprintf(buf, "d:%d\n", val);
+ sprintf(buf, "duration:%d\n", val);
debug_log_printk(rc->r_dev, buf);
/**
*software decode multiple protocols by using Time Measurement of
*multif-format IR controller
*/
+
+ if (r_dev->ir_learning_on && !r_dev->ir_learning_done) {
+ pgs = r_dev->pulses;
+ if (pgs->len >= r_dev->max_learned_pulse) {
+ remote_reg_update_bits(rc, MULTI_IR_ID, REG_REG1,
+ BIT(15), 0);
+ return IRQ_HANDLED;
+ }
+ if (!r_dev->use_fifo) {
+ if (r_dev->auto_report)
+ mod_timer(&r_dev->learning_done,
+ jiffies + msecs_to_jiffies(50));
+ /*get pulse durations unit:10us*/
+ pgs->pulse[pgs->len] = val & GENMASK(30, 0);
+ /*get pulse level*/
+ remote_reg_read(rc, MULTI_IR_ID, REG_STATUS, &val);
+ val = !!((val >> 8) & 0x01);
+ pgs->pulse[pgs->len] &= ~BIT(31);
+ if (val)
+ pgs->pulse[pgs->len] |= BIT(31);
+
+ r_dev->pulses->len++;
+ } else {
+ schedule_work(&rc->fifo_work);
+ }
+ return IRQ_HANDLED;
+ }
+
if (MULTI_IR_SOFTWARE_DECODE(rc->protocol)) {
rc->ir_work = MULTI_IR_ID;
duration = val*10*1000;
}
dev_info(chip->dev, "led_blink_frq = %ld\n", chip->r_dev->delay_on);
+ ret = of_property_read_bool(pdev->dev.of_node, "demod_enable");
+ if (ret)
+ chip->r_dev->demod_enable = 1;
+
+ ret = of_property_read_bool(pdev->dev.of_node, "use_fifo");
+ if (ret)
+ chip->r_dev->use_fifo = 1;
+
+ ret = of_property_read_bool(pdev->dev.of_node, "auto_report");
+ if (ret)
+ chip->r_dev->auto_report = 1;
+
p = devm_pinctrl_get_select_default(&pdev->dev);
if (IS_ERR(p)) {
dev_err(chip->dev, "pinctrl error, %ld\n", PTR_ERR(p));
return 0;
}
+void demod_init(struct remote_chip *chip)
+{
+ int val;
+ unsigned int mask;
+
+ mask = GENMASK(29, 16) | BIT(31);
+ val = BIT(31) | (0x1FF << 16);
+
+ remote_reg_update_bits(chip, MULTI_IR_ID, REG_DEMOD_CNTL1, mask, val);
+}
+
+void demod_reset(struct remote_chip *chip)
+{
+ unsigned int mask;
+
+ mask = BIT(30);
+ remote_reg_update_bits(chip, MULTI_IR_ID, REG_DEMOD_CNTL0, mask, mask);
+}
+
+static void ir_learning_done(unsigned long cookie)
+{
+
+ struct remote_dev *dev = (struct remote_dev *)cookie;
+ struct remote_chip *chip = (struct remote_chip *) dev->platform_data;
+ unsigned long flags;
+
+ if (dev->pulses->len < 3) {
+ dev->pulses->len = 0;
+ return;
+ }
+
+ spin_lock_irqsave(&chip->slock, flags);
+ dev->ir_learning_done = true;
+ spin_unlock_irqrestore(&chip->slock, flags);
+
+ /*data recive done*/
+ remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15), 0);
+ schedule_delayed_work(&chip->ir_workqueue, msecs_to_jiffies(100));
+
+}
+
static int ir_hardware_init(struct platform_device *pdev)
{
int ret;
chip->r_dev->set_custom_code = set_custom_code;
chip->r_dev->is_valid_custom = is_valid_custom;
chip->r_dev->is_next_repeat = is_next_repeat;
+ chip->r_dev->max_learned_pulse = MAX_LEARNED_PULSE;
chip->set_register_config = ir_register_default_config;
platform_set_drvdata(pdev, chip);
led_trigger_register_simple("rc_feedback", &dev->led_feedback);
+ setup_timer(&dev->learning_done, ir_learning_done, (unsigned long)dev);
+ if (dev->demod_enable)
+ demod_init(chip);
+ INIT_DELAYED_WORK(&chip->ir_workqueue, learning_done_workqueue);
+ INIT_WORK(&chip->fifo_work, get_fifo_data_work);
return 0;
error_register_remote:
{
struct remote_chip *chip = dev_get_drvdata(dev);
+ if (chip->r_dev->ir_learning_on) {
+ cancel_work_sync(&chip->fifo_work);
+ del_timer_sync(&chip->r_dev->learning_done);
+ cancel_delayed_work_sync(&chip->ir_workqueue);
+ }
+
if (is_pm_freeze_mode())
return 0;
#define IR_DATA_IS_VALID(data) (data & 0x8)
#define IR_CONTROLLER_BUSY(x) ((x >> 7) & 0x1)
-
#define CURSOR_MOVE_ACCELERATE {0, 2, 2, 4, 4, 6, 8, 10, 12, 14, 16, 18}
+/*bit 31: enable fifo mode
+ * bit 21-23: time out/level trigger interrupt
+ * bit 13-20: trigger interrupt when receive specified numbers of pulse
+ * bit 0-12: trigger interrupt when time out
+ */
+#define FIFO_REG_VAL ((1 << 31) | (7 << 21) | (80 << 13) | (5000 << 0))
enum IR_CONTR_NUMBER {
MULTI_IR_ID = 0,
struct remote_range reg_duration;
char *dev_name;
int protocol;
+ struct delayed_work ir_workqueue;
+ struct work_struct fifo_work;
dev_t chr_devno;
struct class *chr_class;
};
enum remote_reg {
- REG_LDR_ACTIVE = 0x00 << 2,
- REG_LDR_IDLE = 0x01 << 2,
- REG_LDR_REPEAT = 0x02 << 2,
- REG_BIT_0 = 0x03 << 2,
- REG_REG0 = 0x04 << 2,
- REG_FRAME = 0x05 << 2,
- REG_STATUS = 0x06 << 2,
- REG_REG1 = 0x07 << 2,
- REG_REG2 = 0x08 << 2,
- REG_DURATN2 = 0x09 << 2,
- REG_DURATN3 = 0x0a << 2,
- REG_FRAME1 = 0x0b << 2,
- REG_STATUS1 = 0x0c << 2,
- REG_STATUS2 = 0x0d << 2,
- REG_REG3 = 0x0e << 2,
- REG_FRAME_RSV0 = 0x0f << 2,
- REG_FRAME_RSV1 = 0x10 << 2,
- REG_FILTE = 0x11 << 2,
- REG_IRQ_CTL = 0x12 << 2,
- REG_WIDTH_NEW = 0x14 << 2,
- REG_REPEAT_DET = 0x15 << 2
+ REG_LDR_ACTIVE = 0x00 << 2,
+ REG_LDR_IDLE = 0x01 << 2,
+ REG_LDR_REPEAT = 0x02 << 2,
+ REG_BIT_0 = 0x03 << 2,
+ REG_REG0 = 0x04 << 2,
+ REG_FRAME = 0x05 << 2,
+ REG_STATUS = 0x06 << 2,
+ REG_REG1 = 0x07 << 2,
+ REG_REG2 = 0x08 << 2,
+ REG_DURATN2 = 0x09 << 2,
+ REG_DURATN3 = 0x0a << 2,
+ REG_FRAME1 = 0x0b << 2,
+ REG_STATUS1 = 0x0c << 2,
+ REG_STATUS2 = 0x0d << 2,
+ REG_REG3 = 0x0e << 2,
+ REG_FRAME_RSV0 = 0x0f << 2,
+ REG_FRAME_RSV1 = 0x10 << 2,
+ REG_IRQ_CTL = 0x12 << 2,
+ REG_FIFO = 0x13 << 2,
+ REG_WITH = 0x14 << 2,
+ REG_REPEAT_DET = 0x15 << 2,
+ REG_DEMOD_CNTL0 = 0x20 << 2,
+ REG_DEMOD_CNTL1 = 0x21 << 2,
+ REG_DEMOD_IIR_THD = 0x22 << 2,
+ REG_DEMOD_THD0 = 0x23 << 2,
+ REG_DEMOD_THD1 = 0x24 << 2,
+ REG_DEMOD_SUM_CNT0 = 0x25 << 2,
+ REG_DEMOD_SUM_CNT1 = 0x26 << 2,
+ REG_DEMOD_CNT0 = 0x27 << 2,
+ REG_DEMOD_CNT1 = 0x28 << 2
};
int ir_register_default_config(struct remote_chip *chip, int type);
unsigned int reg, unsigned int *val);
int remote_reg_write(struct remote_chip *chip, unsigned char id,
unsigned int reg, unsigned int val);
+int remote_reg_update_bits(struct remote_chip *chip, unsigned char id,
+ unsigned int reg, unsigned int mask, unsigned int val);
int ir_scancode_sort(struct ir_map_tab *ir_map);
struct ir_map_tab_list *seek_map_tab(struct remote_chip *chip, int custom_code);
+const struct aml_remote_reg_proto **ir_get_proto_reg(void);
void ir_tab_free(struct ir_map_tab_list *ir_map_list);
-
+int remote_pulses_malloc(struct remote_chip *chip);
+void remote_pulses_free(struct remote_chip *chip);
+void demod_reset(struct remote_chip *chip);
+void demod_init(struct remote_chip *chip);
#endif
{ REG_LDR_IDLE, 0},
{ REG_LDR_REPEAT, 0},
{ REG_BIT_0, 0},
- { REG_REG0, ((3 << 28) | (0xFA0 << 12) | (9))},
+ { REG_REG0, ((7 << 28) | (0xFA0 << 12) | (9))},
{ REG_STATUS, 0},
{ REG_REG1, 0x8574},
{ REG_REG2, 0x02},
NULL
};
+const struct aml_remote_reg_proto **ir_get_proto_reg(void)
+{
+ return remote_reg_proto;
+}
+
static int ir_contr_init(struct remote_chip *chip, int type, unsigned char id)
{
const struct aml_remote_reg_proto **reg_proto = remote_reg_proto;
chip->ir_contr[id].get_custom_code = (*reg_proto)->get_custom_code;
chip->ir_contr[id].set_custom_code = (*reg_proto)->set_custom_code;
+ if (chip->r_dev->ir_learning_on && chip->r_dev->use_fifo)
+ remote_reg_write(chip, id, REG_FIFO, FIFO_REG_VAL);
+ else
+ remote_reg_write(chip, id, REG_FIFO, 0);
+
return 0;
}
struct device_attribute *attr, char *buf)
{
struct remote_chip *chip = dev_get_drvdata(dev);
+ const struct aml_remote_reg_proto **supported_proto =
+ ir_get_proto_reg();
+ int len;
if (ENABLE_LEGACY_IR(chip->protocol))
- return sprintf(buf, "protocol=%s&%s (0x%x)\n",
+ len = sprintf(buf, "current protocol = %s&%s (0x%x)\n",
chip->ir_contr[LEGACY_IR_ID].proto_name,
chip->ir_contr[MULTI_IR_ID].proto_name,
chip->protocol);
+ else
+ len = sprintf(buf, "currnet protocol = %s (0x%x)\n",
+ chip->ir_contr[MULTI_IR_ID].proto_name,
+ chip->protocol);
+
+ len += sprintf(buf + len, "supported protocol:\n");
+
+ for ( ; (*supported_proto) != NULL ; ) {
+ len += sprintf(buf + len, "%s (0x%x)\n",
+ ((*supported_proto)->name), ((*supported_proto)->protocol));
+ supported_proto++;
+ }
- return sprintf(buf, "protocol=%s (0x%x)\n",
- chip->ir_contr[MULTI_IR_ID].proto_name,
- chip->protocol);
+ return len;
}
static ssize_t protocol_store(struct device *dev,
return count;
}
+static ssize_t ir_learning_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+ struct remote_chip *chip = dev_get_drvdata(dev);
+ struct remote_dev *r_dev = chip->r_dev;
+
+ return sprintf(buf, "%d\n", r_dev->ir_learning_on);
+}
+
+static ssize_t ir_learning_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int ret = 0;
+ int val = 0;
+
+ struct remote_chip *chip = dev_get_drvdata(dev);
+ struct remote_dev *r_dev = chip->r_dev;
+
+ ret = kstrtoint(buf, 0, &val);
+ if (ret != 0)
+ return -EINVAL;
+ if (r_dev->ir_learning_on == val)
+ return count;
+
+ disable_irq(chip->irqno);
+ mutex_lock(&chip->file_lock);
+ r_dev->ir_learning_on = !!val;
+ if (!!val) {
+ if (r_dev->demod_enable)
+ demod_reset(chip);
+
+ if (remote_pulses_malloc(chip) < 0) {
+ mutex_unlock(&chip->file_lock);
+ enable_irq(chip->irqno);
+ return -ENOMEM;
+ }
+ chip->set_register_config(chip, REMOTE_TYPE_RAW_NEC);
+ r_dev->protocol = chip->protocol;/*backup protocol*/
+ chip->protocol = REMOTE_TYPE_RAW_NEC;
+ } else {
+ chip->protocol = r_dev->protocol;
+ chip->set_register_config(chip, chip->protocol);
+ remote_pulses_free(chip);
+ chip->r_dev->ir_learning_done = false;
+ }
+ mutex_unlock(&chip->file_lock);
+ enable_irq(chip->irqno);
+ return count;
+}
+
+static ssize_t learned_pulse_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int len = 0;
+ int i = 0;
+
+ struct remote_chip *chip = dev_get_drvdata(dev);
+ struct remote_dev *r_dev = chip->r_dev;
+
+ if (!r_dev->pulses)
+ return len;
+
+ disable_irq(chip->irqno);
+ mutex_lock(&chip->file_lock);
+ for (i = 0; i < r_dev->pulses->len; i++)
+ len += sprintf(buf + len, "%lds",
+ r_dev->pulses->pulse[i] & GENMASK(30, 0));
+
+ len += sprintf(buf + len, "\n");
+
+ remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15), BIT(15));
+
+ r_dev->ir_learning_done = false;
+
+ mutex_unlock(&chip->file_lock);
+ enable_irq(chip->irqno);
+
+ return len;
+}
+
+static ssize_t learned_pulse_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct remote_chip *chip = dev_get_drvdata(dev);
+ struct remote_dev *r_dev = chip->r_dev;
+
+ if (!r_dev->pulses)
+ return count;
+
+ disable_irq(chip->irqno);
+ mutex_lock(&chip->file_lock);
+ if (buf[0] == 'c') {
+ memset(r_dev->pulses, 0, sizeof(struct pulse_group) +
+ r_dev->max_learned_pulse * sizeof(u32));
+ remote_reg_update_bits(chip, MULTI_IR_ID, REG_REG1, BIT(15),
+ BIT(15));
+
+ r_dev->ir_learning_done = false;
+ }
+ mutex_unlock(&chip->file_lock);
+ enable_irq(chip->irqno);
+ return count;
+}
+
+static ssize_t sum_cnt0_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ int val = 0;
+ struct remote_chip *chip = dev_get_drvdata(dev);
+
+ remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT0, &val);
+
+ return sprintf(buf, "%d\n", val);
+}
+
+static ssize_t sum_cnt1_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+
+ int val = 0;
+ struct remote_chip *chip = dev_get_drvdata(dev);
+
+ remote_reg_read(chip, MULTI_IR_ID, REG_DEMOD_SUM_CNT1, &val);
+
+ return sprintf(buf, "%d\n", val);
+
+}
+
+static ssize_t use_fifo_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct remote_chip *chip = dev_get_drvdata(dev);
+
+ return sprintf(buf, "%d\n", chip->r_dev->use_fifo);
+}
+
+static ssize_t use_fifo_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int val = 0;
+ int len = 0;
+ struct remote_chip *chip = dev_get_drvdata(dev);
+
+ len = kstrtoint(buf, 0, &val);
+
+ if (len != 0) {
+ dev_err(chip->dev, "input parameter error\n");
+ return -EINVAL;
+ }
+
+ chip->r_dev->use_fifo = val;
+
+ return count;
+}
+
+DEVICE_ATTR_RW(use_fifo);
+DEVICE_ATTR_RO(sum_cnt0);
+DEVICE_ATTR_RO(sum_cnt1);
+DEVICE_ATTR_RW(learned_pulse);
+DEVICE_ATTR_RW(ir_learning);
DEVICE_ATTR_RW(led_frq);
DEVICE_ATTR_RW(led_blink);
DEVICE_ATTR_RW(repeat_enable);
&dev_attr_debug_log.attr,
&dev_attr_led_blink.attr,
&dev_attr_led_frq.attr,
+ &dev_attr_ir_learning.attr,
+ &dev_attr_learned_pulse.attr,
+ &dev_attr_sum_cnt0.attr,
+ &dev_attr_sum_cnt1.attr,
+ &dev_attr_use_fifo.attr,
NULL,
};