/* Copyright (c) 2009-2012, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
 * only 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.
 *
 */
#ifndef __MACH_QDSP6_V2_SNDDEV_H
#define __MACH_QDSP6_V2_SNDDEV_H
#include <mach/qdsp6v2/audio_def.h>
#include <sound/q6afe.h>

#define AUDIO_DEV_CTL_MAX_DEV 64
#define DIR_TX	2
#define DIR_RX	1

#define DEVICE_IGNORE	0xffff
#define COPP_IGNORE	0xffffffff
#define SESSION_IGNORE 0x0UL

/* 8 concurrent sessions with Q6 possible,  session:0
   reserved in DSP */
#define MAX_SESSIONS 0x09

/* This represents Maximum bit needed for representing sessions
   per clients, MAX_BIT_PER_CLIENT >= MAX_SESSIONS */
#define MAX_BIT_PER_CLIENT 16

#define VOICE_STATE_INVALID 0x0
#define VOICE_STATE_INCALL 0x1
#define VOICE_STATE_OFFCALL 0x2
#define ONE_TO_MANY 1
#define MANY_TO_ONE 2

struct msm_snddev_info {
	const char *name;
	u32 capability;
	u32 copp_id;
	u32 acdb_id;
	u32 dev_volume;
	struct msm_snddev_ops {
		int (*open)(struct msm_snddev_info *);
		int (*close)(struct msm_snddev_info *);
		int (*set_freq)(struct msm_snddev_info *, u32);
		int (*enable_sidetone)(struct msm_snddev_info *, u32, uint16_t);
		int (*set_device_volume)(struct msm_snddev_info *, u32);
		int (*enable_anc)(struct msm_snddev_info *, u32);
	} dev_ops;
	u8 opened;
	void *private_data;
	bool state;
	u32 sample_rate;
	u32 channel_mode;
	u32 set_sample_rate;
	u64 sessions;
	int usage_count;
	s32 max_voc_rx_vol[VOC_RX_VOL_ARRAY_NUM]; /* [0] is for NB,[1] for WB */
	s32 min_voc_rx_vol[VOC_RX_VOL_ARRAY_NUM];
};

struct msm_volume {
	int volume; /* Volume parameter, in % Scale */
	int pan;
};

extern struct msm_volume msm_vol_ctl;

void msm_snddev_register(struct msm_snddev_info *);
void msm_snddev_unregister(struct msm_snddev_info *);
int msm_snddev_devcount(void);
int msm_snddev_query(int dev_id);
unsigned short msm_snddev_route_dec(int popp_id);
unsigned short msm_snddev_route_enc(int enc_id);

int msm_snddev_set_dec(int popp_id, int copp_id, int set,
					int rate, int channel_mode);
int msm_snddev_set_enc(int popp_id, int copp_id, int set,
					int rate, int channel_mode);

int msm_snddev_is_set(int popp_id, int copp_id);
int msm_get_voc_route(u32 *rx_id, u32 *tx_id);
int msm_set_voc_route(struct msm_snddev_info *dev_info, int stream_type,
			int dev_id);
int msm_snddev_enable_sidetone(u32 dev_id, u32 enable, uint16_t gain);

int msm_set_copp_id(int session_id, int copp_id);

int msm_clear_copp_id(int session_id, int copp_id);

int msm_clear_session_id(int session_id);

int msm_reset_all_device(void);

int reset_device(void);

int msm_clear_all_session(void);

struct msm_snddev_info *audio_dev_ctrl_find_dev(u32 dev_id);

void msm_release_voc_thread(void);

int snddev_voice_set_volume(int vol, int path);

struct auddev_evt_voc_devinfo {
	u32 dev_type; /* Rx or Tx */
	u32 acdb_dev_id; /* acdb id of device */
	u32 dev_sample;  /* Sample rate of device */
	s32 max_rx_vol[VOC_RX_VOL_ARRAY_NUM]; /* unit is mb (milibel),
						[0] is for NB, other for WB */
	s32 min_rx_vol[VOC_RX_VOL_ARRAY_NUM]; /* unit is mb */
	u32 dev_id; /* registered device id */
	u32 dev_port_id;
};

