Commit 8a251ff2 authored by Ramesh Babu K V's avatar Ramesh Babu K V Committed by Greg Kroah-Hartman

intel_sst: rework jack implementation

This patch fixes the below issues w.r.t jack implementation

a) The current jack implementation in driver is implemented
   in intelmid.c. It has moved to vendor files for better managebility
b) Cleaned up jack reporting per upstream comments
c) Implemented jack for msic, added code to read adc and deduce jack
   type based on mic bias
d) Support detection of american headset
Signed-off-by: default avatarDharageswari R <dharageswari.r@intel.com>
Signed-off-by: default avatarRamesh Babu K V <ramesh.babu@intel.com>
[Corrections]
Signed-off-by: default avatarLu Guanqun <guanqun.lu@intel.com>
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent eb02c700
......@@ -30,6 +30,7 @@
* This file is shared between the SST and MAD drivers
*/
#include "intel_sst_ioctl.h"
#include <sound/jack.h>
#define SST_CARD_NAMES "intel_mid_card"
......@@ -88,6 +89,7 @@ struct snd_pmic_ops {
int output_dev_id;
int lineout_dev_id, line_out_names_cnt;
int prev_lineout_dev_id;
bool jack_interrupt_status;
int (*set_input_dev) (u8 value);
int (*set_output_dev) (u8 value);
int (*set_lineout_dev) (u8 value);
......@@ -109,11 +111,25 @@ struct snd_pmic_ops {
int (*power_down_pmic_pb) (unsigned int device);
int (*power_down_pmic_cp) (unsigned int device);
int (*power_down_pmic) (void);
void (*pmic_irq_cb) (void *cb_data, u8 value);
void (*pmic_irq_enable)(void *data);
int (*pmic_jack_enable) (void);
int (*pmic_get_mic_bias)(void *intelmaddata);
int (*pmic_set_headset_state)(int state);
unsigned int hw_dmic_map[MFLD_MAX_HW_CH];
unsigned int available_dmics;
int (*set_hw_dmic_route) (u8 index);
};
extern void sst_mad_send_jack_report(struct snd_jack *jack,
int buttonpressevent,
int status);
int intemad_set_headset_state(int state);
int intelmad_get_mic_bias(void);
struct intel_sst_pcm_control {
int (*open) (struct snd_sst_params *str_param);
int (*device_control) (int cmd, void *arg);
......
......@@ -28,8 +28,8 @@
* Common private declarations for SST
*/
#define SST_DRIVER_VERSION "1.2.15"
#define SST_VERSION_NUM 0x1215
#define SST_DRIVER_VERSION "1.2.17"
#define SST_VERSION_NUM 0x1217
/* driver names */
#define SST_DRV_NAME "intel_sst_driver"
......
This diff is collapsed.
......@@ -67,12 +67,17 @@
#define MIN_VOL 0
#define PLAYBACK_COUNT 1
#define CAPTURE_COUNT 1
#define ADC_ONE_LSB_MULTIPLIER 2346
#define MID_JACK_HS_LONG_PRESS SND_JACK_BTN_0
#define MID_JACK_HS_SHORT_PRESS SND_JACK_BTN_1
extern int sst_card_vendor_id;
struct mad_jack {
struct snd_jack jack;
int jack_status;
int jack_dev_state;
struct timeval buttonpressed;
struct timeval buttonreleased;
};
......@@ -84,6 +89,12 @@ struct mad_jack_msg_wq {
};
struct snd_intelmad_probe_info {
unsigned int cpu_id;
unsigned int irq_cache;
unsigned int size;
};
/**
* struct snd_intelmad - intelmad driver structure
*
......@@ -122,6 +133,7 @@ struct snd_intelmad {
struct mad_jack jack[4];
int playback_cnt;
int capture_cnt;
u16 adc_address;
struct mad_jack_msg_wq mad_jack_msg;
struct workqueue_struct *mad_jack_wq;
u8 jack_prev_state;
......@@ -188,5 +200,7 @@ extern struct snd_control_val intelmad_ctrl_val[];
extern struct snd_kcontrol_new snd_intelmad_controls_mrst[];
extern struct snd_kcontrol_new snd_intelmad_controls_mfld[];
extern struct snd_pmic_ops *intelmad_vendor_ops[];
void sst_mad_send_jack_report(struct snd_jack *jack,
int buttonpressevent , int status);
#endif /* __INTELMID_H */
#ifndef __INTELMID_ADC_CONTROL_H__
#define __INTELMID_ADC_CONTROL_H_
/*
* intelmid_adc_control.h - Intel SST Driver for audio engine
*
* Copyright (C) 2008-10 Intel Corporation
* Authors: R Durgadadoss <r.durgadoss@intel.com>
* Dharageswari R <dharageswari.r@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*
* Common private ADC declarations for SST
*/
#define MSIC_ADC1CNTL1 0x1C0
#define MSIC_ADC_ENBL 0x10
#define MSIC_ADC_START 0x08
#define MSIC_ADC1CNTL3 0x1C2
#define MSIC_ADCTHERM_ENBL 0x04
#define MSIC_ADCRRDATA_ENBL 0x05
#define MSIC_STOPBIT_MASK 16
#define MSIC_ADCTHERM_MASK 4
#define ADC_CHANLS_MAX 15 /* Number of ADC channels */
#define ADC_LOOP_MAX (ADC_CHANLS_MAX - 1)
/* ADC channel code values */
#define AUDIO_DETECT_CODE 0x06
/* ADC base addresses */
#define ADC_CHNL_START_ADDR 0x1C5 /* increments by 1 */
#define ADC_DATA_START_ADDR 0x1D4 /* increments by 2 */
/**
* configure_adc - enables/disables the ADC for conversion
* @val: zero: disables the ADC non-zero:enables the ADC
*
* Enable/Disable the ADC depending on the argument
*
* Can sleep
*/
static inline int configure_adc(int val)
{
int ret;
struct sc_reg_access sc_access = {0,};
sc_access.reg_addr = MSIC_ADC1CNTL1;
ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
if (ret)
return ret;
if (val)
/* Enable and start the ADC */
sc_access.value |= (MSIC_ADC_ENBL | MSIC_ADC_START);
else
/* Just stop the ADC */
sc_access.value &= (~MSIC_ADC_START);
sc_access.reg_addr = MSIC_ADC1CNTL1;
return sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
}
/**
* reset_stopbit - sets the stop bit to 0 on the given channel
* @addr: address of the channel
*
* Can sleep
*/
static inline int reset_stopbit(uint16_t addr)
{
int ret;
struct sc_reg_access sc_access = {0,};
sc_access.reg_addr = addr;
ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
if (ret)
return ret;
/* Set the stop bit to zero */
sc_access.reg_addr = addr;
sc_access.value = (sc_access.value) & 0xEF;
return sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
}
/**
* find_free_channel - finds an empty channel for conversion
*
* If the ADC is not enabled then start using 0th channel
* itself. Otherwise find an empty channel by looking for a
* channel in which the stopbit is set to 1. returns the index
* of the first free channel if succeeds or an error code.
*
* Context: can sleep
*
*/
static inline int find_free_channel(void)
{
int ret;
int i;
struct sc_reg_access sc_access = {0,};
/* check whether ADC is enabled */
sc_access.reg_addr = MSIC_ADC1CNTL1;
ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
if (ret)
return ret;
if ((sc_access.value & MSIC_ADC_ENBL) == 0)
return 0;
/* ADC is already enabled; Looking for an empty channel */
for (i = 0; i < ADC_CHANLS_MAX; i++) {
sc_access.reg_addr = ADC_CHNL_START_ADDR + i;
ret = sst_sc_reg_access(&sc_access, PMIC_READ, 1);
if (ret)
return ret;
if (sc_access.value & MSIC_STOPBIT_MASK) {
ret = i;
break;
}
}
return (ret > ADC_LOOP_MAX) ? (-EINVAL) : ret;
}
/**
* mid_initialize_adc - initializing the ADC
* @dev: our device structure
*
* Initialize the ADC for reading thermistor values. Can sleep.
*/
static inline int mid_initialize_adc(void)
{
int base_addr, chnl_addr;
int ret;
static int channel_index;
struct sc_reg_access sc_access = {0,};
/* Index of the first channel in which the stop bit is set */
channel_index = find_free_channel();
if (channel_index < 0) {
pr_err("No free ADC channels");
return channel_index;
}
base_addr = ADC_CHNL_START_ADDR + channel_index;
if (!(channel_index == 0 || channel_index == ADC_LOOP_MAX)) {
/* Reset stop bit for channels other than 0 and 12 */
ret = reset_stopbit(base_addr);
if (ret)
return ret;
/* Index of the first free channel */
base_addr++;
channel_index++;
}
/* Since this is the last channel, set the stop bit
to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
sc_access.reg_addr = base_addr;
sc_access.value = AUDIO_DETECT_CODE | 0x10;
ret = sst_sc_reg_access(&sc_access, PMIC_WRITE, 1);
if (ret) {
pr_err("unable to enable ADC");
return ret;
}
chnl_addr = ADC_DATA_START_ADDR + 2 * channel_index;
pr_debug("mid_initialize : %x", chnl_addr);
configure_adc(1);
return chnl_addr;
}
#endif
......@@ -29,7 +29,6 @@
#include <sound/core.h>
#include <sound/control.h>
#include "jack.h"
#include "intel_sst.h"
#include "intel_sst_ioctl.h"
#include "intelmid_snd_control.h"
......
......@@ -31,7 +31,6 @@
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
#include "jack.h"
#include "intel_sst.h"
#include "intel_sst_ioctl.h"
#include "intelmid_snd_control.h"
......
......@@ -30,9 +30,10 @@
#include <linux/pci.h>
#include <linux/file.h>
#include <sound/control.h>
#include "intel_sst.h"
#include "intelmid_snd_control.h"
#include "intelmid.h"
enum _reg_v1 {
VOICEPORT1 = 0x180,
......@@ -64,6 +65,7 @@ enum _reg_v1 {
};
int rev_id = 0x20;
static bool jack_det_enabled;
/****
* fs_init_card - initialize the sound card
......@@ -494,10 +496,7 @@ static int fs_set_selected_output_dev(u8 value)
}
}
static int fs_set_selected_lineout_dev(u8 value)
{
return 0;
}
static int fs_set_mute(int dev_id, u8 value)
{
struct sc_reg_access sc_access[6] = {{0,},};
......@@ -756,10 +755,93 @@ static int fs_get_vol(int dev_id, int *value)
return retval;
}
static void fs_pmic_irq_enable(void *data)
{
struct snd_intelmad *intelmaddata = data;
struct sc_reg_access sc_access[] = {
{0x187, 0x00, MASK7},
{0x188, 0x10, MASK4},
{0x18b, 0x10, MASK4},
};
struct sc_reg_access sc_access_write[] = {
{0x198, 0x00, 0x0},
};
pr_debug("Audio interrupt enable\n");
sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, 3);
sst_sc_reg_access(sc_access_write, PMIC_WRITE, 1);
intelmaddata->jack[0].jack_status = 0;
/*intelmaddata->jack[1].jack_status = 0;*/
jack_det_enabled = true;
return;
}
static void fs_pmic_irq_cb(void *cb_data, u8 value)
{
struct mad_jack *mjack = NULL;
struct snd_intelmad *intelmaddata = cb_data;
unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
mjack = &intelmaddata->jack[0];
if (value & 0x4) {
if (!jack_det_enabled)
fs_pmic_irq_enable(intelmaddata);
/* send headphone detect */
pr_debug(":MAD headphone %d\n", value & 0x4);
present = !(mjack->jack_status);
mjack->jack_status = present;
jack_event_flag = 1;
mjack->jack.type = SND_JACK_HEADPHONE;
}
if (value & 0x2) {
/* send short push */
pr_debug(":MAD short push %d\n", value & 0x2);
present = 1;
jack_event_flag = 1;
buttonpressflag = 1;
mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
}
if (value & 0x1) {
/* send long push */
pr_debug(":MAD long push %d\n", value & 0x1);
present = 1;
jack_event_flag = 1;
buttonpressflag = 1;
mjack->jack.type = MID_JACK_HS_LONG_PRESS;
}
if (value & 0x8) {
if (!jack_det_enabled)
fs_pmic_irq_enable(intelmaddata);
/* send headset detect */
pr_debug(":MAD headset = %d\n", value & 0x8);
present = !(mjack->jack_status);
mjack->jack_status = present;
jack_event_flag = 1;
mjack->jack.type = SND_JACK_HEADSET;
}
if (jack_event_flag)
sst_mad_send_jack_report(&mjack->jack,
buttonpressflag, present);
return;
}
static int fs_jack_enable(void)
{
return 0;
}
struct snd_pmic_ops snd_pmic_ops_fs = {
.set_input_dev = fs_set_selected_input_dev,
.set_output_dev = fs_set_selected_output_dev,
.set_lineout_dev = fs_set_selected_lineout_dev,
.set_mute = fs_set_mute,
.get_mute = fs_get_mute,
.set_vol = fs_set_vol,
......@@ -769,9 +851,16 @@ struct snd_pmic_ops snd_pmic_ops_fs = {
.set_pcm_voice_params = fs_set_pcm_voice_params,
.set_voice_port = fs_set_voice_port,
.set_audio_port = fs_set_audio_port,
.power_up_pmic_pb = fs_power_up_pb,
.power_up_pmic_cp = fs_power_up_cp,
.power_down_pmic_pb = fs_power_down_pb,
.power_down_pmic_cp = fs_power_down_cp,
.power_down_pmic = fs_power_down,
.power_up_pmic_pb = fs_power_up_pb,
.power_up_pmic_cp = fs_power_up_cp,
.power_down_pmic_pb = fs_power_down_pb,
.power_down_pmic_cp = fs_power_down_cp,
.power_down_pmic = fs_power_down,
.pmic_irq_cb = fs_pmic_irq_cb,
/*
* Jack detection enabling
* need be delayed till first IRQ happen.
*/
.pmic_irq_enable = NULL,
.pmic_jack_enable = fs_jack_enable,
};
......@@ -31,7 +31,6 @@
#include <linux/file.h>
#include <asm/mrst.h>
#include <sound/pcm.h>
#include "jack.h"
#include <sound/pcm_params.h>
#include <sound/control.h>
#include <sound/initval.h>
......@@ -584,10 +583,6 @@ static int mx_set_selected_input_dev(u8 dev_id)
}
return sst_sc_reg_access(sc_access, PMIC_WRITE, num_reg);
}
static int mx_set_selected_lineout_dev(u8 dev_id)
{
return 0;
}
static int mx_set_mute(int dev_id, u8 value)
{
......@@ -835,10 +830,132 @@ static int mx_get_vol(int dev_id, int *value)
return retval;
}
static u8 mx_get_jack_status(void)
{
struct sc_reg_access sc_access_read = {0,};
sc_access_read.reg_addr = 0x201;
sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
pr_debug("value returned = 0x%x\n", sc_access_read.value);
return sc_access_read.value;
}
static void mx_pmic_irq_enable(void *data)
{
struct snd_intelmad *intelmaddata = data;
intelmaddata->jack_prev_state = 0xc0;
return;
}
static void mx_pmic_irq_cb(void *cb_data, u8 intsts)
{
u8 jack_cur_status, jack_prev_state = 0;
struct mad_jack *mjack = NULL;
unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
time_t timediff;
struct snd_intelmad *intelmaddata = cb_data;
mjack = &intelmaddata->jack[0];
if (intsts & 0x2) {
jack_cur_status = mx_get_jack_status();
jack_prev_state = intelmaddata->jack_prev_state;
if ((jack_prev_state == 0xc0) && (jack_cur_status == 0x40)) {
/*headset insert detected. */
pr_debug("MAD headset inserted\n");
present = 1;
jack_event_flag = 1;
mjack->jack_status = 1;
mjack->jack.type = SND_JACK_HEADSET;
}
if ((jack_prev_state == 0xc0) && (jack_cur_status == 0x00)) {
/* headphone insert detected. */
pr_debug("MAD headphone inserted\n");
present = 1;
jack_event_flag = 1;
mjack->jack.type = SND_JACK_HEADPHONE;
}
if ((jack_prev_state == 0x40) && (jack_cur_status == 0xc0)) {
/* headset remove detected. */
pr_debug("MAD headset removed\n");
present = 0;
jack_event_flag = 1;
mjack->jack_status = 0;
mjack->jack.type = SND_JACK_HEADSET;
}
if ((jack_prev_state == 0x00) && (jack_cur_status == 0xc0)) {
/* headphone remove detected. */
pr_debug("MAD headphone removed\n");
present = 0;
jack_event_flag = 1;
mjack->jack.type = SND_JACK_HEADPHONE;
}
if ((jack_prev_state == 0x40) && (jack_cur_status == 0x00)) {
/* button pressed */
do_gettimeofday(&mjack->buttonpressed);
pr_debug("MAD button press detected\n");
}
if ((jack_prev_state == 0x00) && (jack_cur_status == 0x40)) {
if (mjack->jack_status) {
/*button pressed */
do_gettimeofday(
&mjack->buttonreleased);
/*button pressed */
pr_debug("MAD Button Released detected\n");
timediff = mjack->buttonreleased.tv_sec -
mjack->buttonpressed.tv_sec;
buttonpressflag = 1;
if (timediff > 1) {
pr_debug("MAD long press dtd\n");
/* send headphone detect/undetect */
present = 1;
jack_event_flag = 1;
mjack->jack.type =
MID_JACK_HS_LONG_PRESS;
} else {
pr_debug("MAD short press dtd\n");
/* send headphone detect/undetect */
present = 1;
jack_event_flag = 1;
mjack->jack.type =
MID_JACK_HS_SHORT_PRESS;
}
} else {
/***workaround for maxim
hw issue,0x00 t 0x40 is not
a valid transiton for Headset insertion */
/*headset insert detected. */
pr_debug("MAD headset inserted\n");
present = 1;
jack_event_flag = 1;
mjack->jack_status = 1;
mjack->jack.type = SND_JACK_HEADSET;
}
}
intelmaddata->jack_prev_state = jack_cur_status;
pr_debug("mx_pmic_irq_cb prv_state= 0x%x\n",
intelmaddata->jack_prev_state);
}
if (jack_event_flag)
sst_mad_send_jack_report(&mjack->jack,
buttonpressflag, present);
}
static int mx_jack_enable(void)
{
return 0;
}
struct snd_pmic_ops snd_pmic_ops_mx = {
.set_input_dev = mx_set_selected_input_dev,
.set_output_dev = mx_set_selected_output_dev,
.set_lineout_dev = mx_set_selected_lineout_dev,
.set_mute = mx_set_mute,
.get_mute = mx_get_mute,
.set_vol = mx_set_vol,
......@@ -848,10 +965,13 @@ struct snd_pmic_ops snd_pmic_ops_mx = {
.set_pcm_voice_params = mx_set_pcm_voice_params,
.set_voice_port = mx_set_voice_port,
.set_audio_port = mx_set_audio_port,
.power_up_pmic_pb = mx_power_up_pb,
.power_up_pmic_cp = mx_power_up_cp,
.power_down_pmic_pb = mx_power_down_pb,
.power_down_pmic_cp = mx_power_down_cp,
.power_down_pmic = mx_power_down,
.power_up_pmic_pb = mx_power_up_pb,
.power_up_pmic_cp = mx_power_up_cp,
.power_down_pmic_pb = mx_power_down_pb,
.power_down_pmic_cp = mx_power_down_cp,
.power_down_pmic = mx_power_down,
.pmic_irq_cb = mx_pmic_irq_cb,
.pmic_irq_enable = mx_pmic_irq_enable,
.pmic_jack_enable = mx_jack_enable,
};
......@@ -30,8 +30,10 @@
#include <linux/pci.h>
#include <linux/file.h>
#include <sound/control.h>
#include "intel_sst.h"
#include "intelmid_snd_control.h"
#include "intelmid.h"
enum reg_v3 {
VAUDIOCNT = 0x51,
......@@ -884,10 +886,7 @@ static int nc_set_selected_input_dev(u8 value)
}
return sst_sc_reg_access(sc_access, PMIC_READ_MODIFY, num_val);
}
static int nc_set_selected_lineout_dev(u8 dev_id)
{
return 0;
}
static int nc_get_mute(int dev_id, u8 *value)
{
int retval = 0, mask = 0;
......@@ -989,10 +988,66 @@ static int nc_get_vol(int dev_id, int *value)
return retval;
}
static void nc_pmic_irq_cb(void *cb_data, u8 intsts)
{
u8 value = 0;
struct mad_jack *mjack = NULL;
unsigned int present = 0, jack_event_flag = 0, buttonpressflag = 0;
struct snd_intelmad *intelmaddata = cb_data;
struct sc_reg_access sc_access_read = {0,};
sc_access_read.reg_addr = 0x132;
sst_sc_reg_access(&sc_access_read, PMIC_READ, 1);
value = (sc_access_read.value);
pr_debug("value returned = 0x%x\n", value);
mjack = &intelmaddata->jack[0];
if (intsts & 0x1) {
pr_debug("SST DBG:MAD headset detected\n");
/* send headset detect/undetect */
present = (value == 0x1) ? 1 : 0;
jack_event_flag = 1;
mjack->jack.type = SND_JACK_HEADSET;
}
if (intsts & 0x2) {
pr_debug(":MAD headphone detected\n");
/* send headphone detect/undetect */
present = (value == 0x2) ? 1 : 0;
jack_event_flag = 1;
mjack->jack.type = SND_JACK_HEADPHONE;
}
if (intsts & 0x4) {
pr_debug("MAD short push detected\n");
/* send short push */
present = 1;
jack_event_flag = 1;
buttonpressflag = 1;
mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
}
if (intsts & 0x8) {
pr_debug(":MAD long push detected\n");
/* send long push */
present = 1;
jack_event_flag = 1;
buttonpressflag = 1;
mjack->jack.type = MID_JACK_HS_SHORT_PRESS;
}
if (jack_event_flag)
sst_mad_send_jack_report(&mjack->jack,
buttonpressflag, present);
}
static int nc_jack_enable(void)
{
return 0;
}
struct snd_pmic_ops snd_pmic_ops_nc = {
.set_input_dev = nc_set_selected_input_dev,
.set_output_dev = nc_set_selected_output_dev,
.set_lineout_dev = nc_set_selected_lineout_dev,
.set_mute = nc_set_mute,
.get_mute = nc_get_mute,
.set_vol = nc_set_vol,
......@@ -1006,5 +1061,7 @@ struct snd_pmic_ops snd_pmic_ops_nc = {
.power_up_pmic_cp = nc_power_up_cp,
.power_down_pmic_pb = nc_power_down_pb,
.power_down_pmic_cp = nc_power_down_cp,
.power_down_pmic = nc_power_down,
.power_down_pmic = nc_power_down,
.pmic_irq_cb = nc_pmic_irq_cb,
.pmic_jack_enable = nc_jack_enable,
};
/* Temporary staging glue */
#include <sound/jack.h>
/* These want adding to jack.h as enum entries once approved */
#define SND_JACK_HS_SHORT_PRESS (SND_JACK_HEADSET | 0x0020)
#define SND_JACK_HS_LONG_PRESS (SND_JACK_HEADSET | 0x0040)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment