/arch/arm/mach-fsm/qdsp6/q6audio.c
C | 1852 lines | 1529 code | 298 blank | 25 comment | 229 complexity | efad4e9e4a09de0070cbd51e44fd14f2 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
- /*
- * Copyright (C) 2009 Google, Inc.
- * Copyright (c) 2010, Code Aurora Forum. All rights reserved.
- * Author: Brian Swetland <swetland@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
- #include <linux/mutex.h>
- #include <linux/sched.h>
- #include <linux/wait.h>
- #include <linux/dma-mapping.h>
- #include <linux/clk.h>
- #include <linux/delay.h>
- #include <linux/wakelock.h>
- #include <linux/android_pmem.h>
- #include <linux/firmware.h>
- #include <linux/miscdevice.h>
- #include "dal.h"
- #include "dal_audio.h"
- #include "dal_audio_format.h"
- #include "dal_acdb.h"
- #include "dal_adie.h"
- #include <mach/msm_qdsp6_audio.h>
- #include <linux/msm_audio_aac.h>
- #include <linux/gpio.h>
- #include "q6audio_devices.h"
- #include <mach/debug_mm.h>
- #if 0
- #define TRACE(x...) pr_info("Q6: "x)
- #else
- #define TRACE(x...) do{}while(0)
- #endif
- struct q6_hw_info {
- int min_gain;
- int max_gain;
- };
- /* TODO: provide mechanism to configure from board file */
- static struct q6_hw_info q6_audio_hw[Q6_HW_COUNT] = {
- [Q6_HW_HANDSET] = {
- .min_gain = -400,
- .max_gain = 1100,
- },
- [Q6_HW_HEADSET] = {
- .min_gain = -1100,
- .max_gain = 400,
- },
- [Q6_HW_SPEAKER] = {
- .min_gain = -1000,
- .max_gain = 500,
- },
- [Q6_HW_TTY] = {
- .min_gain = 0,
- .max_gain = 0,
- },
- [Q6_HW_BT_SCO] = {
- .min_gain = -1100,
- .max_gain = 400,
- },
- [Q6_HW_BT_A2DP] = {
- .min_gain = -1100,
- .max_gain = 400,
- },
- };
- static struct wake_lock wakelock;
- static struct wake_lock idlelock;
- static int idlecount;
- static DEFINE_MUTEX(idlecount_lock);
- void audio_prevent_sleep(void)
- {
- mutex_lock(&idlecount_lock);
- if (++idlecount == 1) {
- wake_lock(&wakelock);
- wake_lock(&idlelock);
- }
- mutex_unlock(&idlecount_lock);
- }
- void audio_allow_sleep(void)
- {
- mutex_lock(&idlecount_lock);
- if (--idlecount == 0) {
- wake_unlock(&idlelock);
- wake_unlock(&wakelock);
- }
- mutex_unlock(&idlecount_lock);
- }
- static struct clk *icodec_rx_clk;
- static struct clk *icodec_tx_clk;
- static struct clk *ecodec_clk;
- static struct clk *sdac_clk;
- static struct q6audio_analog_ops default_analog_ops;
- static struct q6audio_analog_ops *analog_ops = &default_analog_ops;
- static uint32_t tx_clk_freq = 8000;
- static int tx_mute_status = 0;
- static int rx_vol_level = 100;
- static uint32_t tx_acdb = 0;
- static uint32_t rx_acdb = 0;
- void q6audio_register_analog_ops(struct q6audio_analog_ops *ops)
- {
- analog_ops = ops;
- }
- static struct q6_device_info *q6_lookup_device(uint32_t device_id,
- uint32_t acdb_id)
- {
- struct q6_device_info *di = q6_audio_devices;
- if (acdb_id) {
- for (;;) {
- if (di->cad_id == acdb_id && di->id == device_id)
- return di;
- if (di->id == 0) {
- pr_err("[%s:%s] bogus id 0x%08x\n",
- __MM_FILE__, __func__, device_id);
- return di;
- }
- di++;
- }
- } else {
- for (;;) {
- if (di->id == device_id)
- return di;
- if (di->id == 0) {
- pr_err("[%s:%s] bogus id 0x%08x\n",
- __MM_FILE__, __func__, device_id);
- return di;
- }
- di++;
- }
- }
- }
- static uint32_t q6_device_to_codec(uint32_t device_id)
- {
- struct q6_device_info *di = q6_lookup_device(device_id, 0);
- return di->codec;
- }
- static uint32_t q6_device_to_dir(uint32_t device_id)
- {
- struct q6_device_info *di = q6_lookup_device(device_id, 0);
- return di->dir;
- }
- static uint32_t q6_device_to_cad_id(uint32_t device_id)
- {
- struct q6_device_info *di = q6_lookup_device(device_id, 0);
- return di->cad_id;
- }
- static uint32_t q6_device_to_path(uint32_t device_id, uint32_t acdb_id)
- {
- struct q6_device_info *di = q6_lookup_device(device_id, acdb_id);
- return di->path;
- }
- static uint32_t q6_device_to_rate(uint32_t device_id)
- {
- struct q6_device_info *di = q6_lookup_device(device_id, 0);
- return di->rate;
- }
- int q6_device_volume(uint32_t device_id, int level)
- {
- struct q6_device_info *di = q6_lookup_device(device_id, 0);
- struct q6_hw_info *hw;
- hw = &q6_audio_hw[di->hw];
- return hw->min_gain + ((hw->max_gain - hw->min_gain) * level) / 100;
- }
- static inline int adie_open(struct dal_client *client)
- {
- return dal_call_f0(client, DAL_OP_OPEN, 0);
- }
- static inline int adie_close(struct dal_client *client)
- {
- return dal_call_f0(client, DAL_OP_CLOSE, 0);
- }
- static inline int adie_set_path(struct dal_client *client,
- uint32_t id, uint32_t path_type)
- {
- return dal_call_f1(client, ADIE_OP_SET_PATH, id, path_type);
- }
- static inline int adie_set_path_freq_plan(struct dal_client *client,
- uint32_t path_type, uint32_t plan)
- {
- return dal_call_f1(client, ADIE_OP_SET_PATH_FREQUENCY_PLAN,
- path_type, plan);
- }
- static inline int adie_proceed_to_stage(struct dal_client *client,
- uint32_t path_type, uint32_t stage)
- {
- return dal_call_f1(client, ADIE_OP_PROCEED_TO_STAGE,
- path_type, stage);
- }
- static inline int adie_mute_path(struct dal_client *client,
- uint32_t path_type, uint32_t mute_state)
- {
- return dal_call_f1(client, ADIE_OP_MUTE_PATH, path_type, mute_state);
- }
- static int adie_refcount;
- static struct dal_client *adie;
- static struct dal_client *adsp;
- static struct dal_client *acdb;
- static int adie_enable(void)
- {
- adie_refcount++;
- if (adie_refcount == 1)
- adie_open(adie);
- return 0;
- }
- static int adie_disable(void)
- {
- adie_refcount--;
-