aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/irda
diff options
context:
space:
mode:
authorsbrissen <sbrissen@hotmail.com>2013-06-21 07:40:19 -0400
committerDaniel Hillenbrand <codeworkx@cyanogenmod.org>2013-06-25 17:05:03 +0200
commitcb93f68cb9ab19d9647962568b4c895548a869e8 (patch)
tree489bbfb6351db1d685e81c3d8c9c118544b68be4 /drivers/irda
parent5b3cb3ccc3df3b6106b5ae91f1ca77fcb1d99064 (diff)
downloadkernel_samsung_smdk4412-cb93f68cb9ab19d9647962568b4c895548a869e8.zip
kernel_samsung_smdk4412-cb93f68cb9ab19d9647962568b4c895548a869e8.tar.gz
kernel_samsung_smdk4412-cb93f68cb9ab19d9647962568b4c895548a869e8.tar.bz2
smdk4412: add i925/p4noteltevzw support
Change-Id: I17d3befd6a6538c16db0675253927068a09085c6
Diffstat (limited to 'drivers/irda')
-rw-r--r--drivers/irda/ir_remote_con_mc96.c189
1 files changed, 150 insertions, 39 deletions
diff --git a/drivers/irda/ir_remote_con_mc96.c b/drivers/irda/ir_remote_con_mc96.c
index 5c624c8..9063137 100644
--- a/drivers/irda/ir_remote_con_mc96.c
+++ b/drivers/irda/ir_remote_con_mc96.c
@@ -32,11 +32,12 @@
#include <linux/device.h>
#include <linux/ir_remote_con_mc96.h>
#include <linux/earlysuspend.h>
-#include <linux/spinlock.h>
#include "irda_fw.h"
+#include <mach/gpio-rev00-p4notepq.h>
#define MAX_SIZE 2048
#define MC96_READ_LENGTH 8
+#define DUMMY 0xffff
#define USE_STOP_MODE
@@ -45,7 +46,6 @@ struct ir_remocon_data {
struct i2c_client *client;
struct mc96_platform_data *pdata;
struct early_suspend early_suspend;
- spinlock_t lock;
char signal[MAX_SIZE];
int length;
int count;
@@ -60,31 +60,45 @@ static void ir_remocon_early_suspend(struct early_suspend *h);
static void ir_remocon_late_resume(struct early_suspend *h);
#endif
+static int count_number;
+static int ack_number;
+static int retry_count;
+static int download_pass;
+
static int irda_fw_update(struct ir_remocon_data *ir_data)
{
struct ir_remocon_data *data = ir_data;
struct i2c_client *client = data->client;
- int i, ret;
+ int i, k, ret, ret2, checksum, checksum2;
u8 buf_ir_test[8];
+ msleep(20);
data->pdata->ir_vdd_onoff(0);
- data->pdata->ir_wake_en(1);
+ msleep(20);
data->pdata->ir_vdd_onoff(1);
+ data->pdata->ir_wake_en(1);
msleep(100);
ret = i2c_master_recv(client, buf_ir_test, MC96_READ_LENGTH);
if (ret < 0) {
- printk(KERN_ERR "1. %s: err %d\n", __func__, ret);
+ printk(KERN_ERR "%s: err %d\n", __func__, ret);
ret = i2c_master_recv(client, buf_ir_test, MC96_READ_LENGTH);
- if (ret < 0)
- goto err_i2c_fail;
+ if (ret < 0) {
+ printk(KERN_INFO "%s: broken FW!\n", __func__);
+ retry_count = 1;
+ }
}
ret = buf_ir_test[2] << 8 | buf_ir_test[3];
- if (ret < FW_VERSION) {
+
+ if (ret == 0xffff)
+ ret = 0x202;
+
+ if ((ret != FW_VERSION) || (retry_count != 0)) {
printk(KERN_INFO "2. %s: chip : %04x, bin : %04x, need update!\n",
__func__, ret, FW_VERSION);
data->pdata->ir_vdd_onoff(0);
data->pdata->ir_wake_en(0);
+ msleep(20);
data->pdata->ir_vdd_onoff(1);
msleep(100);
@@ -94,11 +108,19 @@ static int irda_fw_update(struct ir_remocon_data *ir_data)
ret = buf_ir_test[6] << 8 | buf_ir_test[7];
- if (ret == 0x01fe)
- printk(KERN_INFO "4. %s: boot mode, FW download start\n",
- __func__);
- else
+ checksum = 0;
+
+ for (k = 0; k < 6; k++)
+ checksum += buf_ir_test[k];
+
+ if (ret == checksum)
+ printk(KERN_INFO "%s: boot mode, FW download start! ret=%04x\n",
+ __func__, ret);
+ else {
+ printk(KERN_ERR "ABOV IC bootcode broken\n");
goto err_bootmode;
+ }
+
msleep(30);
for (i = 0; i < FRAME_COUNT; i++) {
@@ -121,41 +143,72 @@ static int irda_fw_update(struct ir_remocon_data *ir_data)
printk(KERN_ERR "5. %s: err %d\n", __func__, ret);
ret = buf_ir_test[6] << 8 | buf_ir_test[7];
+ checksum = 0;
+ for (k = 0; k < 6; k++)
+ checksum += buf_ir_test[k];
+
+ msleep(20);
+
+ ret2 = i2c_master_recv(client, buf_ir_test, MC96_READ_LENGTH);
+ if (ret2 < 0)
+ printk(KERN_ERR "6. %s: err %d\n", __func__, ret2);
+
+ ret2 = buf_ir_test[6] << 8 | buf_ir_test[7];
+ for (k = 0; k < 6; k++)
+ checksum2 += buf_ir_test[k];
- if (ret == 0x02a3)
- printk(KERN_INFO "6. %s: boot down complete\n",
+ if (ret == checksum) {
+ printk(KERN_INFO "1. %s: boot down complete\n",
__func__);
- else
+ download_pass = 1;
+ } else if (ret2 == checksum2) {
+ printk(KERN_INFO "2. %s: boot down complete\n",
+ __func__);
+ download_pass = 1;
+ } else {
+ retry_count++;
+ printk(KERN_ERR "FW Checksum fail. Retry = %d\n",
+ retry_count);
goto err_bootmode;
+ }
data->pdata->ir_vdd_onoff(0);
- data->pdata->ir_wake_en(1);
+ msleep(20);
data->pdata->ir_vdd_onoff(1);
+ data->pdata->ir_wake_en(1);
msleep(60);
ret = i2c_master_recv(client, buf_ir_test, MC96_READ_LENGTH);
ret = buf_ir_test[2] << 8 | buf_ir_test[3];
- printk(KERN_INFO "7. %s: user mode dev: %04x\n", __func__, ret);
+ printk(KERN_INFO "7. %s: user mode : Upgrade FW_version : %04x\n",
+ __func__, ret);
+ data->pdata->ir_wake_en(0);
data->pdata->ir_vdd_onoff(0);
data->on_off = 0;
+ msleep(100);
} else {
- printk(KERN_INFO "8. %s: chip : %04x, bin : %04x, latest FW_version now\n",
+ if (ret != DUMMY)
+ printk(KERN_INFO "8. %s: chip : %04x, bin : %04x, latest FW_ver\n",
__func__, ret, FW_VERSION);
data->pdata->ir_wake_en(0);
data->pdata->ir_vdd_onoff(0);
data->on_off = 0;
+ msleep(100);
+
+ if (ret == FW_VERSION)
+ download_pass = 1;
}
return 0;
-err_i2c_fail:
- printk(KERN_ERR "%s: update fail! i2c ret : %x\n",
- __func__, ret);
err_update:
printk(KERN_ERR "%s: update fail! count : %x, ret = %x\n",
__func__, i, ret);
+ return ret;
err_bootmode:
- printk(KERN_ERR "%s: update fail, ret = %x\n", __func__, ret);
+ printk(KERN_ERR "%s: update fail, checksum = %x ret = %x\n",
+ __func__, checksum, ret);
+ data->pdata->ir_wake_en(0);
data->pdata->ir_vdd_onoff(0);
data->on_off = 0;
return ret;
@@ -165,9 +218,9 @@ static void irda_add_checksum_length(struct ir_remocon_data *ir_data, int count)
{
struct ir_remocon_data *data = ir_data;
int i = 0, csum = 0;
-
+#if 0
printk(KERN_INFO "%s: length: %04x\n", __func__, count);
-
+#endif
data->signal[0] = count >> 8;
data->signal[1] = count & 0xff;
@@ -191,8 +244,8 @@ static int irda_read_device_info(struct ir_remocon_data *ir_data)
int ret;
printk(KERN_INFO"%s called\n", __func__);
- data->pdata->ir_wake_en(1);
data->pdata->ir_vdd_onoff(1);
+ data->pdata->ir_wake_en(1);
msleep(60);
ret = i2c_master_recv(client, buf_ir_test, MC96_READ_LENGTH);
@@ -216,17 +269,22 @@ static void ir_remocon_work(struct ir_remocon_data *ir_data, int count)
struct i2c_client *client = data->client;
int buf_size = count+2;
- int ret, i;
+ int ret;
int sleep_timing;
int end_data;
int emission_time;
- unsigned long flags;
+ int ack_pin_onoff;
+
+ if (count_number >= 100)
+ count_number = 0;
+
+ count_number++;
printk(KERN_INFO "%s: total buf_size: %d\n", __func__, buf_size);
irda_add_checksum_length(data, count);
- spin_lock_irqsave(&data->lock, flags);
+ mutex_lock(&data->mutex);
ret = i2c_master_send(client, data->signal, buf_size);
if (ret < 0) {
@@ -236,24 +294,57 @@ static void ir_remocon_work(struct ir_remocon_data *ir_data, int count)
dev_err(&client->dev, "%s: err2 %d\n", __func__, ret);
}
- spin_unlock_irqrestore(&data->lock, flags);
+ mdelay(10);
+
+ ack_pin_onoff = 0;
+ if (gpio_get_value(GPIO_IRDA_IRQ)) {
+ printk(KERN_INFO "%s : %d Checksum NG!\n",
+ __func__, count_number);
+ ack_pin_onoff = 1;
+ } else {
+ printk(KERN_INFO "%s : %d Checksum OK!\n",
+ __func__, count_number);
+ ack_pin_onoff = 2;
+ }
+ ack_number = ack_pin_onoff;
+
+ mutex_unlock(&data->mutex);
/*
- for (i = 0; i < buf_size; i++) {
+ for (int i = 0; i < buf_size; i++) {
printk(KERN_INFO "%s: data[%d] : 0x%02x\n", __func__, i,
data->signal[i]);
}
*/
data->count = 2;
-
end_data = data->signal[count-2] << 8 | data->signal[count-1];
emission_time = \
(1000 * (data->ir_sum - end_data) / (data->ir_freq)) + 10;
sleep_timing = emission_time - 130;
if (sleep_timing > 0)
msleep(sleep_timing);
+/*
printk(KERN_INFO "%s: sleep_timing = %d\n", __func__, sleep_timing);
+*/
+ emission_time = \
+ (1000 * (data->ir_sum) / (data->ir_freq)) + 50;
+ if (emission_time > 0)
+ msleep(emission_time);
+ printk(KERN_INFO "%s: emission_time = %d\n",
+ __func__, emission_time);
+
+ if (gpio_get_value(GPIO_IRDA_IRQ)) {
+ printk(KERN_INFO "%s : %d Sending IR OK!\n",
+ __func__, count_number);
+ ack_pin_onoff = 4;
+ } else {
+ printk(KERN_INFO "%s : %d Sending IR NG!\n",
+ __func__, count_number);
+ ack_pin_onoff = 2;
+ }
+
+ ack_number += ack_pin_onoff;
#ifndef USE_STOP_MODE
data->pdata->ir_vdd_onoff(0);
data->on_off = 0;
@@ -279,11 +370,12 @@ static ssize_t remocon_store(struct device *dev, struct device_attribute *attr,
data->ir_freq = _data;
if (data->on_off) {
data->pdata->ir_wake_en(0);
+ udelay(200);
data->pdata->ir_wake_en(1);
- msleep(20);
+ msleep(30);
} else {
- data->pdata->ir_wake_en(1);
data->pdata->ir_vdd_onoff(1);
+ data->pdata->ir_wake_en(1);
msleep(60);
data->on_off = 1;
}
@@ -328,7 +420,21 @@ static ssize_t remocon_show(struct device *dev, struct device_attribute *attr,
return strlen(buf);
}
+static ssize_t remocon_ack(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct ir_remocon_data *data = dev_get_drvdata(dev);
+
+ printk(KERN_INFO "%s : ack_number = %d\n", __func__, ack_number);
+
+ if (ack_number == 6)
+ return sprintf(buf, "1\n");
+ else
+ return sprintf(buf, "0\n");
+}
+
static DEVICE_ATTR(ir_send, 0664, remocon_show, remocon_store);
+static DEVICE_ATTR(ir_send_result, 0664, remocon_ack, NULL);
static ssize_t check_ir_show(struct device *dev, struct device_attribute *attr,
char *buf)
@@ -349,9 +455,9 @@ static int __devinit ir_remocon_probe(struct i2c_client *client,
struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
struct ir_remocon_data *data;
struct device *ir_remocon_dev;
- int error;
+ int i, error;
- printk(KERN_INFO "%s probe!\n", __func__);
+ printk(KERN_INFO "%s start!\n", __func__);
if (!i2c_check_functionality(adapter, I2C_FUNC_I2C))
return -EIO;
@@ -366,16 +472,17 @@ static int __devinit ir_remocon_probe(struct i2c_client *client,
data->client = client;
data->pdata = client->dev.platform_data;
- data->pdata->ir_remote_init();
mutex_init(&data->mutex);
data->count = 2;
data->on_off = 0;
i2c_set_clientdata(client, data);
- irda_fw_update(data);
-
- spin_lock_init(&data->lock);
+ for (i = 0; i < 6; i++) {
+ if (download_pass == 1)
+ break;
+ irda_fw_update(data);
+ }
/*
irda_read_device_info(data);
*/
@@ -388,6 +495,10 @@ static int __devinit ir_remocon_probe(struct i2c_client *client,
pr_err("Failed to create device file(%s)!\n",
dev_attr_ir_send.attr.name);
+ if (device_create_file(ir_remocon_dev, &dev_attr_ir_send_result) < 0)
+ pr_err("Failed to create device file(%s)!\n",
+ dev_attr_ir_send.attr.name);
+
if (device_create_file(ir_remocon_dev, &dev_attr_check_ir) < 0)
pr_err("Failed to create device file(%s)!\n",
dev_attr_check_ir.attr.name);