Loading include/sound/soc.h +1 −1 Original line number Diff line number Diff line Loading @@ -381,7 +381,7 @@ struct snd_soc_pcm_stream { unsigned int rate_max; /* max rate */ unsigned int channels_min; /* min channels */ unsigned int channels_max; /* max channels */ unsigned int active; /* num of active users of the stream */ unsigned int active; /* stream is in use */ void *dma_data; /* used by platform code */ }; Loading sound/soc/codecs/wm8994.c +31 −25 Original line number Diff line number Diff line Loading @@ -3015,18 +3015,22 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: if (codec->bias_level == SND_SOC_BIAS_STANDBY) { /* Switch over to startup biases */ snd_soc_update_bits(codec, WM8994_ANTIPOP_2, WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_VMID_BUF_ENA | WM8994_VMID_RAMP_MASK, WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_VMID_BUF_ENA | (1 << WM8994_VMID_RAMP_SHIFT)); /* Disable main biases */ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0); WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0); /* Discharge line */ snd_soc_update_bits(codec, WM8994_ANTIPOP_1, Loading @@ -3039,10 +3043,11 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, /* Switch off startup biases */ snd_soc_update_bits(codec, WM8994_ANTIPOP_2, WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_VMID_BUF_ENA | WM8994_VMID_RAMP_MASK, 0); } break; } codec->bias_level = level; Loading Loading @@ -3866,12 +3871,13 @@ static int wm8994_codec_probe(struct platform_device *pdev) case 3: wm8994->hubs.dcs_codes = -5; wm8994->hubs.hp_startup_mode = 1; wm8994->hubs.dcs_readback_mode = 1; break; default: wm8994->hubs.dcs_readback_mode = 1; break; } ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994_mic_irq, "Mic 1 detect", wm8994); if (ret != 0) Loading sound/soc/codecs/wm_hubs.c +51 −32 Original line number Diff line number Diff line Loading @@ -62,21 +62,27 @@ static const char *speaker_mode_text[] = { static const struct soc_enum speaker_mode = SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); static void wait_for_dc_servo(struct snd_soc_codec *codec) static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) { unsigned int reg; int count = 0; unsigned int val; val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; /* Trigger the command */ snd_soc_write(codec, WM8993_DC_SERVO_0, val); dev_dbg(codec->dev, "Waiting for DC servo...\n"); do { count++; msleep(1); reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0); reg = snd_soc_read(codec, WM8993_DC_SERVO_0); dev_dbg(codec->dev, "DC servo: %x\n", reg); } while (reg & WM8993_DCS_DATAPATH_BUSY && count < 400); } while (reg & op && count < 400); if (reg & WM8993_DCS_DATAPATH_BUSY) if (reg & op) dev_err(codec->dev, "Timed out waiting for DC Servo\n"); } Loading @@ -86,51 +92,58 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec) static void calibrate_dc_servo(struct snd_soc_codec *codec) { struct wm_hubs_data *hubs = codec->private_data; u16 reg, dcs_cfg; u16 reg, reg_l, reg_r, dcs_cfg; /* Set for 32 series updates */ snd_soc_update_bits(codec, WM8993_DC_SERVO_1, WM8993_DCS_SERIES_NO_01_MASK, 32 << WM8993_DCS_SERIES_NO_01_SHIFT); /* Enable the DC servo. Write all bits to avoid triggering startup * or write calibration. */ snd_soc_update_bits(codec, WM8993_DC_SERVO_0, 0xFFFF, WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1 | WM8993_DCS_TRIG_SERIES_1 | WM8993_DCS_TRIG_SERIES_0); wait_for_dc_servo(codec); wait_for_dc_servo(codec, WM8993_DCS_TRIG_SERIES_0 | WM8993_DCS_TRIG_SERIES_1); /* Apply correction to DC servo result */ if (hubs->dcs_codes) { dev_dbg(codec->dev, "Applying %d code DC servo correction\n", hubs->dcs_codes); /* Different chips in the family support different * readback methods. */ switch (hubs->dcs_readback_mode) { case 0: reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) & WM8993_DCS_INTEG_CHAN_0_MASK;; reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) & WM8993_DCS_INTEG_CHAN_1_MASK; break; case 1: reg = snd_soc_read(codec, WM8993_DC_SERVO_3); reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; break; default: WARN(1, "Unknown DCS readback method"); break; } /* HPOUT1L */ reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) & WM8993_DCS_INTEG_CHAN_0_MASK;; reg += hubs->dcs_codes; dcs_cfg = reg << WM8993_DCS_DAC_WR_VAL_1_SHIFT; if (reg_l + hubs->dcs_codes > 0 && reg_l + hubs->dcs_codes < 0xff) reg_l += hubs->dcs_codes; dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT; /* HPOUT1R */ reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) & WM8993_DCS_INTEG_CHAN_1_MASK; reg += hubs->dcs_codes; dcs_cfg |= reg; if (reg_r + hubs->dcs_codes > 0 && reg_r + hubs->dcs_codes < 0xff) reg_r += hubs->dcs_codes; dcs_cfg |= reg_r; /* Do it */ snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); snd_soc_update_bits(codec, WM8993_DC_SERVO_0, WM8993_DCS_TRIG_DAC_WR_0 | WM8993_DCS_TRIG_DAC_WR_1, wait_for_dc_servo(codec, WM8993_DCS_TRIG_DAC_WR_0 | WM8993_DCS_TRIG_DAC_WR_1); wait_for_dc_servo(codec); } } Loading @@ -141,10 +154,16 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct wm_hubs_data *hubs = codec->private_data; int ret; ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); /* If we're applying an offset correction then updating the * callibration would be likely to introduce further offsets. */ if (hubs->dcs_codes) return ret; /* Only need to do this if the outputs are active */ if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) Loading sound/soc/codecs/wm_hubs.h +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ extern const unsigned int wm_hubs_spkmix_tlv[]; /* This *must* be the first element of the codec->private_data struct */ struct wm_hubs_data { int dcs_codes; int dcs_readback_mode; int hp_startup_mode; }; Loading sound/soc/omap/omap-pcm.c +8 −9 Original line number Diff line number Diff line Loading @@ -60,12 +60,11 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data) struct omap_runtime_data *prtd = runtime->private_data; unsigned long flags; if ((cpu_is_omap1510()) && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) { if ((cpu_is_omap1510())) { /* * OMAP1510 doesn't fully support DMA progress counter * and there is no software emulation implemented yet, * so have to maintain our own playback progress counter * so have to maintain our own progress counters * that can be used by omap_pcm_pointer() instead. */ spin_lock_irqsave(&prtd->lock, flags); Loading Loading @@ -191,8 +190,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) dma_params.frame_count = runtime->periods; omap_set_dma_params(prtd->dma_ch, &dma_params); if ((cpu_is_omap1510()) && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) if ((cpu_is_omap1510())) omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); else Loading Loading @@ -250,14 +248,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) dma_addr_t ptr; snd_pcm_uframes_t offset; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { if (cpu_is_omap1510()) { offset = prtd->period_index * runtime->period_size; } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { ptr = omap_get_dma_dst_pos(prtd->dma_ch); offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); } else if (!(cpu_is_omap1510())) { } else { ptr = omap_get_dma_src_pos(prtd->dma_ch); offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); } else offset = prtd->period_index * runtime->period_size; } if (offset >= runtime->buffer_size) offset = 0; Loading Loading
include/sound/soc.h +1 −1 Original line number Diff line number Diff line Loading @@ -381,7 +381,7 @@ struct snd_soc_pcm_stream { unsigned int rate_max; /* max rate */ unsigned int channels_min; /* min channels */ unsigned int channels_max; /* max channels */ unsigned int active; /* num of active users of the stream */ unsigned int active; /* stream is in use */ void *dma_data; /* used by platform code */ }; Loading
sound/soc/codecs/wm8994.c +31 −25 Original line number Diff line number Diff line Loading @@ -3015,18 +3015,22 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, break; case SND_SOC_BIAS_OFF: if (codec->bias_level == SND_SOC_BIAS_STANDBY) { /* Switch over to startup biases */ snd_soc_update_bits(codec, WM8994_ANTIPOP_2, WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_VMID_BUF_ENA | WM8994_VMID_RAMP_MASK, WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_VMID_BUF_ENA | (1 << WM8994_VMID_RAMP_SHIFT)); /* Disable main biases */ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0); WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0); /* Discharge line */ snd_soc_update_bits(codec, WM8994_ANTIPOP_1, Loading @@ -3039,10 +3043,11 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, /* Switch off startup biases */ snd_soc_update_bits(codec, WM8994_ANTIPOP_2, WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_BIAS_SRC | WM8994_STARTUP_BIAS_ENA | WM8994_VMID_BUF_ENA | WM8994_VMID_RAMP_MASK, 0); } break; } codec->bias_level = level; Loading Loading @@ -3866,12 +3871,13 @@ static int wm8994_codec_probe(struct platform_device *pdev) case 3: wm8994->hubs.dcs_codes = -5; wm8994->hubs.hp_startup_mode = 1; wm8994->hubs.dcs_readback_mode = 1; break; default: wm8994->hubs.dcs_readback_mode = 1; break; } ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994_mic_irq, "Mic 1 detect", wm8994); if (ret != 0) Loading
sound/soc/codecs/wm_hubs.c +51 −32 Original line number Diff line number Diff line Loading @@ -62,21 +62,27 @@ static const char *speaker_mode_text[] = { static const struct soc_enum speaker_mode = SOC_ENUM_SINGLE(WM8993_SPKMIXR_ATTENUATION, 8, 2, speaker_mode_text); static void wait_for_dc_servo(struct snd_soc_codec *codec) static void wait_for_dc_servo(struct snd_soc_codec *codec, unsigned int op) { unsigned int reg; int count = 0; unsigned int val; val = op | WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1; /* Trigger the command */ snd_soc_write(codec, WM8993_DC_SERVO_0, val); dev_dbg(codec->dev, "Waiting for DC servo...\n"); do { count++; msleep(1); reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_0); reg = snd_soc_read(codec, WM8993_DC_SERVO_0); dev_dbg(codec->dev, "DC servo: %x\n", reg); } while (reg & WM8993_DCS_DATAPATH_BUSY && count < 400); } while (reg & op && count < 400); if (reg & WM8993_DCS_DATAPATH_BUSY) if (reg & op) dev_err(codec->dev, "Timed out waiting for DC Servo\n"); } Loading @@ -86,51 +92,58 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec) static void calibrate_dc_servo(struct snd_soc_codec *codec) { struct wm_hubs_data *hubs = codec->private_data; u16 reg, dcs_cfg; u16 reg, reg_l, reg_r, dcs_cfg; /* Set for 32 series updates */ snd_soc_update_bits(codec, WM8993_DC_SERVO_1, WM8993_DCS_SERIES_NO_01_MASK, 32 << WM8993_DCS_SERIES_NO_01_SHIFT); /* Enable the DC servo. Write all bits to avoid triggering startup * or write calibration. */ snd_soc_update_bits(codec, WM8993_DC_SERVO_0, 0xFFFF, WM8993_DCS_ENA_CHAN_0 | WM8993_DCS_ENA_CHAN_1 | WM8993_DCS_TRIG_SERIES_1 | WM8993_DCS_TRIG_SERIES_0); wait_for_dc_servo(codec); wait_for_dc_servo(codec, WM8993_DCS_TRIG_SERIES_0 | WM8993_DCS_TRIG_SERIES_1); /* Apply correction to DC servo result */ if (hubs->dcs_codes) { dev_dbg(codec->dev, "Applying %d code DC servo correction\n", hubs->dcs_codes); /* Different chips in the family support different * readback methods. */ switch (hubs->dcs_readback_mode) { case 0: reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) & WM8993_DCS_INTEG_CHAN_0_MASK;; reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) & WM8993_DCS_INTEG_CHAN_1_MASK; break; case 1: reg = snd_soc_read(codec, WM8993_DC_SERVO_3); reg_l = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; reg_r = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; break; default: WARN(1, "Unknown DCS readback method"); break; } /* HPOUT1L */ reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) & WM8993_DCS_INTEG_CHAN_0_MASK;; reg += hubs->dcs_codes; dcs_cfg = reg << WM8993_DCS_DAC_WR_VAL_1_SHIFT; if (reg_l + hubs->dcs_codes > 0 && reg_l + hubs->dcs_codes < 0xff) reg_l += hubs->dcs_codes; dcs_cfg = reg_l << WM8993_DCS_DAC_WR_VAL_1_SHIFT; /* HPOUT1R */ reg = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) & WM8993_DCS_INTEG_CHAN_1_MASK; reg += hubs->dcs_codes; dcs_cfg |= reg; if (reg_r + hubs->dcs_codes > 0 && reg_r + hubs->dcs_codes < 0xff) reg_r += hubs->dcs_codes; dcs_cfg |= reg_r; /* Do it */ snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); snd_soc_update_bits(codec, WM8993_DC_SERVO_0, WM8993_DCS_TRIG_DAC_WR_0 | WM8993_DCS_TRIG_DAC_WR_1, wait_for_dc_servo(codec, WM8993_DCS_TRIG_DAC_WR_0 | WM8993_DCS_TRIG_DAC_WR_1); wait_for_dc_servo(codec); } } Loading @@ -141,10 +154,16 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); struct wm_hubs_data *hubs = codec->private_data; int ret; ret = snd_soc_put_volsw_2r(kcontrol, ucontrol); /* If we're applying an offset correction then updating the * callibration would be likely to introduce further offsets. */ if (hubs->dcs_codes) return ret; /* Only need to do this if the outputs are active */ if (snd_soc_read(codec, WM8993_POWER_MANAGEMENT_1) & (WM8993_HPOUT1L_ENA | WM8993_HPOUT1R_ENA)) Loading
sound/soc/codecs/wm_hubs.h +1 −0 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ extern const unsigned int wm_hubs_spkmix_tlv[]; /* This *must* be the first element of the codec->private_data struct */ struct wm_hubs_data { int dcs_codes; int dcs_readback_mode; int hp_startup_mode; }; Loading
sound/soc/omap/omap-pcm.c +8 −9 Original line number Diff line number Diff line Loading @@ -60,12 +60,11 @@ static void omap_pcm_dma_irq(int ch, u16 stat, void *data) struct omap_runtime_data *prtd = runtime->private_data; unsigned long flags; if ((cpu_is_omap1510()) && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) { if ((cpu_is_omap1510())) { /* * OMAP1510 doesn't fully support DMA progress counter * and there is no software emulation implemented yet, * so have to maintain our own playback progress counter * so have to maintain our own progress counters * that can be used by omap_pcm_pointer() instead. */ spin_lock_irqsave(&prtd->lock, flags); Loading Loading @@ -191,8 +190,7 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream) dma_params.frame_count = runtime->periods; omap_set_dma_params(prtd->dma_ch, &dma_params); if ((cpu_is_omap1510()) && (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)) if ((cpu_is_omap1510())) omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ | OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ); else Loading Loading @@ -250,14 +248,15 @@ static snd_pcm_uframes_t omap_pcm_pointer(struct snd_pcm_substream *substream) dma_addr_t ptr; snd_pcm_uframes_t offset; if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { if (cpu_is_omap1510()) { offset = prtd->period_index * runtime->period_size; } else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { ptr = omap_get_dma_dst_pos(prtd->dma_ch); offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); } else if (!(cpu_is_omap1510())) { } else { ptr = omap_get_dma_src_pos(prtd->dma_ch); offset = bytes_to_frames(runtime, ptr - runtime->dma_addr); } else offset = prtd->period_index * runtime->period_size; } if (offset >= runtime->buffer_size) offset = 0; Loading