From: Tony Lindgren Date: Fri, 5 Dec 2008 17:50:19 +0000 (-0800) Subject: REMOVE OMAP LEGACY CODE: Delete old tsc2301-mixer.c X-Git-Tag: v2.6.28-omap1~90 X-Git-Url: http://pilppa.com/gitweb/?a=commitdiff_plain;h=c65c733e1af5eac5681233309fed38538c9e06d2;p=linux-2.6-omap-h63xx.git REMOVE OMAP LEGACY CODE: Delete old tsc2301-mixer.c As pointed out by Jarkko Nikula. All future development must be done on the alsa list with linux-omap list Cc'd. Signed-off-by: Tony Lindgren --- diff --git a/arch/arm/mach-omap2/board-n800-audio.c b/arch/arm/mach-omap2/board-n800-audio.c index e28390e0c19..fd83313aa35 100644 --- a/arch/arm/mach-omap2/board-n800-audio.c +++ b/arch/arm/mach-omap2/board-n800-audio.c @@ -31,297 +31,10 @@ #include -#if defined(CONFIG_SPI_TSC2301_AUDIO) && defined(CONFIG_SND_OMAP24XX_EAC) -#define AUDIO_ENABLED - -static struct clk *sys_clkout2; -static struct clk *sys_clkout2_src; -static struct clk *func96m_clk; -static struct device *eac_device; -static struct device *tsc2301_device; - -static int enable_audio; -static int audio_ok; -static spinlock_t audio_lock; - -/* - * Leaving EAC and sys_clkout2 pins multiplexed to those subsystems results - * in about 2 mA extra current leak when audios are powered down. The - * workaround is to multiplex them to protected mode (with pull-ups enabled) - * whenever audio is not being used. - */ -static int eac_mux_disabled = 0; -static int clkout2_mux_disabled = 0; -static u32 saved_mux[2]; - -static void n800_enable_eac_mux(void) -{ - if (!eac_mux_disabled) - return; - __raw_writel(saved_mux[1], OMAP2_IO_ADDRESS(0x48000124)); - eac_mux_disabled = 0; -} - -static void n800_disable_eac_mux(void) -{ - if (eac_mux_disabled) { - WARN_ON(eac_mux_disabled); - return; - } - saved_mux[1] = __raw_readl(OMAP2_IO_ADDRESS(0x48000124)); - __raw_writel(0x1f1f1f1f, OMAP2_IO_ADDRESS(0x48000124)); - eac_mux_disabled = 1; -} - -static void n800_enable_clkout2_mux(void) -{ - if (!clkout2_mux_disabled) - return; - __raw_writel(saved_mux[0], OMAP2_IO_ADDRESS(0x480000e8)); - clkout2_mux_disabled = 0; -} - -static void n800_disable_clkout2_mux(void) -{ - u32 l; - - if (clkout2_mux_disabled) { - WARN_ON(clkout2_mux_disabled); - return; - } - saved_mux[0] = __raw_readl(OMAP2_IO_ADDRESS(0x480000e8)); - l = saved_mux[0] & ~0xff; - l |= 0x1f; - __raw_writel(l, OMAP2_IO_ADDRESS(0x480000e8)); - clkout2_mux_disabled = 1; -} - -static int n800_eac_enable_ext_clocks(struct device *dev) -{ - BUG_ON(tsc2301_device == NULL); - n800_enable_eac_mux(); - tsc2301_mixer_enable_mclk(tsc2301_device); - - return 0; -} - -static void n800_eac_disable_ext_clocks(struct device *dev) -{ - BUG_ON(tsc2301_device == NULL); - tsc2301_mixer_disable_mclk(tsc2301_device); - n800_disable_eac_mux(); -} - -static int n800_audio_set_power(void *pdata, int dac, int adc) -{ - BUG_ON(pdata != tsc2301_device); - tsc2301_mixer_set_power(tsc2301_device, dac, adc); - - return 0; -} - -static int n800_audio_register_controls(void *pdata, struct snd_card *card) -{ - BUG_ON(pdata != tsc2301_device); - return tsc2301_mixer_register_controls(tsc2301_device, card); -} - -static struct eac_codec n800_eac_codec = { - .mclk_src = EAC_MCLK_EXT_2x12288000, - .codec_mode = EAC_CODEC_I2S_MASTER, - .codec_conf.i2s.polarity_changed_mode = 0, - .codec_conf.i2s.sync_delay_enable = 0, - .default_rate = 48000, - .set_power = n800_audio_set_power, - .register_controls = n800_audio_register_controls, - .short_name = "TSC2301", -}; - -static int n800_register_codec(void) -{ - int r, do_enable = 0; - unsigned long flags; - - n800_eac_codec.private_data = tsc2301_device; - r = eac_register_codec(eac_device, &n800_eac_codec); - if (r < 0) - return r; - spin_lock_irqsave(&audio_lock, flags); - audio_ok = 1; - if (enable_audio) - do_enable = 1; - spin_unlock_irqrestore(&audio_lock, flags); - if (do_enable) - eac_set_mode(eac_device, 1, 1); - return 0; -} - -static void n800_unregister_codec(void) -{ - audio_ok = 0; - eac_unregister_codec(eac_device); - eac_set_mode(eac_device, 0, 0); -} - -static int n800_eac_init(struct device *dev) -{ - int r; - - BUG_ON(eac_device != NULL); - eac_device = dev; - if (tsc2301_device != NULL) { - r = n800_register_codec(); - if (r < 0) - return r; - } - - return 0; -} - -static void n800_eac_cleanup(struct device *dev) -{ - eac_device = NULL; - if (tsc2301_device != NULL) - n800_unregister_codec(); -} - -static int n800_codec_get_clocks(struct device *dev) -{ - sys_clkout2_src = clk_get(dev, "sys_clkout2_src"); - if (IS_ERR(sys_clkout2_src)) { - dev_err(dev, "Could not get sys_clkout2_src clock\n"); - return -ENODEV; - } - sys_clkout2 = clk_get(dev, "sys_clkout2"); - if (IS_ERR(sys_clkout2)) { - dev_err(dev, "Could not get sys_clkout2 clock\n"); - clk_put(sys_clkout2_src); - return -ENODEV; - } - /* configure 12 MHz output on SYS_CLKOUT2. Therefore we must use - * 96 MHz as its parent in order to get 12 MHz */ - func96m_clk = clk_get(dev, "func_96m_ck"); - if (IS_ERR(func96m_clk)) { - dev_err(dev, "Could not get func 96M clock\n"); - clk_put(sys_clkout2); - clk_put(sys_clkout2_src); - return -ENODEV; - } - - clk_set_parent(sys_clkout2_src, func96m_clk); - clk_set_rate(sys_clkout2, 12000000); - - return 0; -} - -static void n800_codec_put_clocks(struct device *dev) -{ - clk_put(func96m_clk); - clk_put(sys_clkout2); - clk_put(sys_clkout2_src); -} - -static int n800_codec_enable_clock(struct device *dev) -{ - n800_enable_clkout2_mux(); - return clk_enable(sys_clkout2); -} - -static void n800_codec_disable_clock(struct device *dev) -{ - clk_disable(sys_clkout2); - n800_disable_clkout2_mux(); -} - -static int n800_codec_init(struct device *dev) -{ - int r; - - BUG_ON(tsc2301_device != NULL); - tsc2301_device = dev; - if ((r = n800_codec_get_clocks(dev)) < 0) - return r; - if (eac_device != NULL) { - r = n800_register_codec(); - if (r < 0) { - n800_codec_put_clocks(dev); - return r; - } - } - return 0; -} - -static void n800_codec_cleanup(struct device *dev) -{ - tsc2301_device = NULL; - if (eac_device != NULL) - n800_unregister_codec(); - n800_codec_put_clocks(dev); -} - -static struct eac_platform_data n800_eac_data = { - .init = n800_eac_init, - .cleanup = n800_eac_cleanup, - .enable_ext_clocks = n800_eac_enable_ext_clocks, - .disable_ext_clocks = n800_eac_disable_ext_clocks, -}; - -static const struct tsc2301_mixer_gpio n800_mixer_gpios[] = { - { - .name = "Headset Amplifier", - .gpio = 1, - .deactivate_on_pd = 1, - }, { - .name = "Speaker Amplifier", - .gpio = 2, - .def_enable = 1, - .deactivate_on_pd = 1, - }, { - .name = "Headset Mic Select", - .gpio = 3, - } -}; - -static struct platform_device retu_headset_device = { - .name = "retu-headset", - .id = -1, - .dev = { - .release = NULL, - }, -}; - void __init n800_audio_init(struct tsc2301_platform_data *tc) { - spin_lock_init(&audio_lock); - - if (platform_device_register(&retu_headset_device) < 0) - return; - omap_init_eac(&n800_eac_data); - - tc->pll_pdc = 7; - tc->pll_a = 7; - tc->pll_n = 9; - tc->pll_output = 1; - tc->mclk_ratio = TSC2301_MCLK_256xFS; - tc->i2s_sample_rate = TSC2301_I2S_SR_48000; - tc->i2s_format = TSC2301_I2S_FORMAT0; - tc->power_down_blocks = TSC2301_REG_PD_MISC_MOPD; - tc->mixer_gpios = n800_mixer_gpios; - tc->n_mixer_gpios = ARRAY_SIZE(n800_mixer_gpios); - tc->codec_init = n800_codec_init; - tc->codec_cleanup = n800_codec_cleanup; - tc->enable_clock = n800_codec_enable_clock; - tc->disable_clock = n800_codec_disable_clock; } -#else - -void __init n800_audio_init(struct tsc2301_platform_data *tc) -{ -} - -#endif - #ifdef CONFIG_OMAP_DSP int n800_audio_enable(struct dsp_kfunc_device *kdev, int stage) diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 1c2e7fc928e..7bfff235ffc 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -40,7 +40,6 @@ obj-$(CONFIG_SPI_TSC2102) += tsc2102.o obj-$(CONFIG_SPI_TSC210X) += tsc210x.o obj-$(CONFIG_SPI_TSC2301) += tsc2301.o tsc2301-objs := tsc2301-core.o -tsc2301-$(CONFIG_SPI_TSC2301_AUDIO) += tsc2301-mixer.o # ... add above this line ... # SPI slave controller drivers (upstream link) diff --git a/drivers/spi/tsc2301-core.c b/drivers/spi/tsc2301-core.c index 4b565b774c4..d64a274e246 100644 --- a/drivers/spi/tsc2301-core.c +++ b/drivers/spi/tsc2301-core.c @@ -205,12 +205,8 @@ static int __devinit tsc2301_probe(struct spi_device *spi) r = tsc2301_ts_init(tsc, pdata); if (r) goto err2; - r = tsc2301_mixer_init(tsc, pdata); - if (r) - goto err3; return 0; -err3: tsc2301_ts_exit(tsc); err2: tsc2301_kp_exit(tsc); @@ -223,7 +219,6 @@ static int __devexit tsc2301_remove(struct spi_device *spi) { struct tsc2301 *tsc = dev_get_drvdata(&spi->dev); - tsc2301_mixer_exit(tsc); tsc2301_ts_exit(tsc); tsc2301_kp_exit(tsc); if (tsc->reset_gpio >= 0) @@ -239,19 +234,14 @@ static int tsc2301_suspend(struct spi_device *spi, pm_message_t mesg) struct tsc2301 *tsc = dev_get_drvdata(&spi->dev); int r; - if ((r = tsc2301_mixer_suspend(tsc)) < 0) - return r; if ((r = tsc2301_kp_suspend(tsc)) < 0) - goto err1; - if ((r = tsc2301_ts_suspend(tsc)) < 0) - goto err2; + return r; + if ((r = tsc2301_ts_suspend(tsc)) < 0) { + tsc2301_kp_resume(tsc); + return r; + } return 0; -err2: - tsc2301_kp_resume(tsc); -err1: - tsc2301_mixer_resume(tsc); - return r; } static int tsc2301_resume(struct spi_device *spi) @@ -260,7 +250,7 @@ static int tsc2301_resume(struct spi_device *spi) tsc2301_ts_resume(tsc); tsc2301_kp_resume(tsc); - tsc2301_mixer_resume(tsc); + return 0; } #endif diff --git a/drivers/spi/tsc2301-mixer.c b/drivers/spi/tsc2301-mixer.c deleted file mode 100644 index 31ec87c0083..00000000000 --- a/drivers/spi/tsc2301-mixer.c +++ /dev/null @@ -1,1004 +0,0 @@ -/* - * ALSA Mixer implementation for TSC2301 - * - * Copyright (C) 2006 Nokia Corporation. - * - * Contact: Jarkko Nikula - * Juha Yrjola - * - * Some notes about TSC2301: - * - PLL will stop when DAC and ADC's are powered down. - * - Touchscreen will stop working when audio part is powered up and if audio - * MCLK is stopped. Problem is avoided if audio is powered down before - * stopping MCLK. - * - Audio DAC or audio outputs will activate only after 100 msec from the - * chip power-up. Reason seems to be VCM since there is no this delay if the - * chip and VCM (bit AVPD on PD/MISC) were not powered down. The chip will - * consume about 1 mA if all other audio blocks are powered down except the - * chip itself and VCM. Full power down consumes only about few uA. - * - Power-down transition could happen earliest about 100 msec after the chip - * power-up. Otherwise power-down will fail if there is no that 100 msec - * on time before it. It's not obvious why is that since chip reports - * power-up to be completed and also PLL output on GPIO_0 is active in few - * milliseconds. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * version 2 as published by the Free Software Foundation. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA - * 02110-1301 USA - * - */ - -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -/* shadow register indexes */ -enum { - /* audio control and volume registers */ - AUDCNTL_INDEX, - ADCVOL_INDEX, - DACVOL_INDEX, - BPVOL_INDEX, - /* keyclick control register (not needed here) */ - /* audio power control register */ - PD_MISC_INDEX, - /* TSC2301 GPIO control register */ - GPIO_INDEX, - - SHADOW_REG_COUNT, -}; - -/* structure for driver private data */ -struct tsc2301_mixer { - struct tsc2301 *tsc; - struct mutex mutex; - - /* shadow registers holding TSC2301 audio registers. Used to hold - * their states during the sleep and also to reduce communication with - * the chip since get callback functions could get register values - * directly from these shadow registers without needing to read them - * from the chip */ - u16 shadow_regs[SHADOW_REG_COUNT]; - - /* audio controller driver usage of the ADC and DAC */ - unsigned adc_enabled:1, dac_enabled:1; - unsigned pll_output:1; - unsigned mclk_enabled; - - /* latest audio power-up timestamp */ - unsigned long pu_jiffies; - - /* these are used when upper layer(s) are going to power-down TSC2301 - * before 100 msec is passed from power-up */ - struct delayed_work delayed_power_down; - unsigned delayed_pd_active:1; - - int (* platform_init)(struct device *); - void (* platform_cleanup)(struct device *); - - struct tsc2301_mixer_gpio *mixer_gpios; - int n_mixer_gpios; -}; - -#define TSC2301_DAC_DELAY msecs_to_jiffies(100) -#define TSC2301_MIN_PU_PERIOD msecs_to_jiffies(100) - -#define TSC2301_REG_TO_PVAL(reg) \ - (TSC2301_REG_TO_PAGE(reg) << 6 | TSC2301_REG_TO_ADDR(reg)) -#define TSC2301_PVAL_TO_REG(v) \ - (TSC2301_REG((((v) >> 6) & 3),((v) & 0x1f))) - -#define TSC2301_VOLUME_MASK 0x7f -#define TSC2301_MIN_ADCVOL 6 -#define TSC2301_MIN_DACVOL 0 -#define TSC2301_MIN_BPVOL 31 -#define TSC2301_MUTE_LEFT_SHIFT 15 -#define TSC2301_VOL_LEFT_SHIFT 8 -#define TSC2301_MUTE_RIGHT_SHIFT 7 -#define TSC2301_VOL_RIGHT_SHIFT 0 - -#define TSC2301_INM_MASK 3 -#define TSC2301_INML_SHIFT 12 -#define TSC2301_INMR_SHIFT 10 - -#define TSC2301_MICG_MASK 3 -#define TSC2301_MICG_MIN 1 /* values 0 & 1 both mean 0 dB */ -#define TSC2301_MICG_SHIFT 8 - -#define TSC2301_REG_AUDCNTL_MCLK(v) (((v) & 3) << 6) -#define TSC2301_REG_AUDCNTL_I2SFS(v) (((v) & 0xf) << 2) -#define TSC2301_REG_AUDCNTL_I2SFM(v) (((v) & 3) << 0) - -#define TSC2301_SINGLE(xname, xindex, reg, shadow_index, shift, mask, min) \ -{\ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_tsc2301_info_single, \ - .get = snd_tsc2301_get_single, \ - .put = snd_tsc2301_put_single, \ - .private_value = TSC2301_REG_TO_PVAL(reg) | \ - (shadow_index << 8) | (shift << 16) | (mask << 24) | \ - (min << 28) \ -} -#define TSC2301_SINGLE_MINVAL(v) (((v) >> 28) & 15) -#define TSC2301_SINGLE_SHIFT(v) (((v) >> 16) & 15) -#define TSC2301_SINGLE_MASK(v) (((v) >> 24) & 15) - -#define TSC2301_DOUBLE(xname, xindex, reg, shadow_index, ls, rs, mask, min) \ -{\ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_tsc2301_info_double, \ - .get = snd_tsc2301_get_double, \ - .put = snd_tsc2301_put_double, \ - .private_value = TSC2301_REG_TO_PVAL(reg) | \ - (shadow_index << 8) | (min << 11) | \ - (ls << 16) | (rs << 20) | (mask << 24) \ -} -#define TSC2301_DOUBLE_MINVAL(v) (((v) >> 11) & 0x1f) -#define TSC2301_DOUBLE_LEFT_SHIFT(v) (((v) >> 16) & 15) -#define TSC2301_DOUBLE_RIGHT_SHIFT(v) (((v) >> 20) & 15) -#define TSC2301_DOUBLE_MASK(v) (((v) >> 24) & TSC2301_VOLUME_MASK) - -#define TSC2301_MUX(xname, xindex, reg, shadow_index, ls, rs, mask) \ -{\ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_tsc2301_info_mux, \ - .get = snd_tsc2301_get_mux, \ - .put = snd_tsc2301_put_mux, \ - .private_value = TSC2301_REG_TO_PVAL(reg) | \ - (shadow_index << 8) | (ls << 16) | (rs << 20) | (mask << 24) \ -} -#define TSC2301_MUX_LEFT_SHIFT(v) (((v) >> 16) & 15) -#define TSC2301_MUX_RIGHT_SHIFT(v) (((v) >> 20) & 15) -#define TSC2301_MUX_MASK(v) (((v) >> 24) & TSC2301_VOLUME_MASK) - -#define TSC2301_BOOL(xname, xindex, reg, shadow_index, shift, invert, state) \ -{ \ - .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ - .name = xname, \ - .index = xindex, \ - .info = snd_tsc2301_info_bool, \ - .get = snd_tsc2301_get_bool, \ - .put = snd_tsc2301_put_bool, \ - .private_value = TSC2301_REG_TO_PVAL(reg) | \ - (shadow_index << 8) | (shift << 16) | \ - (invert << 24) | (state << 25) \ -} -#define TSC2301_BOOL_SHIFT(v) (((v) >> 16) & 7) -#define TSC2301_BOOL_INVERT(v) (((v) >> 24) & 1) -#define TSC2301_BOOL_STATE(v) (((v) >> 25) & 1) - -#define TSC2301_SHADOW_INDEX(v) (((v) >> 8) & 7) - -/* - * Power-down handler for additional GPIO mixer controls. GPIO state of GPIO - * controls whose power-down flag is enabled are set to their false/deactivate - * state - * - * Must be called tsc->mixer->mutex locked - */ -static void tsc2301_gpio_power_down(struct tsc2301 *tsc) -{ - struct tsc2301_mixer *mix = tsc->mixer; - u16 temp; - int i; - - temp = mix->shadow_regs[GPIO_INDEX]; - for (i = 0; i < mix->n_mixer_gpios; i++) { - const struct tsc2301_mixer_gpio *mg; - - mg = mix->mixer_gpios + i; - if (mg->deactivate_on_pd) { - int gpio = mg->gpio; - - temp &= ~(1 << gpio); - temp |= mg->inverted << gpio; - } - } - tsc2301_write_reg(tsc, TSC2301_REG_GPIO, temp); -} - -/* - * Powers down/up audio blocks which are muted or become unused. - * shadow_index >= 0, changes power state of single audio block - * shadow_index < 0, changes power state of all blocks - * - * Must be called tsc->mixer->mutex locked - */ -#define TSC2301_MUTE_MASK \ - ((1 << TSC2301_MUTE_LEFT_SHIFT) | (1 << TSC2301_MUTE_RIGHT_SHIFT)) -static void tsc2301_power_ctrl(struct tsc2301 *tsc, int shadow_index, - int poll_pdsts) -{ - struct tsc2301_mixer *mix = tsc->mixer; - u16 pd_ctrl, pd_ctrl_old, w; - unsigned long timeout; - int power_up = 0; - - if (mix->delayed_pd_active) { - mix->delayed_pd_active = 0; - mix->mclk_enabled--; - cancel_delayed_work(&mix->delayed_power_down); - } - - pd_ctrl = pd_ctrl_old = mix->shadow_regs[PD_MISC_INDEX]; - /* power control helper based on used space mixer selections. See - * actual power control decisions below */ - if (shadow_index < 0 || shadow_index == ADCVOL_INDEX) { - /* ADC left and right power down control */ - if (mix->shadow_regs[ADCVOL_INDEX] & - (1 << TSC2301_MUTE_LEFT_SHIFT)) - /* left ADC muted. Power down the left ADC */ - pd_ctrl |= TSC2301_REG_PD_MISC_ADPDL; - else - pd_ctrl &= ~TSC2301_REG_PD_MISC_ADPDL; - if (mix->shadow_regs[ADCVOL_INDEX] & - (1 << TSC2301_MUTE_LEFT_SHIFT)) - /* right ADC muted. Power down the right ADC */ - pd_ctrl |= TSC2301_REG_PD_MISC_ADPDR; - else - pd_ctrl &= ~TSC2301_REG_PD_MISC_ADPDR; - } - if (shadow_index < 0 || shadow_index == DACVOL_INDEX) { - /* DAC power down control */ - if ((mix->shadow_regs[DACVOL_INDEX] & - TSC2301_MUTE_MASK) == TSC2301_MUTE_MASK) - /* both DACs muted. Power down the DAC */ - pd_ctrl |= TSC2301_REG_PD_MISC_DAPD; - else - pd_ctrl &= ~TSC2301_REG_PD_MISC_DAPD; - } - if (shadow_index < 0 || shadow_index == BPVOL_INDEX) { - /* line bypass power down control */ - if ((mix->shadow_regs[BPVOL_INDEX] & - TSC2301_MUTE_MASK) == TSC2301_MUTE_MASK) - /* both line bypasses muted. Power down the bypass - * path */ - pd_ctrl |= TSC2301_REG_PD_MISC_ABPD; - else - pd_ctrl &= ~TSC2301_REG_PD_MISC_ABPD; - } - if (shadow_index < 0 || shadow_index == AUDCNTL_INDEX) { - /* mic bias power down control */ - if ((mix->shadow_regs[AUDCNTL_INDEX] & - (3 << TSC2301_INML_SHIFT)) && - (mix->shadow_regs[AUDCNTL_INDEX] & - (3 << TSC2301_INMR_SHIFT))) - /* both ADC channels use other than mic input. Power - * down the mic bias output */ - pd_ctrl |= TSC2301_REG_PD_MISC_MIBPD; - else - pd_ctrl &= ~TSC2301_REG_PD_MISC_MIBPD; - } - - /* power control decisions based on codec usage and user space mixer - * selections detected above */ - pd_ctrl &= ~TSC2301_REG_PD_MISC_APD; /* audio not powered down */ - if (mix->mclk_enabled) { - if (!mix->adc_enabled) { - /* ADC not used, power down both ADC's and mic bias - * output independently of user space mixer - * selections */ - pd_ctrl |= TSC2301_REG_PD_MISC_ADPDL; - pd_ctrl |= TSC2301_REG_PD_MISC_ADPDR; - pd_ctrl |= TSC2301_REG_PD_MISC_MIBPD; - } - if (!mix->dac_enabled) { - /* DAC not used, power down DAC independently of user - * space mixer selections */ - pd_ctrl |= TSC2301_REG_PD_MISC_DAPD; - } - - if (mix->pll_output) { - /* GPIO_0 is configured as PLL output so audio - * controller is expecting clock from TSC2301. Either - * ADC or DAC must be active in order to keep PLL on */ - if ((pd_ctrl & TSC2301_REG_PD_MISC_ADPDL) && - (pd_ctrl & TSC2301_REG_PD_MISC_ADPDR) && - (pd_ctrl & TSC2301_REG_PD_MISC_DAPD)) { - /* neither ADC or DAC used. Force ADC on in - * order to keep PLL active */ - pd_ctrl &= ~(TSC2301_REG_PD_MISC_ADPDL | - TSC2301_REG_PD_MISC_ADPDR); - } - } - } else { - /* audio input clock is not enabled so power down DAC and ADC - * in order to shutdown PLL and to keep touchscreen and keypad - * parts working. Touchscreen and keypad use audio clock when - * PLL is on and internal clock otherwise */ - pd_ctrl |= TSC2301_REG_PD_MISC_DAPD | - TSC2301_REG_PD_MISC_ADPDL | - TSC2301_REG_PD_MISC_ADPDR; - } - - if ((pd_ctrl & TSC2301_REG_PD_MISC_ADPDL) && - (pd_ctrl & TSC2301_REG_PD_MISC_ADPDR) && - (pd_ctrl & TSC2301_REG_PD_MISC_DAPD) && - (pd_ctrl & TSC2301_REG_PD_MISC_ABPD)) { - /* all ADC, DAC and line bypass path unused. Power down the - * whole audio part of the TSC2301 */ - pd_ctrl |= TSC2301_REG_PD_MISC_APD; - } - - if (pd_ctrl == pd_ctrl_old) - return; - - /* power down control changed. Update into TSC2301 */ - if ((pd_ctrl ^ pd_ctrl_old) & TSC2301_REG_PD_MISC_APD) { - /* whole audio power state changed. Update GPIO states */ - if (pd_ctrl & TSC2301_REG_PD_MISC_APD) { - /* power down GPIO controls before powering down - * the codec */ - tsc2301_gpio_power_down(tsc); - /* we must really ensure that codec has been on no less - * than 100 msec before doing power-down */ - timeout = mix->pu_jiffies + TSC2301_MIN_PU_PERIOD - - jiffies; - if (timeout <= TSC2301_MIN_PU_PERIOD) { - mix->delayed_pd_active = 1; - mix->mclk_enabled++; - schedule_delayed_work(&mix->delayed_power_down, - timeout + 1); - return; - } - } else - /* restore GPIOs after codec is powered up */ - power_up = 1; - } - mix->shadow_regs[PD_MISC_INDEX] = pd_ctrl; - tsc2301_write_reg(tsc, TSC2301_REG_PD_MISC, pd_ctrl); - if (power_up) - mix->pu_jiffies = jiffies; - if (!poll_pdsts) { - if (power_up) - tsc2301_write_reg(tsc, TSC2301_REG_GPIO, - mix->shadow_regs[GPIO_INDEX]); - return; - } - - /* wait until power-up/-down is completed */ - timeout = jiffies + msecs_to_jiffies(100); - w = 0; - do { - if (time_after(jiffies, timeout)) { - /* Print a warning only if the I2S clock is not - * present / out of sync. This can happen during - * init time, when that clock will be turned on - * by another driver like in the OMAP EAC with - * external clock case. - */ - if (w & TSC2301_REG_PD_MISC_OTSYN) { - dev_warn(&tsc->spi->dev, - "I2S clock not in sync or off.\n"); - } else { - dev_err(&tsc->spi->dev, - "power-up/-down timed out " - "(0x%04x, 0x%04x -> 0x%04x)\n", - w, pd_ctrl_old, pd_ctrl); - } - goto out; - } - w = tsc2301_read_reg(tsc, TSC2301_REG_PD_MISC); - } while (!(w & TSC2301_REG_PD_MISC_PDSTS)); - -out: - if (((pd_ctrl ^ pd_ctrl_old) & TSC2301_REG_PD_MISC_DAPD) && - !(pd_ctrl & TSC2301_REG_PD_MISC_DAPD)) { - /* DAC powered up now. Ensure that DAC and audio outputs are - * activated. They are up 100 msec after the chip power-up - * command */ - timeout = mix->pu_jiffies + TSC2301_DAC_DELAY - jiffies; - if (timeout <= TSC2301_DAC_DELAY) - schedule_timeout_interruptible(timeout); - /* FIXME: This is lazy. We restore GPIOs only after activating - * the DAC. It would be better to do some kind of delayed GPIO - * restore. That ensures that we restore them also if only ADC - * path is activated. But this is required only if there is - * some input amplifier, bias control, etc. and their power - * state is under TSC GPIO control */ - tsc2301_write_reg(tsc, TSC2301_REG_GPIO, - mix->shadow_regs[GPIO_INDEX]); - } -} - -static int snd_tsc2301_info_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - int mask = TSC2301_SINGLE_MASK(kcontrol->private_value); - int minval = TSC2301_SINGLE_MINVAL(kcontrol->private_value); - - uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 1; - uinfo->value.integer.min = minval; - uinfo->value.integer.max = mask; - - return 0; -} - -static int snd_tsc2301_get_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tsc2301 *tsc = kcontrol->private_data; - unsigned long priv = kcontrol->private_value; - int mask = TSC2301_SINGLE_MASK(priv); - int shift = TSC2301_SINGLE_SHIFT(priv); - int shadow_index = TSC2301_SHADOW_INDEX(priv); - u16 shadow_reg; - - shadow_reg = tsc->mixer->shadow_regs[shadow_index]; - - ucontrol->value.integer.value[0] = (shadow_reg >> shift) & mask; - - return 0; -} - -static int snd_tsc2301_put_single(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tsc2301 *tsc = kcontrol->private_data; - unsigned long priv = kcontrol->private_value; - int mask = TSC2301_SINGLE_MASK(priv); - int shadow_index = TSC2301_SHADOW_INDEX(priv); - u16 shadow_reg, shadow_reg_old; - int shift = TSC2301_SINGLE_SHIFT(priv); - int reg = TSC2301_PVAL_TO_REG(priv); - int changed; - - mutex_lock(&tsc->mixer->mutex); - shadow_reg = shadow_reg_old = tsc->mixer->shadow_regs[shadow_index]; - - /* zero bits to be modified */ - shadow_reg &= ~(mask << shift); - /* modify with new value */ - shadow_reg |= ((ucontrol->value.integer.value[0] & mask) << shift); - - changed = (shadow_reg != shadow_reg_old); - tsc->mixer->shadow_regs[shadow_index] = shadow_reg; - - /* update into TSC2301 if necessary */ - if (changed) - tsc2301_write_reg(tsc, reg, shadow_reg); - mutex_unlock(&tsc->mixer->mutex); - - return changed; -} - -static int snd_tsc2301_info_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - /* mask == 1 : Switch - * mask > 1 : Max volume */ - int mask = TSC2301_DOUBLE_MASK(kcontrol->private_value); - int minval = TSC2301_DOUBLE_MINVAL(kcontrol->private_value); - - uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : - SNDRV_CTL_ELEM_TYPE_INTEGER; - uinfo->count = 2; - uinfo->value.integer.min = minval; - uinfo->value.integer.max = mask; - - return 0; -} - -static int snd_tsc2301_get_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tsc2301 *tsc = kcontrol->private_data; - unsigned long priv = kcontrol->private_value; - /* mask == 1 : Switch - * mask > 1 : Volume */ - int mask = TSC2301_DOUBLE_MASK(priv); - int ls = TSC2301_DOUBLE_LEFT_SHIFT(priv); - int rs = TSC2301_DOUBLE_RIGHT_SHIFT(priv); - int shadow_index = TSC2301_SHADOW_INDEX(priv); - u16 shadow_reg; - - shadow_reg = tsc->mixer->shadow_regs[shadow_index]; - - /* invert mute bits for the switches */ - if (mask == 1) - shadow_reg = ~shadow_reg; - - ucontrol->value.integer.value[0] = (shadow_reg >> ls) & mask; - ucontrol->value.integer.value[1] = (shadow_reg >> rs) & mask; - - return 0; -} - -static int snd_tsc2301_put_double(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tsc2301 *tsc = kcontrol->private_data; - unsigned long priv = kcontrol->private_value; - /* mask == 1 : Switch - * mask > 1 : Volume */ - int mask = TSC2301_DOUBLE_MASK(priv); - int shadow_index = TSC2301_SHADOW_INDEX(priv); - u16 shadow_reg, shadow_reg_old; - int ls = TSC2301_DOUBLE_LEFT_SHIFT(priv); - int rs = TSC2301_DOUBLE_RIGHT_SHIFT(priv); - int reg = TSC2301_PVAL_TO_REG(priv); - int changed; - - mutex_lock(&tsc->mixer->mutex); - shadow_reg = shadow_reg_old = tsc->mixer->shadow_regs[shadow_index]; - - /* zero bits to be modified */ - shadow_reg &= ~((mask << ls) | (mask << rs)); - /* modify with new value */ - if (mask == 1) { - /* switch. Invert switch values for the mute bits */ - shadow_reg |= - ((~ucontrol->value.integer.value[0] & mask) << ls) | - ((~ucontrol->value.integer.value[1] & mask) << rs); - } else { - /* volume */ - shadow_reg |= - (ucontrol->value.integer.value[0] << ls) | - (ucontrol->value.integer.value[1] << rs); - } - - changed = (shadow_reg != shadow_reg_old); - tsc->mixer->shadow_regs[shadow_index] = shadow_reg; - - /* update into TSC2301 if necessary */ - if (changed) - tsc2301_write_reg(tsc, reg, shadow_reg); - - if (mask == 1) - /* check is need to power down/up audio blocks in case of - * muted state change */ - tsc2301_power_ctrl(tsc, shadow_index, 0); - mutex_unlock(&tsc->mixer->mutex); - - return changed; -} - -static int snd_tsc2301_info_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - static char *texts[4] = {"Mic", "Line", "Line swapped", "Line mono"}; - - uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; - uinfo->count = 2; - uinfo->value.enumerated.items = 4; - if (uinfo->value.enumerated.item > 3) - uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, - texts[uinfo->value.enumerated.item]); - - return 0; -} - -static int snd_tsc2301_get_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tsc2301 *tsc = kcontrol->private_data; - unsigned long priv = kcontrol->private_value; - int mask = TSC2301_MUX_MASK(priv); - int ls = TSC2301_MUX_LEFT_SHIFT(priv); - int rs = TSC2301_MUX_RIGHT_SHIFT(priv); - int shadow_index = TSC2301_SHADOW_INDEX(priv); - u16 shadow_reg; - - shadow_reg = tsc->mixer->shadow_regs[shadow_index]; - ucontrol->value.enumerated.item[0] = (shadow_reg >> ls) & mask; - ucontrol->value.enumerated.item[1] = (shadow_reg >> rs) & mask; - - return 0; -} - -static int snd_tsc2301_put_mux(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tsc2301 *tsc = kcontrol->private_data; - unsigned long priv = kcontrol->private_value; - int mask = TSC2301_MUX_MASK(priv); - int shadow_index = TSC2301_SHADOW_INDEX(priv); - u16 shadow_reg, shadow_reg_old; - int ls = TSC2301_MUX_LEFT_SHIFT(priv); - int rs = TSC2301_MUX_RIGHT_SHIFT(priv); - int reg = TSC2301_PVAL_TO_REG(priv); - int changed; - - mutex_lock(&tsc->mixer->mutex); - shadow_reg = shadow_reg_old = tsc->mixer->shadow_regs[shadow_index]; - - /* zero bits to be modified */ - shadow_reg &= ~((mask << ls) | (mask << rs)); - /* modify with new value */ - shadow_reg |= (ucontrol->value.enumerated.item[0] << ls); - shadow_reg |= (ucontrol->value.enumerated.item[1] << rs); - - changed = (shadow_reg != shadow_reg_old); - - /* update into TSC2301 if necessary */ - if (changed) { - tsc->mixer->shadow_regs[shadow_index] = shadow_reg; - tsc2301_write_reg(tsc, reg, shadow_reg); - } - - /* check is need to power up/down audio blocks in case of ADC input - * change */ - tsc2301_power_ctrl(tsc, shadow_index, 0); - mutex_unlock(&tsc->mixer->mutex); - - return changed; -} - -static int snd_tsc2301_info_bool(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - - return 0; -} - -static int snd_tsc2301_get_bool(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tsc2301 *tsc = kcontrol->private_data; - unsigned long priv = kcontrol->private_value; - int shadow_index = TSC2301_SHADOW_INDEX(priv); - int shift = TSC2301_BOOL_SHIFT(priv); - int invert = TSC2301_BOOL_INVERT(priv); - u16 shadow_reg; - - shadow_reg = tsc->mixer->shadow_regs[shadow_index]; - ucontrol->value.integer.value[0] = - invert ^ ((shadow_reg >> shift) & 1); - - return 0; -} - -static int snd_tsc2301_put_bool(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_value *ucontrol) -{ - struct tsc2301 *tsc = kcontrol->private_data; - unsigned long priv = kcontrol->private_value; - int shadow_index = TSC2301_SHADOW_INDEX(priv); - int shift = TSC2301_BOOL_SHIFT(priv); - int invert = TSC2301_BOOL_INVERT(priv); - int reg = TSC2301_PVAL_TO_REG(priv); - u16 shadow_reg, shadow_reg_old; - int changed; - - mutex_lock(&tsc->mixer->mutex); - shadow_reg = shadow_reg_old = tsc->mixer->shadow_regs[shadow_index]; - - /* zero bit to be modified */ - shadow_reg &= ~(1 << shift); - /* modify with new value */ - shadow_reg |= - (invert ^ (ucontrol->value.integer.value[0] & 1)) << shift; - - changed = (shadow_reg != shadow_reg_old); - - /* update into TSC2301 if necessary */ - if (changed) { - tsc->mixer->shadow_regs[shadow_index] = shadow_reg; - if ((shadow_index == GPIO_INDEX) && - (tsc->mixer->shadow_regs[PD_MISC_INDEX] & - TSC2301_REG_PD_MISC_APD)) { - /* changing GPIO control and audio is powered down. - * Update GPIO states according to their power-down - * flag */ - tsc2301_gpio_power_down(tsc); - } else - tsc2301_write_reg(tsc, reg, shadow_reg); - } - mutex_unlock(&tsc->mixer->mutex); - - return changed; -} - -/* TSC2301 internal mixer controls */ -static struct snd_kcontrol_new snd_tsc2301_controls[] = { - /* stereo ADC input switches and volumes */ - TSC2301_DOUBLE("Capture Switch", 0, - TSC2301_REG_ADCVOL, ADCVOL_INDEX, - TSC2301_MUTE_LEFT_SHIFT, TSC2301_MUTE_RIGHT_SHIFT, - 1, 0), - TSC2301_DOUBLE("Capture Volume", 0, - TSC2301_REG_ADCVOL, ADCVOL_INDEX, - TSC2301_VOL_LEFT_SHIFT, TSC2301_VOL_RIGHT_SHIFT, - TSC2301_VOLUME_MASK, TSC2301_MIN_ADCVOL), - - /* stereo DAC output switches and volumes */ - TSC2301_DOUBLE("PCM Playback Switch", 0, - TSC2301_REG_DACVOL, DACVOL_INDEX, - TSC2301_MUTE_LEFT_SHIFT, TSC2301_MUTE_RIGHT_SHIFT, - 1, 0), - TSC2301_DOUBLE("PCM Playback Volume", 0, - TSC2301_REG_DACVOL, DACVOL_INDEX, - TSC2301_VOL_LEFT_SHIFT, TSC2301_VOL_RIGHT_SHIFT, - TSC2301_VOLUME_MASK, TSC2301_MIN_DACVOL), - - /* stereo line input bypass switches and volumes */ - TSC2301_DOUBLE("Line Playback Switch", 0, - TSC2301_REG_BPVOL, BPVOL_INDEX, - TSC2301_MUTE_LEFT_SHIFT, TSC2301_MUTE_RIGHT_SHIFT, - 1, 0), - TSC2301_DOUBLE("Line Playback Volume", 0, - TSC2301_REG_BPVOL, BPVOL_INDEX, - TSC2301_VOL_LEFT_SHIFT, TSC2301_VOL_RIGHT_SHIFT, - TSC2301_VOLUME_MASK, TSC2301_MIN_BPVOL), - - /* mono microphone input gain */ - TSC2301_SINGLE("Mic Boost", 0, - TSC2301_REG_AUDCNTL, AUDCNTL_INDEX, - TSC2301_MICG_SHIFT, - TSC2301_MICG_MASK, TSC2301_MICG_MIN), - - /* ADC input sources. Both channels could be selected separately */ - TSC2301_MUX("Capture Source", 0, - TSC2301_REG_AUDCNTL, AUDCNTL_INDEX, - TSC2301_INML_SHIFT, TSC2301_INMR_SHIFT, - TSC2301_INM_MASK), -}; - -/* must be called tsc->mixer->mutex locked */ -static void tsc2301_flush_shadow_regs(struct tsc2301 *tsc) -{ - int i, page, addr; - u16 temp; - - page = TSC2301_REG_TO_PAGE(TSC2301_REG_AUDCNTL); - addr = TSC2301_REG_TO_ADDR(TSC2301_REG_AUDCNTL); - - for (i = 0; i < 4; i++) { - temp = tsc->mixer->shadow_regs[i]; - tsc2301_write_reg(tsc, TSC2301_REG(page, addr + i), temp); - } - temp = tsc->mixer->shadow_regs[GPIO_INDEX]; - tsc2301_write_reg(tsc, TSC2301_REG_GPIO, temp); - - /* Update power state of all audio blocks depending are they - * muted or unused. */ - tsc2301_power_ctrl(tsc, -1, 0); -} - -#ifdef CONFIG_PM -int tsc2301_mixer_suspend(struct tsc2301 *tsc) -{ - /* power down entire audio section inside TSC2301 in case the - * chip is still powered during the system sleep. However this driver - * doesn't require that chip is powered because registers are restored - * in function tsc2301_mixer_resume */ - mutex_lock(&tsc->mixer->mutex); - tsc2301_gpio_power_down(tsc); - tsc->mixer->shadow_regs[PD_MISC_INDEX] |= TSC2301_REG_PD_MISC_APD; - tsc2301_write_reg(tsc, TSC2301_REG_PD_MISC, - tsc->mixer->shadow_regs[PD_MISC_INDEX]); - mutex_unlock(&tsc->mixer->mutex); - return 0; -} - -void tsc2301_mixer_resume(struct tsc2301 *tsc) -{ - /* power up the TSC2301 audio section and restore registers */ - mutex_lock(&tsc->mixer->mutex); - tsc->mixer->shadow_regs[PD_MISC_INDEX] &= ~TSC2301_REG_PD_MISC_APD; - tsc2301_flush_shadow_regs(tsc); - mutex_unlock(&tsc->mixer->mutex); -} -#endif - -void tsc2301_mixer_enable_mclk(struct device *dev) -{ - struct tsc2301 *tsc = dev_get_drvdata(dev); - struct tsc2301_mixer *mix = tsc->mixer; - - mutex_lock(&mix->mutex); - if (!mix->mclk_enabled++ && tsc->enable_clock != NULL) { - tsc->enable_clock(dev); - } - tsc2301_power_ctrl(tsc, -1, 1); - mutex_unlock(&mix->mutex); -} - -void tsc2301_mixer_disable_mclk(struct device *dev) -{ - struct tsc2301 *tsc = dev_get_drvdata(dev); - struct tsc2301_mixer *mix = tsc->mixer; - - mutex_lock(&mix->mutex); - mix->mclk_enabled--; - tsc2301_power_ctrl(tsc, -1, 1); - if (!mix->mclk_enabled && tsc->disable_clock != NULL) { - tsc->disable_clock(dev); - } - mutex_unlock(&mix->mutex); -} - -static void tsc2301_mixer_delayed_power_down(struct work_struct *work) -{ - struct tsc2301_mixer *mix = container_of(work, struct tsc2301_mixer, - delayed_power_down.work); - struct tsc2301 *tsc = mix->tsc; - - mutex_lock(&mix->mutex); - if (!mix->delayed_pd_active) { - mutex_unlock(&mix->mutex); - return; - } - mix->delayed_pd_active = 0; - mutex_unlock(&mix->mutex); - tsc2301_mixer_disable_mclk(&tsc->spi->dev); -} - -/* - * Allows audio controller driver to notify its usage of ADC and DAC - */ -void tsc2301_mixer_set_power(struct device *dev, int dac, int adc) -{ - struct tsc2301 *tsc = dev_get_drvdata(dev); - - mutex_lock(&tsc->mixer->mutex); - tsc->mixer->adc_enabled = adc; - tsc->mixer->dac_enabled = dac; - - /* update power state of all audio blocks */ - tsc2301_power_ctrl(tsc, -1, 1); - mutex_unlock(&tsc->mixer->mutex); -} - -/* - * Registers TSC2301 ALSA Mixer controls for the given sound card - */ -int tsc2301_mixer_register_controls(struct device *dev, struct snd_card *card) -{ - struct tsc2301 *tsc = dev_get_drvdata(dev); - struct tsc2301_mixer *mix = tsc->mixer; - int i, err; - - /* Register ALSA mixer controls */ - for (i = 0; i < ARRAY_SIZE(snd_tsc2301_controls); i++) { - err = snd_ctl_add(card, - snd_ctl_new1(&snd_tsc2301_controls[i], tsc)); - if (err < 0) - return err; - } - - if (!mix->n_mixer_gpios) - return 0; - - /* Register additional GPIO controls if defined */ - for (i = 0; i < mix->n_mixer_gpios; i++) { - const struct tsc2301_mixer_gpio *mg = mix->mixer_gpios + i; - struct snd_kcontrol *ctrlp; - struct snd_kcontrol_new ctrl = - TSC2301_BOOL((char *)mg->name, 0, - TSC2301_REG_GPIO, GPIO_INDEX, - mg->gpio, mg->inverted, mg->def_enable); - - ctrlp = snd_ctl_new1(&ctrl, tsc); - err = snd_ctl_add(card, ctrlp); - if (err < 0) - return err; - } - - return 0; -} - -int tsc2301_mixer_init(struct tsc2301 *tsc, - struct tsc2301_platform_data *pdata) -{ - struct tsc2301_mixer *mix; - int err = 0; - u16 w; - - mix = kzalloc(sizeof(*mix), GFP_KERNEL); - if (mix == NULL) - return -ENOMEM; - tsc->mixer = mix; - - mix->tsc = tsc; - mutex_init(&mix->mutex); - mix->platform_init = pdata->codec_init; - mix->platform_cleanup = pdata->codec_cleanup; - mix->pll_output = pdata->pll_output; - - INIT_DELAYED_WORK(&mix->delayed_power_down, - tsc2301_mixer_delayed_power_down); - - /* initialize shadow register default values */ - w = 0xc000; - w |= (pdata->mclk_ratio << 6) | (pdata->i2s_sample_rate << 2); - w |= pdata->i2s_format; - mix->shadow_regs[AUDCNTL_INDEX] = w; - mix->shadow_regs[ADCVOL_INDEX] = 0xd7d7; - mix->shadow_regs[DACVOL_INDEX] = 0xffff; - mix->shadow_regs[BPVOL_INDEX] = 0xe7e7; - mix->shadow_regs[PD_MISC_INDEX] = pdata->power_down_blocks; - - /* if extra mixer controls configured, then configure associated - * GPIOs as output and drive their default state */ - if (pdata->n_mixer_gpios) { - int i; - - w = 0; - for (i = 0; i < pdata->n_mixer_gpios; i++) { - const struct tsc2301_mixer_gpio *mg; - int gpio; - - mg = pdata->mixer_gpios + i; - gpio = mg->gpio; - w |= (1 << gpio) << 8; - w |= (mg->inverted ^ mg->def_enable) << gpio; - } - mix->shadow_regs[GPIO_INDEX] = w; - - mix->mixer_gpios = kmalloc(sizeof(*pdata->mixer_gpios) * - pdata->n_mixer_gpios, - GFP_KERNEL); - if (mix->mixer_gpios == NULL) { - err = -ENOMEM; - goto err1; - } - memcpy(mix->mixer_gpios, pdata->mixer_gpios, - sizeof(*pdata->mixer_gpios) * pdata->n_mixer_gpios); - mix->n_mixer_gpios = pdata->n_mixer_gpios; - } - - /* PLL control */ - tsc2301_write_pll(tsc, pdata->pll_n, pdata->pll_a, pdata->pll_pdc, - 0, mix->pll_output ? 0 : 1); - - tsc2301_flush_shadow_regs(tsc); - - if (mix->platform_init != NULL) { - err = mix->platform_init(&tsc->spi->dev); - if (err < 0) - goto err2; - } - - return 0; -err2: - if (mix->mixer_gpios != NULL) - kfree(mix->mixer_gpios); -err1: - kfree(mix); - return err; -} - -void tsc2301_mixer_exit(struct tsc2301 *tsc) -{ - struct tsc2301_mixer *mixer = tsc->mixer; - - if (mixer->platform_cleanup != NULL) - mixer->platform_cleanup(&tsc->spi->dev); - - if (mixer->mixer_gpios != NULL) - kfree(mixer->mixer_gpios); -} - -MODULE_AUTHOR("Jarkko Nikula "); -MODULE_LICENSE("GPL"); diff --git a/include/linux/spi/tsc2301.h b/include/linux/spi/tsc2301.h index 4552ebaad56..62e586286bc 100644 --- a/include/linux/spi/tsc2301.h +++ b/include/linux/spi/tsc2301.h @@ -191,17 +191,6 @@ TSC2301_DECL_MOD(ts) TSC2301_DECL_EMPTY_MOD(ts) #endif -#ifdef CONFIG_SPI_TSC2301_AUDIO -TSC2301_DECL_MOD(mixer) -extern void tsc2301_mixer_set_power(struct device *tsc_dev, int dac, int adc); - -struct snd_card; -extern int tsc2301_mixer_register_controls(struct device *tsc_dev, - struct snd_card *card); -#else -TSC2301_DECL_EMPTY_MOD(mixer) -#endif - extern void tsc2301_mixer_enable_mclk(struct device *tsc_dev); extern void tsc2301_mixer_disable_mclk(struct device *tsc_dev);