cregit-Linux how code gets into the kernel

Release 4.7 sound/soc/codecs/da7219-aad.c

Directory: sound/soc/codecs
/*
 * da7219-aad.c - Dialog DA7219 ALSA SoC AAD Driver
 *
 * Copyright (c) 2015 Dialog Semiconductor Ltd.
 *
 * Author: Adam Thomson <Adam.Thomson.Opensource@diasemi.com>
 *
 * This program is free software; you can redistribute  it and/or modify it
 * under  the terms of  the GNU General  Public License as published by the
 * Free Software Foundation;  either version 2 of the  License, or (at your
 * option) any later version.
 */

#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/pm_wakeirq.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/workqueue.h>
#include <sound/soc.h>
#include <sound/jack.h>
#include <sound/da7219.h>

#include "da7219.h"
#include "da7219-aad.h"


/*
 * Detection control
 */


void da7219_aad_jack_det(struct snd_soc_codec *codec, struct snd_soc_jack *jack) { struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); da7219->aad->jack = jack; da7219->aad->jack_inserted = false; /* Send an initial empty report */ snd_soc_jack_report(jack, 0, DA7219_AAD_REPORT_ALL_MASK); /* Enable/Disable jack detection */ snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, DA7219_ACCDET_EN_MASK, (jack ? DA7219_ACCDET_EN_MASK : 0)); }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson69100.00%1100.00%
Total69100.00%1100.00%

EXPORT_SYMBOL_GPL(da7219_aad_jack_det); /* * Button/HPTest work */
static void da7219_aad_btn_det_work(struct work_struct *work) { struct da7219_aad_priv *da7219_aad = container_of(work, struct da7219_aad_priv, btn_det_work); struct snd_soc_codec *codec = da7219_aad->codec; struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); u8 statusa, micbias_ctrl; bool micbias_up = false; int retries = 0; /* Drive headphones/lineout */ snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK, DA7219_HP_L_AMP_OE_MASK); snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, DA7219_HP_R_AMP_OE_MASK); /* Make sure mic bias is up */ snd_soc_dapm_force_enable_pin(dapm, "Mic Bias"); snd_soc_dapm_sync(dapm); do { statusa = snd_soc_read(codec, DA7219_ACCDET_STATUS_A); if (statusa & DA7219_MICBIAS_UP_STS_MASK) micbias_up = true; else if (retries++ < DA7219_AAD_MICBIAS_CHK_RETRIES) msleep(DA7219_AAD_MICBIAS_CHK_DELAY); } while ((!micbias_up) && (retries < DA7219_AAD_MICBIAS_CHK_RETRIES)); if (retries >= DA7219_AAD_MICBIAS_CHK_RETRIES) dev_warn(codec->dev, "Mic bias status check timed out"); /* * Mic bias pulse required to enable mic, must be done before enabling * button detection to prevent erroneous button readings. */ if (da7219_aad->micbias_pulse_lvl && da7219_aad->micbias_pulse_time) { /* Pulse higher level voltage */ micbias_ctrl = snd_soc_read(codec, DA7219_MICBIAS_CTRL); snd_soc_update_bits(codec, DA7219_MICBIAS_CTRL, DA7219_MICBIAS1_LEVEL_MASK, da7219_aad->micbias_pulse_lvl); msleep(da7219_aad->micbias_pulse_time); snd_soc_write(codec, DA7219_MICBIAS_CTRL, micbias_ctrl); } snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, DA7219_BUTTON_CONFIG_MASK, da7219_aad->btn_cfg); }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson225100.00%1100.00%
Total225100.00%1100.00%


