/* We can't use the same notifier block for more than one supply and * there's no way I can see to get from a callback to the caller * except container_of().
*/ #define WM8962_REGULATOR_EVENT(n) \ staticint wm8962_regulator_event_##n(struct notifier_block *nb, \ unsignedlong event, void *data) \
{ \ struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
disable_nb[n]); \ if (event & REGULATOR_EVENT_DISABLE) { \
regcache_mark_dirty(wm8962->regmap); \
} \ return 0; \
}
staticbool wm8962_volatile_register(struct device *dev, unsignedint reg)
{ switch (reg) { case WM8962_CLOCKING1: case WM8962_SOFTWARE_RESET: case WM8962_THERMAL_SHUTDOWN_STATUS: case WM8962_ADDITIONAL_CONTROL_4: case WM8962_DC_SERVO_6: case WM8962_INTERRUPT_STATUS_1: case WM8962_INTERRUPT_STATUS_2: case WM8962_DSP2_EXECCONTROL: returntrue; default: returnfalse;
}
}
staticbool wm8962_readable_register(struct device *dev, unsignedint reg)
{ switch (reg) { case WM8962_LEFT_INPUT_VOLUME: case WM8962_RIGHT_INPUT_VOLUME: case WM8962_HPOUTL_VOLUME: case WM8962_HPOUTR_VOLUME: case WM8962_CLOCKING1: case WM8962_ADC_DAC_CONTROL_1: case WM8962_ADC_DAC_CONTROL_2: case WM8962_AUDIO_INTERFACE_0: case WM8962_CLOCKING2: case WM8962_AUDIO_INTERFACE_1: case WM8962_LEFT_DAC_VOLUME: case WM8962_RIGHT_DAC_VOLUME: case WM8962_AUDIO_INTERFACE_2: case WM8962_SOFTWARE_RESET: case WM8962_ALC1: case WM8962_ALC2: case WM8962_ALC3: case WM8962_NOISE_GATE: case WM8962_LEFT_ADC_VOLUME: case WM8962_RIGHT_ADC_VOLUME: case WM8962_ADDITIONAL_CONTROL_1: case WM8962_ADDITIONAL_CONTROL_2: case WM8962_PWR_MGMT_1: case WM8962_PWR_MGMT_2: case WM8962_ADDITIONAL_CONTROL_3: case WM8962_ANTI_POP: case WM8962_CLOCKING_3: case WM8962_INPUT_MIXER_CONTROL_1: case WM8962_LEFT_INPUT_MIXER_VOLUME: case WM8962_RIGHT_INPUT_MIXER_VOLUME: case WM8962_INPUT_MIXER_CONTROL_2: case WM8962_INPUT_BIAS_CONTROL: case WM8962_LEFT_INPUT_PGA_CONTROL: case WM8962_RIGHT_INPUT_PGA_CONTROL: case WM8962_SPKOUTL_VOLUME: case WM8962_SPKOUTR_VOLUME: case WM8962_THERMAL_SHUTDOWN_STATUS: case WM8962_ADDITIONAL_CONTROL_4: case WM8962_CLASS_D_CONTROL_1: case WM8962_CLASS_D_CONTROL_2: case WM8962_CLOCKING_4: case WM8962_DAC_DSP_MIXING_1: case WM8962_DAC_DSP_MIXING_2: case WM8962_DC_SERVO_0: case WM8962_DC_SERVO_1: case WM8962_DC_SERVO_4: case WM8962_DC_SERVO_6: case WM8962_ANALOGUE_PGA_BIAS: case WM8962_ANALOGUE_HP_0: case WM8962_ANALOGUE_HP_2: case WM8962_CHARGE_PUMP_1: case WM8962_CHARGE_PUMP_B: case WM8962_WRITE_SEQUENCER_CONTROL_1: case WM8962_WRITE_SEQUENCER_CONTROL_2: case WM8962_WRITE_SEQUENCER_CONTROL_3: case WM8962_CONTROL_INTERFACE: case WM8962_MIXER_ENABLES: case WM8962_HEADPHONE_MIXER_1: case WM8962_HEADPHONE_MIXER_2: case WM8962_HEADPHONE_MIXER_3: case WM8962_HEADPHONE_MIXER_4: case WM8962_SPEAKER_MIXER_1: case WM8962_SPEAKER_MIXER_2: case WM8962_SPEAKER_MIXER_3: case WM8962_SPEAKER_MIXER_4: case WM8962_SPEAKER_MIXER_5: case WM8962_BEEP_GENERATOR_1: case WM8962_OSCILLATOR_TRIM_3: case WM8962_OSCILLATOR_TRIM_4: case WM8962_OSCILLATOR_TRIM_7: case WM8962_ANALOGUE_CLOCKING1: case WM8962_ANALOGUE_CLOCKING2: case WM8962_ANALOGUE_CLOCKING3: case WM8962_PLL_SOFTWARE_RESET: case WM8962_PLL2: case WM8962_PLL_4: case WM8962_PLL_9: case WM8962_PLL_10: case WM8962_PLL_11: case WM8962_PLL_12: case WM8962_PLL_13: case WM8962_PLL_14: case WM8962_PLL_15: case WM8962_PLL_16: case WM8962_FLL_CONTROL_1: case WM8962_FLL_CONTROL_2: case WM8962_FLL_CONTROL_3: case WM8962_FLL_CONTROL_5: case WM8962_FLL_CONTROL_6: case WM8962_FLL_CONTROL_7: case WM8962_FLL_CONTROL_8: case WM8962_GENERAL_TEST_1: case WM8962_DF1: case WM8962_DF2: case WM8962_DF3: case WM8962_DF4: case WM8962_DF5: case WM8962_DF6: case WM8962_DF7: case WM8962_LHPF1: case WM8962_LHPF2: case WM8962_THREED1: case WM8962_THREED2: case WM8962_THREED3: case WM8962_THREED4: case WM8962_DRC_1: case WM8962_DRC_2: case WM8962_DRC_3: case WM8962_DRC_4: case WM8962_DRC_5: case WM8962_TLOOPBACK: case WM8962_EQ1: case WM8962_EQ2: case WM8962_EQ3: case WM8962_EQ4: case WM8962_EQ5: case WM8962_EQ6: case WM8962_EQ7: case WM8962_EQ8: case WM8962_EQ9: case WM8962_EQ10: case WM8962_EQ11: case WM8962_EQ12: case WM8962_EQ13: case WM8962_EQ14: case WM8962_EQ15: case WM8962_EQ16: case WM8962_EQ17: case WM8962_EQ18: case WM8962_EQ19: case WM8962_EQ20: case WM8962_EQ21: case WM8962_EQ22: case WM8962_EQ23: case WM8962_EQ24: case WM8962_EQ25: case WM8962_EQ26: case WM8962_EQ27: case WM8962_EQ28: case WM8962_EQ29: case WM8962_EQ30: case WM8962_EQ31: case WM8962_EQ32: case WM8962_EQ33: case WM8962_EQ34: case WM8962_EQ35: case WM8962_EQ36: case WM8962_EQ37: case WM8962_EQ38: case WM8962_EQ39: case WM8962_EQ40: case WM8962_EQ41: case WM8962_GPIO_2: case WM8962_GPIO_3: case WM8962_GPIO_5: case WM8962_GPIO_6: case WM8962_INTERRUPT_STATUS_1: case WM8962_INTERRUPT_STATUS_2: case WM8962_INTERRUPT_STATUS_1_MASK: case WM8962_INTERRUPT_STATUS_2_MASK: case WM8962_INTERRUPT_CONTROL: case WM8962_IRQ_DEBOUNCE: case WM8962_MICINT_SOURCE_POL: case WM8962_DSP2_POWER_MANAGEMENT: case WM8962_DSP2_EXECCONTROL: case WM8962_DSP2_INSTRUCTION_RAM_0: case WM8962_DSP2_ADDRESS_RAM_2: case WM8962_DSP2_ADDRESS_RAM_1: case WM8962_DSP2_ADDRESS_RAM_0: case WM8962_DSP2_DATA1_RAM_1: case WM8962_DSP2_DATA1_RAM_0: case WM8962_DSP2_DATA2_RAM_1: case WM8962_DSP2_DATA2_RAM_0: case WM8962_DSP2_DATA3_RAM_1: case WM8962_DSP2_DATA3_RAM_0: case WM8962_DSP2_COEFF_RAM_0: case WM8962_RETUNEADC_SHARED_COEFF_1: case WM8962_RETUNEADC_SHARED_COEFF_0: case WM8962_RETUNEDAC_SHARED_COEFF_1: case WM8962_RETUNEDAC_SHARED_COEFF_0: case WM8962_SOUNDSTAGE_ENABLES_1: case WM8962_SOUNDSTAGE_ENABLES_0: case WM8962_HDBASS_AI_1: case WM8962_HDBASS_AI_0: case WM8962_HDBASS_AR_1: case WM8962_HDBASS_AR_0: case WM8962_HDBASS_B_1: case WM8962_HDBASS_B_0: case WM8962_HDBASS_K_1: case WM8962_HDBASS_K_0: case WM8962_HDBASS_N1_1: case WM8962_HDBASS_N1_0: case WM8962_HDBASS_N2_1: case WM8962_HDBASS_N2_0: case WM8962_HDBASS_N3_1: case WM8962_HDBASS_N3_0: case WM8962_HDBASS_N4_1: case WM8962_HDBASS_N4_0: case WM8962_HDBASS_N5_1: case WM8962_HDBASS_N5_0: case WM8962_HDBASS_X1_1: case WM8962_HDBASS_X1_0: case WM8962_HDBASS_X2_1: case WM8962_HDBASS_X2_0: case WM8962_HDBASS_X3_1: case WM8962_HDBASS_X3_0: case WM8962_HDBASS_ATK_1: case WM8962_HDBASS_ATK_0: case WM8962_HDBASS_DCY_1: case WM8962_HDBASS_DCY_0: case WM8962_HDBASS_PG_1: case WM8962_HDBASS_PG_0: case WM8962_HPF_C_1: case WM8962_HPF_C_0: case WM8962_ADCL_RETUNE_C1_1: case WM8962_ADCL_RETUNE_C1_0: case WM8962_ADCL_RETUNE_C2_1: case WM8962_ADCL_RETUNE_C2_0: case WM8962_ADCL_RETUNE_C3_1: case WM8962_ADCL_RETUNE_C3_0: case WM8962_ADCL_RETUNE_C4_1: case WM8962_ADCL_RETUNE_C4_0: case WM8962_ADCL_RETUNE_C5_1: case WM8962_ADCL_RETUNE_C5_0: case WM8962_ADCL_RETUNE_C6_1: case WM8962_ADCL_RETUNE_C6_0: case WM8962_ADCL_RETUNE_C7_1: case WM8962_ADCL_RETUNE_C7_0: case WM8962_ADCL_RETUNE_C8_1: case WM8962_ADCL_RETUNE_C8_0: case WM8962_ADCL_RETUNE_C9_1: case WM8962_ADCL_RETUNE_C9_0: case WM8962_ADCL_RETUNE_C10_1: case WM8962_ADCL_RETUNE_C10_0: case WM8962_ADCL_RETUNE_C11_1: case WM8962_ADCL_RETUNE_C11_0: case WM8962_ADCL_RETUNE_C12_1: case WM8962_ADCL_RETUNE_C12_0: case WM8962_ADCL_RETUNE_C13_1: case WM8962_ADCL_RETUNE_C13_0: case WM8962_ADCL_RETUNE_C14_1: case WM8962_ADCL_RETUNE_C14_0: case WM8962_ADCL_RETUNE_C15_1: case WM8962_ADCL_RETUNE_C15_0: case WM8962_ADCL_RETUNE_C16_1: case WM8962_ADCL_RETUNE_C16_0: case WM8962_ADCL_RETUNE_C17_1: case WM8962_ADCL_RETUNE_C17_0: case WM8962_ADCL_RETUNE_C18_1: case WM8962_ADCL_RETUNE_C18_0: case WM8962_ADCL_RETUNE_C19_1: case WM8962_ADCL_RETUNE_C19_0: case WM8962_ADCL_RETUNE_C20_1: case WM8962_ADCL_RETUNE_C20_0: case WM8962_ADCL_RETUNE_C21_1: case WM8962_ADCL_RETUNE_C21_0: case WM8962_ADCL_RETUNE_C22_1: case WM8962_ADCL_RETUNE_C22_0: case WM8962_ADCL_RETUNE_C23_1: case WM8962_ADCL_RETUNE_C23_0: case WM8962_ADCL_RETUNE_C24_1: case WM8962_ADCL_RETUNE_C24_0: case WM8962_ADCL_RETUNE_C25_1: case WM8962_ADCL_RETUNE_C25_0: case WM8962_ADCL_RETUNE_C26_1: case WM8962_ADCL_RETUNE_C26_0: case WM8962_ADCL_RETUNE_C27_1: case WM8962_ADCL_RETUNE_C27_0: case WM8962_ADCL_RETUNE_C28_1: case WM8962_ADCL_RETUNE_C28_0: case WM8962_ADCL_RETUNE_C29_1: case WM8962_ADCL_RETUNE_C29_0: case WM8962_ADCL_RETUNE_C30_1: case WM8962_ADCL_RETUNE_C30_0: case WM8962_ADCL_RETUNE_C31_1: case WM8962_ADCL_RETUNE_C31_0: case WM8962_ADCL_RETUNE_C32_1: case WM8962_ADCL_RETUNE_C32_0: case WM8962_RETUNEADC_PG2_1: case WM8962_RETUNEADC_PG2_0: case WM8962_RETUNEADC_PG_1: case WM8962_RETUNEADC_PG_0: case WM8962_ADCR_RETUNE_C1_1: case WM8962_ADCR_RETUNE_C1_0: case WM8962_ADCR_RETUNE_C2_1: case WM8962_ADCR_RETUNE_C2_0: case WM8962_ADCR_RETUNE_C3_1: case WM8962_ADCR_RETUNE_C3_0: case WM8962_ADCR_RETUNE_C4_1: case WM8962_ADCR_RETUNE_C4_0: case WM8962_ADCR_RETUNE_C5_1: case WM8962_ADCR_RETUNE_C5_0: case WM8962_ADCR_RETUNE_C6_1: case WM8962_ADCR_RETUNE_C6_0: case WM8962_ADCR_RETUNE_C7_1: case WM8962_ADCR_RETUNE_C7_0: case WM8962_ADCR_RETUNE_C8_1: case WM8962_ADCR_RETUNE_C8_0: case WM8962_ADCR_RETUNE_C9_1: case WM8962_ADCR_RETUNE_C9_0: case WM8962_ADCR_RETUNE_C10_1: case WM8962_ADCR_RETUNE_C10_0: case WM8962_ADCR_RETUNE_C11_1: case WM8962_ADCR_RETUNE_C11_0: case WM8962_ADCR_RETUNE_C12_1: case WM8962_ADCR_RETUNE_C12_0: case WM8962_ADCR_RETUNE_C13_1: case WM8962_ADCR_RETUNE_C13_0: case WM8962_ADCR_RETUNE_C14_1: case WM8962_ADCR_RETUNE_C14_0: case WM8962_ADCR_RETUNE_C15_1: case WM8962_ADCR_RETUNE_C15_0: case WM8962_ADCR_RETUNE_C16_1: case WM8962_ADCR_RETUNE_C16_0: case WM8962_ADCR_RETUNE_C17_1: case WM8962_ADCR_RETUNE_C17_0: case WM8962_ADCR_RETUNE_C18_1: case WM8962_ADCR_RETUNE_C18_0: case WM8962_ADCR_RETUNE_C19_1: case WM8962_ADCR_RETUNE_C19_0: case WM8962_ADCR_RETUNE_C20_1: case WM8962_ADCR_RETUNE_C20_0: case WM8962_ADCR_RETUNE_C21_1: case WM8962_ADCR_RETUNE_C21_0: case WM8962_ADCR_RETUNE_C22_1: case WM8962_ADCR_RETUNE_C22_0: case WM8962_ADCR_RETUNE_C23_1: case WM8962_ADCR_RETUNE_C23_0: case WM8962_ADCR_RETUNE_C24_1: case WM8962_ADCR_RETUNE_C24_0: case WM8962_ADCR_RETUNE_C25_1: case WM8962_ADCR_RETUNE_C25_0: case WM8962_ADCR_RETUNE_C26_1: case WM8962_ADCR_RETUNE_C26_0: case WM8962_ADCR_RETUNE_C27_1: case WM8962_ADCR_RETUNE_C27_0: case WM8962_ADCR_RETUNE_C28_1: case WM8962_ADCR_RETUNE_C28_0: case WM8962_ADCR_RETUNE_C29_1: case WM8962_ADCR_RETUNE_C29_0: case WM8962_ADCR_RETUNE_C30_1: case WM8962_ADCR_RETUNE_C30_0: case WM8962_ADCR_RETUNE_C31_1: case WM8962_ADCR_RETUNE_C31_0: case WM8962_ADCR_RETUNE_C32_1: case WM8962_ADCR_RETUNE_C32_0: case WM8962_DACL_RETUNE_C1_1: case WM8962_DACL_RETUNE_C1_0: case WM8962_DACL_RETUNE_C2_1: case WM8962_DACL_RETUNE_C2_0: case WM8962_DACL_RETUNE_C3_1: case WM8962_DACL_RETUNE_C3_0: case WM8962_DACL_RETUNE_C4_1: case WM8962_DACL_RETUNE_C4_0: case WM8962_DACL_RETUNE_C5_1: case WM8962_DACL_RETUNE_C5_0: case WM8962_DACL_RETUNE_C6_1: case WM8962_DACL_RETUNE_C6_0: case WM8962_DACL_RETUNE_C7_1: case WM8962_DACL_RETUNE_C7_0: case WM8962_DACL_RETUNE_C8_1: case WM8962_DACL_RETUNE_C8_0: case WM8962_DACL_RETUNE_C9_1: case WM8962_DACL_RETUNE_C9_0: case WM8962_DACL_RETUNE_C10_1: case WM8962_DACL_RETUNE_C10_0: case WM8962_DACL_RETUNE_C11_1: case WM8962_DACL_RETUNE_C11_0: case WM8962_DACL_RETUNE_C12_1: case WM8962_DACL_RETUNE_C12_0: case WM8962_DACL_RETUNE_C13_1: case WM8962_DACL_RETUNE_C13_0: case WM8962_DACL_RETUNE_C14_1: case WM8962_DACL_RETUNE_C14_0: case WM8962_DACL_RETUNE_C15_1: case WM8962_DACL_RETUNE_C15_0: case WM8962_DACL_RETUNE_C16_1: case WM8962_DACL_RETUNE_C16_0: case WM8962_DACL_RETUNE_C17_1: case WM8962_DACL_RETUNE_C17_0: case WM8962_DACL_RETUNE_C18_1: case WM8962_DACL_RETUNE_C18_0: case WM8962_DACL_RETUNE_C19_1: case WM8962_DACL_RETUNE_C19_0: case WM8962_DACL_RETUNE_C20_1: case WM8962_DACL_RETUNE_C20_0: case WM8962_DACL_RETUNE_C21_1: case WM8962_DACL_RETUNE_C21_0: case WM8962_DACL_RETUNE_C22_1: case WM8962_DACL_RETUNE_C22_0: case WM8962_DACL_RETUNE_C23_1: case WM8962_DACL_RETUNE_C23_0: case WM8962_DACL_RETUNE_C24_1: case WM8962_DACL_RETUNE_C24_0: case WM8962_DACL_RETUNE_C25_1: case WM8962_DACL_RETUNE_C25_0: case WM8962_DACL_RETUNE_C26_1: case WM8962_DACL_RETUNE_C26_0: case WM8962_DACL_RETUNE_C27_1: case WM8962_DACL_RETUNE_C27_0: case WM8962_DACL_RETUNE_C28_1: case WM8962_DACL_RETUNE_C28_0: case WM8962_DACL_RETUNE_C29_1: case WM8962_DACL_RETUNE_C29_0: case WM8962_DACL_RETUNE_C30_1: case WM8962_DACL_RETUNE_C30_0: case WM8962_DACL_RETUNE_C31_1: case WM8962_DACL_RETUNE_C31_0: case WM8962_DACL_RETUNE_C32_1: case WM8962_DACL_RETUNE_C32_0: case WM8962_RETUNEDAC_PG2_1: case WM8962_RETUNEDAC_PG2_0: case WM8962_RETUNEDAC_PG_1: case WM8962_RETUNEDAC_PG_0: case WM8962_DACR_RETUNE_C1_1: case WM8962_DACR_RETUNE_C1_0: case WM8962_DACR_RETUNE_C2_1: case WM8962_DACR_RETUNE_C2_0: case WM8962_DACR_RETUNE_C3_1: case WM8962_DACR_RETUNE_C3_0: case WM8962_DACR_RETUNE_C4_1: case WM8962_DACR_RETUNE_C4_0: case WM8962_DACR_RETUNE_C5_1: case WM8962_DACR_RETUNE_C5_0: case WM8962_DACR_RETUNE_C6_1: case WM8962_DACR_RETUNE_C6_0: case WM8962_DACR_RETUNE_C7_1: case WM8962_DACR_RETUNE_C7_0: case WM8962_DACR_RETUNE_C8_1: case WM8962_DACR_RETUNE_C8_0: case WM8962_DACR_RETUNE_C9_1: case WM8962_DACR_RETUNE_C9_0: case WM8962_DACR_RETUNE_C10_1: case WM8962_DACR_RETUNE_C10_0: case WM8962_DACR_RETUNE_C11_1: case WM8962_DACR_RETUNE_C11_0: case WM8962_DACR_RETUNE_C12_1: case WM8962_DACR_RETUNE_C12_0: case WM8962_DACR_RETUNE_C13_1: case WM8962_DACR_RETUNE_C13_0: case WM8962_DACR_RETUNE_C14_1: case WM8962_DACR_RETUNE_C14_0: case WM8962_DACR_RETUNE_C15_1: case WM8962_DACR_RETUNE_C15_0: case WM8962_DACR_RETUNE_C16_1: case WM8962_DACR_RETUNE_C16_0: case WM8962_DACR_RETUNE_C17_1: case WM8962_DACR_RETUNE_C17_0: case WM8962_DACR_RETUNE_C18_1: case WM8962_DACR_RETUNE_C18_0: case WM8962_DACR_RETUNE_C19_1: case WM8962_DACR_RETUNE_C19_0: case WM8962_DACR_RETUNE_C20_1: case WM8962_DACR_RETUNE_C20_0: case WM8962_DACR_RETUNE_C21_1: case WM8962_DACR_RETUNE_C21_0: case WM8962_DACR_RETUNE_C22_1: case WM8962_DACR_RETUNE_C22_0: case WM8962_DACR_RETUNE_C23_1: case WM8962_DACR_RETUNE_C23_0: case WM8962_DACR_RETUNE_C24_1: case WM8962_DACR_RETUNE_C24_0: case WM8962_DACR_RETUNE_C25_1: case WM8962_DACR_RETUNE_C25_0: case WM8962_DACR_RETUNE_C26_1: case WM8962_DACR_RETUNE_C26_0: case WM8962_DACR_RETUNE_C27_1: case WM8962_DACR_RETUNE_C27_0: case WM8962_DACR_RETUNE_C28_1: case WM8962_DACR_RETUNE_C28_0: case WM8962_DACR_RETUNE_C29_1: case WM8962_DACR_RETUNE_C29_0: case WM8962_DACR_RETUNE_C30_1: case WM8962_DACR_RETUNE_C30_0: case WM8962_DACR_RETUNE_C31_1: case WM8962_DACR_RETUNE_C31_0: case WM8962_DACR_RETUNE_C32_1: case WM8962_DACR_RETUNE_C32_0: case WM8962_VSS_XHD2_1: case WM8962_VSS_XHD2_0: case WM8962_VSS_XHD3_1: case WM8962_VSS_XHD3_0: case WM8962_VSS_XHN1_1: case WM8962_VSS_XHN1_0: case WM8962_VSS_XHN2_1: case WM8962_VSS_XHN2_0: case WM8962_VSS_XHN3_1: case WM8962_VSS_XHN3_0: case WM8962_VSS_XLA_1: case WM8962_VSS_XLA_0: case WM8962_VSS_XLB_1: case WM8962_VSS_XLB_0: case WM8962_VSS_XLG_1: case WM8962_VSS_XLG_0: case WM8962_VSS_PG2_1: case WM8962_VSS_PG2_0: case WM8962_VSS_PG_1: case WM8962_VSS_PG_0: case WM8962_VSS_XTD1_1: case WM8962_VSS_XTD1_0: case WM8962_VSS_XTD2_1: case WM8962_VSS_XTD2_0: case WM8962_VSS_XTD3_1: case WM8962_VSS_XTD3_0: case WM8962_VSS_XTD4_1: case WM8962_VSS_XTD4_0: case WM8962_VSS_XTD5_1: case WM8962_VSS_XTD5_0: case WM8962_VSS_XTD6_1: case WM8962_VSS_XTD6_0: case WM8962_VSS_XTD7_1: case WM8962_VSS_XTD7_0: case WM8962_VSS_XTD8_1: case WM8962_VSS_XTD8_0: case WM8962_VSS_XTD9_1: case WM8962_VSS_XTD9_0: case WM8962_VSS_XTD10_1: case WM8962_VSS_XTD10_0: case WM8962_VSS_XTD11_1: case WM8962_VSS_XTD11_0: case WM8962_VSS_XTD12_1: case WM8962_VSS_XTD12_0: case WM8962_VSS_XTD13_1: case WM8962_VSS_XTD13_0: case WM8962_VSS_XTD14_1: case WM8962_VSS_XTD14_0: case WM8962_VSS_XTD15_1: case WM8962_VSS_XTD15_0: case WM8962_VSS_XTD16_1: case WM8962_VSS_XTD16_0: case WM8962_VSS_XTD17_1: case WM8962_VSS_XTD17_0: case WM8962_VSS_XTD18_1: case WM8962_VSS_XTD18_0: case WM8962_VSS_XTD19_1: case WM8962_VSS_XTD19_0: case WM8962_VSS_XTD20_1: case WM8962_VSS_XTD20_0: case WM8962_VSS_XTD21_1: case WM8962_VSS_XTD21_0: case WM8962_VSS_XTD22_1: case WM8962_VSS_XTD22_0: case WM8962_VSS_XTD23_1: case WM8962_VSS_XTD23_0: case WM8962_VSS_XTD24_1: case WM8962_VSS_XTD24_0: case WM8962_VSS_XTD25_1: case WM8962_VSS_XTD25_0: case WM8962_VSS_XTD26_1: case WM8962_VSS_XTD26_0: case WM8962_VSS_XTD27_1: case WM8962_VSS_XTD27_0: case WM8962_VSS_XTD28_1: case WM8962_VSS_XTD28_0: case WM8962_VSS_XTD29_1: case WM8962_VSS_XTD29_0: case WM8962_VSS_XTD30_1: case WM8962_VSS_XTD30_0: case WM8962_VSS_XTD31_1: case WM8962_VSS_XTD31_0: case WM8962_VSS_XTD32_1: case WM8962_VSS_XTD32_0: case WM8962_VSS_XTS1_1: case WM8962_VSS_XTS1_0: case WM8962_VSS_XTS2_1: case WM8962_VSS_XTS2_0: case WM8962_VSS_XTS3_1: case WM8962_VSS_XTS3_0: case WM8962_VSS_XTS4_1: case WM8962_VSS_XTS4_0: case WM8962_VSS_XTS5_1: case WM8962_VSS_XTS5_0: case WM8962_VSS_XTS6_1: case WM8962_VSS_XTS6_0: case WM8962_VSS_XTS7_1: case WM8962_VSS_XTS7_0: case WM8962_VSS_XTS8_1: case WM8962_VSS_XTS8_0: case WM8962_VSS_XTS9_1: case WM8962_VSS_XTS9_0: case WM8962_VSS_XTS10_1: case WM8962_VSS_XTS10_0: case WM8962_VSS_XTS11_1: case WM8962_VSS_XTS11_0: case WM8962_VSS_XTS12_1: case WM8962_VSS_XTS12_0: case WM8962_VSS_XTS13_1: case WM8962_VSS_XTS13_0: case WM8962_VSS_XTS14_1: case WM8962_VSS_XTS14_0: case WM8962_VSS_XTS15_1: case WM8962_VSS_XTS15_0: case WM8962_VSS_XTS16_1: case WM8962_VSS_XTS16_0: case WM8962_VSS_XTS17_1: case WM8962_VSS_XTS17_0: case WM8962_VSS_XTS18_1: case WM8962_VSS_XTS18_0: case WM8962_VSS_XTS19_1: case WM8962_VSS_XTS19_0: case WM8962_VSS_XTS20_1: case WM8962_VSS_XTS20_0: case WM8962_VSS_XTS21_1: case WM8962_VSS_XTS21_0: case WM8962_VSS_XTS22_1: case WM8962_VSS_XTS22_0: case WM8962_VSS_XTS23_1: case WM8962_VSS_XTS23_0: case WM8962_VSS_XTS24_1: case WM8962_VSS_XTS24_0: case WM8962_VSS_XTS25_1: case WM8962_VSS_XTS25_0: case WM8962_VSS_XTS26_1: case WM8962_VSS_XTS26_0: case WM8962_VSS_XTS27_1: case WM8962_VSS_XTS27_0: case WM8962_VSS_XTS28_1: case WM8962_VSS_XTS28_0: case WM8962_VSS_XTS29_1: case WM8962_VSS_XTS29_0: case WM8962_VSS_XTS30_1: case WM8962_VSS_XTS30_0: case WM8962_VSS_XTS31_1: case WM8962_VSS_XTS31_0: case WM8962_VSS_XTS32_1: case WM8962_VSS_XTS32_0: returntrue; default: returnfalse;
}
}
staticint wm8962_reset(struct wm8962_priv *wm8962)
{ int ret;
ret = regmap_write(wm8962->regmap, WM8962_SOFTWARE_RESET, 0x6243); if (ret != 0) return ret;
if (dsp2_running) { if (wm8962->dsp2_ena)
wm8962_dsp2_set_enable(component, wm8962->dsp2_ena); else
wm8962_dsp2_stop(component);
}
out:
mutex_unlock(&wm8962->dsp2_ena_lock);
return ret;
}
/* The VU bits for the headphones are in a different register to the mute * bits and only take effect on the PGA if it is actually powered.
*/ staticint wm8962_put_hp_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); int ret;
/* Apply the update (if any) */
ret = snd_soc_put_volsw(kcontrol, ucontrol); if (ret == 0) return 0;
/* If the left PGA is enabled hit that VU bit... */
ret = snd_soc_component_read(component, WM8962_PWR_MGMT_2); if (ret & WM8962_HPOUTL_PGA_ENA) {
snd_soc_component_write(component, WM8962_HPOUTL_VOLUME,
snd_soc_component_read(component, WM8962_HPOUTL_VOLUME)); return 1;
}
/* ...otherwise the right. The VU is stereo. */ if (ret & WM8962_HPOUTR_PGA_ENA)
snd_soc_component_write(component, WM8962_HPOUTR_VOLUME,
snd_soc_component_read(component, WM8962_HPOUTR_VOLUME));
return 1;
}
/* The VU bits for the speakers are in a different register to the mute * bits and only take effect on the PGA if it is actually powered.
*/ staticint wm8962_put_spk_sw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); int ret;
/* Apply the update (if any) */
ret = snd_soc_put_volsw(kcontrol, ucontrol); if (ret == 0) return 0;
/* If the left PGA is enabled hit that VU bit... */
ret = snd_soc_component_read(component, WM8962_PWR_MGMT_2); if (ret & WM8962_SPKOUTL_PGA_ENA) {
snd_soc_component_write(component, WM8962_SPKOUTL_VOLUME,
snd_soc_component_read(component, WM8962_SPKOUTL_VOLUME)); return 1;
}
/* ...otherwise the right. The VU is stereo. */ if (ret & WM8962_SPKOUTR_PGA_ENA)
snd_soc_component_write(component, WM8962_SPKOUTR_VOLUME,
snd_soc_component_read(component, WM8962_SPKOUTR_VOLUME));
/* Wait for it to complete, should be well under 100ms */
timeout = 0; do {
msleep(1);
reg = snd_soc_component_read(component, WM8962_DC_SERVO_6); if (reg < 0) {
dev_err(component->dev, "Failed to read DCS status: %d\n",
reg); continue;
}
dev_dbg(component->dev, "DCS status: %x\n", reg);
} while (++timeout < 200 && (reg & expected) != expected);
if ((reg & expected) != expected)
dev_err(component->dev, "DC servo timed out\n"); else
dev_dbg(component->dev, "DC servo complete after %dms\n",
timeout);
/* VU bits for the output PGAs only take effect while the PGA is powered */ staticint out_pga_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event)
{ struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); int reg;
switch (w->shift) { case WM8962_HPOUTR_PGA_ENA_SHIFT:
reg = WM8962_HPOUTR_VOLUME; break; case WM8962_HPOUTL_PGA_ENA_SHIFT:
reg = WM8962_HPOUTL_VOLUME; break; case WM8962_SPKOUTR_PGA_ENA_SHIFT:
reg = WM8962_SPKOUTR_VOLUME; break; case WM8962_SPKOUTL_PGA_ENA_SHIFT:
reg = WM8962_SPKOUTL_VOLUME; break; default:
WARN(1, "Invalid shift %d\n", w->shift); return -EINVAL;
}
staticvoid wm8962_configure_bclk(struct snd_soc_component *component)
{ struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component); int best, min_diff, diff; int dspclk, i; int clocking2 = 0; int clocking4 = 0; int aif2 = 0;
if (!wm8962->sysclk_rate) {
dev_dbg(component->dev, "No SYSCLK configured\n"); return;
}
if (!wm8962->bclk || !wm8962->lrclk) {
dev_dbg(component->dev, "No audio clocks configured\n"); return;
}
for (i = 0; i < ARRAY_SIZE(sysclk_rates); i++) { if (sysclk_rates[i] == wm8962->sysclk_rate / wm8962->lrclk) {
clocking4 |= i << WM8962_SYSCLK_RATE_SHIFT; break;
}
}
if (i == ARRAY_SIZE(sysclk_rates)) {
dev_err(component->dev, "Unsupported sysclk ratio %d\n",
wm8962->sysclk_rate / wm8962->lrclk); return;
}
dev_dbg(component->dev, "Selected sysclk ratio %d\n", sysclk_rates[i]);
/* DSPCLK_DIV can be only generated correctly after enabling SYSCLK. * So we here provisionally enable it and then disable it afterward * if current bias_level hasn't reached SND_SOC_BIAS_ON.
*/ if (snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_ON)
snd_soc_component_update_bits(component, WM8962_CLOCKING2,
WM8962_SYSCLK_ENA_MASK, WM8962_SYSCLK_ENA);
/* DSPCLK_DIV field in WM8962_CLOCKING1 register is used to generate * correct frequency of LRCLK and BCLK. Sometimes the read-only value * can't be updated timely after enabling SYSCLK. This results in wrong * calculation values. Delay is introduced here to wait for newest * value from register. The time of the delay should be at least * 500~1000us according to test.
*/
usleep_range(500, 1000);
dspclk = snd_soc_component_read(component, WM8962_CLOCKING1);
if (snd_soc_component_get_bias_level(component) != SND_SOC_BIAS_ON)
snd_soc_component_update_bits(component, WM8962_CLOCKING2,
WM8962_SYSCLK_ENA_MASK, 0);
if (dspclk < 0) {
dev_err(component->dev, "Failed to read DSPCLK: %d\n", dspclk); return;
}
dev_dbg(component->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, wm8962->bclk);
/* Search a proper bclk, not exact match. */
best = 0;
min_diff = INT_MAX; for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { if (bclk_divs[i] < 0) continue;
diff = (dspclk / bclk_divs[i]) - wm8962->bclk; if (diff < 0) /* Table is sorted */ break; if (diff < min_diff) {
best = i;
min_diff = diff;
}
}
wm8962->bclk = dspclk / bclk_divs[best];
clocking2 |= best;
dev_dbg(component->dev, "Selected BCLK_DIV %d for %dHz\n",
bclk_divs[best], wm8962->bclk);
/* Fref must be <=13.5MHz */
div = 1;
fll_div->fll_refclk_div = 0; while ((Fref / div) > 13500000) {
div *= 2;
fll_div->fll_refclk_div++;
if (div > 4) {
pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
Fref); return -EINVAL;
}
}
pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
/* Apply the division for our remaining calculations */
Fref /= div;
/* Fvco should be 90-100MHz; don't check the upper bound */
div = 2; while (Fout * div < 90000000) {
div++; if (div > 64) {
pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
Fout); return -EINVAL;
}
}
target = Fout * div;
fll_div->fll_outdiv = div - 1;
pr_debug("FLL Fvco=%dHz\n", target);
/* Find an appropriate FLL_FRATIO and factor it out of the target */ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) { if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
fll_div->fll_fratio = fll_fratios[i].fll_fratio;
fratio = fll_fratios[i].ratio; break;
}
} if (i == ARRAY_SIZE(fll_fratios)) {
pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref); return -EINVAL;
}
dev_dbg(component->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
/* This should be a massive overestimate but go even * higher if we'll error out
*/ if (wm8962->irq)
time_left = msecs_to_jiffies(5); else
time_left = msecs_to_jiffies(1);
staticint wm8962_mute(struct snd_soc_dai *dai, int mute, int direction)
{ struct snd_soc_component *component = dai->component; int val, ret;
if (mute)
val = WM8962_DAC_MUTE | WM8962_DAC_MUTE_ALT; else
val = 0;
/** * The DAC mute bit is mirrored in two registers, update both to keep * the register cache consistent.
*/
ret = snd_soc_component_update_bits(component, WM8962_CLASS_D_CONTROL_1,
WM8962_DAC_MUTE_ALT, val); if (ret < 0) return ret;
/** * wm8962_mic_detect - Enable microphone detection via the WM8962 IRQ * * @component: WM8962 component * @jack: jack to report detection events on * * Enable microphone detection via IRQ on the WM8962. If GPIOs are * being used to bring out signals to the processor then only platform * data configuration is needed for WM8962 and processor GPIOs should * be configured using snd_soc_jack_add_gpios() instead. * * If no jack is supplied detection will be disabled.
*/ int wm8962_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *jack)
{ struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component); struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); int irq_mask, enable;
staticvoid wm8962_beep_work(struct work_struct *work)
{ struct wm8962_priv *wm8962 =
container_of(work, struct wm8962_priv, beep_work); struct snd_soc_component *component = wm8962->component; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); int i; int reg = 0; int best = 0;
if (wm8962->beep_rate) { for (i = 0; i < ARRAY_SIZE(beep_rates); i++) { if (abs(wm8962->beep_rate - beep_rates[i]) <
abs(wm8962->beep_rate - beep_rates[best]))
best = i;
}
dev_dbg(component->dev, "Set beep rate %dHz for requested %dHz\n",
beep_rates[best], wm8962->beep_rate);
/* For usability define a way of injecting beep events for the device - * many systems will not have a keyboard.
*/ staticint wm8962_beep_event(struct input_dev *dev, unsignedint type, unsignedint code, int hz)
{ struct snd_soc_component *component = input_get_drvdata(dev); struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component);
staticvoid wm8962_set_gpio_mode(struct wm8962_priv *wm8962, int gpio)
{ int mask = 0; int val = 0;
/* Some of the GPIOs are behind MFP configuration and need to
* be put into GPIO mode. */ switch (gpio) { case 2:
mask = WM8962_CLKOUT2_SEL_MASK;
val = 1 << WM8962_CLKOUT2_SEL_SHIFT; break; case 3:
mask = WM8962_CLKOUT3_SEL_MASK;
val = 1 << WM8962_CLKOUT3_SEL_SHIFT; break; default: break;
}
if (mask)
regmap_update_bits(wm8962->regmap, WM8962_ANALOGUE_CLOCKING1,
mask, val);
}
/* The WM8962 GPIOs aren't linearly numbered. For simplicity * we export linear numbers and error out if the unsupported * ones are requsted.
*/ switch (offset + 1) { case 2: case 3: case 5: case 6: break; default: return -EINVAL;
}
/* This should really be moved into the regulator core */ for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++) {
ret = devm_regulator_register_notifier(
wm8962->supplies[i].consumer,
&wm8962->disable_nb[i]); if (ret != 0) {
dev_err(component->dev, "Failed to register regulator notifier: %d\n",
ret);
}
}
wm8962_add_widgets(component);
/* Save boards having to disable DMIC when not in use */
dmicclk = false;
dmicdat = false; for (i = 1; i < WM8962_MAX_GPIO; i++) { /* * Register 515 (WM8962_GPIO_BASE + 3) does not exist, * so skip its access
*/ if (i == 3) continue; switch (snd_soc_component_read(component, WM8962_GPIO_BASE + i)
& WM8962_GP2_FN_MASK) { case WM8962_GPIO_FN_DMICCLK:
dmicclk = true; break; case WM8962_GPIO_FN_DMICDAT:
dmicdat = true; break; default: break;
}
} if (!dmicclk || !dmicdat) {
dev_dbg(component->dev, "DMIC not in use, disabling\n");
snd_soc_dapm_nc_pin(dapm, "DMICDAT");
} if (dmicclk != dmicdat)
dev_warn(component->dev, "DMIC GPIOs partially configured\n");
if (of_property_read_bool(np, "spk-mono"))
pdata->spk_mono = true;
if (of_property_read_u32(np, "mic-cfg", &val32) >= 0)
pdata->mic_cfg = val32;
if (of_property_read_u32_array(np, "gpio-cfg", pdata->gpio_init,
ARRAY_SIZE(pdata->gpio_init)) >= 0) for (i = 0; i < ARRAY_SIZE(pdata->gpio_init); i++) { /* * The range of GPIO register value is [0x0, 0xffff] * While the default value of each register is 0x0 * Any other value will be regarded as default value
*/ if (pdata->gpio_init[i] > 0xffff)
pdata->gpio_init[i] = 0x0;
}
/* If platform data was supplied, update the default data in priv */ if (pdata) {
memcpy(&wm8962->pdata, pdata, sizeof(struct wm8962_pdata));
} elseif (i2c->dev.of_node) {
ret = wm8962_set_pdata_from_of(i2c, &wm8962->pdata); if (ret != 0) return ret;
}
for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
wm8962->supplies[i].supply = wm8962_supply_names[i];
ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies),
wm8962->supplies); if (ret != 0) {
dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); goto err;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
wm8962->supplies); if (ret != 0) {
dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); return ret;
}
wm8962->regmap = devm_regmap_init_i2c(i2c, &wm8962_regmap); if (IS_ERR(wm8962->regmap)) {
ret = PTR_ERR(wm8962->regmap);
dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret); goto err_enable;
}
/* * We haven't marked the chip revision as volatile due to * sharing a register with the right input volume; explicitly * bypass the cache to read it.
*/
regcache_cache_bypass(wm8962->regmap, true);
ret = regmap_read(wm8962->regmap, WM8962_SOFTWARE_RESET, ®); if (ret < 0) {
dev_err(&i2c->dev, "Failed to read ID register\n"); goto err_enable;
} if (reg != 0x6243) {
dev_err(&i2c->dev, "Device is not a WM8962, ID %x != 0x6243\n", reg);
ret = -EINVAL; goto err_enable;
}
ret = regmap_read(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME, ®); if (ret < 0) {
dev_err(&i2c->dev, "Failed to read device revision: %d\n",
ret); goto err_enable;
}
ret = wm8962_reset(wm8962); if (ret < 0) {
dev_err(&i2c->dev, "Failed to issue reset\n"); goto err_enable;
}
/* SYSCLK defaults to on; make sure it is off so we can safely * write to registers if the device is declocked.
*/
regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2,
WM8962_SYSCLK_ENA, 0);
/* Ensure we have soft control over all registers */
regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2,
WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
/* Ensure that the oscillator and PLLs are disabled */
regmap_update_bits(wm8962->regmap, WM8962_PLL2,
WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
0);
/* Apply static configuration for GPIOs */ for (i = 0; i < ARRAY_SIZE(wm8962->pdata.gpio_init); i++) if (wm8962->pdata.gpio_init[i]) {
wm8962_set_gpio_mode(wm8962, i + 1);
regmap_write(wm8962->regmap, 0x200 + i,
wm8962->pdata.gpio_init[i] & 0xffff);
}
/* Put the speakers into mono mode? */ if (wm8962->pdata.spk_mono)
regmap_update_bits(wm8962->regmap, WM8962_CLASS_D_CONTROL_2,
WM8962_SPK_MONO_MASK, WM8962_SPK_MONO);
/* Stereo control for EQ */
regmap_update_bits(wm8962->regmap, WM8962_EQ1,
WM8962_EQ_SHARED_COEFF, 0);
/* Don't debouce interrupts so we don't need SYSCLK */
regmap_update_bits(wm8962->regmap, WM8962_IRQ_DEBOUNCE,
WM8962_FLL_LOCK_DB | WM8962_PLL3_LOCK_DB |
WM8962_PLL2_LOCK_DB | WM8962_TEMP_SHUT_DB,
0);
if (wm8962->pdata.in4_dc_measure) {
ret = regmap_register_patch(wm8962->regmap,
wm8962_dc_measure,
ARRAY_SIZE(wm8962_dc_measure)); if (ret != 0)
dev_err(&i2c->dev, "Failed to configure for DC measurement: %d\n",
ret);
}
ret = clk_prepare_enable(wm8962->pdata.mclk); if (ret) {
dev_err(dev, "Failed to enable MCLK: %d\n", ret); return ret;
}
ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
wm8962->supplies); if (ret != 0) {
dev_err(dev, "Failed to enable supplies: %d\n", ret); goto disable_clock;
}
regcache_cache_only(wm8962->regmap, false);
wm8962_reset(wm8962);
regcache_mark_dirty(wm8962->regmap);
/* SYSCLK defaults to on; make sure it is off so we can safely * write to registers if the device is declocked.
*/
regmap_write_bits(wm8962->regmap, WM8962_CLOCKING2,
WM8962_SYSCLK_ENA, 0);
/* Ensure we have soft control over all registers */
regmap_update_bits(wm8962->regmap, WM8962_CLOCKING2,
WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
/* Ensure that the oscillator and PLLs are disabled */
regmap_update_bits(wm8962->regmap, WM8962_PLL2,
WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
0);
MODULE_DESCRIPTION("ASoC WM8962 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
Messung V0.5 in Prozent
¤ Diese beiden folgenden Angebotsgruppen bietet das Unternehmen0.67Angebot
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-04-29)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.