Revert "htcleo: add audio drivers, qdsp6 modifications and enhanced venc driver"

This reverts commit b739bce6290e5e21b4a90a3efaef4b3178c873fc.

Conflicts:

	arch/arm/configs/htcleo_defconfig
	arch/arm/mach-msm/Makefile
	arch/arm/mach-msm/board-htcleo.c
This commit is contained in:
Markinus 2010-08-30 12:48:18 +02:00
parent 92fe430b32
commit 8137654e8f
24 changed files with 2027 additions and 5134 deletions

View File

@ -220,8 +220,8 @@ CONFIG_MACH_HTCLEO=y
CONFIG_HTC_35MM_JACK=y
# CONFIG_HTC_PWRSPLY is not set
# CONFIG_HTC_PWRSINK is not set
CONFIG_MSM_DALRPC=y
# CONFIG_MSM_DALRPC_TEST is not set
# CONFIG_MSM_DALRPC is not set
CONFIG_CACHE_FLUSH_RANGE_LIMIT=0x40000
CONFIG_MSM7X00A_USE_GP_TIMER=y
# CONFIG_MSM7X00A_USE_DG_TIMER is not set
@ -251,10 +251,7 @@ CONFIG_MSM_RPCSERVERS=y
# CONFIG_MSM_CPU_FREQ_SCREEN is not set
# CONFIG_MSM_HW3D is not set
CONFIG_MSM_QDSP6=y
CONFIG_QSD_AUDIO=y
CONFIG_QSD_HTC_FM=y
# CONFIG_MSM_CLOCK_CTRL_DEBUG is not set
CONFIG_ARCH_MSM_FLASHLIGHT=y
CONFIG_WIFI_CONTROL_FUNC=y
CONFIG_WIFI_MEM_PREALLOC=y
CONFIG_WIFI_NVS_PROC_CREATE=y
@ -265,8 +262,7 @@ CONFIG_HTCLEO_ENABLE_MULTI_TOUCH=y
# CONFIG_ENABLE_BRAVO_UART_DRV is not set
# CONFIG_ENABLE_USE_DESIRE_AMSS is not set
CONFIG_PHYS_OFFSET=0x11800000
# CONFIG_HTC_ACOUSTIC is not set
# CONFIG_HTC_ACOUSTIC_QSD is not set
#
# Processor Type
#

View File

@ -112,7 +112,8 @@ obj-$(CONFIG_MACH_BRAVOC) += board-bravoc-microp.o clock.o
obj-$(CONFIG_MACH_HTCLEO) += board-htcleo.o board-htcleo-spi.o board-htcleo-panel.o board-htcleo-keypad.o
obj-$(CONFIG_MACH_HTCLEO) += board-htcleo-ts.o board-htcleo-mmc.o ieee754-df.o board-htcleo-power.o
obj-$(CONFIG_MACH_HTCLEO) += board-htcleo-battery.o board-htcleo-log.o board-htcleo-acoustic.o board-htcleo-audio.o
obj-$(CONFIG_MACH_HTCLEO) += board-htcleo-battery.o board-htcleo-log.o
obj-$(CONFIG_MACH_HTCLEO) += board-htcleo-bt.o board-htcleo-microp.o board-htcleo-wifi.o
obj-$(CONFIG_MACH_HTCLEO) += clock-wince.o

View File

@ -1,247 +0,0 @@
/* arch/arm/mach-msm/board-htcleo-acoustic.c
*
* Copyright (C) 2010 Cotulla
*
* 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/device.h>
#include <linux/fs.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/uaccess.h>
#include <linux/mutex.h>
#include <linux/gpio.h>
#include <mach/msm_smd.h>
#include <mach/msm_rpcrouter.h>
#include <mach/msm_iomap.h>
#include <mach/htc_acoustic_qsd.h>
#include <mach/msm_qdsp6_audio.h>
#include "smd_private.h"
#include "dex_comm.h"
#define ACOUSTIC_IOCTL_MAGIC 'p'
#define ACOUSTIC_UPDATE_ADIE \
_IOW(ACOUSTIC_IOCTL_MAGIC, 24, unsigned int)
#define HTC_ACOUSTIC_TABLE_SIZE (0x20000)
#define D(fmt, args...) printk(KERN_INFO "htc-acoustic: "fmt, ##args)
#define E(fmt, args...) printk(KERN_ERR "htc-acoustic: "fmt, ##args)
static uint32_t htc_acoustic_vir_addr;
static struct mutex api_lock;
static struct qsd_acoustic_ops *the_ops;
void acoustic_register_ops(struct qsd_acoustic_ops *ops)
{
the_ops = ops;
}
int turn_mic_bias_on(int on)
{
D("%s called %d\n", __func__, on);
if (the_ops->enable_mic_bias)
the_ops->enable_mic_bias(on);
return 0;
}
EXPORT_SYMBOL(turn_mic_bias_on);
int force_headset_speaker_on(int enable)
{
printk("force_headset_speaker_on((%d)\n", enable);
if (enable)
dex_audio(0x53);
else
dex_audio(0x54);
return 0;
}
EXPORT_SYMBOL(force_headset_speaker_on);
int enable_aux_loopback(uint32_t enable)
{
printk("enable_aux_loopback(%d)\n", enable);
if (enable)
dex_audio(0x51);
else
dex_audio(0x52);
return 0;
}
EXPORT_SYMBOL(enable_aux_loopback);
int set_aux_gain(int level)
{
/* struct aux_gain_req {
struct rpc_request_hdr hdr;
int level;
} aux_req;
D("%s called %d\n", __func__, level);
if (is_rpc_connect() == -1)
return -1;
aux_req.level = cpu_to_be32(level);
return msm_rpc_call(endpoint,
ONCRPC_SET_AUX_PGA_GAIN_PROC,
&aux_req, sizeof(aux_req), 5 * HZ);*/
return 0;
}
EXPORT_SYMBOL(set_aux_gain);
static int acoustic_mmap(struct file *file, struct vm_area_struct *vma)
{
unsigned long pgoff;
int rc = -EINVAL;
size_t size;
D("mmap\n");
mutex_lock(&api_lock);
size = vma->vm_end - vma->vm_start;
if (vma->vm_pgoff != 0) {
E("mmap failed: page offset %lx\n", vma->vm_pgoff);
goto done;
}
if (!htc_acoustic_vir_addr) {
E("mmap failed: smem region not allocated\n");
rc = -EIO;
goto done;
}
pgoff = MSM_SHARED_RAM_PHYS +
(htc_acoustic_vir_addr - (uint32_t)MSM_SHARED_RAM_BASE);
pgoff = ((pgoff + 4095) & ~4095);
htc_acoustic_vir_addr = ((htc_acoustic_vir_addr + 4095) & ~4095);
if (pgoff <= 0) {
E("pgoff wrong. %ld\n", pgoff);
goto done;
}
if (size <= HTC_ACOUSTIC_TABLE_SIZE) {
pgoff = pgoff >> PAGE_SHIFT;
} else {
E("size > HTC_ACOUSTIC_TABLE_SIZE %d\n", size);
goto done;
}
vma->vm_flags |= VM_IO | VM_RESERVED;
rc = io_remap_pfn_range(vma, vma->vm_start, pgoff,
size, vma->vm_page_prot);
if (rc < 0)
E("mmap failed: remap error %d\n", rc);
done: mutex_unlock(&api_lock);
return rc;
}
static int acoustic_open(struct inode *inode, struct file *file)
{
int rc = -EIO;
D("open\n");
mutex_lock(&api_lock);
if (!htc_acoustic_vir_addr)
{
htc_acoustic_vir_addr = (uint32_t)MSM_SHARED_RAM_BASE + 0xF8000;
}
rc = 0;
mutex_unlock(&api_lock);
return rc;
}
static int acoustic_release(struct inode *inode, struct file *file)
{
D("release\n");
return 0;
}
static long acoustic_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
int rc = 0;
D("ioctl\n");
mutex_lock(&api_lock);
switch (cmd) {
case ACOUSTIC_UPDATE_ADIE:
{
unsigned data = 0xE5;
D("ioctl: ACOUSTIC_UPDATE_ADIE called %d.\n", current->pid);
// CotullaTODO: finish this code. if we need android tables really...
D("ioctl: done.\n");
break;
}
default:
E("ioctl: invalid command\n");
rc = -EINVAL;
}
mutex_unlock(&api_lock);
return rc;
}
struct rpc_set_uplink_mute_args {
int mute;
};
static struct file_operations acoustic_fops = {
.owner = THIS_MODULE,
.open = acoustic_open,
.release = acoustic_release,
.mmap = acoustic_mmap,
.unlocked_ioctl = acoustic_ioctl,
};
static struct miscdevice acoustic_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "htc-acoustic",
.fops = &acoustic_fops,
};
static int __init acoustic_init(void)
{
mutex_init(&api_lock);
return misc_register(&acoustic_misc);
}
static void __exit acoustic_exit(void)
{
misc_deregister(&acoustic_misc);
}
module_init(acoustic_init);
module_exit(acoustic_exit);

View File

@ -1,330 +0,0 @@
/* arch/arm/mach-msm/board-htcleo-audio.c
*
* Copyright (C) 2010 Cotulla
*
* 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/gpio.h>
#include <linux/delay.h>
#include <mach/msm_qdsp6_audio.h>
#include <mach/htc_acoustic_qsd.h>
#include <asm/gpio.h>
#include <mach/gpio.h>
#include "board-htcleo.h"
#include "devices.h"
#include "dex_comm.h"
#include "proc_comm.h"
#include "pmic.h"
#if 1
#define D(fmt, args...) printk(KERN_INFO "Audio: "fmt, ##args)
#else
#define D(fmt, args...) do {} while (0)
#endif
static struct mutex mic_lock;
static struct mutex bt_sco_lock;
#if 1
// LEO
static struct q6_hw_info q6_audio_hw[Q6_HW_COUNT] =
{
[Q6_HW_HANDSET] =
{
.min_gain = -2000,
.max_gain = 0,
},
[Q6_HW_HEADSET] =
{
.min_gain = -2000,
.max_gain = 0,
},
[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,
},
};
#else
// old desire one
static struct q6_hw_info q6_audio_hw[Q6_HW_COUNT] =
{
[Q6_HW_HANDSET] = {
.min_gain = -2000,
.max_gain = 0,
},
[Q6_HW_HEADSET] = {
.min_gain = -2000,
.max_gain = 0,
},
[Q6_HW_SPEAKER] = {
.min_gain = -1500,
.max_gain = 0,
},
[Q6_HW_TTY] = {
.min_gain = -2000,
.max_gain = 0,
},
[Q6_HW_BT_SCO] = {
.min_gain = -2000,
.max_gain = 0,
},
[Q6_HW_BT_A2DP] = {
.min_gain = -2000,
.max_gain = 0,
},
};
#endif
void htcleo_headset_enable(int en)
{
D("%s %d\n", __func__, en);
/* enable audio amp */
if (en) mdelay(60);
gpio_set_value(HTCLEO_AUD_JACKHP_EN, !!en);
}
void htcleo_speaker_enable(int en)
{
struct spkr_config_mode scm;
memset(&scm, 0, sizeof(scm));
D("%s %d\n", __func__, en);
if (en)
{
scm.is_right_chan_en = 0;
scm.is_left_chan_en = 1;
scm.is_stereo_en = 0;
scm.is_hpf_en = 0; //1; // CotullaTODO: check it
pmic_spkr_en_mute(LEFT_SPKR, 0);
pmic_spkr_en_mute(RIGHT_SPKR, 0);
pmic_set_spkr_configuration(&scm);
pmic_spkr_set_mux_hpf_corner_freq(SPKR_FREQ_0_76KHZ);
pmic_spkr_en(LEFT_SPKR, 1);
pmic_spkr_en(RIGHT_SPKR, 0);
pmic_spkr_en_hpf(ON_CMD); // +LEO
/* unmute */
pmic_spkr_en_mute(LEFT_SPKR, 1);
mdelay(40);
}
else
{
pmic_spkr_en_mute(LEFT_SPKR, 0);
pmic_spkr_en_hpf(OFF_CMD); // +LEO
pmic_spkr_en(LEFT_SPKR, 0);
pmic_spkr_en(RIGHT_SPKR, 0);
pmic_set_spkr_configuration(&scm);
}
}
void htcleo_receiver_enable(int en)
{
// if (is_cdma_version(system_rev) &&
// ((system_rev == 0xC1) || (system_rev == 0xC2))) {
struct spkr_config_mode scm;
memset(&scm, 0, sizeof(scm));
D("%s %d\n", __func__, en);
if (en)
{
scm.is_right_chan_en = 1;
scm.is_left_chan_en = 0;
scm.is_stereo_en = 0;
scm.is_hpf_en = 1;
pmic_spkr_en_mute(RIGHT_SPKR, 0);
pmic_set_spkr_configuration(&scm);
pmic_spkr_en(RIGHT_SPKR, 1);
/* unmute */
pmic_spkr_en_mute(RIGHT_SPKR, 1);
}
else
{
pmic_spkr_en_mute(RIGHT_SPKR, 0);
pmic_spkr_en(RIGHT_SPKR, 0);
pmic_set_spkr_configuration(&scm);
}
// }
}
static uint32_t bt_sco_enable[] =
{
PCOM_GPIO_CFG(HTCLEO_BT_PCM_OUT, 1, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA),
PCOM_GPIO_CFG(HTCLEO_BT_PCM_IN, 1, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA),
PCOM_GPIO_CFG(HTCLEO_BT_PCM_SYNC, 2, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA),
PCOM_GPIO_CFG(HTCLEO_BT_PCM_CLK, 2, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA)
};
static uint32_t bt_sco_disable[] =
{
PCOM_GPIO_CFG(HTCLEO_BT_PCM_OUT, 0, GPIO_OUTPUT, GPIO_NO_PULL, GPIO_2MA),
PCOM_GPIO_CFG(HTCLEO_BT_PCM_IN, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA),
PCOM_GPIO_CFG(HTCLEO_BT_PCM_SYNC, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA),
PCOM_GPIO_CFG(HTCLEO_BT_PCM_CLK, 0, GPIO_INPUT, GPIO_NO_PULL, GPIO_2MA)
};
void htcleo_bt_sco_enable(int en)
{
static int bt_sco_refcount;
D("%s %d\n", __func__, en);
mutex_lock(&bt_sco_lock);
if (en)
{
if (++bt_sco_refcount == 1)
{
config_gpio_table(bt_sco_enable, ARRAY_SIZE(bt_sco_enable));
}
}
else
{
if (--bt_sco_refcount == 0)
{
config_gpio_table(bt_sco_disable, ARRAY_SIZE(bt_sco_disable));
gpio_set_value(HTCLEO_BT_PCM_OUT, 0);
}
}
mutex_unlock(&bt_sco_lock);
}
void htcleo_mic_enable(int en)
{
static int old_state = 0, new_state = 0;
D("%s %d\n", __func__, en);
mutex_lock(&mic_lock);
if (!!en)
new_state++;
else
new_state--;
if (new_state == 1 && old_state == 0)
{
gpio_set_value(HTCLEO_AUD_2V5_EN, 1);
mdelay(60);
}
else if (new_state == 0 && old_state == 1)
{
gpio_set_value(HTCLEO_AUD_2V5_EN, 0);
}
else
{
D("%s: do nothing %d %d\n", __func__, old_state, new_state);
}
old_state = new_state;
mutex_unlock(&mic_lock);
}
void htcleo_analog_init(void)
{
D("%s\n", __func__);
/* stereo pmic init */
pmic_spkr_set_gain(LEFT_SPKR, SPKR_GAIN_PLUS12DB);
pmic_spkr_set_gain(RIGHT_SPKR, SPKR_GAIN_PLUS12DB);
pmic_spkr_en_right_chan(OFF_CMD);
pmic_spkr_en_left_chan(OFF_CMD);
pmic_spkr_add_right_left_chan(OFF_CMD);
pmic_spkr_en_stereo(OFF_CMD);
pmic_spkr_select_usb_with_hpf_20hz(OFF_CMD);
pmic_spkr_bypass_mux(OFF_CMD);
pmic_spkr_en_hpf(OFF_CMD);
pmic_spkr_en_sink_curr_from_ref_volt_cir(OFF_CMD);
pmic_spkr_set_mux_hpf_corner_freq(SPKR_FREQ_0_76KHZ);
pmic_mic_set_volt(MIC_VOLT_1_80V);
gpio_request(HTCLEO_AUD_JACKHP_EN, "aud_jackhp_en");
gpio_request(HTCLEO_BT_PCM_OUT, "bt_pcm_out");
gpio_direction_output(HTCLEO_AUD_JACKHP_EN, 0);
mutex_lock(&bt_sco_lock);
config_gpio_table(bt_sco_disable, ARRAY_SIZE(bt_sco_disable));
gpio_direction_output(HTCLEO_BT_PCM_OUT, 0);
mutex_unlock(&bt_sco_lock);
}
int htcleo_get_rx_vol(uint8_t hw, int level)
{
int vol;
if (level > 100)
level = 100;
else if (level < 0)
level = 0;
// TODO: is it correct?
struct q6_hw_info *info;
info = &q6_audio_hw[hw];
vol = info->min_gain + ((info->max_gain - info->min_gain) * level) / 100;
D("%s %d\n", __func__, vol);
return vol;
}
static struct qsd_acoustic_ops acoustic =
{
.enable_mic_bias = htcleo_mic_enable,
};
static struct q6audio_analog_ops ops =
{
.init = htcleo_analog_init,
.speaker_enable = htcleo_speaker_enable,
.headset_enable = htcleo_headset_enable,
.receiver_enable = htcleo_receiver_enable,
.bt_sco_enable = htcleo_bt_sco_enable,
.int_mic_enable = htcleo_mic_enable,
.ext_mic_enable = htcleo_mic_enable,
.get_rx_vol = htcleo_get_rx_vol,
};
void __init htcleo_audio_init(void)
{
mutex_init(&mic_lock);
mutex_init(&bt_sco_lock);
q6audio_register_analog_ops(&ops);
acoustic_register_ops(&acoustic);
// q6audio_set_acdb_file("default_PMIC.acdb");
}
// END OF FILE