static void da7219_aad_hptest_work(struct work_struct *work) { struct da7219_aad_priv *da7219_aad = container_of(work, struct da7219_aad_priv, hptest_work); struct snd_soc_codec *codec = da7219_aad->codec; struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); u16 tonegen_freq_hptest; u8 accdet_cfg8; int report = 0; /* Lock DAPM and any Kcontrols that are affected by this test */ snd_soc_dapm_mutex_lock(dapm); mutex_lock(&da7219->lock); /* Bypass cache so it saves current settings */ regcache_cache_bypass(da7219->regmap, true); /* Make sure Tone Generator is disabled */ snd_soc_write(codec, DA7219_TONE_GEN_CFG1, 0); /* Enable HPTest block, 1KOhms check */ snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8, DA7219_HPTEST_EN_MASK | DA7219_HPTEST_RES_SEL_MASK, DA7219_HPTEST_EN_MASK | DA7219_HPTEST_RES_SEL_1KOHMS); /* Set gains to 0db */ snd_soc_write(codec, DA7219_DAC_L_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB); snd_soc_write(codec, DA7219_DAC_R_GAIN, DA7219_DAC_DIGITAL_GAIN_0DB); snd_soc_write(codec, DA7219_HP_L_GAIN, DA7219_HP_AMP_GAIN_0DB); snd_soc_write(codec, DA7219_HP_R_GAIN, DA7219_HP_AMP_GAIN_0DB); /* Disable DAC filters, EQs and soft mute */ snd_soc_update_bits(codec, DA7219_DAC_FILTERS1, DA7219_HPF_MODE_MASK, 0); snd_soc_update_bits(codec, DA7219_DAC_FILTERS4, DA7219_DAC_EQ_EN_MASK, 0); snd_soc_update_bits(codec, DA7219_DAC_FILTERS5, DA7219_DAC_SOFTMUTE_EN_MASK, 0); /* Enable HP left & right paths */ snd_soc_update_bits(codec, DA7219_CP_CTRL, DA7219_CP_EN_MASK, DA7219_CP_EN_MASK); snd_soc_update_bits(codec, DA7219_DIG_ROUTING_DAC, DA7219_DAC_L_SRC_MASK | DA7219_DAC_R_SRC_MASK, DA7219_DAC_L_SRC_TONEGEN | DA7219_DAC_R_SRC_TONEGEN); snd_soc_update_bits(codec, DA7219_DAC_L_CTRL, DA7219_DAC_L_EN_MASK | DA7219_DAC_L_MUTE_EN_MASK, DA7219_DAC_L_EN_MASK); snd_soc_update_bits(codec, DA7219_DAC_R_CTRL, DA7219_DAC_R_EN_MASK | DA7219_DAC_R_MUTE_EN_MASK, DA7219_DAC_R_EN_MASK); snd_soc_update_bits(codec, DA7219_MIXOUT_L_SELECT, DA7219_MIXOUT_L_MIX_SELECT_MASK, DA7219_MIXOUT_L_MIX_SELECT_MASK); snd_soc_update_bits(codec, DA7219_MIXOUT_R_SELECT, DA7219_MIXOUT_R_MIX_SELECT_MASK, DA7219_MIXOUT_R_MIX_SELECT_MASK); snd_soc_update_bits(codec, DA7219_DROUTING_ST_OUTFILT_1L, DA7219_OUTFILT_ST_1L_SRC_MASK, DA7219_DMIX_ST_SRC_OUTFILT1L); snd_soc_update_bits(codec, DA7219_DROUTING_ST_OUTFILT_1R, DA7219_OUTFILT_ST_1R_SRC_MASK, DA7219_DMIX_ST_SRC_OUTFILT1R); snd_soc_update_bits(codec, DA7219_MIXOUT_L_CTRL, DA7219_MIXOUT_L_AMP_EN_MASK, DA7219_MIXOUT_L_AMP_EN_MASK); snd_soc_update_bits(codec, DA7219_MIXOUT_R_CTRL, DA7219_MIXOUT_R_AMP_EN_MASK, DA7219_MIXOUT_R_AMP_EN_MASK); snd_soc_write(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK | DA7219_HP_L_AMP_EN_MASK); snd_soc_write(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK | DA7219_HP_R_AMP_EN_MASK); /* Configure & start Tone Generator */ snd_soc_write(codec, DA7219_TONE_GEN_ON_PER, DA7219_BEEP_ON_PER_MASK); tonegen_freq_hptest = cpu_to_le16(DA7219_AAD_HPTEST_RAMP_FREQ); regmap_raw_write(da7219->regmap, DA7219_TONE_GEN_FREQ1_L, &tonegen_freq_hptest, sizeof(tonegen_freq_hptest)); snd_soc_update_bits(codec, DA7219_TONE_GEN_CFG2, DA7219_SWG_SEL_MASK | DA7219_TONE_GEN_GAIN_MASK, DA7219_SWG_SEL_SRAMP | DA7219_TONE_GEN_GAIN_MINUS_15DB); snd_soc_write(codec, DA7219_TONE_GEN_CFG1, DA7219_START_STOPN_MASK); msleep(DA7219_AAD_HPTEST_PERIOD); /* Grab comparator reading */ accdet_cfg8 = snd_soc_read(codec, DA7219_ACCDET_CONFIG_8); if (accdet_cfg8 & DA7219_HPTEST_COMP_MASK) report |= SND_JACK_HEADPHONE; else report |= SND_JACK_LINEOUT; /* Stop tone generator */ snd_soc_write(codec, DA7219_TONE_GEN_CFG1, 0); msleep(DA7219_AAD_HPTEST_PERIOD); /* Restore original settings from cache */ regcache_mark_dirty(da7219->regmap); regcache_sync_region(da7219->regmap, DA7219_HP_L_CTRL, DA7219_HP_R_CTRL); regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_CTRL, DA7219_MIXOUT_R_CTRL); regcache_sync_region(da7219->regmap, DA7219_DROUTING_ST_OUTFILT_1L, DA7219_DROUTING_ST_OUTFILT_1R); regcache_sync_region(da7219->regmap, DA7219_MIXOUT_L_SELECT, DA7219_MIXOUT_R_SELECT); regcache_sync_region(da7219->regmap, DA7219_DAC_L_CTRL, DA7219_DAC_R_CTRL); regcache_sync_region(da7219->regmap, DA7219_DIG_ROUTING_DAC, DA7219_DIG_ROUTING_DAC); regcache_sync_region(da7219->regmap, DA7219_CP_CTRL, DA7219_CP_CTRL); regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS5, DA7219_DAC_FILTERS5); regcache_sync_region(da7219->regmap, DA7219_DAC_FILTERS4, DA7219_DAC_FILTERS1); regcache_sync_region(da7219->regmap, DA7219_HP_L_GAIN, DA7219_HP_R_GAIN); regcache_sync_region(da7219->regmap, DA7219_DAC_L_GAIN, DA7219_DAC_R_GAIN); regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_ON_PER, DA7219_TONE_GEN_ON_PER); regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_FREQ1_L, DA7219_TONE_GEN_FREQ1_U); regcache_sync_region(da7219->regmap, DA7219_TONE_GEN_CFG1, DA7219_TONE_GEN_CFG2); regcache_cache_bypass(da7219->regmap, false); /* Disable HPTest block */ snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_8, DA7219_HPTEST_EN_MASK, 0); /* Drive Headphones/lineout */ snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK, DA7219_HP_L_AMP_OE_MASK); snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, DA7219_HP_R_AMP_OE_MASK); mutex_unlock(&da7219->lock); snd_soc_dapm_mutex_unlock(dapm); /* * Only send report if jack hasn't been removed during process, * otherwise it's invalid and we drop it. */ if (da7219_aad->jack_inserted) snd_soc_jack_report(da7219_aad->jack, report, SND_JACK_HEADSET | SND_JACK_LINEOUT); }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson670100.00%1100.00%
Total670100.00%1100.00%

