diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-04-05 14:19:32 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-04-05 14:19:32 -0400 |
commit | 53a61d967a480307db4c8f7950ddb8bb1a0fda9b (patch) | |
tree | 6b3ce07b14db2986a175f30e6477ed40445c7c17 /sound/soc | |
parent | 8876698406147986a9a7748586a54c4b14514c0e (diff) | |
parent | 5f712b2b73a9fc87fcc52124cfe8adefaa0c92f5 (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.c | 56 | ||||
-rw-r--r-- | sound/soc/codecs/wm_hubs.c | 83 | ||||
-rw-r--r-- | sound/soc/codecs/wm_hubs.h | 1 | ||||
-rw-r--r-- | sound/soc/omap/omap-pcm.c | 17 |
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[] = { | |||
62 | static const struct soc_enum speaker_mode = | 62 | static 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 | ||
65 | static void wait_for_dc_servo(struct snd_soc_codec *codec) | 65 | static 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) | |||
86 | static void calibrate_dc_servo(struct snd_soc_codec *codec) | 92 | static 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 */ |
22 | struct wm_hubs_data { | 22 | struct 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; |