aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2010-04-05 14:19:32 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2010-04-05 14:19:32 -0400
commit53a61d967a480307db4c8f7950ddb8bb1a0fda9b (patch)
tree6b3ce07b14db2986a175f30e6477ed40445c7c17 /sound/soc
parent8876698406147986a9a7748586a54c4b14514c0e (diff)
parent5f712b2b73a9fc87fcc52124cfe8adefaa0c92f5 (diff)
Merge branch 'for-2.6.34' into for-2.6.35
Conflicts due to context changes next to the backported DMA data change: include/sound/soc.h
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/wm8994.c56
-rw-r--r--sound/soc/codecs/wm_hubs.c83
-rw-r--r--sound/soc/codecs/wm_hubs.h1
-rw-r--r--sound/soc/omap/omap-pcm.c17
4 files changed, 91 insertions, 66 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index fc3dce814924..e00201e0820e 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -3015,34 +3015,39 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
3015 break; 3015 break;
3016 3016
3017 case SND_SOC_BIAS_OFF: 3017 case SND_SOC_BIAS_OFF:
3018 /* Switch over to startup biases */ 3018 if (codec->bias_level == SND_SOC_BIAS_STANDBY) {
3019 snd_soc_update_bits(codec, WM8994_ANTIPOP_2, 3019 /* Switch over to startup biases */
3020 WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | 3020 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
3021 WM8994_VMID_BUF_ENA | 3021 WM8994_BIAS_SRC |
3022 WM8994_VMID_RAMP_MASK, 3022 WM8994_STARTUP_BIAS_ENA |
3023 WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | 3023 WM8994_VMID_BUF_ENA |
3024 WM8994_VMID_BUF_ENA | 3024 WM8994_VMID_RAMP_MASK,
3025 (1 << WM8994_VMID_RAMP_SHIFT)); 3025 WM8994_BIAS_SRC |
3026 3026 WM8994_STARTUP_BIAS_ENA |
3027 /* Disable main biases */ 3027 WM8994_VMID_BUF_ENA |
3028 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, 3028 (1 << WM8994_VMID_RAMP_SHIFT));
3029 WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
3030 3029
3031 /* Discharge line */ 3030 /* Disable main biases */
3032 snd_soc_update_bits(codec, WM8994_ANTIPOP_1, 3031 snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
3033 WM8994_LINEOUT1_DISCH | 3032 WM8994_BIAS_ENA |
3034 WM8994_LINEOUT2_DISCH, 3033 WM8994_VMID_SEL_MASK, 0);
3035 WM8994_LINEOUT1_DISCH |
3036 WM8994_LINEOUT2_DISCH);
3037 3034
3038 msleep(5); 3035 /* Discharge line */
3036 snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
3037 WM8994_LINEOUT1_DISCH |
3038 WM8994_LINEOUT2_DISCH,
3039 WM8994_LINEOUT1_DISCH |
3040 WM8994_LINEOUT2_DISCH);
3039 3041
3040 /* Switch off startup biases */ 3042 msleep(5);
3041 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
3042 WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA |
3043 WM8994_VMID_BUF_ENA |
3044 WM8994_VMID_RAMP_MASK, 0);
3045 3043
3044 /* Switch off startup biases */
3045 snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
3046 WM8994_BIAS_SRC |
3047 WM8994_STARTUP_BIAS_ENA |
3048 WM8994_VMID_BUF_ENA |
3049 WM8994_VMID_RAMP_MASK, 0);
3050 }
3046 break; 3051 break;
3047 } 3052 }
3048 codec->bias_level = level; 3053 codec->bias_level = level;
@@ -3866,11 +3871,12 @@ static int wm8994_codec_probe(struct platform_device *pdev)
3866 case 3: 3871 case 3:
3867 wm8994->hubs.dcs_codes = -5; 3872 wm8994->hubs.dcs_codes = -5;
3868 wm8994->hubs.hp_startup_mode = 1; 3873 wm8994->hubs.hp_startup_mode = 1;
3874 wm8994->hubs.dcs_readback_mode = 1;
3869 break; 3875 break;
3870 default: 3876 default:
3877 wm8994->hubs.dcs_readback_mode = 1;
3871 break; 3878 break;
3872 } 3879 }
3873
3874 3880
3875 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, 3881 ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
3876 wm8994_mic_irq, "Mic 1 detect", wm8994); 3882 wm8994_mic_irq, "Mic 1 detect", wm8994);
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index 486bdd21a98a..e1f225a3ac46 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -62,21 +62,27 @@ static const char *speaker_mode_text[] = {
62static const struct soc_enum speaker_mode = 62static const struct soc_enum speaker_mode =
63 SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); 63 SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text);
64 64
65static void wait_for_dc_servo(struct snd_soc_codec *codec) 65static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op)
66{ 66{
67 unsigned int reg; 67 unsigned int reg;
68 int count = 0; 68 int count = 0;
69 unsigned int val;
70
71 val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1;
72
73 /* Trigger the command */
74 snd_soc_write(codec, WM8993_DC_SERVO_0, val);
69 75
70 dev_dbg(codec->dev, "Waiting for DC servo...\n"); 76 dev_dbg(codec->dev, "Waiting for DC servo...\n");
71 77
72 do { 78 do {
73 count++; 79 count++;
74 msleep(1); 80 msleep(1);
75 reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0); 81 reg = snd_soc_read(codec, WM8993_DC_SERVO_0);
76 dev_dbg(codec->dev, "DC servo: %x\n", reg); 82 dev_dbg(codec->dev, "DC servo: %x\n", reg);
77 } while (reg & WM8993_DCS_DATAPATH_BUSY && count < 400); 83 } while (reg & op && count < 400);
78 84
79 if (reg & WM8993_DCS_DATAPATH_BUSY) 85 if (reg & op)
80 dev_err(codec->dev, "Timed out waiting for DC Servo\n"); 86 dev_err(codec->dev, "Timed out waiting for DC Servo\n");
81} 87}
82 88
@@ -86,51 +92,58 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec)
86static void calibrate_dc_servo(struct snd_soc_codec *codec) 92static void calibrate_dc_servo(struct snd_soc_codec *codec)
87{ 93{
88 struct wm_hubs_data *hubs = codec->private_data; 94 struct wm_hubs_data *hubs = codec->private_data;
89 u16 reg, dcs_cfg; 95 u16 reg, reg_l, reg_r, dcs_cfg;
90 96
91 /* Set for 32 series updates */ 97 /* Set for 32 series updates */
92 snd_soc_update_bits(codec, WM8993_DC_SERVO_1, 98 snd_soc_update_bits(codec, WM8993_DC_SERVO_1,
93 WM8993_DCS_SERIES_NO_01_MASK, 99 WM8993_DCS_SERIES_NO_01_MASK,
94 32 << WM8993_DCS_SERIES_NO_01_SHIFT); 100 32 << WM8993_DCS_SERIES_NO_01_SHIFT);
95 101 wait_for_dc_servo(codec,
96 /* Enable the DC servo. Write all bits to avoid triggering startup 102 WM8993_DCS_TRIG_SERIES_0 | WM8993_DCS_TRIG_SERIES_1);
97 * or write calibration.
98 */
99 snd_soc_update_bits(codec, WM8993_DC_SERVO_0,
100 0xFFFF,
101 WM8993_DCS_ENA_CHAN_0 |
102 WM8993_DCS_ENA_CHAN_1 |
103 WM8993_DCS_TRIG_SERIES_1 |
104 WM8993_DCS_TRIG_SERIES_0);
105
106 wait_for_dc_servo(codec);
107 103
108 /* Apply correction to DC servo result */ 104 /* Apply correction to DC servo result */
109 if (hubs->dcs_codes) { 105 if (hubs->dcs_codes) {
110 dev_dbg(codec->dev, "Applying %d code DC servo correction\n", 106 dev_dbg(codec->dev, "Applying %d code DC servo correction\n",
111 hubs->dcs_codes); 107 hubs->dcs_codes);
112 108
109 /* Different chips in the family support different
110 * readback methods.
111 */
112 switch (hubs->dcs_readback_mode) {
113 case 0:
114 reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1)
115 & WM8993_DCS_INTEG_CHAN_0_MASK;;
116 reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2)
117 & WM8993_DCS_INTEG_CHAN_1_MASK;
118 break;
119 case 1:
120 reg = snd_soc_read(codec, WM8993_DC_SERVO_3);
121 reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
122 >> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
123 reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
124 break;
125 default:
126 WARN(1, "Unknown DCS readback method");
127 break;
128 }
129
113 /* HPOUT1L */ 130 /* HPOUT1L */
114 reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) & 131 if (reg_l + hubs->dcs_codes > 0 &&
115 WM8993_DCS_INTEG_CHAN_0_MASK;; 132 reg_l + hubs->dcs_codes < 0xff)
116 reg += hubs->dcs_codes; 133 reg_l += hubs->dcs_codes;
117 dcs_cfg = reg << WM8993_DCS_DAC_WR_VAL_1_SHIFT; 134 dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
118 135
119 /* HPOUT1R */ 136 /* HPOUT1R */
120 reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) & 137 if (reg_r + hubs->dcs_codes > 0 &&
121 WM8993_DCS_INTEG_CHAN_1_MASK; 138 reg_r + hubs->dcs_codes < 0xff)
122 reg += hubs->dcs_codes; 139 reg_r += hubs->dcs_codes;
123 dcs_cfg |= reg; 140 dcs_cfg |= reg_r;
124 141
125 /* Do it */ 142 /* Do it */
126 snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); 143 snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg);
127 snd_soc_update_bits(codec, WM8993_DC_SERVO_0, 144 wait_for_dc_servo(codec,
128 WM8993_DCS_TRIG_DAC_WR_0 | 145 WM8993_DCS_TRIG_DAC_WR_0 |
129 WM8993_DCS_TRIG_DAC_WR_1, 146 WM8993_DCS_TRIG_DAC_WR_1);
130 WM8993_DCS_TRIG_DAC_WR_0 |
131 WM8993_DCS_TRIG_DAC_WR_1);
132
133 wait_for_dc_servo(codec);
134 } 147 }
135} 148}
136 149
@@ -141,10 +154,16 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
141 struct snd_ctl_elem_value *ucontrol) 154 struct snd_ctl_elem_value *ucontrol)
142{ 155{
143 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); 156 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
157 struct wm_hubs_data *hubs = codec->private_data;
144 int ret; 158 int ret;
145 159
146 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); 160 ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
147 161
162 /* If we're applying an offset correction then updating the
163 * callibration would be likely to introduce further offsets. */
164 if (hubs->dcs_codes)
165 return ret;
166
148 /* Only need to do this if the outputs are active */ 167 /* Only need to do this if the outputs are active */
149 if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) 168 if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1)
150 & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) 169 & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA))
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index 420104fe9c90..e51c16683589 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -21,6 +21,7 @@ extern const unsigned int wm_hubs_spkmix_tlv[];
21/* This *must* be the first element of the codec->private_data struct */ 21/* This *must* be the first element of the codec->private_data struct */
22struct wm_hubs_data { 22struct wm_hubs_data {
23 int dcs_codes; 23 int dcs_codes;
24 int dcs_readback_mode;
24 int hp_startup_mode; 25 int hp_startup_mode;
25}; 26};
26 27
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 39538c0f81f0..39456447132c 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -60,12 +60,11 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data)
60 struct omap_runtime_data *prtd = runtime->private_data; 60 struct omap_runtime_data *prtd = runtime->private_data;
61 unsigned long flags; 61 unsigned long flags;
62 62
63 if ((cpu_is_omap1510()) && 63 if ((cpu_is_omap1510())) {
64 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) {
65 /* 64 /*
66 * OMAP1510 doesn't fully support DMA progress counter 65 * OMAP1510 doesn't fully support DMA progress counter
67 * and there is no software emulation implemented yet, 66 * and there is no software emulation implemented yet,
68 * so have to maintain our own playback progress counter 67 * so have to maintain our own progress counters
69 * that can be used by omap_pcm_pointer() instead. 68 * that can be used by omap_pcm_pointer() instead.
70 */ 69 */
71 spin_lock_irqsave(&prtd->lock, flags); 70 spin_lock_irqsave(&prtd->lock, flags);
@@ -191,8 +190,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
191 dma_params.frame_count = runtime->periods; 190 dma_params.frame_count = runtime->periods;
192 omap_set_dma_params(prtd->dma_ch, &dma_params); 191 omap_set_dma_params(prtd->dma_ch, &dma_params);
193 192
194 if ((cpu_is_omap1510()) && 193 if ((cpu_is_omap1510()))
195 (substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
196 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | 194 omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ |
197 OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); 195 OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
198 else 196 else
@@ -250,14 +248,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream)
250 dma_addr_t ptr; 248 dma_addr_t ptr;
251 snd_pcm_uframes_t offset; 249 snd_pcm_uframes_t offset;
252 250
253 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { 251 if (cpu_is_omap1510()) {
252 offset = prtd->period_index * runtime->period_size;
253 } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
254 ptr = omap_get_dma_dst_pos(prtd->dma_ch); 254 ptr = omap_get_dma_dst_pos(prtd->dma_ch);
255 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); 255 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
256 } else if (!(cpu_is_omap1510())) { 256 } else {
257 ptr = omap_get_dma_src_pos(prtd->dma_ch); 257 ptr = omap_get_dma_src_pos(prtd->dma_ch);
258 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); 258 offset = bytes_to_frames(runtime, ptr - runtime->dma_addr);
259 } else 259 }
260 offset = prtd->period_index * runtime->period_size;
261 260
262 if (offset >= runtime->buffer_size) 261 if (offset >= runtime->buffer_size)
263 offset = 0; 262 offset = 0;