/* * IRQ */
static irqreturn_t da7219_aad_irq_thread(int irq, void *data) { struct da7219_aad_priv *da7219_aad = data; struct snd_soc_codec *codec = da7219_aad->codec; struct snd_soc_dapm_context *dapm = snd_soc_codec_get_dapm(codec); struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); u8 events[DA7219_AAD_IRQ_REG_MAX]; u8 statusa; int i, report = 0, mask = 0; /* Read current IRQ events */ regmap_bulk_read(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, events, DA7219_AAD_IRQ_REG_MAX); if (!events[DA7219_AAD_IRQ_REG_A] && !events[DA7219_AAD_IRQ_REG_B]) return IRQ_NONE; /* Read status register for jack insertion & type status */ statusa = snd_soc_read(codec, DA7219_ACCDET_STATUS_A); /* Clear events */ regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_EVENT_A, events, DA7219_AAD_IRQ_REG_MAX); dev_dbg(codec->dev, "IRQ events = 0x%x|0x%x, status = 0x%x\n", events[DA7219_AAD_IRQ_REG_A], events[DA7219_AAD_IRQ_REG_B], statusa); if (statusa & DA7219_JACK_INSERTION_STS_MASK) { /* Jack Insertion */ if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_INSERTED_MASK) { report |= SND_JACK_MECHANICAL; mask |= SND_JACK_MECHANICAL; da7219_aad->jack_inserted = true; } /* Jack type detection */ if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_DETECT_COMPLETE_MASK) { /* * If 4-pole, then enable button detection, else perform * HP impedance test to determine output type to report. * * We schedule work here as the tasks themselves can * take time to complete, and in particular for hptest * we want to be able to check if the jack was removed * during the procedure as this will invalidate the * result. By doing this as work, the IRQ thread can * handle a removal, and we can check at the end of * hptest if we have a valid result or not. */ if (statusa & DA7219_JACK_TYPE_STS_MASK) { report |= SND_JACK_HEADSET; mask |= SND_JACK_HEADSET | SND_JACK_LINEOUT; schedule_work(&da7219_aad->btn_det_work); } else { schedule_work(&da7219_aad->hptest_work); } } /* Button support for 4-pole jack */ if (statusa & DA7219_JACK_TYPE_STS_MASK) { for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) { /* Button Press */ if (events[DA7219_AAD_IRQ_REG_B] & (DA7219_E_BUTTON_A_PRESSED_MASK << i)) { report |= SND_JACK_BTN_0 >> i; mask |= SND_JACK_BTN_0 >> i; } } snd_soc_jack_report(da7219_aad->jack, report, mask); for (i = 0; i < DA7219_AAD_MAX_BUTTONS; ++i) { /* Button Release */ if (events[DA7219_AAD_IRQ_REG_B] & (DA7219_E_BUTTON_A_RELEASED_MASK >> i)) { report &= ~(SND_JACK_BTN_0 >> i); mask |= SND_JACK_BTN_0 >> i; } } } } else { /* Jack removal */ if (events[DA7219_AAD_IRQ_REG_A] & DA7219_E_JACK_REMOVED_MASK) { report = 0; mask |= DA7219_AAD_REPORT_ALL_MASK; da7219_aad->jack_inserted = false; /* Un-drive headphones/lineout */ snd_soc_update_bits(codec, DA7219_HP_R_CTRL, DA7219_HP_R_AMP_OE_MASK, 0); snd_soc_update_bits(codec, DA7219_HP_L_CTRL, DA7219_HP_L_AMP_OE_MASK, 0); /* Ensure button detection disabled */ snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, DA7219_BUTTON_CONFIG_MASK, 0); /* Disable mic bias */ snd_soc_dapm_disable_pin(dapm, "Mic Bias"); snd_soc_dapm_sync(dapm); /* Cancel any pending work */ cancel_work_sync(&da7219_aad->btn_det_work); cancel_work_sync(&da7219_aad->hptest_work); } } snd_soc_jack_report(da7219_aad->jack, report, mask); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson446100.00%1100.00%
Total446100.00%1100.00%

