Message ID | 65EE16ACC360FA4D99C96DC085B3F7721CDBAA@039-SN1MPN1-002.039d.mgd.msft.net (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
> -----Original Message----- > From: linux-arm-kernel-bounces@lists.infradead.org [mailto:linux-arm- > kernel-bounces@lists.infradead.org] On Behalf Of Dong Aisheng-B29396 > Sent: Wednesday, July 13, 2011 8:19 PM > To: Wolfram Sang > Cc: alsa-devel@alsa-project.org; s.hauer@pengutronix.de; > broonie@opensource.wolfsonmicro.com; u.kleine-koenig@pengutronix.de; > lrg@ti.com; linux-arm-kernel@lists.infradead.org > Subject: RE: [PATCH V2 03/10] ASoc: mxs: add mxs-sgtl5000 machine driver > > > > Proper regulator support for mxs is not in mainline yet. Is that > planned? > > How do you do it? > > Yes, it's not in mainline yet. > Fixed regulator may be a method. > However currently I just removed VDDIO and VDDA checking in sgtl5000 > driver. > Additionally, it seems sgtl5000 driver still needs another fix to get it > running. > I copy the patch as below for your info(Just for test). > I'm going to do that in my following work. > For regulator issue, One method is that just add two regulator (VDDA&VDDIO) needed by sgtl5000 in platform code to make sgtl5000 work first. If that I could add it in my the following patches. Or we do not add it (just leave sgtl5000 unwork), instead, we directly implement the full regulator support for MX28 power management? What's your suggestion? Regards Dong Aisheng
> For regulator issue, One method is that just add two regulator (VDDA&VDDIO) > needed by sgtl5000 in platform code to make sgtl5000 work first. > If that I could add it in my the following patches. > > Or we do not add it (just leave sgtl5000 unwork), instead, we directly > implement the full regulator support for MX28 power management? > > What's your suggestion? Hmmm, as we started now with the audio patches, I'd think we should concentrate on getting them in shape first. So, my preference would be adding just the two regulators. Whenever the power management gets complete, they should be easy to include/adapt, if I didn't miss anything. With your sgtl-patch, I can set the alsa-controls like volume. Yet the WAV played via simple aplay has a massive hall (like a concert at the other end of the cathedral ;)). Interrupting aplay, and trying again gives me sometimes: Playing WAVE 'machinae supremacy - great gianna sisters.wav' : Signed 16 bit Little Endian, Rate 44100 Hz, Stereo [ 15.940000] private_candidate: dma0chan0 busy [ 15.950000] private_candidate: dma0chan1 busy [ 15.950000] private_candidate: dma0chan2 filter said false [ 15.960000] private_candidate: dma0chan3 filter said false [ 15.960000] private_candidate: dma0chan4 filter said false [ 15.970000] private_candidate: dma0chan5 filter said false [ 15.970000] private_candidate: dma0chan6 filter said false [ 15.980000] private_candidate: dma0chan7 filter said false [ 15.980000] private_candidate: dma0chan8 filter said false [ 15.990000] private_candidate: dma0chan9 filter said false [ 15.990000] private_candidate: dma0chan10 filter said false [ 16.000000] private_candidate: dma0chan11 filter said false [ 16.010000] private_candidate: dma0chan12 filter said false [ 16.010000] private_candidate: dma0chan13 filter said false [ 16.020000] private_candidate: dma0chan14 filter said false [ 16.020000] private_candidate: dma0chan15 filter said false [ 16.030000] private_candidate: dma1chan0 filter said false [ 16.030000] private_candidate: dma1chan1 filter said false [ 16.040000] private_candidate: dma1chan2 filter said false [ 16.050000] private_candidate: dma1chan3 filter said false [ 16.050000] Division by zero in kernel. [ 16.050000] [<c0025cac>] (unwind_backtrace+0x0/0xe4) from [<c012a1b4>] (Ldiv0+0x8/0x10) [ 16.060000] [<c012a1b4>] (Ldiv0+0x8/0x10) from [<c012a184>] (__aeabi_uidivmod+0x8/0x18) [ 16.070000] [<c012a184>] (__aeabi_uidivmod+0x8/0x18) from [<c01ad5c8>] (audio_dma_irq+0x28/0x38) [ 16.080000] [<c01ad5c8>] (audio_dma_irq+0x28/0x38) from [<c013b200>] (mxs_dma_tasklet+0x18/0x1c) [ 16.090000] [<c013b200>] (mxs_dma_tasklet+0x18/0x1c) from [<c0037430>] (tasklet_action+0x88/0xe0) [ 16.100000] [<c0037430>] (tasklet_action+0x88/0xe0) from [<c0037918>] (__do_softirq+0x84/0x11c) [ 16.110000] [<c0037918>] (__do_softirq+0x84/0x11c) from [<c0037d1c>] (irq_exit+0x40/0x90) [ 16.110000] [<c0037d1c>] (irq_exit+0x40/0x90) from [<c0021064>] (asm_do_IRQ+0x64/0x84) [ 16.120000] [<c0021064>] (asm_do_IRQ+0x64/0x84) from [<c0021b14>] (__irq_svc+0x34/0x60) [ 16.130000] Exception stack(0xc7a13de0 to 0xc7a13e28) [ 16.140000] 3de0: 00000000 00000000 00000000 00000000 c0316368 c7927b00 00000050 60000013 [ 16.140000] 3e00: 00000000 00000000 c0316390 c031f13c 00000000 c7a13e28 c0060fd0 c0060298 [ 16.150000] 3e20: 60000013 ffffffff [ 16.160000] [<c0021b14>] (__irq_svc+0x34/0x60) from [<c0060298>] (__setup_irq+0x280/0x340) [ 16.160000] [<c0060298>] (__setup_irq+0x280/0x340) from [<c0060424>] (request_threaded_irq+0xcc/0x11c) [ 16.170000] [<c0060424>] (request_threaded_irq+0xcc/0x11c) from [<c013b684>] (mxs_dma_alloc_chan_resources+0x70/0xe8) [ 16.180000] [<c013b684>] (mxs_dma_alloc_chan_resources+0x70/0xe8) from [<c013a3d0>] (dma_chan_get+0x88/0x110) [ 16.190000] [<c013a3d0>] (dma_chan_get+0x88/0x110) from [<c013a4d0>] (__dma_request_channel+0x78/0x18c) [ 16.200000] [<c013a4d0>] (__dma_request_channel+0x78/0x18c) from [<c01ad3e0>] (snd_mxs_pcm_hw_params+0x70/0x1d4) [ 16.210000] [<c01ad3e0>] (snd_mxs_pcm_hw_params+0x70/0x1d4) from [<c01a3a0c>] (soc_pcm_hw_params+0x100/0x1ac) [ 16.220000] [<c01a3a0c>] (soc_pcm_hw_params+0x100/0x1ac) from [<c019cd1c>] (snd_pcm_hw_params+0x98/0x33c) [ 16.230000] [<c019cd1c>] (snd_pcm_hw_params+0x98/0x33c) from [<c019dc10>] (snd_pcm_common_ioctl1+0x1e4/0x4f8) [ 16.240000] [<c019dc10>] (snd_pcm_common_ioctl1+0x1e4/0x4f8) from [<c019e374>] (snd_pcm_playback_ioctl1+0x200/0x220) [ 16.250000] [<c019e374>] (snd_pcm_playback_ioctl1+0x200/0x220) from [<c0097b24>] (do_vfs_ioctl+0x258/0x288) [ 16.260000] [<c0097b24>] (do_vfs_ioctl+0x258/0x288) from [<c0097b88>] (sys_ioctl+0x34/0x54) [ 16.270000] [<c0097b88>] (sys_ioctl+0x34/0x54) from [<c0021ea0>] (ret_fast_syscall+0x0/0x2c) [ 16.280000] __dma_request_channel: success (dma1chan4) [ 16.290000] dma dma1chan4: cannot prepare slave dma [ 16.290000] asoc: platform mxs-pcm-audio.0 hw params failed aplay: set_params:1053: Unable to install hw params: ACCESS: RW_INTERLEAVED FORMAT: S16_LE SUBFORMAT: STD SAMPLE_BITS: 16 FRAME_BITS: 32 CHANNELS: 2 RATE: 44100 PERIOD_TIME: (46439 46440) PERIOD_SIZE: 2048 PERIOD_BYTES: 8192 PERIODS: 8 BUFFER_TIME: (371519 371520) BUFFER_SIZE: 16384 BUFFER_BYTES: 65536 TICK_TIME: 0 After that OOPS, playing works again (still with the hall). Didn't have the time to look at these issues yet, but since I was writing to you anyway, I thought I'd mention it... Regards, Wolfram
> -----Original Message----- > From: Wolfram Sang [mailto:w.sang@pengutronix.de] > Sent: Wednesday, July 13, 2011 10:01 PM > To: Dong Aisheng-B29396 > Cc: alsa-devel@alsa-project.org; s.hauer@pengutronix.de; > broonie@opensource.wolfsonmicro.com; u.kleine-koenig@pengutronix.de; > lrg@ti.com; linux-arm-kernel@lists.infradead.org > Subject: Re: [PATCH V2 03/10] ASoc: mxs: add mxs-sgtl5000 machine driver > > With your sgtl-patch, I can set the alsa-controls like volume. Yet the > WAV played via simple aplay has a massive hall (like a concert at the > other end of the cathedral ;)). You mean the sound is incorrect? Regards Dong Aisheng
On Wed, Jul 13, 2011 at 02:22:42PM +0000, Dong Aisheng-B29396 wrote: > > -----Original Message----- > > From: Wolfram Sang [mailto:w.sang@pengutronix.de] > > Sent: Wednesday, July 13, 2011 10:01 PM > > To: Dong Aisheng-B29396 > > Cc: alsa-devel@alsa-project.org; s.hauer@pengutronix.de; > > broonie@opensource.wolfsonmicro.com; u.kleine-koenig@pengutronix.de; > > lrg@ti.com; linux-arm-kernel@lists.infradead.org > > Subject: Re: [PATCH V2 03/10] ASoc: mxs: add mxs-sgtl5000 machine driver > > > > With your sgtl-patch, I can set the alsa-controls like volume. Yet the > > WAV played via simple aplay has a massive hall (like a concert at the > > other end of the cathedral ;)). > > You mean the sound is incorrect? It was, but is fixed now. There was something wrong in our audio-path electrically. Together with your DMA patch, music sounds fine now \o/
2011/7/13 Wolfram Sang <w.sang@pengutronix.de>: > On Wed, Jul 13, 2011 at 02:22:42PM +0000, Dong Aisheng-B29396 wrote: >> >> You mean the sound is incorrect? > > It was, but is fixed now. There was something wrong in our audio-path > electrically. Together with your DMA patch, music sounds fine now \o/ > It's good. Thanks for the test. Regards Dong Aisheng
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index ff29380..c29f153 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -33,87 +33,18 @@ #define SGTL5000_DAP_REG_OFFSET 0x0100 #define SGTL5000_MAX_REG_OFFSET 0x013A -/* default value of sgtl5000 registers except DAP */ -static const u16 sgtl5000_regs[SGTL5000_MAX_REG_OFFSET >> 1] = { - 0xa011, /* 0x0000, CHIP_ID. 11 stand for revison 17 */ - 0x0000, /* 0x0002, CHIP_DIG_POWER. */ - 0x0008, /* 0x0004, CHIP_CKL_CTRL */ - 0x0010, /* 0x0006, CHIP_I2S_CTRL */ - 0x0000, /* 0x0008, reserved */ - 0x0008, /* 0x000A, CHIP_SSS_CTRL */ - 0x0000, /* 0x000C, reserved */ - 0x020c, /* 0x000E, CHIP_ADCDAC_CTRL */ - 0x3c3c, /* 0x0010, CHIP_DAC_VOL */ - 0x0000, /* 0x0012, reserved */ - 0x015f, /* 0x0014, CHIP_PAD_STRENGTH */ - 0x0000, /* 0x0016, reserved */ - 0x0000, /* 0x0018, reserved */ - 0x0000, /* 0x001A, reserved */ - 0x0000, /* 0x001E, reserved */ - 0x0000, /* 0x0020, CHIP_ANA_ADC_CTRL */ - 0x1818, /* 0x0022, CHIP_ANA_HP_CTRL */ - 0x0111, /* 0x0024, CHIP_ANN_CTRL */ - 0x0000, /* 0x0026, CHIP_LINREG_CTRL */ - 0x0000, /* 0x0028, CHIP_REF_CTRL */ - 0x0000, /* 0x002A, CHIP_MIC_CTRL */ - 0x0000, /* 0x002C, CHIP_LINE_OUT_CTRL */ - 0x0404, /* 0x002E, CHIP_LINE_OUT_VOL */ - 0x7060, /* 0x0030, CHIP_ANA_POWER */ - 0x5000, /* 0x0032, CHIP_PLL_CTRL */ - 0x0000, /* 0x0034, CHIP_CLK_TOP_CTRL */ - 0x0000, /* 0x0036, CHIP_ANA_STATUS */ - 0x0000, /* 0x0038, reserved */ - 0x0000, /* 0x003A, CHIP_ANA_TEST2 */ - 0x0000, /* 0x003C, CHIP_SHORT_CTRL */ - 0x0000, /* reserved */ -}; - -/* default value of dap registers */ -static const u16 sgtl5000_dap_regs[] = { - 0x0000, /* 0x0100, DAP_CONTROL */ - 0x0000, /* 0x0102, DAP_PEQ */ - 0x0040, /* 0x0104, DAP_BASS_ENHANCE */ - 0x051f, /* 0x0106, DAP_BASS_ENHANCE_CTRL */ - 0x0000, /* 0x0108, DAP_AUDIO_EQ */ - 0x0040, /* 0x010A, DAP_SGTL_SURROUND */ - 0x0000, /* 0x010C, DAP_FILTER_COEF_ACCESS */ - 0x0000, /* 0x010E, DAP_COEF_WR_B0_MSB */ - 0x0000, /* 0x0110, DAP_COEF_WR_B0_LSB */ - 0x0000, /* 0x0112, reserved */ - 0x0000, /* 0x0114, reserved */ - 0x002f, /* 0x0116, DAP_AUDIO_EQ_BASS_BAND0 */ - 0x002f, /* 0x0118, DAP_AUDIO_EQ_BAND0 */ - 0x002f, /* 0x011A, DAP_AUDIO_EQ_BAND2 */ - 0x002f, /* 0x011C, DAP_AUDIO_EQ_BAND3 */ - 0x002f, /* 0x011E, DAP_AUDIO_EQ_TREBLE_BAND4 */ - 0x8000, /* 0x0120, DAP_MAIN_CHAN */ - 0x0000, /* 0x0122, DAP_MIX_CHAN */ - 0x0510, /* 0x0124, DAP_AVC_CTRL */ - 0x1473, /* 0x0126, DAP_AVC_THRESHOLD */ - 0x0028, /* 0x0128, DAP_AVC_ATTACK */ - 0x0050, /* 0x012A, DAP_AVC_DECAY */ - 0x0000, /* 0x012C, DAP_COEF_WR_B1_MSB */ - 0x0000, /* 0x012E, DAP_COEF_WR_B1_LSB */ - 0x0000, /* 0x0130, DAP_COEF_WR_B2_MSB */ - 0x0000, /* 0x0132, DAP_COEF_WR_B2_LSB */ - 0x0000, /* 0x0134, DAP_COEF_WR_A1_MSB */ - 0x0000, /* 0x0136, DAP_COEF_WR_A1_LSB */ - 0x0000, /* 0x0138, DAP_COEF_WR_A2_MSB */ - 0x0000, /* 0x013A, DAP_COEF_WR_A2_LSB */ -}; - /* regulator supplies for sgtl5000, VDDD is an optional external supply */ enum sgtl5000_regulator_supplies { - VDDA, - VDDIO, +// VDDA, +// VDDIO, VDDD, SGTL5000_SUPPLY_NUM }; /* vddd is optional supply */ static const char *supply_names[SGTL5000_SUPPLY_NUM] = { - "VDDA", - "VDDIO", +// "VDDA", +// "VDDIO", "VDDD" }; @@ -780,6 +711,11 @@ static int ldo_regulator_is_enabled(struct regulator_dev *dev) return ldo->enabled; } +/* + * enable internal VDDD power supply. Since register + * cache not fill yet, we have to use hw_read and write + * instead of snd_soc_read and snd_soc_write. + */ static int ldo_regulator_enable(struct regulator_dev *dev) { struct ldo_regulator *ldo = rdev_get_drvdata(dev); @@ -797,17 +733,17 @@ static int ldo_regulator_enable(struct regulator_dev *dev) ldo->voltage = (1600 - reg * 50) * 1000; /* set voltage to register */ - snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL, - (0x1 << 4) - 1, reg); + codec->write(codec, SGTL5000_CHIP_LINREG_CTRL, reg); - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_LINEREG_D_POWERUP, - SGTL5000_LINEREG_D_POWERUP); + reg = codec->hw_read(codec, SGTL5000_CHIP_ANA_POWER); + reg |= SGTL5000_LINEREG_D_POWERUP; + codec->write(codec, SGTL5000_CHIP_ANA_POWER, reg); + reg &= ~SGTL5000_LINREG_SIMPLE_POWERUP; /* when internal ldo enabled, simple digital power can be disabled */ - snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER, - SGTL5000_LINREG_SIMPLE_POWERUP, - 0); + codec->write(codec, SGTL5000_CHIP_ANA_POWER, reg); + + udelay(10); ldo->enabled = 1; return 0; @@ -1022,13 +958,11 @@ static int sgtl5000_suspend(struct snd_soc_codec *codec, pm_message_t state) static int sgtl5000_restore_regs(struct snd_soc_codec *codec) { u16 *cache = codec->reg_cache; - int i; - int regular_regs = SGTL5000_CHIP_SHORT_CTRL >> 1; + int reg; + int step = codec->driver->reg_cache_step; /* restore regular registers */ - for (i = 0; i < regular_regs; i++) { - int reg = i << 1; - + for (reg = 0; reg < SGTL5000_CHIP_SHORT_CTRL; reg += step) { /* this regs depends on the others */ if (reg == SGTL5000_CHIP_ANA_POWER || reg == SGTL5000_CHIP_CLK_CTRL || @@ -1037,35 +971,32 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec) reg == SGTL5000_CHIP_CLK_CTRL) continue; - snd_soc_write(codec, reg, cache[i]); + snd_soc_write(codec, reg, cache[reg]); } /* restore dap registers */ - for (i = SGTL5000_DAP_REG_OFFSET >> 1; - i < SGTL5000_MAX_REG_OFFSET >> 1; i++) { - int reg = i << 1; - - snd_soc_write(codec, reg, cache[i]); - } + for (reg = SGTL5000_DAP_REG_OFFSET; + reg < SGTL5000_MAX_REG_OFFSET; reg += step) + snd_soc_write(codec, reg, cache[reg]); /* * restore power and other regs according * to set_power() and set_clock() */ snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL, - cache[SGTL5000_CHIP_LINREG_CTRL >> 1]); + cache[SGTL5000_CHIP_LINREG_CTRL]); snd_soc_write(codec, SGTL5000_CHIP_ANA_POWER, - cache[SGTL5000_CHIP_ANA_POWER >> 1]); + cache[SGTL5000_CHIP_ANA_POWER]); snd_soc_write(codec, SGTL5000_CHIP_CLK_CTRL, - cache[SGTL5000_CHIP_CLK_CTRL >> 1]); + cache[SGTL5000_CHIP_CLK_CTRL]); snd_soc_write(codec, SGTL5000_CHIP_REF_CTRL, - cache[SGTL5000_CHIP_REF_CTRL >> 1]); + cache[SGTL5000_CHIP_REF_CTRL]); snd_soc_write(codec, SGTL5000_CHIP_LINE_OUT_CTRL, - cache[SGTL5000_CHIP_LINE_OUT_CTRL >> 1]); + cache[SGTL5000_CHIP_LINE_OUT_CTRL]); return 0; } @@ -1105,12 +1036,12 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec) int vag; struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); - vdda = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer); - vddio = regulator_get_voltage(sgtl5000->supplies[VDDIO].consumer); +// vdda = regulator_get_voltage(sgtl5000->supplies[VDDA].consumer); +// vddio = regulator_get_voltage(sgtl5000->supplies[VDDIO].consumer); vddd = regulator_get_voltage(sgtl5000->supplies[VDDD].consumer); - vdda = vdda / 1000; - vddio = vddio / 1000; + vdda = 3300; + vddio = 3300; vddd = vddd / 1000; if (vdda <= 0 || vddio <= 0 || vddd < 0) { @@ -1335,6 +1266,22 @@ err_regulator_free: } +static int sgtl5000_fill_reg_cache(struct snd_soc_codec *codec) +{ + int reg; + int step = codec->driver->reg_cache_step; + u16 *cache = codec->reg_cache; + + for (reg = SGTL5000_DAP_REG_OFFSET; + reg <= SGTL5000_MAX_REG_OFFSET; reg += step) + cache[reg] = codec->hw_read(codec, reg); + + for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += step) + cache[reg] = codec->hw_read(codec, reg); + + return 0; +} + static int sgtl5000_probe(struct snd_soc_codec *codec) { int ret; @@ -1351,6 +1298,8 @@ static int sgtl5000_probe(struct snd_soc_codec *codec) if (ret) return ret; + sgtl5000_fill_reg_cache(codec); + /* power up sgtl5000 */ ret = sgtl5000_set_power_regs(codec); if (ret) @@ -1443,10 +1392,9 @@ static struct snd_soc_codec_driver sgtl5000_driver = { .suspend = sgtl5000_suspend, .resume = sgtl5000_resume, .set_bias_level = sgtl5000_set_bias_level, - .reg_cache_size = ARRAY_SIZE(sgtl5000_regs), + .reg_cache_size = SGTL5000_MAX_REG_OFFSET, .reg_word_size = sizeof(u16), .reg_cache_step = 2, - .reg_cache_default = sgtl5000_regs, .volatile_register = sgtl5000_volatile_register, }; @@ -1466,9 +1414,6 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client, * at init phase makes life easy. * FIXME: should we drop 'const' of sgtl5000_regs? */ - memcpy((void *)(&sgtl5000_regs[0] + (SGTL5000_DAP_REG_OFFSET >> 1)), - sgtl5000_dap_regs, - SGTL5000_MAX_REG_OFFSET - SGTL5000_DAP_REG_OFFSET); i2c_set_clientdata(client, sgtl5000);