/*
* 88pm860x-codec.c -- 88PM860x ALSA SoC Audio Driver
*
* Copyright 2010 Marvell International Ltd.
* Author: Haojian Zhuang <haojian.zhuang@marvell.com>
*
* 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.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/mfd/88pm860x.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include <sound/tlv.h>
#include <sound/initval.h>
#include <sound/jack.h>
#include <trace/events/asoc.h>
#include "88pm860x-codec.h"
#define MAX_NAME_LEN 20
#define REG_CACHE_SIZE 0x40
#define REG_CACHE_BASE 0xb0
/* Status Register 1 (0x01) */
#define REG_STATUS_1 0x01
#define MIC_STATUS (1 << 7)
#define HOOK_STATUS (1 << 6)
#define HEADSET_STATUS (1 << 5)
/* Mic Detection Register (0x37) */
#define REG_MIC_DET 0x37
#define CONTINUOUS_POLLING (3 << 1)
#define EN_MIC_DET (1 << 0)
#define MICDET_MASK 0x07
/* Headset Detection Register (0x38) */
#define REG_HS_DET 0x38
#define EN_HS_DET (1 << 0)
/* Misc2 Register (0x42) */
#define REG_MISC2 0x42
#define AUDIO_PLL (1 << 5)
#define AUDIO_SECTION_RESET (1 << 4)
#define AUDIO_SECTION_ON (1 << 3)
/* PCM Interface Register 2 (0xb1) */
#define PCM_INF2_BCLK (1 << 6) /* Bit clock polarity */
#define PCM_INF2_FS (1 << 5) /* Frame Sync polarity */
#define PCM_INF2_MASTER (1 << 4) /* Master / Slave */
#define PCM_INF2_18WL (1 << 3) /* 18 / 16 bits */
#define PCM_GENERAL_I2S 0
#define PCM_EXACT_I2S 1
#define PCM_LEFT_I2S 2
#define PCM_RIGHT_I2S 3
#define PCM_SHORT_FS 4
#define PCM_LONG_FS 5
#define PCM_MODE_MASK 7
/* I2S Interface Register 4 (0xbe) */
#define I2S_EQU_BYP (1 << 6)
/* DAC Offset Register (0xcb) */
#define DAC_MUTE (1 << 7)
#define MUTE_LEFT (1 << 6)
#define MUTE_RIGHT (1 << 2)
/* ADC Analog Register 1 (0xd0) */
#define REG_ADC_ANA_1 0xd0
#define MIC1BIAS_MASK 0x60
/* Earpiece/Speaker Control Register 2 (0xda) */
#define REG_EAR2 0xda
#define RSYNC_CHANGE (1 << 2)
/* Audio Supplies Register 2 (0xdc) */
#define REG_SUPPLIES2 0xdc
#define LDO15_READY (1 << 4)
#define LDO15_EN (1 << 3)
#define CPUMP_READY (1 << 2)
#define CPUMP_EN (1 << 1)
#define AUDIO_EN (1 << 0)
#define SUPPLY_MASK (LDO15_EN | CPUMP_EN | AUDIO_EN)
/* Audio Enable Register 1 (0xdd) */
#define ADC_MOD_RIGHT (1 << 1)
#define ADC_MOD_LEFT (1 << 0)
/* Audio Enable Register 2 (0xde) */
#define ADC_LEFT (1 << 5)
#define ADC_RIGHT (1 << 4)
/* DAC Enable Register 2 (0xe1) */
#define DAC_LEFT (1 << 5)
#define DAC_RIGHT (1 << 4)
#define MODULATOR (1 << 3)
/* Shorts Register (0xeb) */
#define REG_SHORTS 0xeb
#define CLR_SHORT_LO2 (1 << 7)
#define SHORT_LO2 (1 << 6)
#define CLR_SHORT_LO1 (1 << 5)
#define SHORT_LO1 (1 << 4)
#define CLR_SHORT_HS2 (1 << 3)
#define SHORT_HS2 (1 << 2)
#define CLR_SHORT_HS1 (1 << 1)
#define SHORT_HS1 (1 << 0)
/*
* This widget should be just after DAC & PGA in DAPM power-on sequence and
* before DAC & PGA in DAPM power-off sequence.
*/
#define PM860X_DAPM_OUTPUT(wname, wevent) \
SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, 0, 0, NULL, 0, wevent, \
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD)
struct pm860x_det {
struct snd_soc_jack