/* * DT to pdata conversion */
static enum da7219_aad_micbias_pulse_lvl da7219_aad_of_micbias_pulse_lvl(struct snd_soc_codec *codec, u32 val) { switch (val) { case 2800: return DA7219_AAD_MICBIAS_PULSE_LVL_2_8V; case 2900: return DA7219_AAD_MICBIAS_PULSE_LVL_2_9V; default: dev_warn(codec->dev, "Invalid micbias pulse level"); return DA7219_AAD_MICBIAS_PULSE_LVL_OFF; } }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson46100.00%1100.00%
Total46100.00%1100.00%


static enum da7219_aad_btn_cfg da7219_aad_of_btn_cfg(struct snd_soc_codec *codec, u32 val) { switch (val) { case 2: return DA7219_AAD_BTN_CFG_2MS; case 5: return DA7219_AAD_BTN_CFG_5MS; case 10: return DA7219_AAD_BTN_CFG_10MS; case 50: return DA7219_AAD_BTN_CFG_50MS; case 100: return DA7219_AAD_BTN_CFG_100MS; case 200: return DA7219_AAD_BTN_CFG_200MS; case 500: return DA7219_AAD_BTN_CFG_500MS; default: dev_warn(codec->dev, "Invalid button config"); return DA7219_AAD_BTN_CFG_10MS; } }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson76100.00%1100.00%
Total76100.00%1100.00%


