void wm8350_free(struct wm8350 *wm8350) { #if BATTERY struct wm8350_power *power = &wm8350->power; #endif wm8350_mask_irq(wm8350, WM8350_IRQ_GPIO(7)); wm8350_free_irq(wm8350, WM8350_IRQ_GPIO(7)); wm8350_mask_irq(wm8350, WM8350_IRQ_WKUP_ONKEY); wm8350_free_irq(wm8350, WM8350_IRQ_WKUP_ONKEY); #if BATTERY wm8350_charger_enable(power, 0); wm8350_fast_charger_enable(power, 0); #endif if (wm8350->nirq) free_irq(wm8350->nirq, wm8350); flush_scheduled_work(); if (wm8350->pmic.dev.is_registered) device_unregister(&wm8350->pmic.dev); if (wm8350->rtc.dev.is_registered) device_unregister(&wm8350->rtc.dev); if (wm8350->wdg.dev.is_registered) device_unregister(&wm8350->wdg.dev); if (wm8350->power.dev.is_registered) device_unregister(&wm8350->power.dev); platform_device_unregister(imx_snd_device); }
/* * Handle commands from user-space */ static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct wm8350_rtc *wm_rtc = to_wm8350_rtc_device(dev); struct wm8350 *wm8350 = to_wm8350_from_rtc(wm_rtc); switch (cmd) { case RTC_AIE_OFF: /* alarm off */ wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_ALM); wm_rtc->alarm_enabled = 0; break; case RTC_AIE_ON: /* alarm on */ wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_ALM); wm_rtc->alarm_enabled = 1; break; case RTC_UIE_OFF: /* update off */ wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); wm_rtc->update_enabled = 0; break; case RTC_UIE_ON: /* update on */ wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); wm_rtc->update_enabled = 1; break; case RTC_PIE_ON: if (!wm_rtc->pie_enabled) { enable_irq(wm_rtc->per_irq); wm_rtc->pie_enabled = 1; } break; case RTC_PIE_OFF: if (wm_rtc->pie_enabled) { disable_irq(wm_rtc->per_irq); wm_rtc->pie_enabled = 0; } break; case RTC_IRQP_READ: /* read periodic alarm frequency */ return wm_rtc->pie_freq; case RTC_IRQP_SET: /* set periodic alarm frequency */ return wm8350_rtc_set_pie(wm_rtc, arg); default: return -ENOIOCTLCMD; } return 0; }
static int imx_3stack_wm8350_remove(struct platform_device *pdev) { struct imx_3stack_priv *priv = &machine_priv; struct wm8350 *wm8350 = priv->wm8350; wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); return 0; }
static int wm8350_regulator_remove(struct platform_device *pdev) { struct regulator_dev *rdev = platform_get_drvdata(pdev); struct wm8350 *wm8350 = rdev_get_drvdata(rdev); wm8350_mask_irq(wm8350, wm8350_reg[pdev->id].irq); wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq); regulator_unregister(rdev); return 0; }
static int __exit wm8350_rtc_remove(struct platform_device *pdev) { struct wm8350 *wm8350 = platform_get_drvdata(pdev); struct wm8350_rtc *wm_rtc = &wm8350->rtc; int ret; if (wm_rtc->per_irq) free_irq(wm_rtc->per_irq, wm8350); wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_ALM); wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); rtc_device_unregister(wm_rtc->rtc); ret = wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_RTC_TICK_ENA); if (ret < 0) printk(KERN_ERR "wm8350-rtc: failed to enable RTC\n"); return 0; }
static void wm8350_irq_call_handler(struct wm8350 *wm8350, int irq) { mutex_lock(&wm8350->irq_mutex); if (wm8350->irq[irq].handler) wm8350->irq[irq].handler(wm8350, irq, wm8350->irq[irq].data); else { dev_err(wm8350->dev, "irq %d nobody cared. now masked.\n", irq); wm8350_mask_irq(wm8350, irq); } mutex_unlock(&wm8350->irq_mutex); }
static int __devexit wm8350_rtc_remove(struct platform_device *pdev) { struct wm8350 *wm8350 = platform_get_drvdata(pdev); struct wm8350_rtc *wm_rtc = &wm8350->rtc; wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); wm8350_free_irq(wm8350, WM8350_IRQ_RTC_SEC); wm8350_free_irq(wm8350, WM8350_IRQ_RTC_ALM); rtc_device_unregister(wm_rtc->rtc); return 0; }
static int wm8350_remove(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec = socdev->card->codec; struct wm8350 *wm8350 = codec->control_data; struct wm8350_data *priv = codec->private_data; int ret; wm8350_clear_bits(wm8350, WM8350_JACK_DETECT, WM8350_JDL_ENA | WM8350_JDR_ENA); wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_4, WM8350_TOCLK_ENA); wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); wm8350_free_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); priv->hpl.jack = NULL; priv->hpr.jack = NULL; /* cancel any work waiting to be queued. */ ret = cancel_delayed_work(&codec->delayed_work); /* if there was any work waiting then we run it now and * wait for its completion */ if (ret) { schedule_delayed_work(&codec->delayed_work, 0); flush_scheduled_work(); } wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF); wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); return 0; }
static int wm8350_rtc_update_irq_enable(struct device *dev, unsigned int enabled) { struct wm8350 *wm8350 = dev_get_drvdata(dev); /* Suppress duplicate changes since genirq nests enable and * disable calls. */ if (enabled == wm8350->rtc.update_enabled) return 0; if (enabled) wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); else wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); wm8350->rtc.update_enabled = enabled; return 0; }
/* * Handle commands from user-space */ static int wm8350_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg) { struct wm8350 *wm8350 = dev_get_drvdata(dev); switch (cmd) { case RTC_AIE_OFF: return wm8350_rtc_stop_alarm(wm8350); case RTC_AIE_ON: return wm8350_rtc_start_alarm(wm8350); case RTC_UIE_OFF: wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); break; case RTC_UIE_ON: wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC); break; default: return -ENOIOCTLCMD; } return 0; }
static void free_charger_irq(struct wm8350 *wm8350) { wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_HOT); wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_COLD); wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_BAT_FAIL); wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_TO); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_TO); wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_END); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_END); wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_START); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_START); wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P9); wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_3P1); wm8350_mask_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); wm8350_free_irq(wm8350, WM8350_IRQ_CHG_VBATT_LT_2P85); wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_USB_FB); wm8350_free_irq(wm8350, WM8350_IRQ_EXT_USB_FB); wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); wm8350_free_irq(wm8350, WM8350_IRQ_EXT_WALL_FB); wm8350_mask_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); wm8350_free_irq(wm8350, WM8350_IRQ_EXT_BAT_FB); }
static void imx_3stack_jack_handler(struct wm8350 *wm8350, int irq, void *data) { wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); schedule_delayed_work(&hp_event, msecs_to_jiffies(200)); }
static int wm8350_rtc_probe(struct platform_device *pdev) { struct wm8350 *wm8350 = platform_get_drvdata(pdev); struct wm8350_rtc *wm_rtc = &wm8350->rtc; int ret = 0; u16 timectl, power5; timectl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); if (timectl & WM8350_RTC_BCD) { dev_err(&pdev->dev, "RTC BCD mode not supported\n"); return -EINVAL; } if (timectl & WM8350_RTC_12HR) { dev_err(&pdev->dev, "RTC 12 hour mode not supported\n"); return -EINVAL; } /* enable the RTC if it's not already enabled */ power5 = wm8350_reg_read(wm8350, WM8350_POWER_MGMT_5); if (!(power5 & WM8350_RTC_TICK_ENA)) { dev_info(wm8350->dev, "Starting RTC\n"); wm8350_reg_unlock(wm8350); ret = wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_RTC_TICK_ENA); if (ret < 0) { dev_err(&pdev->dev, "failed to enable RTC: %d\n", ret); return ret; } wm8350_reg_lock(wm8350); } if (timectl & WM8350_RTC_STS) { int retries; ret = wm8350_clear_bits(wm8350, WM8350_RTC_TIME_CONTROL, WM8350_RTC_SET); if (ret < 0) { dev_err(&pdev->dev, "failed to start: %d\n", ret); return ret; } retries = WM8350_SET_TIME_RETRIES; do { timectl = wm8350_reg_read(wm8350, WM8350_RTC_TIME_CONTROL); } while (timectl & WM8350_RTC_STS && --retries); if (retries == 0) { dev_err(&pdev->dev, "failed to start: timeout\n"); return -ENODEV; } } device_init_wakeup(&pdev->dev, 1); wm_rtc->rtc = devm_rtc_device_register(&pdev->dev, "wm8350", &wm8350_rtc_ops, THIS_MODULE); if (IS_ERR(wm_rtc->rtc)) { ret = PTR_ERR(wm_rtc->rtc); dev_err(&pdev->dev, "failed to register RTC: %d\n", ret); return ret; } wm8350_register_irq(wm8350, WM8350_IRQ_RTC_SEC, wm8350_rtc_update_handler, 0, "RTC Seconds", wm8350); wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC); wm8350_register_irq(wm8350, WM8350_IRQ_RTC_ALM, wm8350_rtc_alarm_handler, 0, "RTC Alarm", wm8350); return 0; }
static int wm8350_probe(struct platform_device *pdev) { struct snd_soc_device *socdev = platform_get_drvdata(pdev); struct snd_soc_codec *codec; struct wm8350 *wm8350; struct wm8350_data *priv; int ret; struct wm8350_output *out1; struct wm8350_output *out2; BUG_ON(!wm8350_codec); socdev->card->codec = wm8350_codec; codec = socdev->card->codec; wm8350 = codec->control_data; priv = codec->private_data; /* Enable the codec */ wm8350_set_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA); /* Enable robust clocking mode in ADC */ wm8350_codec_write(codec, WM8350_SECURITY, 0xa7); wm8350_codec_write(codec, 0xde, 0x13); wm8350_codec_write(codec, WM8350_SECURITY, 0); /* read OUT1 & OUT2 volumes */ out1 = &priv->out1; out2 = &priv->out2; out1->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT1_VOLUME) & WM8350_OUT1L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT; out1->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT1_VOLUME) & WM8350_OUT1R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT; out2->left_vol = (wm8350_reg_read(wm8350, WM8350_LOUT2_VOLUME) & WM8350_OUT2L_VOL_MASK) >> WM8350_OUT1L_VOL_SHIFT; out2->right_vol = (wm8350_reg_read(wm8350, WM8350_ROUT2_VOLUME) & WM8350_OUT2R_VOL_MASK) >> WM8350_OUT1R_VOL_SHIFT; wm8350_reg_write(wm8350, WM8350_LOUT1_VOLUME, 0); wm8350_reg_write(wm8350, WM8350_ROUT1_VOLUME, 0); wm8350_reg_write(wm8350, WM8350_LOUT2_VOLUME, 0); wm8350_reg_write(wm8350, WM8350_ROUT2_VOLUME, 0); /* Latch VU bits & mute */ wm8350_set_bits(wm8350, WM8350_LOUT1_VOLUME, WM8350_OUT1_VU | WM8350_OUT1L_MUTE); wm8350_set_bits(wm8350, WM8350_LOUT2_VOLUME, WM8350_OUT2_VU | WM8350_OUT2L_MUTE); wm8350_set_bits(wm8350, WM8350_ROUT1_VOLUME, WM8350_OUT1_VU | WM8350_OUT1R_MUTE); wm8350_set_bits(wm8350, WM8350_ROUT2_VOLUME, WM8350_OUT2_VU | WM8350_OUT2R_MUTE); wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L); wm8350_mask_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R); wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_L, wm8350_hp_jack_handler, priv); wm8350_register_irq(wm8350, WM8350_IRQ_CODEC_JCK_DET_R, wm8350_hp_jack_handler, priv); ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); if (ret < 0) { dev_err(&pdev->dev, "failed to create pcms\n"); return ret; } snd_soc_add_controls(codec, wm8350_snd_controls, ARRAY_SIZE(wm8350_snd_controls)); wm8350_add_widgets(codec); wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY); return 0; }