htcleo: add headset driver

There is a problem with the Mic GPIO. This isnt comming..
This has to be fixed.
This commit is contained in:
Markinus 2010-08-31 14:04:06 +02:00
parent 7a022ba4a8
commit 2ed8402379
7 changed files with 252 additions and 24 deletions

View File

@ -209,16 +209,26 @@ CONFIG_MSM_DEBUG_UART_NONE=y
# CONFIG_MSM_DEBUG_UART2 is not set
# CONFIG_MSM_DEBUG_UART3 is not set
#
# HTC headset driver
#
CONFIG_HTC_HEADSET_MGR=y
# CONFIG_HTC_HEADSET_H2W is not set
CONFIG_HTC_HEADSET_GPIO=y
# CONFIG_HTC_HEADSET_MICROP is not set
# CONFIG_HTC_HEADSET_PMIC is not set
#
# MSM Board Type
#
CONFIG_AAT1271_FLASHLIGHT=y
CONFIG_MICROP_COMMON=y
CONFIG_MACH_HTCLEO=y
# CONFIG_MACH_SWORDFISH is not set
# CONFIG_MACH_MAHIMAHI is not set
# CONFIG_MACH_QSD8X50_FFA is not set
# CONFIG_HTC_HEADSET is not set
CONFIG_HTC_35MM_JACK=y
# CONFIG_HTC_35MM_JACK is not set
# CONFIG_HTC_PWRSPLY is not set
# CONFIG_HTC_PWRSINK is not set
# CONFIG_MSM_DALRPC_TEST is not set

View File

@ -234,6 +234,47 @@ int microp_write_interrupt(struct i2c_client *client,
return ret;
}
int microp_set_adc_req(uint8_t value)
{
struct i2c_client *client;
int ret;
uint8_t cmd[1];
client = private_microp_client;
cmd[0] = value;
ret = i2c_write_block(client, MICROP_I2C_WCMD_ADC_REQ, cmd, 1);
if (ret < 0)
{
dev_err(&client->dev, "%s: request adc fail\n", __func__);
return -EIO;
}
return 0;
}
int microp_get_remote_adc(uint32_t *val)
{
struct i2c_client *client;
int ret;
uint8_t data[4];
if (!val)
return -EIO;
client = private_microp_client;
ret = i2c_read_block(client, MICROP_I2C_RCMD_ADC_VALUE, data, 2);
if (ret < 0)
{
dev_err(&client->dev, "%s: request adc fail\n", __func__);
return -EIO;
}
// printk("%x %x\n", data[0], data[1]);
*val = data[1] | (data[0] << 8);
printk("remote adc %d\n", *val);
return 0;
}
int microp_read_adc(uint8_t *data)
{
struct i2c_client *client;

View File

@ -38,24 +38,6 @@ static int htcleo_microp_function_init(struct i2c_client *client)
pdata = client->dev.platform_data;
cdata = i2c_get_clientdata(client);
/* Headset remote key */
ret = microp_function_check(client, MICROP_FUNCTION_REMOTEKEY);
if (ret >= 0) {
i = ret;
pdata->function_node[MICROP_FUNCTION_REMOTEKEY] = i;
cdata->int_pin.int_remotekey =
pdata->microp_function[i].int_pin;
for (j = 0; j < 6; j++) {
data[j] = (uint8_t)(pdata->microp_function[i].levels[j] >> 8);
data[j + 6] = (uint8_t)(pdata->microp_function[i].levels[j]);
}
ret = microp_i2c_write(MICROP_I2C_WCMD_REMOTEKEY_TABLE,
data, 12);
if (ret)
goto exit;
}
/* Reset button interrupt */
ret = microp_write_interrupt(client, (1<<8), 1);
if (ret)

View File

@ -46,16 +46,20 @@
#include <mach/msm_flashlight.h>
#include <mach/msm_serial_hs.h>
#include <mach/perflock.h>
#include <mach/htc_headset_mgr.h>
#include <mach/htc_headset_gpio.h>
#ifdef CONFIG_MICROP_COMMON
#include <mach/atmega_microp.h>
void __init htcleo_microp_init(void);
#endif
#include "board-htcleo.h"
#include "board-htcleo-ts.h"
#include "devices.h"
#include "proc_comm.h"
#include "dex_comm.h"
#ifdef CONFIG_MICROP_COMMON
#include <mach/atmega_microp.h>
void __init htcleo_microp_init(void);
#endif
extern int __init htcleo_init_mmc(unsigned debug_uart);
extern void __init htcleo_audio_init(void);
@ -124,6 +128,38 @@ static struct regulator_init_data tps65023_data[5] =
},
},
};
///////////////////////////////////////////////////////////////////////
// Headset
///////////////////////////////////////////////////////////////////////
static struct htc_headset_mgr_platform_data htc_headset_mgr_data = {
};
static struct platform_device htc_headset_mgr = {
.name = "HTC_HEADSET_MGR",
.id = -1,
.dev = {
.platform_data = &htc_headset_mgr_data,
},
};
static struct htc_headset_gpio_platform_data htc_headset_gpio_data = {
.hpin_gpio = HTCLEO_GPIO_HDS_DET,
.mic_detect_gpio = HTCLEO_GPIO_HDS_MIC,
.microp_channel = 1,
.key_enable_gpio = NULL,
.mic_select_gpio = NULL,
};
static struct platform_device htc_headset_gpio = {
.name = "HTC_HEADSET_GPIO",
.id = -1,
.dev = {
.platform_data = &htc_headset_gpio_data,
},
};
///////////////////////////////////////////////////////////////////////
// Compass
@ -610,6 +646,8 @@ static struct platform_device *devices[] __initdata =
&htcleo_flashlight_device,
&htcleo_power,
&qsd_device_spi,
&htc_headset_mgr,
&htc_headset_gpio,
};
///////////////////////////////////////////////////////////////////////
// Vibrator