static enum da7219_aad_mic_det_thr da7219_aad_of_mic_det_thr(struct snd_soc_codec *codec, u32 val) { switch (val) { case 200: return DA7219_AAD_MIC_DET_THR_200_OHMS; case 500: return DA7219_AAD_MIC_DET_THR_500_OHMS; case 750: return DA7219_AAD_MIC_DET_THR_750_OHMS; case 1000: return DA7219_AAD_MIC_DET_THR_1000_OHMS; default: dev_warn(codec->dev, "Invalid mic detect threshold"); return DA7219_AAD_MIC_DET_THR_500_OHMS; } }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson58100.00%1100.00%
Total58100.00%1100.00%


static enum da7219_aad_jack_ins_deb da7219_aad_of_jack_ins_deb(struct snd_soc_codec *codec, u32 val) { switch (val) { case 5: return DA7219_AAD_JACK_INS_DEB_5MS; case 10: return DA7219_AAD_JACK_INS_DEB_10MS; case 20: return DA7219_AAD_JACK_INS_DEB_20MS; case 50: return DA7219_AAD_JACK_INS_DEB_50MS; case 100: return DA7219_AAD_JACK_INS_DEB_100MS; case 200: return DA7219_AAD_JACK_INS_DEB_200MS; case 500: return DA7219_AAD_JACK_INS_DEB_500MS; case 1000: return DA7219_AAD_JACK_INS_DEB_1S; default: dev_warn(codec->dev, "Invalid jack insert debounce"); return DA7219_AAD_JACK_INS_DEB_20MS; } }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson82100.00%1100.00%
Total82100.00%1100.00%


static enum da7219_aad_jack_det_rate da7219_aad_of_jack_det_rate(struct snd_soc_codec *codec, const char *str) { if (!strcmp(str, "32ms_64ms")) { return DA7219_AAD_JACK_DET_RATE_32_64MS; } else if (!strcmp(str, "64ms_128ms")) { return DA7219_AAD_JACK_DET_RATE_64_128MS; } else if (!strcmp(str, "128ms_256ms")) { return DA7219_AAD_JACK_DET_RATE_128_256MS; } else if (!strcmp(str, "256ms_512ms")) { return DA7219_AAD_JACK_DET_RATE_256_512MS; } else { dev_warn(codec->dev, "Invalid jack detect rate"); return DA7219_AAD_JACK_DET_RATE_256_512MS; } }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson95100.00%1100.00%
Total95100.00%1100.00%


static enum da7219_aad_jack_rem_deb da7219_aad_of_jack_rem_deb(struct snd_soc_codec *codec, u32 val) { switch (val) { case 1: return DA7219_AAD_JACK_REM_DEB_1MS; case 5: return DA7219_AAD_JACK_REM_DEB_5MS; case 10: return DA7219_AAD_JACK_REM_DEB_10MS; case 20: return DA7219_AAD_JACK_REM_DEB_20MS; default: dev_warn(codec->dev, "Invalid jack removal debounce"); return DA7219_AAD_JACK_REM_DEB_1MS; } }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson58100.00%1100.00%
Total58100.00%1100.00%


static enum da7219_aad_btn_avg da7219_aad_of_btn_avg(struct snd_soc_codec *codec, u32 val) { switch (val) { case 1: return DA7219_AAD_BTN_AVG_1; case 2: return DA7219_AAD_BTN_AVG_2; case 4: return DA7219_AAD_BTN_AVG_4; case 8: return DA7219_AAD_BTN_AVG_8; default: dev_warn(codec->dev, "Invalid button average value"); return DA7219_AAD_BTN_AVG_2; } }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson58100.00%1100.00%
Total58100.00%1100.00%


static enum da7219_aad_adc_1bit_rpt da7219_aad_of_adc_1bit_rpt(struct snd_soc_codec *codec, u32 val) { switch (val) { case 1: return DA7219_AAD_ADC_1BIT_RPT_1; case 2: return DA7219_AAD_ADC_1BIT_RPT_2; case 4: return DA7219_AAD_ADC_1BIT_RPT_4; case 8: return DA7219_AAD_ADC_1BIT_RPT_8; default: dev_warn(codec->dev, "Invalid ADC 1-bit repeat value"); return DA7219_AAD_ADC_1BIT_RPT_1; } }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson58100.00%1100.00%
Total58100.00%1100.00%


