aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2011-07-12 02:25:03 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2011-07-13 11:38:04 -0400
commitd96ca3cd0bcefdcd1d9ad1f2610dcd959fccd252 (patch)
treee7dddc5b7104d02ae765081024c4e9ea1bf2a3ba
parentb70a51bab9c64d2cabf7c052ebb3f5db2801fd05 (diff)
ASoC: Implement DC servo completion IRQ handling for wm_hubs devices
The individual devices should set the flag dcs_done_irq in the hubs shared data structure to indicate that they will flag the interrupt by calling wm_hubs_dcs_done(). Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/codecs/wm_hubs.c34
-rw-r--r--sound/soc/codecs/wm_hubs.h8
2 files changed, 37 insertions, 5 deletions
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 7e60e2279671..5c2d5657b472 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -63,9 +63,11 @@ static const struct soc_enum speaker_mode =
63 63
64static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) 64static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
65{ 65{
66 struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
66 unsigned int reg; 67 unsigned int reg;
67 int count = 0; 68 int count = 0;
68 unsigned int val; 69 unsigned int val;
70 unsigned long timeout;
69 71
70 val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; 72 val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1;
71 73
@@ -74,18 +76,37 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
74 76
75 dev_dbg(codec->dev, "Waiting for DC servo...\n"); 77 dev_dbg(codec->dev, "Waiting for DC servo...\n");
76 78
77 do { 79 if (hubs->dcs_done_irq) {
78 count++; 80 timeout = wait_for_completion_timeout(&hubs->dcs_done,
79 msleep(1); 81 msecs_to_jiffies(500));
82 if (timeout == 0)
83 dev_warn(codec->dev, "No DC servo interrupt\n");
84
80 reg = snd_soc_read(codec, WM8993_DC_SERVO_0); 85 reg = snd_soc_read(codec, WM8993_DC_SERVO_0);
81 dev_dbg(codec->dev, "DC servo: %x\n", reg); 86 } else {
82 } while (reg & op && count < 400); 87 do {
88 count++;
89 msleep(1);
90 reg = snd_soc_read(codec, WM8993_DC_SERVO_0);
91 dev_dbg(codec->dev, "DC servo: %x\n", reg);
92 } while (reg & op && count < 400);
93 }
83 94
84 if (reg & op) 95 if (reg & op)
85 dev_err(codec->dev, "Timed out waiting for DC Servo %x\n", 96 dev_err(codec->dev, "Timed out waiting for DC Servo %x\n",
86 op); 97 op);
87} 98}
88 99
100irqreturn_t wm_hubs_dcs_done(int irq, void *data)
101{
102 struct wm_hubs_data *hubs = data;
103
104 complete(&hubs->dcs_done);
105
106 return IRQ_HANDLED;
107}
108EXPORT_SYMBOL_GPL(wm_hubs_dcs_done);
109
89/* 110/*
90 * Startup calibration of the DC servo 111 * Startup calibration of the DC servo
91 */ 112 */
@@ -863,8 +884,11 @@ EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_controls);
863int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, 884int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec,
864 int lineout1_diff, int lineout2_diff) 885 int lineout1_diff, int lineout2_diff)
865{ 886{
887 struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
866 struct snd_soc_dapm_context *dapm = &codec->dapm; 888 struct snd_soc_dapm_context *dapm = &codec->dapm;
867 889
890 init_completion(&hubs->dcs_done);
891
868 snd_soc_dapm_add_routes(dapm, analogue_routes, 892 snd_soc_dapm_add_routes(dapm, analogue_routes,
869 ARRAY_SIZE(analogue_routes)); 893 ARRAY_SIZE(analogue_routes));
870 894
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index 0d290d2740ec..676b1252ab91 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -14,6 +14,9 @@
14#ifndef _WM_HUBS_H 14#ifndef _WM_HUBS_H
15#define _WM_HUBS_H 15#define _WM_HUBS_H
16 16
17#include <linux/completion.h>
18#include <linux/interrupt.h>
19
17struct snd_soc_codec; 20struct snd_soc_codec;
18 21
19extern const unsigned int wm_hubs_spkmix_tlv[]; 22extern const unsigned int wm_hubs_spkmix_tlv[];
@@ -28,6 +31,9 @@ struct wm_hubs_data {
28 31
29 bool class_w; 32 bool class_w;
30 u16 class_w_dcs; 33 u16 class_w_dcs;
34
35 bool dcs_done_irq;
36 struct completion dcs_done;
31}; 37};
32 38
33extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); 39extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *);
@@ -38,4 +44,6 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
38 int jd_scthr, int jd_thr, 44 int jd_scthr, int jd_thr,
39 int micbias1_lvl, int micbias2_lvl); 45 int micbias1_lvl, int micbias2_lvl);
40 46
47extern irqreturn_t wm_hubs_dcs_done(int irq, void *data);
48
41#endif 49#endif