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:
parent
7a022ba4a8
commit
2ed8402379
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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(¬ifier);
|
||||
}
|
||||
|
||||
if (pjack_info->mic_detect) {
|
||||
notifier.id = HEADSET_REG_MIC_STATUS;
|
||||
notifier.func = hs_gpio_get_mic;
|
||||
headset_notifier_register(¬ifier);
|
||||
|
||||
notifier.id = HEADSET_REG_KEY_INT_ENABLE;
|
||||
notifier.func = hs_enable_key_irq;
|
||||
headset_notifier_register(¬ifier);
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user