static struct da7219_aad_pdata *da7219_aad_of_to_pdata(struct snd_soc_codec *codec) { struct device_node *np = codec->dev->of_node; struct device_node *aad_np = of_find_node_by_name(np, "da7219_aad"); struct da7219_aad_pdata *aad_pdata; const char *of_str; u32 of_val32; if (!aad_np) return NULL; aad_pdata = devm_kzalloc(codec->dev, sizeof(*aad_pdata), GFP_KERNEL); if (!aad_pdata) goto out; aad_pdata->irq = irq_of_parse_and_map(np, 0); if (of_property_read_u32(aad_np, "dlg,micbias-pulse-lvl", &of_val32) >= 0) aad_pdata->micbias_pulse_lvl = da7219_aad_of_micbias_pulse_lvl(codec, of_val32); else aad_pdata->micbias_pulse_lvl = DA7219_AAD_MICBIAS_PULSE_LVL_OFF; if (of_property_read_u32(aad_np, "dlg,micbias-pulse-time", &of_val32) >= 0) aad_pdata->micbias_pulse_time = of_val32; if (of_property_read_u32(aad_np, "dlg,btn-cfg", &of_val32) >= 0) aad_pdata->btn_cfg = da7219_aad_of_btn_cfg(codec, of_val32); else aad_pdata->btn_cfg = DA7219_AAD_BTN_CFG_10MS; if (of_property_read_u32(aad_np, "dlg,mic-det-thr", &of_val32) >= 0) aad_pdata->mic_det_thr = da7219_aad_of_mic_det_thr(codec, of_val32); else aad_pdata->mic_det_thr = DA7219_AAD_MIC_DET_THR_500_OHMS; if (of_property_read_u32(aad_np, "dlg,jack-ins-deb", &of_val32) >= 0) aad_pdata->jack_ins_deb = da7219_aad_of_jack_ins_deb(codec, of_val32); else aad_pdata->jack_ins_deb = DA7219_AAD_JACK_INS_DEB_20MS; if (!of_property_read_string(aad_np, "dlg,jack-det-rate", &of_str)) aad_pdata->jack_det_rate = da7219_aad_of_jack_det_rate(codec, of_str); else aad_pdata->jack_det_rate = DA7219_AAD_JACK_DET_RATE_256_512MS; if (of_property_read_u32(aad_np, "dlg,jack-rem-deb", &of_val32) >= 0) aad_pdata->jack_rem_deb = da7219_aad_of_jack_rem_deb(codec, of_val32); else aad_pdata->jack_rem_deb = DA7219_AAD_JACK_REM_DEB_1MS; if (of_property_read_u32(aad_np, "dlg,a-d-btn-thr", &of_val32) >= 0) aad_pdata->a_d_btn_thr = (u8) of_val32; else aad_pdata->a_d_btn_thr = 0xA; if (of_property_read_u32(aad_np, "dlg,d-b-btn-thr", &of_val32) >= 0) aad_pdata->d_b_btn_thr = (u8) of_val32; else aad_pdata->d_b_btn_thr = 0x16; if (of_property_read_u32(aad_np, "dlg,b-c-btn-thr", &of_val32) >= 0) aad_pdata->b_c_btn_thr = (u8) of_val32; else aad_pdata->b_c_btn_thr = 0x21; if (of_property_read_u32(aad_np, "dlg,c-mic-btn-thr", &of_val32) >= 0) aad_pdata->c_mic_btn_thr = (u8) of_val32; else aad_pdata->c_mic_btn_thr = 0x3E; if (of_property_read_u32(aad_np, "dlg,btn-avg", &of_val32) >= 0) aad_pdata->btn_avg = da7219_aad_of_btn_avg(codec, of_val32); else aad_pdata->btn_avg = DA7219_AAD_BTN_AVG_2; if (of_property_read_u32(aad_np, "dlg,adc-1bit-rpt", &of_val32) >= 0) aad_pdata->adc_1bit_rpt = da7219_aad_of_adc_1bit_rpt(codec, of_val32); else aad_pdata->adc_1bit_rpt = DA7219_AAD_ADC_1BIT_RPT_1; out: of_node_put(aad_np); return aad_pdata; }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson498100.00%1100.00%
Total498100.00%1100.00%