struct auddev_evt_audcal_info {
	u32 dev_id;
	u32 acdb_id;
	u32 sample_rate;
	u32 dev_type;
	u32 sessions;
};

union msm_vol_mute {
	int vol;
	bool mute;
};

struct auddev_evt_voc_mute_info {
	u32 dev_type;
	u32 acdb_dev_id;
	u32 voice_session_id;
	union msm_vol_mute dev_vm_val;
};

struct auddev_evt_freq_info {
	u32 dev_type;
	u32 acdb_dev_id;
	u32 sample_rate;
};

union auddev_evt_data {
	struct auddev_evt_voc_devinfo voc_devinfo;
	struct auddev_evt_voc_mute_info voc_vm_info;
	struct auddev_evt_freq_info freq_info;
	u32 routing_id;
	s32 session_vol;
	s32 voice_state;
	struct auddev_evt_audcal_info audcal_info;
	u32 voice_session_id;
};

struct message_header {
	uint32_t id;
	uint32_t data_len;
};

#define AUDDEV_EVT_DEV_CHG_VOICE 0x01 /* device change event */
#define AUDDEV_EVT_DEV_RDY 0x02 /* device ready event */
#define AUDDEV_EVT_DEV_RLS 0x04 /* device released event */
#define AUDDEV_EVT_REL_PENDING 0x08 /* device release pending */
#define AUDDEV_EVT_DEVICE_VOL_MUTE_CHG 0x10 /* device volume changed */
#define AUDDEV_EVT_START_VOICE 0x20 /* voice call start */
#define AUDDEV_EVT_END_VOICE 0x40 /* voice call end */
#define AUDDEV_EVT_STREAM_VOL_CHG 0x80 /* device volume changed */
#define AUDDEV_EVT_FREQ_CHG 0x100 /* Change in freq */
#define AUDDEV_EVT_VOICE_STATE_CHG 0x200 /* Change in voice state */

#define AUDDEV_CLNT_VOC 0x1 /*Vocoder clients*/
#define AUDDEV_CLNT_DEC 0x2 /*Decoder clients*/
#define AUDDEV_CLNT_ENC 0x3 /* Encoder clients */
#define AUDDEV_CLNT_AUDIOCAL 0x4 /* AudioCalibration client */

#define AUDIO_DEV_CTL_MAX_LISTNER 20 /* Max Listeners Supported */

struct msm_snd_evt_listner {
	uint32_t evt_id;
	uint32_t clnt_type;
	uint32_t clnt_id;
	void *private_data;
	void (*auddev_evt_listener)(u32 evt_id,
		union auddev_evt_data *evt_payload,
		void *private_data);
	struct msm_snd_evt_listner *cb_next;
	struct msm_snd_evt_listner *cb_prev;
};

struct event_listner {
	struct msm_snd_evt_listner *cb;
	u32 num_listner;
	int state; /* Call state */ /* TODO remove this if not req*/
};

extern struct event_listner event;
int auddev_register_evt_listner(u32 evt_id, u32 clnt_type, u32 clnt_id,
		void (*listner)(u32 evt_id,
			union auddev_evt_data *evt_payload,
			void *private_data),
		void *private_data);
int auddev_unregister_evt_listner(u32 clnt_type, u32 clnt_id);
void mixer_post_event(u32 evt_id, u32 dev_id);
void broadcast_event(u32 evt_id, u32 dev_id, u64 session_id);
int auddev_cfg_tx_copp_topology(int session_id, int cfg);
int msm_snddev_request_freq(int *freq, u32 session_id,
			u32 capability, u32 clnt_type);
int msm_snddev_withdraw_freq(u32 session_id,
			u32 capability, u32 clnt_type);
int msm_device_is_voice(int dev_id);
int msm_get_voc_freq(int *tx_freq, int *rx_freq);
int msm_snddev_get_enc_freq(int session_id);
int msm_set_voice_vol(int dir, s32 volume, u32 session_id);
int msm_set_voice_mute(int dir, int mute, u32 session_id);
int msm_get_voice_state(void);
int msm_enable_incall_recording(int popp_id, int rec_mode, int rate,
				int channel_mode);
int msm_disable_incall_recording(uint32_t popp_id, uint32_t rec_mode);
#endif