View File

@ -1,351 +0,0 @@
/* board-htcleo-hds.c
*
* Copyright (C) 2010 Cotulla
*
* 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/delay.h>
#include <linux/earlysuspend.h>
#include <linux/hrtimer.h>
#include <linux/i2c.h>
#include <linux/irq.h>
#include <linux/gpio.h>
#include <linux/input.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <asm/gpio.h>
#include <mach/htc_35mm_jack.h>
#include "board-htcleo.h"
#include "gpio_chip.h"
int microp_get_remote_adc(uint32_t *val);
int microp_set_adc_req(uint8_t value, int enable);
static int headset_has_mic(void);
static int enable_headset_plug_event(void);
static int enable_key_event(void);
static int disable_key_event(void);
static struct h35mm_platform_data htcleo_h35mm_data =
{
.plug_event_enable = enable_headset_plug_event,
.headset_has_mic = headset_has_mic,
.key_event_enable = enable_key_event,
.key_event_disable = disable_key_event,
};
static struct platform_device htcleo_h35mm =
{
.name = "htc_headset",
.id = -1,
.dev =
{
.platform_data = &htcleo_h35mm_data,
},
};
/////////////////////////////////////////////////////////////////////////////////////////////
struct hds_data
{
int inited;
int gpio_mic;
int gpio_det;
int irq_mic;
int irq_det;
int headset_is_in;
int is_hpin_pin_stable;
int last_pressed_key;
struct work_struct work_det;
struct work_struct work_mic;
struct delayed_work hpin_debounce_work;
};
static struct hds_data hds;
/////////////////////////////////////////////////////////////////////////////////////////////
static int headset_detect_mic(void)
{
return !gpio_get_value(hds.gpio_mic);
}
static int headset_is_in(void)
{
return !gpio_get_value(hds.gpio_det);
}
static int get_remote_keycode(int *keycode)
{
uint32_t val;
uint32_t btn = 0;
microp_set_adc_req(1, 1);
if (microp_get_remote_adc(&val))
{
// failed. who know why? ignore
*keycode = 0;
return 1;
}
if((val >= 0) && (val <= 33))
{
btn = 1;
}
else if((val >= 38) && (val <= 82))
{
btn = 2;
}
else if((val >= 95) && (val <= 200))
{
btn = 3;
}
else if(val > 200)
{
// check previous key
if (hds.last_pressed_key)
{
*keycode = hds.last_pressed_key | 0x80;
hds.last_pressed_key = 0;
return 0;
}
*keycode = 0;
return 1;
}
hds.last_pressed_key = btn;
*keycode = btn;
return 0;
}
static int headset_has_mic(void)
{
int mic1 = -1;
int mic2 = -1;
int count = 0;
mic2 = headset_detect_mic();
/* debounce the detection wait until 2 consecutive read are equal */
while ((mic1 != mic2) && (count < 10))
{
mic1 = mic2;
msleep(600);
mic2 = headset_detect_mic();
count++;
}
printk("%s: microphone (%d) %s\n", __func__, count, mic1 ? "present" : "not present");
return mic1;
}
static int enable_headset_plug_event(void)
{
uint16_t stat;
enable_irq(hds.irq_det);
// see if headset state has changed
stat = headset_is_in();
printk("headsetisin: old %d new %d\n", hds.headset_is_in, stat);
if (hds.headset_is_in != stat)
{
hds.headset_is_in = stat;
printk("Headset state changed\n");
htc_35mm_jack_plug_event(stat, &hds.is_hpin_pin_stable);
}
return 1;
}
static int enable_key_event(void)
{
printk("enable_key_event\n");
enable_irq(hds.irq_mic);
return 0;
}
static int disable_key_event(void)
{
printk("disable_key_event\n");
disable_irq(hds.irq_mic);
return 0;
}
static void hpin_debounce_do_work(struct work_struct *work)
{
int insert = 0;
insert = headset_is_in();
printk("debonce new %d old %d\n", insert, hds.headset_is_in);
if (insert != hds.headset_is_in)
{
// clear keypress state
hds.last_pressed_key = 0;
hds.headset_is_in = insert;
printk("headset %s\n", insert ? "inserted" : "removed");
htc_35mm_jack_plug_event(hds.headset_is_in, &hds.is_hpin_pin_stable);
}
}
static void det_intr_work_func(struct work_struct *work)
{
int value1;
printk("det_intr_work_func\n");
hds.is_hpin_pin_stable = 0;
// TODO:
// wake_lock_timeout(&microp_i2c_wakelock, 3 * HZ);
if (!hds.headset_is_in)
schedule_delayed_work(&hds.hpin_debounce_work, msecs_to_jiffies(500));
else
schedule_delayed_work(&hds.hpin_debounce_work, msecs_to_jiffies(300));
}
static void mic_intr_work_func(struct work_struct *work)
{
int keycode = 0;
int value1;
printk("mic_intr_work_func\n");
if ((get_remote_keycode(&keycode) == 0) && (hds.is_hpin_pin_stable))
{
printk("keycode %d\n", keycode);
htc_35mm_key_event(keycode, &hds.is_hpin_pin_stable);
}
}
static irqreturn_t detect_irq_handler(int irq, void *dev_id)
{
int value1, value2;
int retry_limit = 10;
do
{
value1 = gpio_get_value(hds.gpio_det);
set_irq_type(hds.irq_det, value1 ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
value2 = gpio_get_value(hds.gpio_det);
} while (value1 != value2 && retry_limit-- > 0);
schedule_work(&hds.work_det);
return IRQ_HANDLED;
}
static irqreturn_t mic_irq_handler(int irq, void *dev_id)
{
int value1, value2;
int retry_limit = 10;
do
{
value1 = gpio_get_value(hds.gpio_mic);
set_irq_type(hds.irq_mic, value1 ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
value2 = gpio_get_value(hds.gpio_mic);
} while (value1 != value2 && retry_limit-- > 0);
schedule_work(&hds.work_mic);
return IRQ_HANDLED;
}
/////////////////////////////////////////////////////////////////////////////////////////////
static int htcleo_hds_probe(struct platform_device *pdev)
{
int rc = 0;
printk("htcleo_hds_probe()\n");
// allow run it only once
if (hds.inited != 0)
{
return -1;
}
hds.last_pressed_key = 0;
hds.inited = 1;
hds.gpio_mic = HTCLEO_GPIO_HDS_MIC;
hds.gpio_det = HTCLEO_GPIO_HDS_DET;
hds.irq_mic = gpio_to_irq(hds.gpio_mic);
hds.irq_det = gpio_to_irq(hds.gpio_det);
gpio_request(hds.gpio_det, "hds_detect");
gpio_request(hds.gpio_mic, "hds_mic");
gpio_direction_input(hds.gpio_det);
gpio_direction_input(hds.gpio_mic);
hds.headset_is_in = 0;
hds.is_hpin_pin_stable = 1;
INIT_WORK(&hds.work_det, det_intr_work_func);
INIT_WORK(&hds.work_mic, mic_intr_work_func);
INIT_DELAYED_WORK(&hds.hpin_debounce_work, hpin_debounce_do_work);
rc = request_irq(hds.irq_det, detect_irq_handler, IRQF_DISABLED | IRQF_TRIGGER_LOW, "hds_detect_intr", 0);
rc = request_irq(hds.irq_mic, mic_irq_handler, IRQF_DISABLED | IRQF_TRIGGER_LOW, "hds_mic_intr", 0);
disable_irq(hds.irq_mic);
platform_device_register(&htcleo_h35mm);
return rc;
}
static int htcleo_hds_remove(struct platform_device *dev)
{
platform_device_unregister(&htcleo_h35mm);
free_irq(hds.irq_det, 0);
free_irq(hds.irq_mic, 0);
gpio_free(hds.gpio_det);
gpio_free(hds.gpio_mic);
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////
static struct platform_driver htcleo_hds_driver =
{
.probe = htcleo_hds_probe,
.remove = htcleo_hds_remove,
.driver =
{
.name = "htcleo_hds",
.owner = THIS_MODULE,
},
};
static int __init htcleo_hds_init(void)
{
return platform_driver_register(&htcleo_hds_driver);
}
static void __exit htcleo_hds_exit(void)
{
platform_driver_unregister(&htcleo_hds_driver);
}
module_init(htcleo_hds_init);
module_exit(htcleo_hds_exit);
MODULE_AUTHOR("Cotulla");
MODULE_DESCRIPTION("HTC LEO headset driver");
MODULE_LICENSE("GPL");

View File

@ -58,7 +58,6 @@ void __init htcleo_microp_init(void);
#endif
extern int __init htcleo_init_mmc(unsigned debug_uart);
extern void __init htcleo_audio_init(void);
///////////////////////////////////////////////////////////////////////
// SPI
@ -741,7 +740,6 @@ static void __init htcleo_init(void)
platform_device_register(&htcleo_timed_gpios);
htcleo_bt_init();
htcleo_audio_init();
#ifdef CONFIG_USB_ANDROID
msm_hsusb_set_vbus_state(htcleo_get_vbus_state());

View File

@ -33,8 +33,7 @@ struct audio_client {
int dsp_buf; /* next buffer the DSP will touch */
int running;
int session;
int open_done;
int open_status;
wait_queue_head_t wait;
struct dal_client *client;
@ -92,7 +91,6 @@ int q6audio_set_tx_mute(int mute);
int q6audio_reinit_acdb(char* filename);
int q6audio_update_acdb(uint32_t id_src, uint32_t id_dst);
int q6audio_set_rx_volume(int level);
int q6audio_set_rx_mute(int mute);
int q6audio_set_stream_volume(struct audio_client *ac, int vol);
struct q6audio_analog_ops {

View File

@ -1,15 +1,11 @@
obj-y += dal.o
ifndef CONFIG_ARCH_HTCLEO
obj-y += q6audio_htcleo.o
else
obj-y += q6audio.o
endif
obj-y += pcm_out.o
obj-y += pcm_in.o
obj-y += mp3.o
obj-y += routing.o
#obj-y += routing.o
obj-y += audio_ctl.o
obj-y += msm_q6vdec.o
obj-y += msm_q6venc.o
obj-y += aac_in.o
obj-y += qcelp_in.o
#obj-y += aac_in.o
#obj-y += qcelp_in.o

View File

@ -1,217 +0,0 @@
/* arch/arm/mach-msm/qdsp6/aac_in.c
*
* Copyright (C) 2009 Google, Inc.
* Copyright (C) 2009 HTC Corporation
*
* 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/fs.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/msm_audio.h>
#include <mach/msm_qdsp6_audio.h>
#define BUFSZ (4096)
#define DMASZ (BUFSZ * 2)
#if 0
#define TRACE(x...) pr_info("Q6: "x)
#else
#define TRACE(x...) do{}while(0)
#endif
static DEFINE_MUTEX(aac_in_lock);
static int aac_in_opened = 0;
static struct aac_format *af;
void audio_client_dump(struct audio_client *ac);
static long aac_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int rc = 0;
switch (cmd) {
case AUDIO_SET_VOLUME:
break;
case AUDIO_GET_STATS: {
struct msm_audio_stats stats;
memset(&stats, 0, sizeof(stats));
if (copy_to_user((void*) arg, &stats, sizeof(stats)))
return -EFAULT;
return 0;
}
case AUDIO_START: {
uint32_t acdb_id;
rc = 0;
if (arg == 0) {
acdb_id = 0;
} else if (copy_from_user(&acdb_id,
(void*) arg, sizeof(acdb_id))) {
rc = -EFAULT;
break;
}
mutex_lock(&aac_in_lock);
if (file->private_data) {
rc = -EBUSY;
} else {
file->private_data = q6audio_open_aac(
BUFSZ, 48000, AUDIO_FLAG_READ, af, acdb_id);
if (!file->private_data)
rc = -ENOMEM;
}
mutex_unlock(&aac_in_lock);
break;
}
case AUDIO_STOP:
break;
case AUDIO_FLUSH:
break;
case AUDIO_SET_CONFIG: {
struct msm_audio_config config;
if (copy_from_user(&config, (void*) arg, sizeof(config))) {
rc = -EFAULT;
break;
}
if (config.sample_rate != 48000)
pr_info("only 48KHz AAC encode supported\n");
af->channel_config = config.channel_count;
break;
}
case AUDIO_GET_CONFIG: {
struct msm_audio_config config;
config.buffer_size = BUFSZ;
config.buffer_count = 2;
config.sample_rate = 48000;
config.channel_count = af->channel_config;
config.unused[0] = 0;
config.unused[1] = 0;
config.unused[2] = 0;
if (copy_to_user((void*) arg, &config, sizeof(config))) {
rc = -EFAULT;
}
break;
}
default:
rc = -EINVAL;
}
return rc;
}
static int aac_in_open(struct inode *inode, struct file *file)
{
int rc;
pr_info("aac_in: open\n");
mutex_lock(&aac_in_lock);
if (aac_in_opened) {
pr_err("aac_in: busy\n");
rc = -EBUSY;
} else {
af = kzalloc(sizeof(*af), GFP_KERNEL);
memset(af, 0, sizeof(struct aac_format));
af->sample_rate = 3; /* 48000 */
af->channel_config = 1;
af->block_formats = AUDIO_AAC_FORMAT_ADTS;
af->audio_object_type = 2; /* CAD to ADSP format */
af->bit_rate = 192000;
aac_in_opened = 1;
rc = 0;
}
mutex_unlock(&aac_in_lock);
return rc;
}
static ssize_t aac_in_read(struct file *file, char __user *buf,
size_t count, loff_t *pos)
{
struct audio_client *ac;
struct audio_buffer *ab;
const char __user *start = buf;
int xfer, res = 0;
mutex_lock(&aac_in_lock);
ac = file->private_data;
if (!ac) {
res = -ENODEV;
goto fail;
}
while (count > 0) {
ab = ac->buf + ac->cpu_buf;
if (ab->used)
if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
audio_client_dump(ac);
pr_err("aac_read: timeout. dsp dead?\n");
BUG();
}
xfer = count;
if (xfer > ab->size)
xfer = ab->size;
if (copy_to_user(buf, ab->data, xfer)) {
res = -EFAULT;
goto fail;
}
buf += xfer;
count -= xfer;
ab->used = 1;
q6audio_read(ac, ab);
ac->cpu_buf ^= 1;
}
fail:
res = buf - start;
mutex_unlock(&aac_in_lock);
return res;
}
static int aac_in_release(struct inode *inode, struct file *file)
{
int rc = 0;
pr_info("aac_in: release\n");
mutex_lock(&aac_in_lock);
if (file->private_data)
rc = q6audio_close(file->private_data);
kfree(af);
aac_in_opened = 0;
mutex_unlock(&aac_in_lock);
return rc;
}
static struct file_operations aac_in_fops = {
.owner = THIS_MODULE,
.open = aac_in_open,
.read = aac_in_read,
.release = aac_in_release,
.unlocked_ioctl = aac_in_ioctl,
};
struct miscdevice aac_in_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "msm_aac_in",
.fops = &aac_in_fops,
};
static int __init aac_in_init(void) {
return misc_register(&aac_in_misc);
}
device_initcall(aac_in_init);

View File

@ -25,20 +25,10 @@
#define BUFSZ (0)
#if 1
#define AUDIO_INFO(x...) pr_info("Audio: "x)
#else
#define AUDIO_INFO(x...) do{}while(0)
#endif
// from board-htcleo-accoustic
extern int set_aux_gain(int level);
static DEFINE_MUTEX(voice_lock);
static DEFINE_MUTEX(fm_lock);
static int voice_started;
static int fm_started;
int global_now_phone_call;
static struct audio_client *voc_tx_clnt;
static struct audio_client *voc_rx_clnt;
@ -48,7 +38,6 @@ static int q6_voice_start(uint32_t rx_acdb_id, uint32_t tx_acdb_id)
{
int rc = 0;
printk("VOICE START (%d %d)\n", rx_acdb_id, tx_acdb_id);
mutex_lock(&voice_lock);
if (voice_started) {
@ -56,7 +45,6 @@ static int q6_voice_start(uint32_t rx_acdb_id, uint32_t tx_acdb_id)
rc = -EBUSY;
goto done;
}
global_now_phone_call = 1;
voc_rx_clnt = q6voice_open(AUDIO_FLAG_WRITE, rx_acdb_id);
if (!voc_rx_clnt) {
@ -81,9 +69,7 @@ done:
static int q6_voice_stop(void)
{
mutex_lock(&voice_lock);
global_now_phone_call = 0;
if (voice_started)
{
if (voice_started) {
q6voice_close(voc_tx_clnt);
q6voice_close(voc_rx_clnt);
voice_started = 0;
@ -141,12 +127,9 @@ static int q6_ioctl(struct inode *inode, struct file *file,
uint32_t id[2];
char filename[64];
// printk("$$$ AUDIO IOCTL=%08X\n", cmd);
switch (cmd) {
case AUDIO_SWITCH_DEVICE:
rc = copy_from_user(&id, (void *)arg, sizeof(id));
AUDIO_INFO("SWITCH DEVICE %d, acdb %d\n", id[0], id[1]);
if (!rc)
rc = q6audio_do_routing(id[0], id[1]);
break;
@ -173,19 +156,15 @@ static int q6_ioctl(struct inode *inode, struct file *file,
rc = -EFAULT;
break;
}
AUDIO_INFO("voice: start\n");
rc = q6_voice_start(id[0], id[1]);
break;
case AUDIO_STOP_VOICE:
AUDIO_INFO("voice: stop\n");
rc = q6_voice_stop();
break;
case AUDIO_START_FM:
AUDIO_INFO("FM: start\n");
rc = q6_fm_start();
break;
case AUDIO_STOP_FM:
AUDIO_INFO("FM: stop\n");
rc = q6_fm_stop();
break;
case AUDIO_REINIT_ACDB:
@ -199,25 +178,9 @@ static int q6_ioctl(struct inode *inode, struct file *file,
rc = -EFAULT;
break;
}
AUDIO_INFO("audio_ctl: enable aux loopback %d\n", enable);
rc = enable_aux_loopback(enable);
break;
}
case AUDIO_SET_AUXPGA_GAIN: {
int level;
if (copy_from_user(&level, (void*) arg, sizeof(level))) {
rc = -EFAULT;
break;
}
AUDIO_INFO("audio_ctl: set aux gain %d\n", level);
rc = set_aux_gain(level);
break;
}
case AUDIO_SET_RX_MUTE:
rc = copy_from_user(&n, (void *)arg, sizeof(n));
if (!rc)
rc = q6audio_set_rx_mute(n);
break;
default:
rc = -EINVAL;
}

View File

@ -31,20 +31,20 @@
#define DAL_TRACE 0
struct dal_hdr {
uint32_t length:16; /* message length (header inclusive) */
uint32_t version:8; /* DAL protocol version */
uint32_t length:16; /* message length (header inclusive) */
uint32_t version:8; /* DAL protocol version */
uint32_t priority:7;
uint32_t async:1;
uint32_t ddi:16; /* DDI method number */
uint32_t prototype:8; /* DDI serialization format */
uint32_t msgid:8; /* message id (DDI, ATTACH, DETACH, ...) */
uint32_t prototype:8; /* DDI serialization format */
uint32_t msgid:8; /* message id (DDI, ATTACH, DETACH, ...) */
void *from;
void *to;
} __attribute__((packed));
#define TRACE_DATA_MAX 128
#define TRACE_LOG_MAX 32
#define TRACE_LOG_MASK (TRACE_LOG_MAX - 1)
#define TRACE_DATA_MAX 128
#define TRACE_LOG_MAX 32
#define TRACE_LOG_MASK (TRACE_LOG_MAX - 1)
struct dal_trace {
unsigned timestamp;
@ -129,17 +129,17 @@ void dal_trace(struct dal_client *c)
if (c->tr_log)
return;
c->tr_log = kzalloc(sizeof(struct dal_trace) * TRACE_LOG_MAX,
GFP_KERNEL);
GFP_KERNEL);
}
void dal_trace_print(struct dal_hdr *hdr, unsigned *data, int len, unsigned when)
{
int i;
printk("DAL %08x -> %08x L=%03x A=%d D=%04x P=%02x M=%02x T=%d",
(unsigned) hdr->from, (unsigned) hdr->to,
hdr->length, hdr->async,
hdr->ddi, hdr->prototype, hdr->msgid,
when);
(unsigned) hdr->from, (unsigned) hdr->to,
hdr->length, hdr->async,
hdr->ddi, hdr->prototype, hdr->msgid,
when);
len /= 4;
for (i = 0; i < len; i++) {
if (!(i & 7))
@ -226,7 +226,7 @@ again:
}
}
pr_err("$$$ receiving unknown message len = %d $$$\n",
dch->count);
dch->count);
dch->active = 0;
dch->ptr = dch->data;
}
@ -262,7 +262,8 @@ check_data:
if (client->event)
client->event(dch->ptr, len, client->cookie);
else
pr_err("dal: client %p has no event handler\n", client);
pr_err("dal: client %p has no event handler\n",
client);
goto again;
}
@ -359,21 +360,20 @@ int dal_call_raw(struct dal_client *client,
smd_write(dch->sch, data, data_len);
spin_unlock_irqrestore(&dch->lock, flags);
if (!wait_event_timeout(client->wait, (client->status != -EBUSY), 5*HZ))
{
if (!wait_event_timeout(client->wait, (client->status != -EBUSY), 5*HZ)) {
dal_trace_dump(client);
pr_err("dal: call timed out. dsp is probably dead.\n");
dal_trace_print(hdr, data, data_len, 0);
// BUG();
BUG();
}
return client->status;
}
int dal_call(struct dal_client *client,
unsigned ddi, unsigned prototype,
void *data, int data_len,
void *reply, int reply_max)
unsigned ddi, unsigned prototype,
void *data, int data_len,
void *reply, int reply_max)
{
struct dal_hdr hdr;
int r;
@ -394,11 +394,11 @@ int dal_call(struct dal_client *client,
mutex_lock(&client->write_lock);
r = dal_call_raw(client, &hdr, data, data_len, reply, reply_max);
mutex_unlock(&client->write_lock);
#if 1
#if 0
if ((r > 3) && (((uint32_t*) reply)[0] == 0)) {
// pr_info("dal call OK\n");
pr_info("dal call OK\n");
} else {
pr_info("dal call %d %d ERROR\n", ddi, prototype);
pr_info("dal call ERROR\n");
}
#endif
return r;
@ -415,67 +415,8 @@ struct dal_reply_attach {
char name[64];
};
struct dal_client *dal_attach_ex(uint32_t device_id, const char *aname, const char *name, dal_event_func_t func, void *cookie)
{
struct dal_hdr hdr;
struct dal_msg_attach msg;
struct dal_reply_attach reply;
struct dal_channel *dch;
struct dal_client *client;
unsigned long flags;
int r;
dch = dal_open_channel(name);
if (!dch)
return 0;
client = kzalloc(sizeof(*client), GFP_KERNEL);
if (!client)
return 0;
client->dch = dch;
client->event = func;
client->cookie = cookie;
mutex_init(&client->write_lock);
spin_lock_init(&client->tr_lock);
init_waitqueue_head(&client->wait);
spin_lock_irqsave(&dch->lock, flags);
list_add(&client->list, &dch->clients);
spin_unlock_irqrestore(&dch->lock, flags);
memset(&hdr, 0, sizeof(hdr));
memset(&msg, 0, sizeof(msg));
hdr.length = sizeof(hdr) + sizeof(msg);
hdr.version = DAL_VERSION;
hdr.msgid = DAL_MSGID_ATTACH;
hdr.from = client;
msg.device_id = device_id;
if (aname)
strcpy(msg.attach, aname);
r = dal_call_raw(client, &hdr, &msg, sizeof(msg),
&reply, sizeof(reply));
if ((r == sizeof(reply)) && (reply.status == 0)) {
reply.name[63] = 0;
pr_info("dal_attach: status = %d, name = '%s'\n",
reply.status, reply.name);
return client;
}
pr_err("dal_attach: failure\n");
dal_detach(client);
return 0;
}
struct dal_client *dal_attach(uint32_t device_id, const char *name,
dal_event_func_t func, void *cookie)
dal_event_func_t func, void *cookie)
{
struct dal_hdr hdr;
struct dal_msg_attach msg;
@ -548,7 +489,7 @@ int dal_detach(struct dal_client *client)
data = (uint32_t) client;
dal_call_raw(client, &hdr, &data, sizeof(data),
&data, sizeof(data));
&data, sizeof(data));
}
dch = client->dch;
@ -602,8 +543,7 @@ int dal_call_f1(struct dal_client *client, uint32_t ddi, uint32_t arg1, uint32_t
int dal_call_f5(struct dal_client *client, uint32_t ddi, void *ibuf, uint32_t ilen)
{
// uint32_t tmp[128];
uint32_t tmp[DAL_DATA_MAX];
uint32_t tmp[128];
int res;
int param_idx = 0;
@ -623,55 +563,23 @@ int dal_call_f5(struct dal_client *client, uint32_t ddi, void *ibuf, uint32_t il
return res;
}
int dal_call_f6(struct dal_client *client, uint32_t ddi, uint32_t cmd, void *ibuf, uint32_t ilen)
{
uint32_t tmp[DAL_DATA_MAX];
int res;
int param_idx = 0;
if (ilen + 4 > DAL_DATA_MAX)
return -EINVAL;
tmp[param_idx] = cmd;
param_idx++;
tmp[param_idx] = ilen;
param_idx++;
memcpy(&tmp[param_idx], ibuf, ilen);
param_idx += DIV_ROUND_UP(ilen, 4);
res = dal_call(client, ddi, 6, tmp, param_idx * 4, tmp, sizeof(tmp));
if (res >= 4)
return (int) tmp[0];
return res;
}
int dal_call_f8(struct dal_client *client, uint32_t ddi, void *ibuf, uint32_t ilen, void *obuf, uint32_t olen)
int dal_call_f9(struct dal_client *client, uint32_t ddi, void *obuf,
uint32_t olen)
{
uint32_t tmp[128];
int res;
int param_idx = 0;
if (ilen + 8 > DAL_DATA_MAX)
if (olen > sizeof(tmp) - 8)
return -EINVAL;
tmp[0] = olen;
tmp[param_idx] = ilen;
param_idx++;
memcpy(&tmp[param_idx], ibuf, ilen);
param_idx += DIV_ROUND_UP(ilen, 4);
tmp[param_idx++] = olen;
res = dal_call(client, ddi, 8, tmp, param_idx * 4, tmp, sizeof(tmp));
res = dal_call(client, ddi, 9, tmp, sizeof(uint32_t), tmp,
sizeof(tmp));
if (res >= 4)
{
res = (int)tmp[0];
}
if (!res)
{
if (!res) {
if (tmp[1] > olen)
return -EIO;
memcpy(obuf, &tmp[2], tmp[1]);
@ -679,37 +587,9 @@ int dal_call_f8(struct dal_client *client, uint32_t ddi, void *ibuf, uint32_t il
return res;
}
int dal_call_f9(struct dal_client *client, uint32_t ddi, void *obuf, uint32_t olen)
{
uint32_t tmp[128];
int res;
int param_idx = 0;
if (olen + 8 > DAL_DATA_MAX)
return -EINVAL;
tmp[param_idx++] = olen;
res = dal_call(client, ddi, 9, tmp, param_idx * 4, tmp, sizeof(tmp));
if (res >= 4)
{
res = (int)tmp[0];
}
if (!res)
{
if (tmp[1] > olen)
return -EIO;
memcpy(obuf, &tmp[2], tmp[1]);
}
return res;
}
int dal_call_f13(struct dal_client *client, uint32_t ddi, void *ibuf1,
uint32_t ilen1, void *ibuf2, uint32_t ilen2, void *obuf, uint32_t olen)
uint32_t ilen1, void *ibuf2, uint32_t ilen2, void *obuf,
uint32_t olen)
{
uint32_t tmp[128];
int res;
@ -742,5 +622,41 @@ int dal_call_f13(struct dal_client *client, uint32_t ddi, void *ibuf1,
return res;
}
int dal_call_f14(struct dal_client *client, uint32_t ddi, void *ibuf,
uint32_t ilen, void *obuf1, uint32_t olen1, void *obuf2,
uint32_t olen2, uint32_t *oalen2)
{
uint32_t tmp[128];
int res;
int param_idx = 0;
// END OF FILE
if (olen1 + olen2 + 8 > DAL_DATA_MAX ||
ilen + 12 > DAL_DATA_MAX)
return -EINVAL;
tmp[param_idx] = ilen;
param_idx++;
memcpy(&tmp[param_idx], ibuf, ilen);
param_idx += DIV_ROUND_UP(ilen, 4);
tmp[param_idx++] = olen1;
tmp[param_idx++] = olen2;
res = dal_call(client, ddi, 14, tmp, param_idx * 4, tmp, sizeof(tmp));
if (res >= 4)
res = (int)tmp[0];
if (!res) {
if (tmp[1] > olen1)
return -EIO;
param_idx = DIV_ROUND_UP(tmp[1], 4) + 2;
if (tmp[param_idx] > olen2)
return -EIO;
memcpy(obuf1, &tmp[2], tmp[1]);
memcpy(obuf2, &tmp[param_idx+1], tmp[param_idx]);
*oalen2 = tmp[param_idx];
}
return res;
}

View File

@ -19,12 +19,16 @@
struct dal_client;
struct dal_info {
uint32_t size;
uint32_t version;
char name[32];
};
typedef void (*dal_event_func_t)(void *data, int len, void *cookie);
struct dal_client *dal_attach(uint32_t device_id, const char *name,
dal_event_func_t func, void *cookie);
struct dal_client *dal_attach_ex(uint32_t device_id, const char *aname,
const char *name, dal_event_func_t func, void *cookie);
int dal_detach(struct dal_client *client);
@ -46,16 +50,14 @@ int dal_call_f1(struct dal_client *client, uint32_t ddi,
uint32_t arg1, uint32_t arg2);
int dal_call_f5(struct dal_client *client, uint32_t ddi,
void *ibuf, uint32_t ilen);
int dal_call_f6(struct dal_client *client, uint32_t ddi,
uint32_t cmd, void *ibuf, uint32_t ilen);
int dal_call_f8(struct dal_client *client, uint32_t ddi,
void *ibuf, uint32_t ilen, void *obuf, uint32_t olen);
int dal_call_f9(struct dal_client *client, uint32_t ddi,
int dal_call_f9(struct dal_client *client, uint32_t ddi,
void *obuf, uint32_t olen);
int dal_call_f13(struct dal_client *client, uint32_t ddi, void *ibuf1,
uint32_t ilen1, void *ibuf2, uint32_t ilen2, void *obuf,
uint32_t olen);
int dal_call_f14(struct dal_client *client, uint32_t ddi, void *ibuf,
uint32_t ilen, void *obuf1, uint32_t olen1, void *obuf2,
uint32_t olen2, uint32_t *oalen2);
/* common DAL operations */
enum {

View File

@ -27,11 +27,7 @@
*/
#define ACDB_DAL_DEVICE 0x02000069
#if defined(CONFIG_MACH_HTCLEO)
#define ACDB_DAL_PORT "SMD_DAL00"
#else
#define ACDB_DAL_PORT "SMD_DAL_AM_AUD"
#endif
#define ACDB_DAL_PORT "SMD_DAL_AM_AUD"
#define ACDB_OP_IOCTL DAL_OP_FIRST_DEVICE_API

View File

@ -32,11 +32,7 @@
#include "dal.h"
#define ADIE_DAL_DEVICE 0x02000029
#if defined(CONFIG_MACH_HTCLEO)
#define ADIE_DAL_PORT "SMD_DAL00"
#else
#define ADIE_DAL_PORT "SMD_DAL_AM_AUD"
#endif
#define ADIE_DAL_PORT "SMD_DAL_AM_AUD"
enum {
ADIE_OP_GET_NUM_PATHS = DAL_OP_FIRST_DEVICE_API,

View File

@ -2,15 +2,15 @@
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora Forum nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora Forum nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@ -30,29 +30,15 @@
#define __DAL_AUDIO_H__
#include "dal_audio_format.h"
#include "dal.h"
#include <mach/msm_qdsp6_audio.h>
#define AUDIO_DAL_DEVICE 0x02000028
#define AUDIO_DAL_PORT "DSP_DAL_AQ_AUD"
enum
{
#if defined(CONFIG_MACH_HTCLEO)
AUDIO_OP_OPEN = DAL_OP_FIRST_DEVICE_API,
AUDIO_OP_WRITE,
AUDIO_OP_READ,
AUDIO_OP_IOCTL,
AUDIO_OP_INIT,
AUDIO_OP_CLOSE,
AUDIO_OP_FLUSH
#else
enum {
AUDIO_OP_CONTROL = DAL_OP_FIRST_DEVICE_API,
AUDIO_OP_DATA,
AUDIO_OP_INIT,
#endif
};
};
/* ---- common audio structures ---- */
@ -60,37 +46,37 @@ enum
/* buffer is a synchronization point or key frame, meaning no data */
/* before it in the stream is required in order to render the stream */
/* from this point onward. */
#define ADSP_AUDIO_BUFFER_FLAG_SYNC_POINT 0x01
#define ADSP_AUDIO_BUFFER_FLAG_SYNC_POINT 0x01
/* This flag, if set, indicates that the buffer object is using valid */
/* physical address used to store the media data */
#define ADSP_AUDIO_BUFFER_FLAG_PHYS_ADDR 0x04
#define ADSP_AUDIO_BUFFER_FLAG_PHYS_ADDR 0x04
/* This flag, if set, indicates that a media start timestamp has been */
/* set for a buffer. */
#define ADSP_AUDIO_BUFFER_FLAG_START_SET 0x08
#define ADSP_AUDIO_BUFFER_FLAG_START_SET 0x08
/* This flag, if set, indicates that a media stop timestamp has been set */
/* for a buffer. */
#define ADSP_AUDIO_BUFFER_FLAG_STOP_SET 0x10
#define ADSP_AUDIO_BUFFER_FLAG_STOP_SET 0x10
/* This flag, if set, indicates that a preroll timestamp has been set */
/* for a buffer. */
#define ADSP_AUDIO_BUFFER_FLAG_PREROLL_SET 0x20
#define ADSP_AUDIO_BUFFER_FLAG_PREROLL_SET 0x20
/* This flag, if set, indicates that the data in the buffer is a fragment of */
/* a larger block of data, and will be continued by the data in the next */
/* buffer to be delivered. */
#define ADSP_AUDIO_BUFFER_FLAG_CONTINUATION 0x40
#define ADSP_AUDIO_BUFFER_FLAG_CONTINUATION 0x40
struct adsp_audio_buffer {
u32 addr; /* Physical Address of buffer */
u32 max_size; /* Maximum size of buffer */
u32 addr; /* Physical Address of buffer */
u32 max_size; /* Maximum size of buffer */
u32 actual_size; /* Actual size of valid data in the buffer */
u32 offset; /* Offset to the first valid byte */
u32 flags; /* ADSP_AUDIO_BUFFER_FLAGs that has been set */
s64 start; /* Start timestamp, if any */
s64 stop; /* Stop timestamp, if any */
u32 offset; /* Offset to the first valid byte */
u32 flags; /* ADSP_AUDIO_BUFFER_FLAGs that has been set */
s64 start; /* Start timestamp, if any */
s64 stop; /* Stop timestamp, if any */
s64 preroll; /* Preroll timestamp, if any */
} __attribute__ ((packed));
@ -100,11 +86,10 @@ struct adsp_audio_buffer {
/* Command/event response types */
#define ADSP_AUDIO_RESPONSE_COMMAND 0
#define ADSP_AUDIO_RESPONSE_ASYNC 1
#define ADSP_AUDIO_RESPONSE_ASYNC 1
#if !defined(CONFIG_MACH_HTCLEO)
struct adsp_command_hdr {
u32 size; /* sizeof(cmd) - sizeof(u32) */
u32 size; /* sizeof(cmd) - sizeof(u32) */
u32 dst;
u32 src;
@ -119,21 +104,13 @@ struct adsp_command_hdr {
u32 padding;
} __attribute__ ((packed));
#else
struct adsp_command_hdr
{
u32 context;
u32 data;
} __attribute__ ((packed));
#endif
#define AUDIO_DOMAIN_APP 0
#define AUDIO_DOMAIN_MODEM 1
#define AUDIO_DOMAIN_MODEM 1
#define AUDIO_DOMAIN_DSP 2
#define AUDIO_SERVICE_AUDIO 0
#define AUDIO_SERVICE_VIDEO 1 /* really? */
#define AUDIO_SERVICE_AUDIO 0
#define AUDIO_SERVICE_VIDEO 1 /* really? */
/* adsp audio addresses are (byte order) domain, service, major, minor */
//#define AUDIO_ADDR(maj,min) ( (((maj) & 0xff) << 16) | (((min) & 0xff) << 24) | (1) )
@ -147,17 +124,17 @@ struct adsp_command_hdr
#define ADSP_AUDIO_ENC_ENHANCED_AAC_PLUS_MODE 2
struct adsp_audio_aac_enc_cfg {
u32 bit_rate; /* bits per second */
u32 encoder_mode; /* ADSP_AUDIO_ENC_* */
u32 bit_rate; /* bits per second */
u32 encoder_mode; /* ADSP_AUDIO_ENC_* */
} __attribute__ ((packed));
#define ADSP_AUDIO_ENC_SBC_ALLOCATION_METHOD_LOUNDNESS 0
#define ADSP_AUDIO_ENC_SBC_ALLOCATION_METHOD_SNR 1
#define ADSP_AUDIO_ENC_SBC_ALLOCATION_METHOD_LOUNDNESS 0
#define ADSP_AUDIO_ENC_SBC_ALLOCATION_METHOD_SNR 1
#define ADSP_AUDIO_ENC_SBC_CHANNEL_MODE_MONO 1
#define ADSP_AUDIO_ENC_SBC_CHANNEL_MODE_STEREO 2
#define ADSP_AUDIO_ENC_SBC_CHANNEL_MODE_DUAL 8
#define ADSP_AUDIO_ENC_SBC_CHANNEL_MODE_JOINT_STEREO 9
#define ADSP_AUDIO_ENC_SBC_CHANNEL_MODE_MONO 1
#define ADSP_AUDIO_ENC_SBC_CHANNEL_MODE_STEREO 2
#define ADSP_AUDIO_ENC_SBC_CHANNEL_MODE_DUAL 8
#define ADSP_AUDIO_ENC_SBC_CHANNEL_MODE_JOINT_STEREO 9
struct adsp_audio_sbc_encoder_cfg {
u32 num_subbands;
@ -168,36 +145,36 @@ struct adsp_audio_sbc_encoder_cfg {
} __attribute__ ((packed));
/* AMR NB encoder modes */
#define ADSP_AUDIO_AMR_MR475 0
#define ADSP_AUDIO_AMR_MR515 1
#define ADSP_AUDIO_AMR_MMR59 2
#define ADSP_AUDIO_AMR_MMR67 3
#define ADSP_AUDIO_AMR_MMR74 4
#define ADSP_AUDIO_AMR_MMR795 5
#define ADSP_AUDIO_AMR_MMR102 6
#define ADSP_AUDIO_AMR_MMR122 7
#define ADSP_AUDIO_AMR_MR475 0
#define ADSP_AUDIO_AMR_MR515 1
#define ADSP_AUDIO_AMR_MMR59 2
#define ADSP_AUDIO_AMR_MMR67 3
#define ADSP_AUDIO_AMR_MMR74 4
#define ADSP_AUDIO_AMR_MMR795 5
#define ADSP_AUDIO_AMR_MMR102 6
#define ADSP_AUDIO_AMR_MMR122 7
/* The following are valid AMR NB DTX modes */
#define ADSP_AUDIO_AMR_DTX_MODE_OFF 0
#define ADSP_AUDIO_AMR_DTX_MODE_ON_VAD1 1
#define ADSP_AUDIO_AMR_DTX_MODE_ON_VAD2 2
#define ADSP_AUDIO_AMR_DTX_MODE_ON_AUTO 3
#define ADSP_AUDIO_AMR_DTX_MODE_ON_VAD1 1
#define ADSP_AUDIO_AMR_DTX_MODE_ON_VAD2 2
#define ADSP_AUDIO_AMR_DTX_MODE_ON_AUTO 3
/* AMR Encoder configuration */
struct adsp_audio_amr_enc_cfg {
u32 mode; /* ADSP_AUDIO_AMR_MR* */
u32 dtx_mode; /* ADSP_AUDIO_AMR_DTX_MODE* */
u32 enable; /* 1 = enable, 0 = disable */
u32 mode; /* ADSP_AUDIO_AMR_MR* */
u32 dtx_mode; /* ADSP_AUDIO_AMR_DTX_MODE* */
u32 enable; /* 1 = enable, 0 = disable */
} __attribute__ ((packed));
struct adsp_audio_qcelp13k_enc_cfg {
u16 min_rate;
u16 max_rate;
u16 min_rate;
u16 max_rate;
} __attribute__ ((packed));
struct adsp_audio_evrc_enc_cfg {
u16 min_rate;
u16 max_rate;
u16 min_rate;
u16 max_rate;
} __attribute__ ((packed));
union adsp_audio_codec_config {
@ -220,9 +197,8 @@ union adsp_audio_codec_config {
#define ADSP_AUDIO_OPEN_STREAM_MODE_SR_CM_NOTIFY 0x0002
/* This bit, if set, indicates that the sync clock is enabled */
#define ADSP_AUDIO_OPEN_STREAM_MODE_ENABLE_SYNC_CLOCK 0x0004
#define ADSP_AUDIO_OPEN_STREAM_MODE_ENABLE_SYNC_CLOCK 0x0004
#if !defined(CONFIG_MACH_HTCLEO)
struct adsp_open_command {
struct adsp_command_hdr hdr;
@ -238,52 +214,22 @@ struct adsp_open_command {
union adsp_audio_codec_config config;
} __attribute__ ((packed));
/* Opcode to open a device stream session to capture audio */
#define ADSP_AUDIO_IOCTL_CMD_OPEN_READ 0x0108dd79
/* Opcode to open a device stream session to render audio */
#define ADSP_AUDIO_IOCTL_CMD_OPEN_WRITE 0x0108dd7a
/* Opcode to open a device session, must open a device */
#define ADSP_AUDIO_IOCTL_CMD_OPEN_DEVICE 0x0108dd7b
/* Close an existing stream or device */
#define ADSP_AUDIO_IOCTL_CMD_CLOSE 0x0108d8bc
#else
struct adsp_open_command
{
struct adsp_command_hdr hdr;
u32 opcode;
u32 numdev;
u32 dev[4];
u32 stream_context;
u32 format;
u32 pblock;
u32 blocklen;
u32 buf_max_size;
u32 priority;
union adsp_audio_codec_config config;
u32 mode;
} __attribute__ ((packed));
/* --- audio control and stream session ioctls ---- */
/* Opcode to open a device stream session to capture audio */
#define ADSP_AUDIO_OPCODE_OPEN_READ 0x01
#define ADSP_AUDIO_IOCTL_CMD_OPEN_READ 0x0108dd79
/* Opcode to open a device stream session to render audio */
#define ADSP_AUDIO_OPCODE_OPEN_WRITE 0x02
#define ADSP_AUDIO_IOCTL_CMD_OPEN_WRITE 0x0108dd7a
/* Opcode to open a device session, must open a device */
#define ADSP_AUDIO_OPCODE_OPEN_DEV 0x04
#define ADSP_AUDIO_IOCTL_CMD_OPEN_DEVICE 0x0108dd7b
/* Close an existing stream or device */
#define ADSP_AUDIO_IOCTL_CMD_CLOSE 0x0108d8bc
#endif
/* A device switch requires three IOCTL */
/* commands in the following sequence: PREPARE, STANDBY, COMMIT */
@ -320,7 +266,7 @@ struct adsp_device_switch_command {
#define ADSP_PATH_RX 0
#define ADSP_PATH_TX 1
#define ADSP_PATH_BOTH 2
#define ADSP_PATH_BOTH 2
/* These commands will affect a logical device and all its associated */
/* streams. */
@ -405,13 +351,13 @@ struct adsp_buffer_command {
/* Do sample slipping/stuffing on AAC outputs. The payload of */
/* this command is struct adsp_audio_slip_sample_command. */
#define ADSP_AUDIO_IOCTL_CMD_STREAM_SLIPSAMPLE 0x0108d40e
#define ADSP_AUDIO_IOCTL_CMD_STREAM_SLIPSAMPLE 0x0108d40e
/* Set stream volume. */
/* This command has data payload, struct adsp_audio_set_volume_command. */
#define ADSP_AUDIO_IOCTL_CMD_SET_STREAM_VOL 0x0108c0de
/* Set stream stereo volume. This command has data payl oad, */
/* Set stream stereo volume. This command has data payload, */
/* struct adsp_audio_set_stereo_volume_command. */
#define ADSP_AUDIO_IOCTL_SET_STREAM_STEREO_VOL 0x0108dd7c
@ -469,39 +415,20 @@ struct adsp_buffer_command {
/* Set session stereo volume. This command has data payload, */
/* struct adsp_audio_set_stereo_volume_command. */
#define ADSP_AUDIO_IOCTL_SET_SESSION_STEREO_VOL 0x0108df3d
#define ADSP_AUDIO_IOCTL_SET_SESSION_STEREO_VOL 0x0108df3d
/* Set L, R cross channel gain for a session. This command has */
/* data payload, struct adsp_audio_set_x_chan_gain_command. */
#define ADSP_AUDIO_IOCTL_SET_SESSION_XCHAN_GAIN 0x0108df3f
#define ADSP_AUDIO_IOCTL_SET_SESSION_XCHAN_GAIN 0x0108df3f
/* Set Session mute state. */
/* This command has data payload, struct adsp_audio_set_mute_command. */
#define ADSP_AUDIO_IOCTL_SET_SESSION_MUTE 0x0108d8be
#define ADSP_AUDIO_IOCTL_SET_SESSION_MUTE 0x0108d8be
/* Configure Equalizer for a stream. */
/* This command has payload struct adsp_audio_set_equalizer_command. */
#define ADSP_AUDIO_IOCTL_SET_SESSION_EQ_CONFIG 0x0108c0e0
#define ADSP_AUDIO_MAX_EQ_BANDS 12
/* Definition for any one band of Equalizer. */
struct adsp_audio_eq_band {
u16 band_idx;
u32 filter_type;
u32 center_freq_hz;
s32 filter_gain;
s32 q_factor;
} __attribute__ ((packed));
struct adsp_audio_set_equalizer_command {
struct adsp_command_hdr hdr;
u32 enable;
u32 num_bands;
struct adsp_audio_eq_band eq_bands[ADSP_AUDIO_MAX_EQ_BANDS];
} __attribute__ ((packed));
/* Set Audio Video sync information. */
/* This command has data payload, struct adsp_audio_set_av_sync_command. */
#define ADSP_AUDIO_IOCTL_SET_SESSION_AVSYNC 0x0108d1e2
@ -531,34 +458,33 @@ struct adsp_set_mute_command {
/* event id after the IOCTL command has been executed. */
/* This event is generated after a media stream session is opened. */
#define ADSP_AUDIO_EVT_STATUS_OPEN 0x0108c0d6
#define ADSP_AUDIO_EVT_STATUS_OPEN 0x0108c0d6
/* This event is generated after a media stream session is closed. */
#define ADSP_AUDIO_EVT_STATUS_CLOSE 0x0108c0d7
#define ADSP_AUDIO_EVT_STATUS_CLOSE 0x0108c0d7
/* Asyncronous buffer consumption. This event is generated after a */
/* recived buffer is consumed during rendering or filled during */
/* capture opeartion. */
#define ADSP_AUDIO_EVT_STATUS_BUF_DONE 0x0108c0d8
#define ADSP_AUDIO_EVT_STATUS_BUF_DONE 0x0108c0d8
/* This event is generated when rendering operation is starving for */
/* data. In order to avoid audio loss at the end of a plauback, the */
/* client should wait for this event before issuing the close command. */
#define ADSP_AUDIO_EVT_STATUS_BUF_UNDERRUN 0x0108c0d9
#define ADSP_AUDIO_EVT_STATUS_BUF_UNDERRUN 0x0108c0d9
/* This event is generated during capture operation when there are no */
/* buffers available to copy the captured audio data */
#define ADSP_AUDIO_EVT_STATUS_BUF_OVERFLOW 0x0108c0da
#define ADSP_AUDIO_EVT_STATUS_BUF_OVERFLOW 0x0108c0da
/* This asynchronous event is generated as a result of an input */
/* sample rate change and/or channel mode change detected by the */
/* decoder. The event payload data is an array of 2 uint32 */
/* values containing the sample rate in Hz and channel mode. */
#define ADSP_AUDIO_EVT_SR_CM_CHANGE 0x0108d329
#define ADSP_AUDIO_EVT_SR_CM_CHANGE 0x0108d329
struct adsp_event_hdr
{
u32 evt_handle; /* DAL common header */
struct adsp_event_hdr {
u32 evt_handle; /* DAL common header */
u32 evt_cookie;
u32 evt_length;
@ -575,48 +501,17 @@ struct adsp_event_hdr
u32 status;
} __attribute__ ((packed));
#if defined(CONFIG_MACH_HTCLEO)
union adsp_event_data
{
u32 val32;
uint8_t data[32];
} __attribute__ ((packed));
struct adsp_audio_event
{
struct adsp_command_hdr hdr;
u32 session;
u32 event_id;
u32 status;
u32 datalen;
union adsp_event_data data;
} __attribute__ ((packed));
struct adsp_audio_dal_event
{
u32 cb_evt;
u32 loc_evt;
u32 size;
struct adsp_audio_event ae;
} __attribute__ ((packed));
#else
struct adsp_buffer_event
{
struct adsp_buffer_event {
struct adsp_event_hdr hdr;
struct adsp_audio_buffer buffer;
} __attribute__ ((packed));
#endif
/* ---- audio device IDs ---- */
/* Device direction Rx/Tx flag */
#define ADSP_AUDIO_RX_DEVICE 0x00
#define ADSP_AUDIO_TX_DEVICE 0x01
#define ADSP_AUDIO_RX_DEVICE 0x00
#define ADSP_AUDIO_TX_DEVICE 0x01
/* Default RX or TX device */
#define ADSP_AUDIO_DEVICE_ID_DEFAULT 0x1081679
@ -631,18 +526,18 @@ struct adsp_buffer_event
/* Special loopback pseudo device to be paired with an RX device */
/* with usage ADSP_AUDIO_DEVICE_USAGE_MIXED_PCM_LOOPBACK */
#define ADSP_AUDIO_DEVICE_ID_MIXED_PCM_LOOPBACK_TX 0x1089bf2
#define ADSP_AUDIO_DEVICE_ID_MIXED_PCM_LOOPBACK_TX 0x1089bf2
/* Sink (RX) devices */
#define ADSP_AUDIO_DEVICE_ID_HANDSET_SPKR 0x107ac88
#define ADSP_AUDIO_DEVICE_ID_HEADSET_SPKR_MONO 0x1081511
#define ADSP_AUDIO_DEVICE_ID_HEADSET_SPKR_STEREO 0x107ac8a
#define ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_MONO 0x1081513
#define ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_MONO_W_MONO_HEADSET 0x108c508
#define ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_MONO_W_MONO_HEADSET 0x108c508
#define ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_MONO_W_STEREO_HEADSET 0x108c894
#define ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_STEREO 0x1081514
#define ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_STEREO 0x1081514
#define ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_STEREO_W_MONO_HEADSET 0x108c895
#define ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_STEREO_W_STEREO_HEADSET 0x108c509
#define ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_STEREO_W_STEREO_HEADSET 0x108c509
#define ADSP_AUDIO_DEVICE_ID_BT_SCO_SPKR 0x1081519
#define ADSP_AUDIO_DEVICE_ID_TTY_HEADSET_SPKR 0x108151c
#define ADSP_AUDIO_DEVICE_ID_I2S_SPKR 0x1089bf4
@ -652,11 +547,11 @@ struct adsp_buffer_event
/* This device must be paired with */
/* ADSP_AUDIO_DEVICE_ID_MIXED_PCM_LOOPBACK_TX using */
/* ADSP_AUDIO_DEVICE_USAGE_MIXED_PCM_LOOPBACK mode */
#define ADSP_AUDIO_DEVICE_ID_BT_A2DP_SPKR 0x108151a
#define ADSP_AUDIO_DEVICE_ID_BT_A2DP_SPKR 0x108151a
/* Voice Destination identifier - specifically used for */
/* controlling Voice module from the Device Control Session */
#define ADSP_AUDIO_DEVICE_ID_VOICE 0x0108df3c
#define ADSP_AUDIO_DEVICE_ID_VOICE 0x0108df3c
/* Audio device usage types. */
/* This is a bit mask to determine which topology to use in the */
@ -667,24 +562,4 @@ struct adsp_buffer_event
#define ADSP_AUDIO_DEVICE_CONTEXT_RECORD 0x20
#define ADSP_AUDIO_DEVICE_CONTEXT_PCM_LOOPBACK 0x40
/* for EQ */
#define CAD_EQ_INVALID_DATA 0xFFFFFFFF
/* Equalizer filter band types */
#define ADSP_AUDIO_EQUALIZER_TYPE_NONE 0
#define ADSP_AUDIO_EQUALIZER_BASS_BOOST 1
#define ADSP_AUDIO_EQUALIZER_BASS_CUT 2
#define ADSP_AUDIO_EQUALIZER_TREBLE_BOOST 3
#define ADSP_AUDIO_EQUALIZER_TREBLE_CUT 4
#define ADSP_AUDIO_EQUALIZER_BAND_BOOST 5
#define ADSP_AUDIO_EQUALIZER_BAND_CUT 6
struct cad_audio_eq_cfg {
u32 enable;
u32 num_bands;
struct adsp_audio_eq_band eq_bands[ADSP_AUDIO_MAX_EQ_BANDS];
} __attribute__ ((packed));
int q6audio_set_stream_eq(struct audio_client *ac, struct cad_audio_eq_cfg *eq_cfg);
#endif

View File

@ -25,7 +25,6 @@
#include <linux/msm_audio.h>
#include <mach/msm_qdsp6_audio.h>
#include "dal_audio.h"
#define BUFSZ (8192)
#define DMASZ (BUFSZ * 2)
@ -40,7 +39,6 @@ struct mp3 {
static long mp3_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct mp3 *mp3 = file->private_data;
struct cad_audio_eq_cfg eq_cfg;
int rc = 0;
if (cmd == AUDIO_GET_STATS) {
@ -62,14 +60,6 @@ static long mp3_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
rc = q6audio_set_stream_volume(mp3->ac, vol);
break;
}
case AUDIO_SET_EQ: {
if (copy_from_user(&eq_cfg, (void *)arg, sizeof(struct cad_audio_eq_cfg))) {
rc = -EFAULT;
break;
}
rc = q6audio_set_stream_eq(mp3->ac, &eq_cfg);
break;
}
case AUDIO_START: {
uint32_t acdb_id;
if (arg == 0) {

View File

@ -66,35 +66,10 @@
#define TRACE(fmt,x...) \
do { pr_debug("%s:%d " fmt, __func__, __LINE__, ##x); } while (0)
#else
#define TRACE(fmt,x...) do { } while (0)
#define TRACE(fmt, x...) do { } while (0)
#endif
static DEFINE_MUTEX(idlecount_lock);
static int idlecount;
static struct wake_lock wakelock;
static struct wake_lock idlelock;
static void prevent_sleep(void)
{
mutex_lock(&idlecount_lock);
if (++idlecount == 1) {
wake_lock(&idlelock);
wake_lock(&wakelock);
}
mutex_unlock(&idlecount_lock);
}
static void allow_sleep(void)
{
mutex_lock(&idlecount_lock);
if (--idlecount == 0) {
wake_unlock(&idlelock);
wake_unlock(&wakelock);
}
mutex_unlock(&idlecount_lock);
}
#define MAX_SUPPORTED_INSTANCES 2
enum {
VDEC_DALRPC_INITIALIZE = DAL_OP_FIRST_DEVICE_API,
@ -162,6 +137,31 @@ static struct cdev vdec_cdev;
static int ref_cnt;
static DEFINE_MUTEX(vdec_ref_lock);
static DEFINE_MUTEX(idlecount_lock);
static int idlecount;
static struct wake_lock wakelock;
static struct wake_lock idlelock;
static void prevent_sleep(void)
{
mutex_lock(&idlecount_lock);
if (++idlecount == 1) {
wake_lock(&idlelock);
wake_lock(&wakelock);
}
mutex_unlock(&idlecount_lock);
}
static void allow_sleep(void)
{
mutex_lock(&idlecount_lock);
if (--idlecount == 0) {
wake_unlock(&idlelock);
wake_unlock(&wakelock);
}
mutex_unlock(&idlecount_lock);
}
static inline int vdec_check_version(u32 client, u32 server)
{
int ret = -EINVAL;
@ -447,6 +447,8 @@ static int vdec_queue(struct vdec_data *vd, void *argp)
rpc.size = sizeof(struct vdec_input_buf_info);
rpc.osize = sizeof(struct vdec_queue_status);
/* complete the writes to the buffer */
wmb();
ret = dal_call(vd->vdec_handle, VDEC_DALRPC_QUEUE, 8,
&rpc, sizeof(rpc), &rpc_res, sizeof(rpc_res));
if (ret < 4) {
@ -587,6 +589,22 @@ static int vdec_freebuffers(struct vdec_data *vd, void *argp)
return ret;
}
static int vdec_getversion(struct vdec_data *vd, void *argp)
{
struct vdec_version ver_info;
int ret = 0;
ver_info.major = VDEC_GET_MAJOR_VERSION(VDEC_INTERFACE_VERSION);
ver_info.minor = VDEC_GET_MINOR_VERSION(VDEC_INTERFACE_VERSION);
ret = copy_to_user(((struct vdec_version *)argp),
&ver_info, sizeof(ver_info));
return ret;
}
static long vdec_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct vdec_data *vd = file->private_data;
@ -638,6 +656,9 @@ static long vdec_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (vd->close_decode)
ret = -EINTR;
else
/* order the reads from the buffer */
rmb();
break;
case VDEC_IOCTL_CLOSE:
@ -663,7 +684,15 @@ static long vdec_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
pr_err("%s: remote function failed (%d)\n",
__func__, ret);
break;
case VDEC_IOCTL_GETVERSION:
TRACE("VDEC_IOCTL_GETVERSION (pid=%d tid=%d)\n",
current->group_leader->pid, current->pid);
ret = vdec_getversion(vd, argp);
if (ret)
pr_err("%s: remote function failed (%d)\n",
__func__, ret);
break;
default:
pr_err("%s: invalid ioctl!\n", __func__);
ret = -EINVAL;
@ -684,7 +713,8 @@ static void vdec_dcdone_handler(struct vdec_data *vd, void *frame,
unsigned long flags;
int found = 0;
if (frame_size != sizeof(struct vdec_frame_info)) {
/*if (frame_size != sizeof(struct vdec_frame_info)) {*/
if (frame_size < sizeof(struct vdec_frame_info)) {
pr_warning("%s: msg size mismatch %d != %d\n", __func__,
frame_size, sizeof(struct vdec_frame_info));
return;
@ -768,13 +798,14 @@ static int vdec_open(struct inode *inode, struct file *file)
int i;
struct vdec_msg_list *l;
struct vdec_data *vd;
struct dal_info version_info;
pr_info("q6vdec_open()\n");
mutex_lock(&vdec_ref_lock);
if (ref_cnt > 0) {
pr_err("%s: Instance alredy running\n", __func__);
if (ref_cnt >= MAX_SUPPORTED_INSTANCES) {
pr_err("%s: Max allowed instances exceeded \n", __func__);
mutex_unlock(&vdec_ref_lock);
return -ENOMEM;
return -EBUSY;
}
ref_cnt++;
mutex_unlock(&vdec_ref_lock);
@ -813,11 +844,26 @@ static int vdec_open(struct inode *inode, struct file *file)
ret = -EIO;
goto vdec_open_err_handle_list;
}
ret = dal_call_f9(vd->vdec_handle, DAL_OP_INFO,
&version_info, sizeof(struct dal_info));
if (ret) {
pr_err("%s: failed to get version \n", __func__);
goto vdec_open_err_handle_version;
}
TRACE("q6vdec_open() interface version 0x%x\n", version_info.version);
if (vdec_check_version(VDEC_INTERFACE_VERSION,
version_info.version)) {
pr_err("%s: driver version mismatch !\n", __func__);
goto vdec_open_err_handle_version;
}
vd->running = 1;
prevent_sleep();
return 0;
vdec_open_err_handle_version:
dal_detach(vd->vdec_handle);
vdec_open_err_handle_list:
{
struct vdec_msg_list *l, *n;
@ -827,6 +873,9 @@ vdec_open_err_handle_list:
}
}
vdec_open_err_handle_vd:
mutex_lock(&vdec_ref_lock);
ref_cnt--;
mutex_unlock(&vdec_ref_lock);
kfree(vd);
return ret;
}

File diff suppressed because it is too large Load Diff

View File

@ -26,12 +26,12 @@
#include <mach/msm_qdsp6_audio.h>
#define BUFSZ (4096)
#define DMASZ (BUFSZ * 2)
#define BUFSZ (256)
static DEFINE_MUTEX(pcm_in_lock);
static uint32_t sample_rate = 8000;
static uint32_t channel_count = 1;
static uint32_t buffer_size = BUFSZ;
static int pcm_in_opened = 0;
void audio_client_dump(struct audio_client *ac);
@ -66,7 +66,7 @@ static long q6_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
rc = -EBUSY;
} else {
file->private_data = q6audio_open_pcm(
BUFSZ, sample_rate, channel_count,
buffer_size, sample_rate, channel_count,
AUDIO_FLAG_READ, acdb_id);
if (!file->private_data)
rc = -ENOMEM;
@ -84,13 +84,26 @@ static long q6_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
rc = -EFAULT;
break;
}
if (!config.channel_count || config.channel_count > 2) {
rc = -EINVAL;
break;
}
if (config.sample_rate < 8000 || config.sample_rate > 48000) {
rc = -EINVAL;
break;
}
if (config.buffer_size < 128 || config.buffer_size > 8192) {
rc = -EINVAL;
break;
}
sample_rate = config.sample_rate;
channel_count = config.channel_count;
buffer_size = config.buffer_size;
break;
}
case AUDIO_GET_CONFIG: {
struct msm_audio_config config;
config.buffer_size = BUFSZ;
config.buffer_size = buffer_size;
config.buffer_count = 2;
config.sample_rate = sample_rate;
config.channel_count = channel_count;
@ -147,7 +160,7 @@ static ssize_t q6_in_read(struct file *file, char __user *buf,
if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
audio_client_dump(ac);
pr_err("pcm_read: timeout. dsp dead?\n");
// BUG();
BUG();
}
xfer = count;

View File

@ -25,33 +25,24 @@
#include <linux/msm_audio.h>
#include <mach/msm_qdsp6_audio.h>
#include "dal_audio.h"
#if 0
#define AUDIO_INFO(x...) pr_info("Audio: "x)
#else
#define AUDIO_INFO(x...) do{}while(0)
#endif
void audio_client_dump(struct audio_client *ac);
#define BUFSZ (4096) //(3072)
#define DMASZ (BUFSZ * 2)
#define BUFSZ (3072)
struct pcm {
struct mutex lock;
struct audio_client *ac;
uint32_t sample_rate;
uint32_t channel_count;
size_t buffer_size;
};
static long pcm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
struct pcm *pcm = file->private_data;
struct cad_audio_eq_cfg eq_cfg;
int rc = 0;
AUDIO_INFO("%s: %X %X\n", __func__, cmd, arg);
if (cmd == AUDIO_GET_STATS) {
struct msm_audio_stats stats;
memset(&stats, 0, sizeof(stats));
@ -71,14 +62,6 @@ static long pcm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
rc = q6audio_set_stream_volume(pcm->ac, vol);
break;
}
case AUDIO_SET_EQ: {
if (copy_from_user(&eq_cfg, (void *)arg, sizeof(struct cad_audio_eq_cfg))) {
rc = -EFAULT;
break;
}
rc = q6audio_set_stream_eq(pcm->ac, &eq_cfg);
break;
}
case AUDIO_START: {
uint32_t acdb_id;
if (arg == 0) {
@ -91,7 +74,7 @@ static long pcm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
if (pcm->ac) {
rc = -EBUSY;
} else {
pcm->ac = q6audio_open_pcm(BUFSZ, pcm->sample_rate,
pcm->ac = q6audio_open_pcm(pcm->buffer_size, pcm->sample_rate,
pcm->channel_count,
AUDIO_FLAG_WRITE, acdb_id);
if (!pcm->ac)
@ -117,13 +100,22 @@ static long pcm_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
rc = -EINVAL;
break;
}
if (config.sample_rate < 8000 || config.sample_rate > 48000) {
rc = -EINVAL;
break;
}
if (config.buffer_size < 128 || config.buffer_size > 8192) {
rc = -EINVAL;
break;
}
pcm->sample_rate = config.sample_rate;
pcm->channel_count = config.channel_count;
pcm->buffer_size = config.buffer_size;
break;
}
case AUDIO_GET_CONFIG: {
struct msm_audio_config config;
config.buffer_size = BUFSZ;
config.buffer_size = pcm->buffer_size;
config.buffer_count = 2;
config.sample_rate = pcm->sample_rate;
config.channel_count = pcm->channel_count;
@ -146,7 +138,6 @@ static int pcm_open(struct inode *inode, struct file *file)
{
struct pcm *pcm;
AUDIO_INFO("%s\n", __func__);
pr_info("pcm_out: open\n");
pcm = kzalloc(sizeof(struct pcm), GFP_KERNEL);
@ -156,6 +147,7 @@ static int pcm_open(struct inode *inode, struct file *file)
mutex_init(&pcm->lock);
pcm->channel_count = 2;
pcm->sample_rate = 44100;
pcm->buffer_size = BUFSZ;
file->private_data = pcm;
return 0;
@ -184,7 +176,7 @@ static ssize_t pcm_write(struct file *file, const char __user *buf,
if (!wait_event_timeout(ac->wait, (ab->used == 0), 5*HZ)) {
audio_client_dump(ac);
pr_err("pcm_write: timeout. dsp dead?\n");
// BUG();
BUG();
}
xfer = count;
@ -207,7 +199,6 @@ static ssize_t pcm_write(struct file *file, const char __user *buf,
static int pcm_release(struct inode *inode, struct file *file)
{
AUDIO_INFO("%s\n", __func__);
struct pcm *pcm = file->private_data;
if (pcm->ac)
q6audio_close(pcm->ac);

View File

@ -31,7 +31,8 @@
#include "dal_acdb.h"
#include "dal_adie.h"
#include <mach/msm_qdsp6_audio.h>
#include <mach/htc_acoustic_qsd.h>
#include <mach/msm_audio_qcp.h>
#include <linux/gpio.h>
#include "q6audio_devices.h"
@ -347,7 +348,7 @@ static int audio_ioctl(struct audio_client *ac, void *ptr, uint32_t len)
if (!wait_event_timeout(ac->wait, (ac->cb_status != -EBUSY), 5*HZ)) {
dal_trace_dump(ac->client);
pr_err("audio_ioctl: timeout. dsp dead?\n");
q6audio_dsp_not_responding();
BUG();
}
return ac->cb_status;
}
@ -437,6 +438,156 @@ static int audio_mp3_open(struct audio_client *ac, uint32_t bufsz,
return audio_ioctl(ac, &rpc, sizeof(rpc));
}
static int audio_aac_open(struct audio_client *ac, uint32_t bufsz,
void *data)
{
struct aac_format *af = data;
struct adsp_open_command rpc;
uint32_t *aac_type;
int idx = sizeof(uint32_t);
struct adsp_audio_binary_format *fmt = &(rpc.format.binary);
memset(&rpc, 0, sizeof(rpc));
fmt->format = ADSP_AUDIO_FORMAT_MPEG4_AAC;
aac_type = (uint32_t *)(fmt->data);
switch (af->block_formats) {
case 0xffff:
if (ac->flags & AUDIO_FLAG_WRITE)
*aac_type = ADSP_AUDIO_AAC_ADTS;
else
*aac_type = ADSP_AUDIO_AAC_MPEG4_ADTS;
break;
case 0:
if (ac->flags & AUDIO_FLAG_WRITE)
*aac_type = ADSP_AUDIO_AAC_ADIF;
else
*aac_type = ADSP_AUDIO_AAC_RAW;
break;
case 1:
*aac_type = ADSP_AUDIO_AAC_RAW;
break;
case 2:
*aac_type = ADSP_AUDIO_AAC_LOAS;
break;
case 3:
*aac_type = ADSP_AUDIO_AAC_FRAMED_RAW;
break;
case 4:
*aac_type = ADSP_AUDIO_AAC_RAW;
break;
default:
pr_err("unsupported AAC type %d\n", af->block_formats);
return -EINVAL;
}
TRACE("aac_open: type %x, obj %d, idx %d\n",
*aac_type, af->audio_object_type, idx);
fmt->data[idx++] = (u8)(((af->audio_object_type & 0x1F) << 3) |
((af->sample_rate >> 1) & 0x7));
fmt->data[idx] = (u8)(((af->sample_rate & 0x1) << 7) |
((af->channel_config & 0x7) << 3));
switch (af->audio_object_type) {
case AAC_OBJECT_ER_LC:
case AAC_OBJECT_ER_LTP:
case AAC_OBJECT_ER_LD:
/* extension flag */
fmt->data[idx++] |= 0x1;
fmt->data[idx] = (u8)(
((af->aac_section_data_resilience_flag & 0x1) << 7) |
((af->aac_scalefactor_data_resilience_flag & 0x1) << 6) |
((af->aac_spectral_data_resilience_flag & 0x1) << 5) |
((af->ep_config & 0x3) << 2));
break;
case AAC_OBJECT_ER_SCALABLE:
fmt->data[idx++] |= 0x1;
/* extension flag */
fmt->data[idx++] = (u8)(
((af->aac_section_data_resilience_flag & 0x1) << 4) |
((af->aac_scalefactor_data_resilience_flag & 0x1) << 3) |
((af->aac_spectral_data_resilience_flag & 0x1) << 2) |
((af->ep_config >> 1) & 0x1));
fmt->data[idx] = (u8)((af->ep_config & 0x1)
<< 7);
break;
case AAC_OBJECT_BSAC:
fmt->data[++idx] = (u8)((af->ep_config & 0x3)
<< 6);
break;
default:
pr_err("dbg unknown object type \n");
break;
}
fmt->num_bytes = idx + 1;
TRACE("aac_open: format %x%x %x%x%x%x %x%x, \n",
fmt->data[0], fmt->data[1], fmt->data[2], fmt->data[3],
fmt->data[4], fmt->data[5], fmt->data[6], fmt->data[7]);
rpc.device = ADSP_AUDIO_DEVICE_ID_DEFAULT;
rpc.config.aac.bit_rate = af->bit_rate;
if (ac->flags & AUDIO_FLAG_WRITE) {
rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_OPEN_WRITE;
rpc.stream_context = ADSP_AUDIO_DEVICE_CONTEXT_PLAYBACK;
} else {
rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_OPEN_READ;
rpc.stream_context = ADSP_AUDIO_DEVICE_CONTEXT_RECORD;
}
if ((af->sbr_on_flag == 0) && (af->sbr_ps_on_flag == 0)) {
rpc.config.aac.encoder_mode =
ADSP_AUDIO_ENC_AAC_LC_ONLY_MODE;
} else if ((af->sbr_on_flag == 1) && (af->sbr_ps_on_flag == 0)) {
rpc.config.aac.encoder_mode =
ADSP_AUDIO_ENC_AAC_PLUS_MODE;
} else if ((af->sbr_on_flag == 1) && (af->sbr_ps_on_flag == 1)) {
rpc.config.aac.encoder_mode =
ADSP_AUDIO_ENC_ENHANCED_AAC_PLUS_MODE;
} else {
pr_err("unsupported SBR flag\n");
return -EINVAL;
}
rpc.buf_max_size = bufsz; /* XXX ??? */
rpc.hdr.response_type = 0;
TRACE("aac_open: opcode %x, stream_context 0x%x, "
"mode %d, bytes %d, bbuffer size %d\n",
rpc.hdr.opcode, rpc.stream_context,
rpc.config.aac.encoder_mode, fmt->num_bytes, bufsz);
return audio_ioctl(ac, &rpc, sizeof(rpc));
}
static int audio_qcelp_open(struct audio_client *ac, uint32_t bufsz,
void *data)
{
struct msm_audio_qcelp_config *qf = data;
struct adsp_open_command rpc;
struct adsp_audio_standard_format *fmt = &(rpc.format.standard);
memset(&rpc, 0, sizeof(rpc));
fmt->format = ADSP_AUDIO_FORMAT_V13K_FS;
fmt->sampling_rate = 8000;
fmt->channels = 1;
fmt->bits_per_sample = 16;
fmt->is_signed = 1;
fmt->is_interleaved = 0;
rpc.device = ADSP_AUDIO_DEVICE_ID_DEFAULT;
rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_OPEN_READ;
rpc.stream_context = ADSP_AUDIO_DEVICE_CONTEXT_RECORD;
rpc.config.qcelp13k.min_rate = (uint16_t) qf->min_bit_rate;
rpc.config.qcelp13k.max_rate = (uint16_t) qf->max_bit_rate;
rpc.buf_max_size = bufsz; /* XXX ??? */
return audio_ioctl(ac, &rpc, sizeof(rpc));
}
static int audio_close(struct audio_client *ac)
{
TRACE("%p: close\n", ac);
@ -583,7 +734,10 @@ static void callback(void *data, int len, void *cookie)
{
struct adsp_event_hdr *e = data;
struct audio_client *ac;
struct adsp_buffer_event *abe = data;
TRACE("audio callback: context %d, event 0x%x, status %d\n",
e->context, e->event_id, e->status);
if (e->context >= SESSION_MAX) {
pr_err("audio callback: bogus session %d\n",
@ -610,6 +764,9 @@ static void callback(void *data, int len, void *cookie)
if (e->event_id == ADSP_AUDIO_EVT_STATUS_BUF_DONE) {
TRACE("%p: CB done (%d)\n", ac, e->status);
TRACE("%p: actual_size %d, buffer_size %d\n",
ac, abe->buffer.actual_size, ac->buf[ac->dsp_buf].size);
if (e->status)
pr_err("buffer status %d\n", e->status);
ac->buf[ac->dsp_buf].used = 0;
@ -891,6 +1048,10 @@ static void audio_rx_analog_enable(int en)
if (analog_ops->receiver_enable)
analog_ops->receiver_enable(en);
break;
case ADSP_AUDIO_DEVICE_ID_I2S_SPKR:
if (analog_ops->i2s_enable)
analog_ops->i2s_enable(en);
break;
}
}
@ -936,7 +1097,8 @@ static int audio_update_acdb(uint32_t adev, uint32_t acdb_id)
return -EINVAL;
}
audio_set_table(ac_control, adev, sz);
if (sz > 0)
audio_set_table(ac_control, adev, sz);
return 0;
}
@ -1213,7 +1375,7 @@ int q6audio_reinit_acdb(char* filename) {
return 0;
mutex_lock(&audio_path_lock);
if (strlen(filename) < 0 || !strcmp(filename, acdb_file)) {
if (strlen(filename) < 0) {
res = -EINVAL;
goto done;
}
@ -1447,7 +1609,7 @@ struct audio_client *q6audio_open_pcm(uint32_t bufsz, uint32_t rate,
if (rc == 0)
break;
if (retry == 0)
q6audio_dsp_not_responding();
BUG();
pr_err("q6audio: open pcm error %d, retrying\n", rc);
msleep(1);
}
@ -1472,7 +1634,7 @@ struct audio_client *q6audio_open_pcm(uint32_t bufsz, uint32_t rate,
if (rc == 0)
break;
if (retry == 0)
q6audio_dsp_not_responding();
BUG();
pr_err("q6audio: stream start error %d, retrying\n", rc);
}
@ -1512,9 +1674,10 @@ struct audio_client *q6voice_open(uint32_t flags, uint32_t acdb_id)
return 0;
ac->flags = flags;
if (ac->flags & AUDIO_FLAG_WRITE)
if (ac->flags & AUDIO_FLAG_WRITE) {
audio_rx_path_enable(1, acdb_id);
else {
audio_rx_mute(ac_control, ADSP_AUDIO_DEVICE_ID_VOICE, 0);
} else {
tx_clk_freq = 8000;
audio_tx_path_enable(1, acdb_id);
}
@ -1524,9 +1687,10 @@ struct audio_client *q6voice_open(uint32_t flags, uint32_t acdb_id)
int q6voice_close(struct audio_client *ac)
{
if (ac->flags & AUDIO_FLAG_WRITE)
if (ac->flags & AUDIO_FLAG_WRITE) {
audio_rx_mute(ac_control, ADSP_AUDIO_DEVICE_ID_VOICE, 1);
audio_rx_path_enable(0, 0);
else
} else
audio_tx_path_enable(0, 0);
audio_client_free(ac);
@ -1572,3 +1736,122 @@ int q6audio_async(struct audio_client *ac)
rpc.response_type = ADSP_AUDIO_RESPONSE_ASYNC;
return audio_ioctl(ac, &rpc, sizeof(rpc));
}
struct audio_client *q6audio_open_aac(uint32_t bufsz, uint32_t rate,
uint32_t flags, void *data, uint32_t acdb_id)
{
struct audio_client *ac;
TRACE("q6audio_open_aac flags=%d rate=%d\n", flags, rate);
if (q6audio_init())
return 0;
ac = audio_client_alloc(bufsz);
if (!ac)
return 0;
ac->flags = flags;
if (ac->flags & AUDIO_FLAG_WRITE)
audio_rx_path_enable(1, acdb_id);
else {
/* TODO: consider concourrency with voice call */
tx_clk_freq = rate;
audio_tx_path_enable(1, acdb_id);
}
audio_aac_open(ac, bufsz, data);
audio_command(ac, ADSP_AUDIO_IOCTL_CMD_SESSION_START);
if (!(ac->flags & AUDIO_FLAG_WRITE)) {
ac->buf[0].used = 1;
ac->buf[1].used = 1;
q6audio_read(ac, &ac->buf[0]);
q6audio_read(ac, &ac->buf[1]);
}
audio_prevent_sleep();
return ac;
}
int q6audio_aac_close(struct audio_client *ac)
{
audio_close(ac);
if (ac->flags & AUDIO_FLAG_WRITE)
audio_rx_path_enable(0, 0);
else
audio_tx_path_enable(0, 0);
audio_client_free(ac);
audio_allow_sleep();
return 0;
}
struct audio_client *q6fm_open(void)
{
struct audio_client *ac;
printk("q6fm_open()\n");
if (q6audio_init())
return 0;
if (audio_rx_device_id != ADSP_AUDIO_DEVICE_ID_HEADSET_SPKR_STEREO &&
audio_rx_device_id != ADSP_AUDIO_DEVICE_ID_SPKR_PHONE_MONO)
return 0;
ac = audio_client_alloc(0);
if (!ac)
return 0;
ac->flags = AUDIO_FLAG_WRITE;
audio_rx_path_enable(1, 0);
enable_aux_loopback(1);
return ac;
}
int q6fm_close(struct audio_client *ac)
{
audio_rx_path_enable(0, 0);
enable_aux_loopback(0);
audio_client_free(ac);
return 0;
}
struct audio_client *q6audio_open_qcelp(uint32_t bufsz, uint32_t rate,
void *data, uint32_t acdb_id)
{
struct audio_client *ac;
if (q6audio_init())
return 0;
ac = audio_client_alloc(bufsz);
if (!ac)
return 0;
ac->flags = AUDIO_FLAG_READ;
tx_clk_freq = rate;
audio_tx_path_enable(1, acdb_id);
audio_qcelp_open(ac, bufsz, data);
audio_command(ac, ADSP_AUDIO_IOCTL_CMD_SESSION_START);
ac->buf[0].used = 1;
ac->buf[1].used = 1;
q6audio_read(ac, &ac->buf[0]);
q6audio_read(ac, &ac->buf[1]);
audio_prevent_sleep();
return ac;
}
int q6audio_qcelp_close(struct audio_client *ac)
{
audio_close(ac);
audio_tx_path_enable(0, 0);
audio_client_free(ac);
audio_allow_sleep();
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,212 +0,0 @@
/* arch/arm/mach-msm/qdsp6/qcelp_in.c
*
* Copyright (C) 2009 Google, Inc.
* Copyright (C) 2009 HTC Corporation
*
* 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/fs.h>
#include <linux/module.h>
#include <linux/miscdevice.h>
#include <linux/mutex.h>
#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/uaccess.h>
#include <linux/msm_audio.h>
#include <mach/msm_qdsp6_audio.h>
#include <mach/msm_audio_qcp.h>
#define BUFSZ (734)
#define DMASZ (BUFSZ * 2)
#if 0
#define TRACE(x...) pr_info("Q6: "x)
#else
#define TRACE(x...) do{}while(0)
#endif
static DEFINE_MUTEX(qcelp_in_lock);
static int qcelp_in_opened = 0;
static struct msm_audio_qcelp_config *qf;
void audio_client_dump(struct audio_client *ac);
static long qcelp_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
int rc = 0;
switch (cmd) {
case AUDIO_SET_VOLUME:
break;
case AUDIO_GET_STATS: {
struct msm_audio_stats stats;
memset(&stats, 0, sizeof(stats));
if (copy_to_user((void*) arg, &stats, sizeof(stats)))
return -EFAULT;
return 0;
}
case AUDIO_START: {
uint32_t acdb_id;
rc = 0;
if (arg == 0) {
acdb_id = 0;
} else if (copy_from_user(&acdb_id, (void*) arg, sizeof(acdb_id))) {
rc = -EFAULT;
break;
}
mutex_lock(&qcelp_in_lock);
if (file->private_data) {
rc = -EBUSY;
} else {
file->private_data = q6audio_open_qcelp(
BUFSZ, 8000, qf, acdb_id);
if (!file->private_data)
rc = -ENOMEM;
}
mutex_unlock(&qcelp_in_lock);
break;
}
case AUDIO_STOP:
break;
case AUDIO_FLUSH:
break;
case AUDIO_GET_CONFIG:
if (copy_to_user((void *)arg, qf,
sizeof(struct msm_audio_qcelp_config)))
return -EFAULT;
break;
case AUDIO_SET_CONFIG:
if (copy_from_user(qf, (void *)arg,
sizeof(struct msm_audio_qcelp_config)))
return -EFAULT;
if (qf->min_bit_rate > 4 || qf->min_bit_rate < 1) {
pr_err("invalid min bitrate\n");
return -EINVAL;
}
if (qf->max_bit_rate > 4 || qf->max_bit_rate < 1) {
pr_err("invalid max bitrate\n");
return -EINVAL;
}
if (qf->cdma_rate > CDMA_RATE_ERASURE ||
qf->cdma_rate < CDMA_RATE_BLANK) {
pr_err("invalid qcelp cdma rate\n");
return -EINVAL;
}
break;
default:
rc = -EINVAL;
}
return rc;
}
static int qcelp_in_open(struct inode *inode, struct file *file)
{
int rc;
pr_info("qcelp_in: open\n");
mutex_lock(&qcelp_in_lock);
if (qcelp_in_opened) {
pr_err("qcelp_in: busy\n");
rc = -EBUSY;
} else {
qf = kzalloc(sizeof(*qf), GFP_KERNEL);
memset(qf, 0, sizeof(struct msm_audio_qcelp_config));
qf->channels = 1;
qf->cdma_rate = 0x04; /* CDMA_RATE_FULL */
qf->min_bit_rate = 1;
qf->max_bit_rate = 4;
qcelp_in_opened = 1;
rc = 0;
}
mutex_unlock(&qcelp_in_lock);
return rc;
}
static ssize_t qcelp_in_read(struct file *file, char __user *buf, size_t count, loff_t *pos)
{
struct audio_client *ac;
struct audio_buffer *ab;
const char __user *start = buf;
int xfer, res = 0;
mutex_lock(&qcelp_in_lock);
ac = file->private_data;
if (!ac) {
res = -ENODEV;
pr_err("qcelp_in_read ac NULL\n");
goto fail;
}
while (count > 0) {
ab = ac->buf + ac->cpu_buf;
TRACE("qcelp_in_read wait count=%d ab=%d ac->buf=%d cpu_buf=%d ac->buf[1]=%d\n",
count, ab, ac->buf, ac->cpu_buf, &(ac->buf[1]));
if (ab->used)
wait_event(ac->wait, (ab->used == 0));
TRACE(" qcelp_in_read event arrive ab->size=%d\n", ab->size);
xfer = count;
if (xfer > ab->size)
xfer = ab->size;
if (copy_to_user(buf, ab->data, xfer)) {
res = -EFAULT;
pr_err("Tomdbg copy to user failed \n");
goto fail;
}
TRACE("qcelp_in read buf = %d,xfer = %d,cnt = %d\n", buf, xfer, count);
buf += xfer;
count -= xfer;
ab->used = 1;
q6audio_read(ac, ab);
ac->cpu_buf ^= 1;
}
fail:
res = buf - start;
mutex_unlock(&qcelp_in_lock);
return res;
}
static int qcelp_in_release(struct inode *inode, struct file *file)
{
int rc = 0;
pr_info("qcelp_in: release\n");
mutex_lock(&qcelp_in_lock);
if (file->private_data)
rc = q6audio_close(file->private_data);
kfree(qf);
qcelp_in_opened = 0;
mutex_unlock(&qcelp_in_lock);
return rc;
}
static struct file_operations qcelp_in_fops = {
.owner = THIS_MODULE,
.open = qcelp_in_open,
.read = qcelp_in_read,
.release = qcelp_in_release,
.unlocked_ioctl = qcelp_in_ioctl,
};
struct miscdevice qcelp_in_misc = {
.minor = MISC_DYNAMIC_MINOR,
.name = "msm_qcelp_in",
.fops = &qcelp_in_fops,
};
static int __init qcelp_in_init(void) {
return misc_register(&qcelp_in_misc);
}
device_initcall(qcelp_in_init);

View File

@ -1,4 +1,4 @@
/* Copyright (c) 2009, Code Aurora Forum. All rights reserved.
/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
@ -7,119 +7,325 @@
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of Code Aurora Forum nor
* * Neither the name of Code Aurora nor
* the names of its contributors may be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
* IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
*/
#ifndef _MSM_VENC_H_
#define _MSM_VENC_H_
#include <linux/types.h>
struct venc_buf {
unsigned int src_id;
#define VENC_MAX_RECON_BUFFERS 2
#define VENC_FLAG_EOS 0x00000001
#define VENC_FLAG_END_OF_FRAME 0x00000010
#define VENC_FLAG_SYNC_FRAME 0x00000020
#define VENC_FLAG_EXTRA_DATA 0x00000040
#define VENC_FLAG_CODEC_CONFIG 0x00000080
enum venc_flush_type {
VENC_FLUSH_INPUT,
VENC_FLUSH_OUTPUT,
VENC_FLUSH_ALL
};
enum venc_state_type {
VENC_STATE_PAUSE = 0x1,
VENC_STATE_START = 0x2,
VENC_STATE_STOP = 0x4
};
enum venc_event_type_enum {
VENC_EVENT_START_STATUS,
VENC_EVENT_STOP_STATUS,
VENC_EVENT_SUSPEND_STATUS,
VENC_EVENT_RESUME_STATUS,
VENC_EVENT_FLUSH_STATUS,
VENC_EVENT_RELEASE_INPUT,
VENC_EVENT_DELIVER_OUTPUT,
VENC_EVENT_UNKNOWN_STATUS
};
enum venc_status_code {
VENC_STATUS_SUCCESS,
VENC_STATUS_ERROR,
VENC_STATUS_INVALID_STATE,
VENC_STATUS_FLUSHING,
VENC_STATUS_INVALID_PARAM,
VENC_STATUS_CMD_QUEUE_FULL,
VENC_STATUS_CRITICAL,
VENC_STATUS_INSUFFICIENT_RESOURCES,
VENC_STATUS_TIMEOUT
};
enum venc_msg_code {
VENC_MSG_INDICATION,
VENC_MSG_INPUT_BUFFER_DONE,
VENC_MSG_OUTPUT_BUFFER_DONE,
VENC_MSG_NEED_OUTPUT_BUFFER,
VENC_MSG_FLUSH,
VENC_MSG_START,
VENC_MSG_STOP,
VENC_MSG_PAUSE,
VENC_MSG_RESUME,
VENC_MSG_STOP_READING_MSG
};
enum venc_error_code {
VENC_S_SUCCESS,
VENC_S_EFAIL,
VENC_S_EFATAL,
VENC_S_EBADPARAM,
VENC_S_EINVALSTATE,
VENC_S_ENOSWRES,
VENC_S_ENOHWRES,
VENC_S_EBUFFREQ,
VENC_S_EINVALCMD,
VENC_S_ETIMEOUT,
VENC_S_ENOREATMPT,
VENC_S_ENOPREREQ,
VENC_S_ECMDQFULL,
VENC_S_ENOTSUPP,
VENC_S_ENOTIMPL,
VENC_S_ENOTPMEM,
VENC_S_EFLUSHED,
VENC_S_EINSUFBUF,
VENC_S_ESAMESTATE,
VENC_S_EINVALTRANS
};
enum venc_mem_region_enum {
VENC_PMEM_EBI1,
VENC_PMEM_SMI
};
struct venc_buf_type {
unsigned int region;
unsigned int phys;
unsigned int size;
int offset;
};
struct venc_qp_range {
unsigned int min_qp;
unsigned int max_qp;
};
struct venc_frame_rate {
unsigned int frame_rate_num;
unsigned int frame_rate_den;
};
struct venc_slice_info {
unsigned int slice_mode;
unsigned int units_per_slice;
};
struct venc_extra_data {
unsigned int slice_extra_data_flag;
unsigned int slice_client_data1;
unsigned int slice_client_data2;
unsigned int slice_client_data3;
unsigned int none_extra_data_flag;
unsigned int none_client_data1;
unsigned int none_client_data2;
unsigned int none_client_data3;
};
struct venc_common_config {
unsigned int standard;
unsigned int input_frame_height;
unsigned int input_frame_width;
unsigned int output_frame_height;
unsigned int output_frame_width;
unsigned int rotation_angle;
unsigned int intra_period;
unsigned int rate_control;
struct venc_frame_rate frame_rate;
unsigned int bitrate;
struct venc_qp_range qp_range;
unsigned int iframe_qp;
unsigned int pframe_qp;
struct venc_slice_info slice_config;
struct venc_extra_data extra_data;
};
struct venc_nonio_buf_config {
struct venc_buf_type recon_buf1;
struct venc_buf_type recon_buf2;
struct venc_buf_type wb_buf;
struct venc_buf_type cmd_buf;
struct venc_buf_type vlc_buf;
};
struct venc_mpeg4_config {
unsigned int profile;
unsigned int level;
unsigned int time_resolution;
unsigned int ac_prediction;
unsigned int hec_interval;
unsigned int data_partition;
unsigned int short_header;
unsigned int rvlc_enable;
};
struct venc_h263_config {
unsigned int profile;
unsigned int level;
};
struct venc_h264_config {
unsigned int profile;
unsigned int level;
unsigned int max_nal;
unsigned int idr_period;
};
struct venc_pmem {
int src;
int fd;
unsigned long offset;
unsigned long size;
unsigned int offset;
void *virt;
void *phys;
unsigned int size;
};
struct q6_init_config {
unsigned short venc_standard;
unsigned short partial_run_length_flag;
unsigned short h263_annex_ispt;
unsigned short h263_annex_jspt;
unsigned short h263_annex_tspt;
unsigned short rc_flag;
unsigned short one_mv_flag;
unsigned short acdc_pred_enable;
unsigned short rounding_bit_ctrl;
unsigned short rotation_flag;
unsigned short max_mvx;
unsigned short max_mvy;
unsigned short enc_frame_height_inmb;
unsigned short enc_frame_width_inmb;
unsigned short dvs_frame_height;
unsigned short dvs_frame_width;
struct venc_buffer {
unsigned char *ptr_buffer;
unsigned int size;
unsigned int len;
unsigned int offset;
long long time_stamp;
unsigned int flags;
unsigned int client_data;
/* unused by userspace, filled in by kernel */
unsigned int ref_frame_buf1_phy;
unsigned int ref_frame_buf2_phy;
unsigned int rlc_buf1_phy;
unsigned int rlc_buf2_phy;
unsigned int rlc_buf_length;
};
struct init_config {
struct venc_buf ref_frame_buf1;
struct venc_buf ref_frame_buf2;
struct venc_buf rlc_buf1;
struct venc_buf rlc_buf2;
struct q6_init_config q6_init_config;
struct venc_buffers {
struct venc_pmem recon_buf[VENC_MAX_RECON_BUFFERS];
struct venc_pmem wb_buf;
struct venc_pmem cmd_buf;
struct venc_pmem vlc_buf;
};
struct q6_encode_param {
unsigned int luma_addr;
unsigned int chroma_addr;
unsigned int x_offset;
unsigned int y_offset;
unsigned int frame_rho_budget;
unsigned int frame_type;
unsigned int qp;
struct venc_buffer_flush {
unsigned int flush_mode;
};
struct encode_param {
struct venc_buf y_addr;
unsigned long uv_offset;
struct q6_encode_param q6_encode_param;
union venc_msg_data {
struct venc_buffer buf;
struct venc_buffer_flush flush_ret;
};
struct intra_refresh {
unsigned int intra_refresh_enable;
unsigned int intra_mb_num;
struct venc_msg {
unsigned int status_code;
unsigned int msg_code;
union venc_msg_data msg_data;
unsigned int msg_data_size;
};
struct rc_config {
unsigned short max_frame_qp_up_delta;
unsigned short max_frame_qp_down_delta;
unsigned short min_frame_qp;
unsigned short max_frame_qp;
union venc_codec_config {
struct venc_mpeg4_config mpeg4_params;
struct venc_h263_config h263_params;
struct venc_h264_config h264_params;
};
struct q6_frame_type {
unsigned int frame_type;
unsigned int frame_len;
unsigned int frame_addr;
unsigned int map_table;
struct venc_q6_config {
struct venc_common_config config_params;
union venc_codec_config codec_params;
struct venc_nonio_buf_config buf_params;
void *callback_event;
};
struct frame_type {
struct venc_buf frame_addr;
struct q6_frame_type q6_frame_type;
struct venc_hdr_config {
struct venc_common_config config_params;
union venc_codec_config codec_params;
};
struct venc_init_config {
struct venc_q6_config q6_config;
struct venc_buffers q6_bufs;
};
struct venc_seq_config {
int size;
struct venc_pmem buf;
struct venc_q6_config q6_config;
};
struct venc_version {
u32 major;
u32 minor;
};
#define VENC_IOCTL_MAGIC 'V'
#define VENC_IOCTL_INITIALIZE _IOW(VENC_IOCTL_MAGIC, 1, struct init_config)
#define VENC_IOCTL_ENCODE _IOW(VENC_IOCTL_MAGIC, 2, struct encode_param)
#define VENC_IOCTL_INTRA_REFRESH _IOW(VENC_IOCTL_MAGIC, 3, struct intra_refresh)
#define VENC_IOCTL_RC_CONFIG _IOW(VENC_IOCTL_MAGIC, 4, struct rc_config)
#define VENC_IOCTL_ENCODE_CONFIG _IOW(VENC_IOCTL_MAGIC, 5, struct init_config)
#define VENC_IOCTL_STOP _IO(VENC_IOCTL_MAGIC, 6)
#define VENC_IOCTL_WAIT_FOR_ENCODE _IOR(VENC_IOCTL_MAGIC, 7, struct frame_type)
#define VENC_IOCTL_STOP_ENCODE _IO(VENC_IOCTL_MAGIC, 8)
#define VENC_IOCTL_CMD_READ_NEXT_MSG \
_IOWR(VENC_IOCTL_MAGIC, 1, struct venc_msg)
#endif /* _MSM_VENC_H_ */
#define VENC_IOCTL_CMD_STOP_READ_MSG _IO(VENC_IOCTL_MAGIC, 2)
#define VENC_IOCTL_SET_INPUT_BUFFER \
_IOW(VENC_IOCTL_MAGIC, 3, struct venc_pmem)
#define VENC_IOCTL_SET_OUTPUT_BUFFER \
_IOW(VENC_IOCTL_MAGIC, 4, struct venc_pmem)
#define VENC_IOCTL_CMD_START _IOW(VENC_IOCTL_MAGIC, 5, struct venc_init_config)
#define VENC_IOCTL_CMD_ENCODE_FRAME \
_IOW(VENC_IOCTL_MAGIC, 6, struct venc_buffer)
#define VENC_IOCTL_CMD_FILL_OUTPUT_BUFFER \
_IOW(VENC_IOCTL_MAGIC, 7, struct venc_buffer)
#define VENC_IOCTL_CMD_FLUSH \
_IOW(VENC_IOCTL_MAGIC, 8, struct venc_buffer_flush)
#define VENC_IOCTL_CMD_PAUSE _IO(VENC_IOCTL_MAGIC, 9)
#define VENC_IOCTL_CMD_RESUME _IO(VENC_IOCTL_MAGIC, 10)
#define VENC_IOCTL_CMD_STOP _IO(VENC_IOCTL_MAGIC, 11)
#define VENC_IOCTL_SET_INTRA_PERIOD \
_IOW(VENC_IOCTL_MAGIC, 12, int)
#define VENC_IOCTL_CMD_REQUEST_IFRAME _IO(VENC_IOCTL_MAGIC, 13)
#define VENC_IOCTL_GET_SEQUENCE_HDR \
_IOWR(VENC_IOCTL_MAGIC, 14, struct venc_seq_config)
#define VENC_IOCTL_SET_INTRA_REFRESH \
_IOW(VENC_IOCTL_MAGIC, 15, int)
#define VENC_IOCTL_SET_FRAME_RATE \
_IOW(VENC_IOCTL_MAGIC, 16, struct venc_frame_rate)
#define VENC_IOCTL_SET_TARGET_BITRATE \
_IOW(VENC_IOCTL_MAGIC, 17, int)
#define VENC_IOCTL_SET_QP_RANGE \
_IOW(VENC_IOCTL_MAGIC, 18, struct venc_qp_range)
#define VENC_IOCTL_GET_VERSION \
_IOR(VENC_IOCTL_MAGIC, 19, struct venc_version)
#endif