static void da7219_aad_handle_pdata(struct snd_soc_codec *codec) { struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); struct da7219_aad_priv *da7219_aad = da7219->aad; struct da7219_pdata *pdata = da7219->pdata; if ((pdata) && (pdata->aad_pdata)) { struct da7219_aad_pdata *aad_pdata = pdata->aad_pdata; u8 cfg, mask; da7219_aad->irq = aad_pdata->irq; switch (aad_pdata->micbias_pulse_lvl) { case DA7219_AAD_MICBIAS_PULSE_LVL_2_8V: case DA7219_AAD_MICBIAS_PULSE_LVL_2_9V: da7219_aad->micbias_pulse_lvl = (aad_pdata->micbias_pulse_lvl << DA7219_MICBIAS1_LEVEL_SHIFT); break; default: break; } da7219_aad->micbias_pulse_time = aad_pdata->micbias_pulse_time; switch (aad_pdata->btn_cfg) { case DA7219_AAD_BTN_CFG_2MS: case DA7219_AAD_BTN_CFG_5MS: case DA7219_AAD_BTN_CFG_10MS: case DA7219_AAD_BTN_CFG_50MS: case DA7219_AAD_BTN_CFG_100MS: case DA7219_AAD_BTN_CFG_200MS: case DA7219_AAD_BTN_CFG_500MS: da7219_aad->btn_cfg = (aad_pdata->btn_cfg << DA7219_BUTTON_CONFIG_SHIFT); } cfg = 0; mask = 0; switch (aad_pdata->mic_det_thr) { case DA7219_AAD_MIC_DET_THR_200_OHMS: case DA7219_AAD_MIC_DET_THR_500_OHMS: case DA7219_AAD_MIC_DET_THR_750_OHMS: case DA7219_AAD_MIC_DET_THR_1000_OHMS: cfg |= (aad_pdata->mic_det_thr << DA7219_MIC_DET_THRESH_SHIFT); mask |= DA7219_MIC_DET_THRESH_MASK; } snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, mask, cfg); cfg = 0; mask = 0; switch (aad_pdata->jack_ins_deb) { case DA7219_AAD_JACK_INS_DEB_5MS: case DA7219_AAD_JACK_INS_DEB_10MS: case DA7219_AAD_JACK_INS_DEB_20MS: case DA7219_AAD_JACK_INS_DEB_50MS: case DA7219_AAD_JACK_INS_DEB_100MS: case DA7219_AAD_JACK_INS_DEB_200MS: case DA7219_AAD_JACK_INS_DEB_500MS: case DA7219_AAD_JACK_INS_DEB_1S: cfg |= (aad_pdata->jack_ins_deb << DA7219_JACKDET_DEBOUNCE_SHIFT); mask |= DA7219_JACKDET_DEBOUNCE_MASK; } switch (aad_pdata->jack_det_rate) { case DA7219_AAD_JACK_DET_RATE_32_64MS: case DA7219_AAD_JACK_DET_RATE_64_128MS: case DA7219_AAD_JACK_DET_RATE_128_256MS: case DA7219_AAD_JACK_DET_RATE_256_512MS: cfg |= (aad_pdata->jack_det_rate << DA7219_JACK_DETECT_RATE_SHIFT); mask |= DA7219_JACK_DETECT_RATE_MASK; } switch (aad_pdata->jack_rem_deb) { case DA7219_AAD_JACK_REM_DEB_1MS: case DA7219_AAD_JACK_REM_DEB_5MS: case DA7219_AAD_JACK_REM_DEB_10MS: case DA7219_AAD_JACK_REM_DEB_20MS: cfg |= (aad_pdata->jack_rem_deb << DA7219_JACKDET_REM_DEB_SHIFT); mask |= DA7219_JACKDET_REM_DEB_MASK; } snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_2, mask, cfg); snd_soc_write(codec, DA7219_ACCDET_CONFIG_3, aad_pdata->a_d_btn_thr); snd_soc_write(codec, DA7219_ACCDET_CONFIG_4, aad_pdata->d_b_btn_thr); snd_soc_write(codec, DA7219_ACCDET_CONFIG_5, aad_pdata->b_c_btn_thr); snd_soc_write(codec, DA7219_ACCDET_CONFIG_6, aad_pdata->c_mic_btn_thr); cfg = 0; mask = 0; switch (aad_pdata->btn_avg) { case DA7219_AAD_BTN_AVG_1: case DA7219_AAD_BTN_AVG_2: case DA7219_AAD_BTN_AVG_4: case DA7219_AAD_BTN_AVG_8: cfg |= (aad_pdata->btn_avg << DA7219_BUTTON_AVERAGE_SHIFT); mask |= DA7219_BUTTON_AVERAGE_MASK; } switch (aad_pdata->adc_1bit_rpt) { case DA7219_AAD_ADC_1BIT_RPT_1: case DA7219_AAD_ADC_1BIT_RPT_2: case DA7219_AAD_ADC_1BIT_RPT_4: case DA7219_AAD_ADC_1BIT_RPT_8: cfg |= (aad_pdata->adc_1bit_rpt << DA7219_ADC_1_BIT_REPEAT_SHIFT); mask |= DA7219_ADC_1_BIT_REPEAT_MASK; } snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_7, mask, cfg); } }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson470100.00%1100.00%
Total470100.00%1100.00%

