Skip to content

Commit

Permalink
ASoC: twl6040: Add jack support for headset and handset
Browse files Browse the repository at this point in the history
This patch adds support for reporting twl6040 headset and
handset jack events.

The machine driver retrieves and report the status  through
twl6040_hs_jack_detect.

A workq is used to debounce of the irq.

Signed-off-by: Jorge Eduardo Candelaria <jorge.candelaria@ti.com>
Signed-off-by: Misael Lopez Cruz <misael.lopez@ti.com>
Signed-off-by: Margarita Olaya Cabrera <magi.olaya@ti.com>
Signed-off-by: Liam Girdwood <lrg@slimlogic.co.uk>
  • Loading branch information
Jorge Eduardo Candelaria authored and Liam Girdwood committed Dec 14, 2010
1 parent dcdeda4 commit a2d2362
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 0 deletions.
67 changes: 67 additions & 0 deletions sound/soc/codecs/twl6040.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@
#define TWL6040_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)

struct twl6040_jack_data {
struct snd_soc_jack *jack;
int report;
};

/* codec private data */
struct twl6040_data {
int audpwron;
Expand All @@ -52,6 +57,11 @@ struct twl6040_data {
unsigned int sysclk;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
struct completion ready;
struct twl6040_jack_data hs_jack;
struct snd_soc_codec *codec;
struct workqueue_struct *workqueue;
struct delayed_work delayed_work;
struct mutex mutex;
};

/*
Expand Down Expand Up @@ -381,6 +391,47 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
return 0;
}

void twl6040_hs_jack_report(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, int report)
{
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
int status;

mutex_lock(&priv->mutex);

/* Sync status */
status = twl6040_read_reg_volatile(codec, TWL6040_REG_STATUS);
if (status & TWL6040_PLUGCOMP)
snd_soc_jack_report(jack, report, report);
else
snd_soc_jack_report(jack, 0, report);

mutex_unlock(&priv->mutex);
}

void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, int report)
{
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
struct twl6040_jack_data *hs_jack = &priv->hs_jack;

hs_jack->jack = jack;
hs_jack->report = report;

twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
}
EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);

static void twl6040_accessory_work(struct work_struct *work)
{
struct twl6040_data *priv = container_of(work,
struct twl6040_data, delayed_work.work);
struct snd_soc_codec *codec = priv->codec;
struct twl6040_jack_data *hs_jack = &priv->hs_jack;

twl6040_hs_jack_report(codec, hs_jack->jack, hs_jack->report);
}

/* audio interrupt handler */
static irqreturn_t twl6040_naudint_handler(int irq, void *data)
{
Expand All @@ -396,6 +447,9 @@ static irqreturn_t twl6040_naudint_handler(int irq, void *data)
break;
case TWL6040_PLUGINT:
case TWL6040_UNPLUGINT:
queue_delayed_work(priv->workqueue, &priv->delayed_work,
msecs_to_jiffies(200));
break;
case TWL6040_HOOKINT:
break;
case TWL6040_HFINT:
Expand Down Expand Up @@ -1023,6 +1077,8 @@ static int twl6040_probe(struct snd_soc_codec *codec)
return -ENOMEM;
snd_soc_codec_set_drvdata(codec, priv);

priv->codec = codec;

if (twl_codec) {
audpwron = twl_codec->audpwron_gpio;
naudint = twl_codec->naudint_irq;
Expand All @@ -1033,6 +1089,14 @@ static int twl6040_probe(struct snd_soc_codec *codec)

priv->audpwron = audpwron;
priv->naudint = naudint;
priv->workqueue = create_singlethread_workqueue("twl6040-codec");

if (!priv->workqueue)
goto work_err;

INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);

mutex_init(&priv->mutex);

init_completion(&priv->ready);

Expand Down Expand Up @@ -1089,6 +1153,8 @@ static int twl6040_probe(struct snd_soc_codec *codec)
if (gpio_is_valid(audpwron))
gpio_free(audpwron);
gpio1_err:
destroy_workqueue(priv->workqueue);
work_err:
kfree(priv);
return ret;
}
Expand All @@ -1107,6 +1173,7 @@ static int twl6040_remove(struct snd_soc_codec *codec)
if (naudint)
free_irq(naudint, codec);

destroy_workqueue(priv->workqueue);
kfree(priv);

return 0;
Expand Down
7 changes: 7 additions & 0 deletions sound/soc/codecs/twl6040.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,4 +135,11 @@
#define TWL6040_HPPLL_ID 1
#define TWL6040_LPPLL_ID 2

/* STATUS (0x2E) fields */

#define TWL6040_PLUGCOMP 0x02

void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, int report);

#endif /* End of __TWL6040_H__ */

0 comments on commit a2d2362

Please sign in to comment.