View File

@ -33,6 +33,7 @@
#include <linux/delay.h>
#include <linux/gpio.h>
#include <mach/atmega_microp.h>
#include <mach/htc_headset_mgr.h>
#include <mach/htc_headset_gpio.h>
@ -49,16 +50,20 @@
struct audio_jack_info {
unsigned int irq_jack;
unsigned int irq_mic;
int audio_jack_detect;
int key_enable_gpio;
int mic_select_gpio;
int audio_jack_flag;
int mic_detect;
int last_pressed_key;
int microp_channel;
struct hrtimer detection_timer;
ktime_t debounce_time;
struct work_struct work;
struct work_struct mic_work;
spinlock_t spin_lock;
struct wake_lock audiojack_wake_lock;
@ -66,6 +71,25 @@ struct audio_jack_info {
static struct audio_jack_info *pjack_info;
static int hs_gpio_get_mic(void)
{
int value;
value = !gpio_get_value(pjack_info->mic_detect);
printk("hs_gpio_get_mic: %d\n", value);
return value;
}
static int hs_enable_key_irq(int status)
{
printk("hs_enable_key_irq: %d\n", status);
if(status)
enable_irq(pjack_info->irq_mic);
else
disable_irq(pjack_info->irq_mic);
return 0;
}
void hs_gpio_key_enable(int enable)
{
DBG_MSG();
@ -82,8 +106,72 @@ void hs_gpio_mic_select(int enable)
gpio_set_value(pjack_info->mic_select_gpio, enable);
}
static int get_remote_keycode(int *keycode)
{
uint32_t val;
uint32_t btn = 0;
microp_set_adc_req(pjack_info->microp_channel);
if (microp_get_remote_adc(&val))
{
// failed. who know why? ignore
*keycode = 0;
return 1;
}
if((val >= 0) && (val <= 33))
{
btn = 1;
}
else if((val >= 38) && (val <= 82))
{
btn = 2;
}
else if((val >= 95) && (val <= 200))
{
btn = 3;
}
else if(val > 200)
{
// check previous key
if (pjack_info->last_pressed_key)
{
*keycode = pjack_info->last_pressed_key | 0x80;
pjack_info->last_pressed_key = 0;
return 0;
}
*keycode = 0;
return 1;
}
pjack_info->last_pressed_key = btn;
*keycode = btn;
return 0;
}
static irqreturn_t mic_irq_handler(int irq, void *dev_id)
{
pr_info("MIC IRQ Handler\n");
int value1, value2;
int retry_limit = 10;
AJ_DBG("");
do {
value1 = gpio_get_value(pjack_info->mic_detect);
set_irq_type(pjack_info->irq_mic, value1 ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
value2 = gpio_get_value(pjack_info->mic_detect);
} while (value1 != value2 && retry_limit-- > 0);
AJ_DBG("value2 = %d (%d retries)", value2, (10-retry_limit));
schedule_work(&pjack_info->mic_work);
return IRQ_HANDLED;
}
static irqreturn_t detect_irq_handler(int irq, void *dev_id)
{
pr_info("DET IRQ Handler\n");
int value1, value2;
int retry_limit = 10;
@ -125,9 +213,26 @@ static enum hrtimer_restart detect_35mm_event_timer_func(struct hrtimer *data)
return HRTIMER_NORESTART;
}
static void mic_work_func(struct work_struct *work)
{
pr_info("MIC Schedule Work\n");
int keycode = 0;
printk("mic_intr_work_func\n");
if (get_remote_keycode(&keycode) == 0)
{
printk("keycode %d\n", keycode);
htc_35mm_remote_notify_button_status(keycode);
}
else
printk("mic error keycode\n");
}
static void audiojack_work_func(struct work_struct *work)
{
int is_insert;
pr_info("DET Schedule Work\n");
unsigned long flags = 0;
spin_lock_irqsave(&pjack_info->spin_lock, flags);
@ -157,6 +262,16 @@ static void hs_gpio_register(void)
notifier.func = hs_gpio_key_enable;
headset_notifier_register(&notifier);
}
if (pjack_info->mic_detect) {
notifier.id = HEADSET_REG_MIC_STATUS;
notifier.func = hs_gpio_get_mic;
headset_notifier_register(&notifier);
notifier.id = HEADSET_REG_KEY_INT_ENABLE;
notifier.func = hs_enable_key_irq;
headset_notifier_register(&notifier);
}
}
static int audiojack_probe(struct platform_device *pdev)
@ -173,7 +288,10 @@ static int audiojack_probe(struct platform_device *pdev)
pjack_info->audio_jack_detect = pdata->hpin_gpio;
pjack_info->key_enable_gpio = pdata->key_enable_gpio;
pjack_info->mic_select_gpio = pdata->mic_select_gpio;
pjack_info->mic_detect = pdata->mic_detect_gpio;
pjack_info->microp_channel = pdata->microp_channel;
pjack_info->audio_jack_flag = 0;
pjack_info->last_pressed_key = 0;
pjack_info->debounce_time = ktime_set(0, 500000000);
hrtimer_init(&pjack_info->detection_timer,
@ -181,6 +299,7 @@ static int audiojack_probe(struct platform_device *pdev)
pjack_info->detection_timer.function = detect_35mm_event_timer_func;
INIT_WORK(&pjack_info->work, audiojack_work_func);
INIT_WORK(&pjack_info->mic_work, mic_work_func);
spin_lock_init(&pjack_info->spin_lock);
wake_lock_init(&pjack_info->audiojack_wake_lock,
@ -212,8 +331,35 @@ static int audiojack_probe(struct platform_device *pdev)
ret = set_irq_wake(pjack_info->irq_jack, 1);
if (ret < 0)
goto err_set_irq_wake;
pr_info("DET IRQ Registered!");
}
if (pjack_info->mic_detect) {
ret = gpio_request(pjack_info->mic_detect,
"mic_detect");
if (ret < 0)
goto err_request_detect_gpio;
ret = gpio_direction_input(pjack_info->mic_detect);
if (ret < 0)
goto err_set_detect_gpio;
pjack_info->irq_mic =
gpio_to_irq(pjack_info->mic_detect);
if (pjack_info->irq_mic < 0) {
ret = pjack_info->irq_mic;
goto err_request_detect_irq;
}
ret = request_irq(pjack_info->irq_mic,
mic_irq_handler, IRQF_DISABLED | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_LOW, "mic_headset", NULL);
if (ret < 0)
goto err_request_detect_irq;
disable_irq(pjack_info->irq_mic);
pr_info("MIC IRQ Registered!");
}
hs_gpio_register();
SYS_MSG("--------------------");
@ -238,9 +384,15 @@ static int audiojack_remove(struct platform_device *pdev)
if (pjack_info->audio_jack_detect)
free_irq(pjack_info->irq_jack, 0);
if (pjack_info->audio_jack_detect)
free_irq(pjack_info->irq_mic, 0);
if (pjack_info->audio_jack_detect)
gpio_free(pjack_info->audio_jack_detect);
if (pjack_info->audio_jack_detect)
gpio_free(pjack_info->mic_detect);
return 0;
}

View File

@ -91,6 +91,7 @@
#define MICROP_I2C_WCMD_READ_ADC_VALUE_REQ 0x60
#define MICROP_I2C_RCMD_ADC_VALUE 0x62
#define MICROP_I2C_WCMD_REMOTEKEY_TABLE 0x63
#define MICROP_I2C_WCMD_ADC_REQ 0x64
#define MICROP_I2C_WCMD_LCM_BURST 0x6A
#define MICROP_I2C_WCMD_LCM_BURST_EN 0x6B
#define MICROP_I2C_WCMD_LCM_REGISTER 0x70
@ -259,6 +260,8 @@ void microp_get_als_kvalue(int i);
int microp_spi_vote_enable(int spi_device, uint8_t enable);
void microp_register_ops(struct microp_ops *ops);
int microp_set_adc_req(uint8_t value);
int microp_get_remote_adc(uint32_t *val);
int microp_read_adc(uint8_t *data);
void microp_mobeam_enable(int enable);

View File

@ -22,8 +22,10 @@
struct htc_headset_gpio_platform_data {
unsigned int hpin_gpio;
unsigned int mic_detect_gpio;
unsigned int key_enable_gpio;
unsigned int mic_select_gpio;
unsigned int microp_channel;
};
#endif