/* * Init/Exit */
int da7219_aad_init(struct snd_soc_codec *codec) { struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); struct da7219_aad_priv *da7219_aad; u8 mask[DA7219_AAD_IRQ_REG_MAX]; int ret; da7219_aad = devm_kzalloc(codec->dev, sizeof(*da7219_aad), GFP_KERNEL); if (!da7219_aad) return -ENOMEM; da7219->aad = da7219_aad; da7219_aad->codec = codec; /* Handle any DT/platform data */ if ((codec->dev->of_node) && (da7219->pdata)) da7219->pdata->aad_pdata = da7219_aad_of_to_pdata(codec); da7219_aad_handle_pdata(codec); /* Disable button detection */ snd_soc_update_bits(codec, DA7219_ACCDET_CONFIG_1, DA7219_BUTTON_CONFIG_MASK, 0); INIT_WORK(&da7219_aad->btn_det_work, da7219_aad_btn_det_work); INIT_WORK(&da7219_aad->hptest_work, da7219_aad_hptest_work); ret = request_threaded_irq(da7219_aad->irq, NULL, da7219_aad_irq_thread, IRQF_TRIGGER_LOW | IRQF_ONESHOT, "da7219-aad", da7219_aad); if (ret) { dev_err(codec->dev, "Failed to request IRQ: %d\n", ret); return ret; } /* Unmask AAD IRQs */ memset(mask, 0, DA7219_AAD_IRQ_REG_MAX); regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A, &mask, DA7219_AAD_IRQ_REG_MAX); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson205100.00%1100.00%
Total205100.00%1100.00%

EXPORT_SYMBOL_GPL(da7219_aad_init);
void da7219_aad_exit(struct snd_soc_codec *codec) { struct da7219_priv *da7219 = snd_soc_codec_get_drvdata(codec); struct da7219_aad_priv *da7219_aad = da7219->aad; u8 mask[DA7219_AAD_IRQ_REG_MAX]; /* Mask off AAD IRQs */ memset(mask, DA7219_BYTE_MASK, DA7219_AAD_IRQ_REG_MAX); regmap_bulk_write(da7219->regmap, DA7219_ACCDET_IRQ_MASK_A, mask, DA7219_AAD_IRQ_REG_MAX); free_irq(da7219_aad->irq, da7219_aad); cancel_work_sync(&da7219_aad->btn_det_work); cancel_work_sync(&da7219_aad->hptest_work); }

Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson83100.00%1100.00%
Total83100.00%1100.00%

EXPORT_SYMBOL_GPL(da7219_aad_exit); MODULE_DESCRIPTION("ASoC DA7219 AAD Driver"); MODULE_AUTHOR("Adam Thomson <Adam.Thomson.Opensource@diasemi.com>"); MODULE_LICENSE("GPL");

Overall Contributors

PersonTokensPropCommitsCommitProp
adam thomsonadam thomson3272100.00%1100.00%
Total3272100.00%1100.00%
Directory: sound/soc/codecs
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}