ir: add ir learning function [1/1]

PD#SWPL-4130

Problem:
No ir learning function in current source code

Solution:
Provide two ways to use ir learning function
1. sysfs
	/*start learning*/
	echo 1 > /sys/class/remote/amremote/ir_learnning
	/*get data*/
	cat /sys/class/remote/amremote/learned_pulse
	/*stop learning*/
	echo 0 > /sys/class/remote/amremote/ir_learnning
2. ioctl
	/*start/stop learnning 1/0*/
	REMOTE_IOC_SET_IR_LEARING
	/*get raw data*/
	REMOTE_IOC_GET_RAW_DATA

Verify:
U200 and W400

Change-Id: Ibb03838402d9baa6e910b3162ffcc63b57048890
Signed-off-by: Qianggui Song <qianggui.song@amlogic.com>
This commit is contained in:
Qianggui Song
2019-01-18 11:26:47 +08:00
committed by Luke Go
parent f7f3031015
commit d52040136f
7 changed files with 556 additions and 30 deletions

View File

@@ -86,5 +86,10 @@ struct ir_sw_decode_para {
#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

View File

@@ -48,6 +48,7 @@ static long remote_ioctl(struct file *file, unsigned int cmd,
void __user *parg = (void __user *)arg;
unsigned long flags;
u32 value;
u8 val;
int retval = 0;
if (!parg) {
@@ -133,6 +134,93 @@ static long remote_ioctl(struct file *file, unsigned int cmd,
}
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;

View File

@@ -58,7 +58,11 @@ enum raw_event_type {
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 {
@@ -75,6 +79,19 @@ 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;

View File

@@ -44,10 +44,51 @@
#include <linux/amlogic/scpi_protocol.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)
{
@@ -74,6 +115,19 @@ int remote_reg_write(struct remote_chip *chip, unsigned char id,
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;
@@ -301,9 +355,64 @@ static void amlremote_tasklet(unsigned long data)
}
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;
@@ -313,12 +422,40 @@ static irqreturn_t ir_interrupt(int irq, void *dev_id)
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;
@@ -516,6 +653,18 @@ static int ir_get_devtree_pdata(struct platform_device *pdev)
}
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));
@@ -562,6 +711,47 @@ static int ir_get_devtree_pdata(struct platform_device *pdev)
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;
@@ -654,6 +844,7 @@ static int remote_probe(struct platform_device *pdev)
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);
@@ -677,6 +868,11 @@ static int remote_probe(struct platform_device *pdev)
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:
@@ -760,6 +956,12 @@ static int remote_suspend(struct device *dev)
{
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;

View File

@@ -25,8 +25,13 @@
#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,
@@ -104,6 +109,8 @@ struct remote_chip {
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;
@@ -167,27 +174,36 @@ enum {
};
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);
@@ -199,11 +215,18 @@ int remote_reg_read(struct remote_chip *chip, unsigned char id,
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);
#if defined(CONFIG_IR_HK_LIRC_HELPER)
extern void remote_wakeup_decode_type(int dec_type);
#endif
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

View File

@@ -88,7 +88,7 @@ static struct remote_reg_map regs_default_nec_sw[] = {
{ 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},
@@ -630,6 +630,11 @@ const struct aml_remote_reg_proto *remote_reg_proto[] = {
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;
@@ -684,6 +689,11 @@ static int ir_contr_init(struct remote_chip *chip, int type, unsigned char id)
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;
}

View File

@@ -43,16 +43,29 @@ static ssize_t protocol_show(struct device *dev,
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);
return sprintf(buf, "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 len;
}
static ssize_t protocol_store(struct device *dev,
@@ -308,6 +321,169 @@ static ssize_t led_frq_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);
@@ -326,6 +502,11 @@ static struct attribute *remote_attrs[] = {
&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,
};