Commit caff4cae authored by Iliyan Malchev's avatar Iliyan Malchev Committed by Greg Kroah-Hartman

Staging: HTC Dream: add qdsp support

QDSP code is neccessarry for communication with some hardware
components on HTC Dream, including camera hardware. It also drives DSP
coproccessor.
Signed-off-by: default avatarPavel Machek <pavel@ucw.cz>
Cc: Brian Swetland <swetland@google.com>
Cc: Iliyan Malchev <ibm@android.com>
Cc: San Mehat <san@android.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 7bf06dac
obj-y += adsp.o
ifeq ($(CONFIG_MSM_AMSS_VERSION_6350),y)
obj-y += adsp_info.o
obj-y += audio_evrc.o audio_qcelp.o audio_amrnb.o audio_aac.o
else
obj-y += adsp_6225.o
endif
obj-y += adsp_driver.o
obj-y += adsp_video_verify_cmd.o
obj-y += adsp_videoenc_verify_cmd.o
obj-y += adsp_jpeg_verify_cmd.o adsp_jpeg_patch_event.o
obj-y += adsp_vfe_verify_cmd.o adsp_vfe_patch_event.o
obj-y += adsp_lpm_verify_cmd.o
obj-y += audio_out.o audio_in.o audio_mp3.o audmgr.o audpp.o
obj-y += snd.o
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* arch/arm/mach-msm/adsp_info.c
*
* Copyright (c) 2008 QUALCOMM Incorporated.
* Copyright (c) 2008 QUALCOMM USA, INC.
*
* 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 "adsp.h"
/* Firmware modules */
#define QDSP_MODULE_KERNEL 0x0106dd4e
#define QDSP_MODULE_AFETASK 0x0106dd6f
#define QDSP_MODULE_AUDPLAY0TASK 0x0106dd70
#define QDSP_MODULE_AUDPLAY1TASK 0x0106dd71
#define QDSP_MODULE_AUDPPTASK 0x0106dd72
#define QDSP_MODULE_VIDEOTASK 0x0106dd73
#define QDSP_MODULE_VIDEO_AAC_VOC 0x0106dd74
#define QDSP_MODULE_PCM_DEC 0x0106dd75
#define QDSP_MODULE_AUDIO_DEC_MP3 0x0106dd76
#define QDSP_MODULE_AUDIO_DEC_AAC 0x0106dd77
#define QDSP_MODULE_AUDIO_DEC_WMA 0x0106dd78
#define QDSP_MODULE_HOSTPCM 0x0106dd79
#define QDSP_MODULE_DTMF 0x0106dd7a
#define QDSP_MODULE_AUDRECTASK 0x0106dd7b
#define QDSP_MODULE_AUDPREPROCTASK 0x0106dd7c
#define QDSP_MODULE_SBC_ENC 0x0106dd7d
#define QDSP_MODULE_VOC_UMTS 0x0106dd9a
#define QDSP_MODULE_VOC_CDMA 0x0106dd98
#define QDSP_MODULE_VOC_PCM 0x0106dd7f
#define QDSP_MODULE_VOCENCTASK 0x0106dd80
#define QDSP_MODULE_VOCDECTASK 0x0106dd81
#define QDSP_MODULE_VOICEPROCTASK 0x0106dd82
#define QDSP_MODULE_VIDEOENCTASK 0x0106dd83
#define QDSP_MODULE_VFETASK 0x0106dd84
#define QDSP_MODULE_WAV_ENC 0x0106dd85
#define QDSP_MODULE_AACLC_ENC 0x0106dd86
#define QDSP_MODULE_VIDEO_AMR 0x0106dd87
#define QDSP_MODULE_VOC_AMR 0x0106dd88
#define QDSP_MODULE_VOC_EVRC 0x0106dd89
#define QDSP_MODULE_VOC_13K 0x0106dd8a
#define QDSP_MODULE_VOC_FGV 0x0106dd8b
#define QDSP_MODULE_DIAGTASK 0x0106dd8c
#define QDSP_MODULE_JPEGTASK 0x0106dd8d
#define QDSP_MODULE_LPMTASK 0x0106dd8e
#define QDSP_MODULE_QCAMTASK 0x0106dd8f
#define QDSP_MODULE_MODMATHTASK 0x0106dd90
#define QDSP_MODULE_AUDPLAY2TASK 0x0106dd91
#define QDSP_MODULE_AUDPLAY3TASK 0x0106dd92
#define QDSP_MODULE_AUDPLAY4TASK 0x0106dd93
#define QDSP_MODULE_GRAPHICSTASK 0x0106dd94
#define QDSP_MODULE_MIDI 0x0106dd95
#define QDSP_MODULE_GAUDIO 0x0106dd96
#define QDSP_MODULE_VDEC_LP_MODE 0x0106dd97
#define QDSP_MODULE_MAX 0x7fffffff
/* DO NOT USE: Force this enum to be a 32bit type to improve speed */
#define QDSP_MODULE_32BIT_DUMMY 0x10000
static uint32_t *qdsp_task_to_module[IMG_MAX];
static uint32_t *qdsp_queue_offset_table[IMG_MAX];
#define QDSP_MODULE(n, clkname, clkrate, verify_cmd_func, patch_event_func) \
{ .name = #n, .pdev_name = "adsp_" #n, .id = QDSP_MODULE_##n, \
.clk_name = clkname, .clk_rate = clkrate, \
.verify_cmd = verify_cmd_func, .patch_event = patch_event_func }
static struct adsp_module_info module_info[] = {
QDSP_MODULE(AUDPLAY0TASK, NULL, 0, NULL, NULL),
QDSP_MODULE(AUDPPTASK, NULL, 0, NULL, NULL),
QDSP_MODULE(AUDRECTASK, NULL, 0, NULL, NULL),
QDSP_MODULE(AUDPREPROCTASK, NULL, 0, NULL, NULL),
QDSP_MODULE(VFETASK, "vfe_clk", 0, adsp_vfe_verify_cmd,
adsp_vfe_patch_event),
QDSP_MODULE(QCAMTASK, NULL, 0, NULL, NULL),
QDSP_MODULE(LPMTASK, NULL, 0, adsp_lpm_verify_cmd, NULL),
QDSP_MODULE(JPEGTASK, "vdc_clk", 96000000, adsp_jpeg_verify_cmd,
adsp_jpeg_patch_event),
QDSP_MODULE(VIDEOTASK, "vdc_clk", 96000000,
adsp_video_verify_cmd, NULL),
QDSP_MODULE(VDEC_LP_MODE, NULL, 0, NULL, NULL),
QDSP_MODULE(VIDEOENCTASK, "vdc_clk", 96000000,
adsp_videoenc_verify_cmd, NULL),
};
int adsp_init_info(struct adsp_info *info)
{
uint32_t img_num;
info->send_irq = 0x00c00200;
info->read_ctrl = 0x00400038;
info->write_ctrl = 0x00400034;
info->max_msg16_size = 193;
info->max_msg32_size = 8;
for (img_num = 0; img_num < IMG_MAX; img_num++)
qdsp_queue_offset_table[img_num] =
&info->init_info_ptr->queue_offsets[img_num][0];
for (img_num = 0; img_num < IMG_MAX; img_num++)
qdsp_task_to_module[img_num] =
&info->init_info_ptr->task_to_module_tbl[img_num][0];
info->max_task_id = 30;
info->max_module_id = QDSP_MODULE_MAX - 1;
info->max_queue_id = QDSP_MAX_NUM_QUEUES;
info->max_image_id = 2;
info->queue_offset = qdsp_queue_offset_table;
info->task_to_module = qdsp_task_to_module;
info->module_count = ARRAY_SIZE(module_info);
info->module = module_info;
return 0;
}
/* arch/arm/mach-msm/qdsp5/adsp_jpeg_patch_event.c
*
* Verification code for aDSP JPEG events.
*
* Copyright (c) 2008 QUALCOMM Incorporated
* Copyright (C) 2008 Google, Inc.
*
* 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 <mach/qdsp5/qdsp5jpegmsg.h>
#include "adsp.h"
int adsp_jpeg_patch_event(struct msm_adsp_module *module,
struct adsp_event *event)
{
if (event->msg_id == JPEG_MSG_ENC_OP_PRODUCED) {
jpeg_msg_enc_op_produced *op = (jpeg_msg_enc_op_produced *)event->data.msg16;
return adsp_pmem_paddr_fixup(module, (void **)&op->op_buf_addr);
}
return 0;
}
/* arch/arm/mach-msm/qdsp5/adsp_jpeg_verify_cmd.c
*
* Verification code for aDSP JPEG packets from userspace.
*
* Copyright (c) 2008 QUALCOMM Incorporated
* Copyright (C) 2008 Google, Inc.
*
* 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 <mach/qdsp5/qdsp5jpegcmdi.h>
#include "adsp.h"
static uint32_t dec_fmt;
static inline void get_sizes(jpeg_cmd_enc_cfg *cmd, uint32_t *luma_size,
uint32_t *chroma_size)
{
uint32_t fmt, luma_width, luma_height;
fmt = cmd->process_cfg & JPEG_CMD_ENC_PROCESS_CFG_IP_DATA_FORMAT_M;
luma_width = (cmd->ip_size_cfg & JPEG_CMD_IP_SIZE_CFG_LUMA_WIDTH_M)
>> 16;
luma_height = cmd->frag_cfg & JPEG_CMD_FRAG_SIZE_LUMA_HEIGHT_M;
*luma_size = luma_width * luma_height;
if (fmt == JPEG_CMD_ENC_PROCESS_CFG_IP_DATA_FORMAT_H2V2)
*chroma_size = *luma_size/2;
else
*chroma_size = *luma_size;
}
static inline int verify_jpeg_cmd_enc_cfg(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
jpeg_cmd_enc_cfg *cmd = (jpeg_cmd_enc_cfg *)cmd_data;
uint32_t luma_size, chroma_size;
int i, num_frags;
if (cmd_size != sizeof(jpeg_cmd_enc_cfg)) {
printk(KERN_ERR "adsp: module %s: JPEG ENC CFG invalid cmd_size %d\n",
module->name, cmd_size);
return -1;
}
get_sizes(cmd, &luma_size, &chroma_size);
num_frags = (cmd->process_cfg >> 10) & 0xf;
num_frags = ((num_frags == 1) ? num_frags : num_frags * 2);
for (i = 0; i < num_frags; i += 2) {
if (adsp_pmem_fixup(module, (void **)(&cmd->frag_cfg_part[i]), luma_size) ||
adsp_pmem_fixup(module, (void **)(&cmd->frag_cfg_part[i+1]), chroma_size))
return -1;
}
if (adsp_pmem_fixup(module, (void **)&cmd->op_buf_0_cfg_part1,
cmd->op_buf_0_cfg_part2) ||
adsp_pmem_fixup(module, (void **)&cmd->op_buf_1_cfg_part1,
cmd->op_buf_1_cfg_part2))
return -1;
return 0;
}
static inline int verify_jpeg_cmd_dec_cfg(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
jpeg_cmd_dec_cfg *cmd = (jpeg_cmd_dec_cfg *)cmd_data;
uint32_t div;
if (cmd_size != sizeof(jpeg_cmd_dec_cfg)) {
printk(KERN_ERR "adsp: module %s: JPEG DEC CFG invalid cmd_size %d\n",
module->name, cmd_size);
return -1;
}
if (adsp_pmem_fixup(module, (void **)&cmd->ip_stream_buf_cfg_part1,
cmd->ip_stream_buf_cfg_part2) ||
adsp_pmem_fixup(module, (void **)&cmd->op_stream_buf_0_cfg_part1,
cmd->op_stream_buf_0_cfg_part2) ||
adsp_pmem_fixup(module, (void **)&cmd->op_stream_buf_1_cfg_part1,
cmd->op_stream_buf_1_cfg_part2))
return -1;
dec_fmt = cmd->op_data_format &
JPEG_CMD_DEC_OP_DATA_FORMAT_M;
div = (dec_fmt == JPEG_CMD_DEC_OP_DATA_FORMAT_H2V2) ? 2 : 1;
if (adsp_pmem_fixup(module, (void **)&cmd->op_stream_buf_0_cfg_part3,
cmd->op_stream_buf_0_cfg_part2 / div) ||
adsp_pmem_fixup(module, (void **)&cmd->op_stream_buf_1_cfg_part3,
cmd->op_stream_buf_1_cfg_part2 / div))
return -1;
return 0;
}
static int verify_jpeg_cfg_cmd(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
uint32_t cmd_id = ((uint32_t *)cmd_data)[0];
switch(cmd_id) {
case JPEG_CMD_ENC_CFG:
return verify_jpeg_cmd_enc_cfg(module, cmd_data, cmd_size);
case JPEG_CMD_DEC_CFG:
return verify_jpeg_cmd_dec_cfg(module, cmd_data, cmd_size);
default:
if (cmd_id > 1) {
printk(KERN_ERR "adsp: module %s: invalid JPEG CFG cmd_id %d\n", module->name, cmd_id);
return -1;
}
}
return 0;
}
static int verify_jpeg_action_cmd(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
uint32_t cmd_id = ((uint32_t *)cmd_data)[0];
switch (cmd_id) {
case JPEG_CMD_ENC_OP_CONSUMED:
{
jpeg_cmd_enc_op_consumed *cmd =
(jpeg_cmd_enc_op_consumed *)cmd_data;
if (cmd_size != sizeof(jpeg_cmd_enc_op_consumed)) {
printk(KERN_ERR "adsp: module %s: JPEG_CMD_ENC_OP_CONSUMED invalid size %d\n",
module->name, cmd_size);
return -1;
}
if (adsp_pmem_fixup(module, (void **)&cmd->op_buf_addr,
cmd->op_buf_size))
return -1;
}
break;
case JPEG_CMD_DEC_OP_CONSUMED:
{
uint32_t div;
jpeg_cmd_dec_op_consumed *cmd =
(jpeg_cmd_dec_op_consumed *)cmd_data;
if (cmd_size != sizeof(jpeg_cmd_enc_op_consumed)) {
printk(KERN_ERR "adsp: module %s: JPEG_CMD_DEC_OP_CONSUMED invalid size %d\n",
module->name, cmd_size);
return -1;
}
div = (dec_fmt == JPEG_CMD_DEC_OP_DATA_FORMAT_H2V2) ? 2 : 1;
if (adsp_pmem_fixup(module, (void **)&cmd->luma_op_buf_addr,
cmd->luma_op_buf_size) ||
adsp_pmem_fixup(module, (void **)&cmd->chroma_op_buf_addr,
cmd->luma_op_buf_size / div))
return -1;
}
break;
default:
if (cmd_id > 7) {
printk(KERN_ERR "adsp: module %s: invalid cmd_id %d\n",
module->name, cmd_id);
return -1;
}
}
return 0;
}
int adsp_jpeg_verify_cmd(struct msm_adsp_module *module,
unsigned int queue_id, void *cmd_data,
size_t cmd_size)
{
switch(queue_id) {
case QDSP_uPJpegCfgCmdQueue:
return verify_jpeg_cfg_cmd(module, cmd_data, cmd_size);
case QDSP_uPJpegActionCmdQueue:
return verify_jpeg_action_cmd(module, cmd_data, cmd_size);
default:
return -1;
}
}
/* arch/arm/mach-msm/qdsp5/adsp_lpm_verify_cmd.c
*
* Verificion code for aDSP LPM packets from userspace.
*
* Copyright (c) 2008 QUALCOMM Incorporated
* Copyright (C) 2008 Google, Inc.
*
* 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 <mach/qdsp5/qdsp5lpmcmdi.h>
#include "adsp.h"
int adsp_lpm_verify_cmd(struct msm_adsp_module *module,
unsigned int queue_id, void *cmd_data,
size_t cmd_size)
{
uint32_t cmd_id, col_height, input_row_incr, output_row_incr,
input_size, output_size;
uint32_t size_mask = 0x0fff;
lpm_cmd_start *cmd;
if (queue_id != QDSP_lpmCommandQueue) {
printk(KERN_ERR "adsp: module %s: wrong queue id %d\n",
module->name, queue_id);
return -1;
}
cmd = (lpm_cmd_start *)cmd_data;
cmd_id = cmd->cmd_id;
if (cmd_id == LPM_CMD_START) {
if (cmd_size != sizeof(lpm_cmd_start)) {
printk(KERN_ERR "adsp: module %s: wrong size %d, expect %d\n",
module->name, cmd_size, sizeof(lpm_cmd_start));
return -1;
}
col_height = cmd->ip_data_cfg_part1 & size_mask;
input_row_incr = cmd->ip_data_cfg_part2 & size_mask;
output_row_incr = cmd->op_data_cfg_part1 & size_mask;
input_size = col_height * input_row_incr;
output_size = col_height * output_row_incr;
if ((cmd->ip_data_cfg_part4 && adsp_pmem_fixup(module,
(void **)(&cmd->ip_data_cfg_part4),
input_size)) ||
(cmd->op_data_cfg_part3 && adsp_pmem_fixup(module,
(void **)(&cmd->op_data_cfg_part3),
output_size)))
return -1;
} else if (cmd_id > 1) {
printk(KERN_ERR "adsp: module %s: invalid cmd_id %d\n",
module->name, cmd_id);
return -1;
}
return 0;
}
/* arch/arm/mach-msm/qdsp5/adsp_vfe_patch_event.c
*
* Verification code for aDSP VFE packets from userspace.
*
* Copyright (c) 2008 QUALCOMM Incorporated
* Copyright (C) 2008 Google, Inc.
*
* 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 <mach/qdsp5/qdsp5vfemsg.h>
#include "adsp.h"
static int patch_op_event(struct msm_adsp_module *module,
struct adsp_event *event)
{
vfe_msg_op1 *op = (vfe_msg_op1 *)event->data.msg16;
if (adsp_pmem_paddr_fixup(module, (void **)&op->op1_buf_y_addr) ||
adsp_pmem_paddr_fixup(module, (void **)&op->op1_buf_cbcr_addr))
return -1;
return 0;
}
static int patch_af_wb_event(struct msm_adsp_module *module,
struct adsp_event *event)
{
vfe_msg_stats_wb_exp *af = (vfe_msg_stats_wb_exp *)event->data.msg16;
return adsp_pmem_paddr_fixup(module, (void **)&af->wb_exp_stats_op_buf);
}
int adsp_vfe_patch_event(struct msm_adsp_module *module,
struct adsp_event *event)
{
switch(event->msg_id) {
case VFE_MSG_OP1:
case VFE_MSG_OP2:
return patch_op_event(module, event);
case VFE_MSG_STATS_AF:
case VFE_MSG_STATS_WB_EXP:
return patch_af_wb_event(module, event);
default:
break;
}
return 0;
}
/* arch/arm/mach-msm/qdsp5/adsp_vfe_verify_cmd.c
*
* Verification code for aDSP VFE packets from userspace.
*
* Copyright (c) 2008 QUALCOMM Incorporated
* Copyright (C) 2008 Google, Inc.
*
* 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 <mach/qdsp5/qdsp5vfecmdi.h>
#include "adsp.h"
static uint32_t size1_y, size2_y, size1_cbcr, size2_cbcr;
static uint32_t af_size = 4228;
static uint32_t awb_size = 8196;
static inline int verify_cmd_op_ack(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
vfe_cmd_op1_ack *cmd = (vfe_cmd_op1_ack *)cmd_data;
void **addr_y = (void **)&cmd->op1_buf_y_addr;
void **addr_cbcr = (void **)(&cmd->op1_buf_cbcr_addr);
if (cmd_size != sizeof(vfe_cmd_op1_ack))
return -1;
if ((*addr_y && adsp_pmem_fixup(module, addr_y, size1_y)) ||
(*addr_cbcr && adsp_pmem_fixup(module, addr_cbcr, size1_cbcr)))
return -1;
return 0;
}
static inline int verify_cmd_stats_autofocus_cfg(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
int i;
vfe_cmd_stats_autofocus_cfg *cmd =
(vfe_cmd_stats_autofocus_cfg *)cmd_data;
if (cmd_size != sizeof(vfe_cmd_stats_autofocus_cfg))
return -1;
for (i = 0; i < 3; i++) {
void **addr = (void **)(&cmd->af_stats_op_buf[i]);
if (*addr && adsp_pmem_fixup(module, addr, af_size))
return -1;
}
return 0;
}
static inline int verify_cmd_stats_wb_exp_cfg(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
vfe_cmd_stats_wb_exp_cfg *cmd =
(vfe_cmd_stats_wb_exp_cfg *)cmd_data;
int i;
if (cmd_size != sizeof(vfe_cmd_stats_wb_exp_cfg))
return -1;
for (i = 0; i < 3; i++) {
void **addr = (void **)(&cmd->wb_exp_stats_op_buf[i]);
if (*addr && adsp_pmem_fixup(module, addr, awb_size))
return -1;
}
return 0;
}
static inline int verify_cmd_stats_af_ack(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
vfe_cmd_stats_af_ack *cmd = (vfe_cmd_stats_af_ack *)cmd_data;
void **addr = (void **)&cmd->af_stats_op_buf;
if (cmd_size != sizeof(vfe_cmd_stats_af_ack))
return -1;
if (*addr && adsp_pmem_fixup(module, addr, af_size))
return -1;
return 0;
}
static inline int verify_cmd_stats_wb_exp_ack(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
vfe_cmd_stats_wb_exp_ack *cmd =
(vfe_cmd_stats_wb_exp_ack *)cmd_data;
void **addr = (void **)&cmd->wb_exp_stats_op_buf;
if (cmd_size != sizeof(vfe_cmd_stats_wb_exp_ack))
return -1;
if (*addr && adsp_pmem_fixup(module, addr, awb_size))
return -1;
return 0;
}
static int verify_vfe_command(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
uint32_t cmd_id = ((uint32_t *)cmd_data)[0];
switch (cmd_id) {
case VFE_CMD_OP1_ACK:
return verify_cmd_op_ack(module, cmd_data, cmd_size);
case VFE_CMD_OP2_ACK:
return verify_cmd_op_ack(module, cmd_data, cmd_size);
case VFE_CMD_STATS_AUTOFOCUS_CFG:
return verify_cmd_stats_autofocus_cfg(module, cmd_data,
cmd_size);
case VFE_CMD_STATS_WB_EXP_CFG:
return verify_cmd_stats_wb_exp_cfg(module, cmd_data, cmd_size);
case VFE_CMD_STATS_AF_ACK:
return verify_cmd_stats_af_ack(module, cmd_data, cmd_size);
case VFE_CMD_STATS_WB_EXP_ACK:
return verify_cmd_stats_wb_exp_ack(module, cmd_data, cmd_size);
default:
if (cmd_id > 29) {
printk(KERN_ERR "adsp: module %s: invalid VFE command id %d\n", module->name, cmd_id);
return -1;
}
}
return 0;
}
static int verify_vfe_command_scale(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
uint32_t cmd_id = ((uint32_t *)cmd_data)[0];
// FIXME: check the size
if (cmd_id > 1) {
printk(KERN_ERR "adsp: module %s: invalid VFE SCALE command id %d\n", module->name, cmd_id);
return -1;
}
return 0;
}
static uint32_t get_size(uint32_t hw)
{
uint32_t height, width;
uint32_t height_mask = 0x3ffc;
uint32_t width_mask = 0x3ffc000;
height = (hw & height_mask) >> 2;
width = (hw & width_mask) >> 14 ;
return height * width;
}
static int verify_vfe_command_table(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
uint32_t cmd_id = ((uint32_t *)cmd_data)[0];
int i;
switch (cmd_id) {
case VFE_CMD_AXI_IP_CFG:
{
vfe_cmd_axi_ip_cfg *cmd = (vfe_cmd_axi_ip_cfg *)cmd_data;
uint32_t size;
if (cmd_size != sizeof(vfe_cmd_axi_ip_cfg)) {
printk(KERN_ERR "adsp: module %s: invalid VFE TABLE (VFE_CMD_AXI_IP_CFG) command size %d\n",
module->name, cmd_size);
return -1;
}
size = get_size(cmd->ip_cfg_part2);
for (i = 0; i < 8; i++) {
void **addr = (void **)
&cmd->ip_buf_addr[i];
if (*addr && adsp_pmem_fixup(module, addr, size))
return -1;
}
}
case VFE_CMD_AXI_OP_CFG:
{
vfe_cmd_axi_op_cfg *cmd = (vfe_cmd_axi_op_cfg *)cmd_data;
void **addr1_y, **addr2_y, **addr1_cbcr, **addr2_cbcr;
if (cmd_size != sizeof(vfe_cmd_axi_op_cfg)) {
printk(KERN_ERR "adsp: module %s: invalid VFE TABLE (VFE_CMD_AXI_OP_CFG) command size %d\n",
module->name, cmd_size);
return -1;
}
size1_y = get_size(cmd->op1_y_cfg_part2);
size1_cbcr = get_size(cmd->op1_cbcr_cfg_part2);
size2_y = get_size(cmd->op2_y_cfg_part2);
size2_cbcr = get_size(cmd->op2_cbcr_cfg_part2);
for (i = 0; i < 8; i++) {
addr1_y = (void **)(&cmd->op1_buf1_addr[2*i]);
addr1_cbcr = (void **)(&cmd->op1_buf1_addr[2*i+1]);
addr2_y = (void **)(&cmd->op2_buf1_addr[2*i]);
addr2_cbcr = (void **)(&cmd->op2_buf1_addr[2*i+1]);
/*
printk("module %s: [%d] %p %p %p %p\n",
module->name, i,
*addr1_y, *addr1_cbcr, *addr2_y, *addr2_cbcr);
*/
if ((*addr1_y && adsp_pmem_fixup(module, addr1_y, size1_y)) ||
(*addr1_cbcr && adsp_pmem_fixup(module, addr1_cbcr, size1_cbcr)) ||
(*addr2_y && adsp_pmem_fixup(module, addr2_y, size2_y)) ||
(*addr2_cbcr && adsp_pmem_fixup(module, addr2_cbcr, size2_cbcr)))
return -1;
}
}
default:
if (cmd_id > 4) {
printk(KERN_ERR "adsp: module %s: invalid VFE TABLE command id %d\n",
module->name, cmd_id);
return -1;
}
}
return 0;
}
int adsp_vfe_verify_cmd(struct msm_adsp_module *module,
unsigned int queue_id, void *cmd_data,
size_t cmd_size)
{
switch (queue_id) {
case QDSP_vfeCommandQueue:
return verify_vfe_command(module, cmd_data, cmd_size);
case QDSP_vfeCommandScaleQueue:
return verify_vfe_command_scale(module, cmd_data, cmd_size);
case QDSP_vfeCommandTableQueue:
return verify_vfe_command_table(module, cmd_data, cmd_size);
default:
printk(KERN_ERR "adsp: module %s: unknown queue id %d\n",
module->name, queue_id);
return -1;
}
}
/* arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
*
* Verificion code for aDSP VDEC packets from userspace.
*
* Copyright (c) 2008 QUALCOMM Incorporated
* Copyright (C) 2008 Google, Inc.
*
* 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/io.h>
#define ADSP_DEBUG_MSGS 0
#if ADSP_DEBUG_MSGS
#define DLOG(fmt,args...) \
do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
##args); } \
while (0)
#else
#define DLOG(x...) do {} while (0)
#endif
#include <mach/qdsp5/qdsp5vdeccmdi.h>
#include "adsp.h"
static inline void *high_low_short_to_ptr(unsigned short high,
unsigned short low)
{
return (void *)((((unsigned long)high) << 16) | ((unsigned long)low));
}
static inline void ptr_to_high_low_short(void *ptr, unsigned short *high,
unsigned short *low)
{
*high = (unsigned short)((((unsigned long)ptr) >> 16) & 0xffff);
*low = (unsigned short)((unsigned long)ptr & 0xffff);
}
static int pmem_fixup_high_low(unsigned short *high,
unsigned short *low,
unsigned short size_high,
unsigned short size_low,
struct msm_adsp_module *module,
unsigned long *addr, unsigned long *size)
{
void *phys_addr;
unsigned long phys_size;
unsigned long kvaddr;
phys_addr = high_low_short_to_ptr(*high, *low);
phys_size = (unsigned long)high_low_short_to_ptr(size_high, size_low);
DLOG("virt %x %x\n", phys_addr, phys_size);
if (adsp_pmem_fixup_kvaddr(module, &phys_addr, &kvaddr, phys_size)) {
DLOG("ah%x al%x sh%x sl%x addr %x size %x\n",
*high, *low, size_high, size_low, phys_addr, phys_size);
return -1;
}
ptr_to_high_low_short(phys_addr, high, low);
DLOG("phys %x %x\n", phys_addr, phys_size);
if (addr)
*addr = kvaddr;
if (size)
*size = phys_size;
return 0;
}
static int verify_vdec_pkt_cmd(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
unsigned short cmd_id = ((unsigned short *)cmd_data)[0];
viddec_cmd_subframe_pkt *pkt;
unsigned long subframe_pkt_addr;
unsigned long subframe_pkt_size;
viddec_cmd_frame_header_packet *frame_header_pkt;
int i, num_addr, skip;
unsigned short *frame_buffer_high, *frame_buffer_low;
unsigned long frame_buffer_size;
unsigned short frame_buffer_size_high, frame_buffer_size_low;
DLOG("cmd_size %d cmd_id %d cmd_data %x\n", cmd_size, cmd_id, cmd_data);
if (cmd_id != VIDDEC_CMD_SUBFRAME_PKT) {
printk(KERN_INFO "adsp_video: unknown video packet %u\n",
cmd_id);
return 0;
}
if (cmd_size < sizeof(viddec_cmd_subframe_pkt))
return -1;
pkt = (viddec_cmd_subframe_pkt *)cmd_data;
if (pmem_fixup_high_low(&(pkt->subframe_packet_high),
&(pkt->subframe_packet_low),
pkt->subframe_packet_size_high,
pkt->subframe_packet_size_low,
module,
&subframe_pkt_addr,
&subframe_pkt_size))
return -1;
/* deref those ptrs and check if they are a frame header packet */
frame_header_pkt = (viddec_cmd_frame_header_packet *)subframe_pkt_addr;
switch (frame_header_pkt->packet_id) {
case 0xB201: /* h.264 */
num_addr = skip = 8;
break;
case 0x4D01: /* mpeg-4 and h.263 */
num_addr = 3;
skip = 0;
break;
default:
return 0;
}
frame_buffer_high = &frame_header_pkt->frame_buffer_0_high;
frame_buffer_low = &frame_header_pkt->frame_buffer_0_low;
frame_buffer_size = (frame_header_pkt->x_dimension *
frame_header_pkt->y_dimension * 3) / 2;
ptr_to_high_low_short((void *)frame_buffer_size,
&frame_buffer_size_high,
&frame_buffer_size_low);
for (i = 0; i < num_addr; i++) {
if (pmem_fixup_high_low(frame_buffer_high, frame_buffer_low,
frame_buffer_size_high,
frame_buffer_size_low,
module,
NULL, NULL))
return -1;
frame_buffer_high += 2;
frame_buffer_low += 2;
}
/* Patch the output buffer. */
frame_buffer_high += 2*skip;
frame_buffer_low += 2*skip;
if (pmem_fixup_high_low(frame_buffer_high, frame_buffer_low,
frame_buffer_size_high,
frame_buffer_size_low, module, NULL, NULL))
return -1;
return 0;
}
int adsp_video_verify_cmd(struct msm_adsp_module *module,
unsigned int queue_id, void *cmd_data,
size_t cmd_size)
{
switch (queue_id) {
case QDSP_mpuVDecPktQueue:
DLOG("\n");
return verify_vdec_pkt_cmd(module, cmd_data, cmd_size);
default:
printk(KERN_INFO "unknown video queue %u\n", queue_id);
return 0;
}
}
/* arch/arm/mach-msm/qdsp5/adsp_video_verify_cmd.c
*
* Verificion code for aDSP VENC packets from userspace.
*
* Copyright (c) 2008 QUALCOMM Incorporated
* Copyright (C) 2008 Google, Inc.
*
* 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/io.h>
#define ADSP_DEBUG_MSGS 0
#if ADSP_DEBUG_MSGS
#define DLOG(fmt,args...) \
do { printk(KERN_INFO "[%s:%s:%d] "fmt, __FILE__, __func__, __LINE__, \
##args); } \
while (0)
#else
#define DLOG(x...) do {} while (0)
#endif
#include <mach/qdsp5/qdsp5venccmdi.h>
#include "adsp.h"
static unsigned short x_dimension, y_dimension;
static inline void *high_low_short_to_ptr(unsigned short high,
unsigned short low)
{
return (void *)((((unsigned long)high) << 16) | ((unsigned long)low));
}
static inline void ptr_to_high_low_short(void *ptr, unsigned short *high,
unsigned short *low)
{
*high = (unsigned short)((((unsigned long)ptr) >> 16) & 0xffff);
*low = (unsigned short)((unsigned long)ptr & 0xffff);
}
static int pmem_fixup_high_low(unsigned short *high,
unsigned short *low,
unsigned short size_high,
unsigned short size_low,
struct msm_adsp_module *module,
unsigned long *addr, unsigned long *size)
{
void *phys_addr;
unsigned long phys_size;
unsigned long kvaddr;
phys_addr = high_low_short_to_ptr(*high, *low);
phys_size = (unsigned long)high_low_short_to_ptr(size_high, size_low);
DLOG("virt %x %x\n", phys_addr, phys_size);
if (adsp_pmem_fixup_kvaddr(module, &phys_addr, &kvaddr, phys_size)) {
DLOG("ah%x al%x sh%x sl%x addr %x size %x\n",
*high, *low, size_high, size_low, phys_addr, phys_size);
return -1;
}
ptr_to_high_low_short(phys_addr, high, low);
DLOG("phys %x %x\n", phys_addr, phys_size);
if (addr)
*addr = kvaddr;
if (size)
*size = phys_size;
return 0;
}
static int verify_venc_cmd(struct msm_adsp_module *module,
void *cmd_data, size_t cmd_size)
{
unsigned short cmd_id = ((unsigned short *)cmd_data)[0];
unsigned long frame_buf_size, luma_buf_size, chroma_buf_size;
unsigned short frame_buf_size_high, frame_buf_size_low;
unsigned short luma_buf_size_high, luma_buf_size_low;
unsigned short chroma_buf_size_high, chroma_buf_size_low;
videnc_cmd_cfg *config_cmd;
videnc_cmd_frame_start *frame_cmd;
videnc_cmd_dis *dis_cmd;
DLOG("cmd_size %d cmd_id %d cmd_data %x\n", cmd_size, cmd_id, cmd_data);
switch (cmd_id) {
case VIDENC_CMD_ACTIVE:
if (cmd_size < sizeof(videnc_cmd_active))
return -1;
break;
case VIDENC_CMD_IDLE:
if (cmd_size < sizeof(videnc_cmd_idle))
return -1;
x_dimension = y_dimension = 0;
break;
case VIDENC_CMD_STATUS_QUERY:
if (cmd_size < sizeof(videnc_cmd_status_query))
return -1;
break;
case VIDENC_CMD_RC_CFG:
if (cmd_size < sizeof(videnc_cmd_rc_cfg))
return -1;
break;
case VIDENC_CMD_INTRA_REFRESH:
if (cmd_size < sizeof(videnc_cmd_intra_refresh))
return -1;
break;
case VIDENC_CMD_DIGITAL_ZOOM:
if (cmd_size < sizeof(videnc_cmd_digital_zoom))
return -1;
break;
case VIDENC_CMD_DIS_CFG:
if (cmd_size < sizeof(videnc_cmd_dis_cfg))
return -1;
break;
case VIDENC_CMD_CFG:
if (cmd_size < sizeof(videnc_cmd_cfg))
return -1;
config_cmd = (videnc_cmd_cfg *)cmd_data;
x_dimension = ((config_cmd->venc_frame_dim) & 0xFF00)>>8;
x_dimension = x_dimension*16;
y_dimension = (config_cmd->venc_frame_dim) & 0xFF;
y_dimension = y_dimension * 16;
break;
case VIDENC_CMD_FRAME_START:
if (cmd_size < sizeof(videnc_cmd_frame_start))
return -1;
frame_cmd = (videnc_cmd_frame_start *)cmd_data;
luma_buf_size = x_dimension * y_dimension;
chroma_buf_size = luma_buf_size>>1;
frame_buf_size = luma_buf_size + chroma_buf_size;
ptr_to_high_low_short((void *)luma_buf_size,
&luma_buf_size_high,
&luma_buf_size_low);
ptr_to_high_low_short((void *)chroma_buf_size,
&chroma_buf_size_high,
&chroma_buf_size_low);
ptr_to_high_low_short((void *)frame_buf_size,
&frame_buf_size_high,
&frame_buf_size_low);
/* Address of raw Y data. */
if (pmem_fixup_high_low(&frame_cmd->input_luma_addr_high,
&frame_cmd->input_luma_addr_low,
luma_buf_size_high,
luma_buf_size_low,
module,
NULL, NULL))
return -1;
/* Address of raw CbCr data */
if (pmem_fixup_high_low(&frame_cmd->input_chroma_addr_high,
&frame_cmd->input_chroma_addr_low,
chroma_buf_size_high,
chroma_buf_size_low,
module,
NULL, NULL))
return -1;
/* Reference VOP */
if (pmem_fixup_high_low(&frame_cmd->ref_vop_buf_ptr_high,
&frame_cmd->ref_vop_buf_ptr_low,
frame_buf_size_high,
frame_buf_size_low,
module,
NULL, NULL))
return -1;
/* Encoded Packet Address */
if (pmem_fixup_high_low(&frame_cmd->enc_pkt_buf_ptr_high,
&frame_cmd->enc_pkt_buf_ptr_low,
frame_cmd->enc_pkt_buf_size_high,
frame_cmd->enc_pkt_buf_size_low,
module,
NULL, NULL))
return -1;
/* Unfiltered VOP Buffer Address */
if (pmem_fixup_high_low(
&frame_cmd->unfilt_recon_vop_buf_ptr_high,
&frame_cmd->unfilt_recon_vop_buf_ptr_low,
frame_buf_size_high,
frame_buf_size_low,
module,
NULL, NULL))
return -1;
/* Filtered VOP Buffer Address */
if (pmem_fixup_high_low(&frame_cmd->filt_recon_vop_buf_ptr_high,
&frame_cmd->filt_recon_vop_buf_ptr_low,
frame_buf_size_high,
frame_buf_size_low,
module,
NULL, NULL))
return -1;
break;
case VIDENC_CMD_DIS:
if (cmd_size < sizeof(videnc_cmd_dis))
return -1;
dis_cmd = (videnc_cmd_dis *)cmd_data;
luma_buf_size = x_dimension * y_dimension;
ptr_to_high_low_short((void *)luma_buf_size,
&luma_buf_size_high,
&luma_buf_size_low);
/* Prev VFE Luma Output Address */
if (pmem_fixup_high_low(&dis_cmd->vfe_out_prev_luma_addr_high,
&dis_cmd->vfe_out_prev_luma_addr_low,
luma_buf_size_high,
luma_buf_size_low,
module,
NULL, NULL))
return -1;
break;
default:
printk(KERN_INFO "adsp_video:unknown encoder video command %u\n",
cmd_id);
return 0;
}
return 0;
}
int adsp_videoenc_verify_cmd(struct msm_adsp_module *module,
unsigned int queue_id, void *cmd_data,
size_t cmd_size)
{
switch (queue_id) {
case QDSP_mpuVEncCmdQueue:
DLOG("\n");
return verify_venc_cmd(module, cmd_data, cmd_size);
default:
printk(KERN_INFO "unknown video queue %u\n", queue_id);
return 0;
}
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* arch/arm/mach-msm/qdsp5/audmgr.c
*
* interface to "audmgr" service on the baseband cpu
*
* Copyright (C) 2008 Google, Inc.
*
* 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/module.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/kthread.h>
#include <linux/wait.h>
#include <asm/atomic.h>
#include <mach/msm_rpcrouter.h>
#include "audmgr.h"
#define STATE_CLOSED 0
#define STATE_DISABLED 1
#define STATE_ENABLING 2
#define STATE_ENABLED 3
#define STATE_DISABLING 4
#define STATE_ERROR 5
static void rpc_ack(struct msm_rpc_endpoint *ept, uint32_t xid)
{
uint32_t rep[6];
rep[0] = cpu_to_be32(xid);
rep[1] = cpu_to_be32(1);
rep[2] = cpu_to_be32(RPCMSG_REPLYSTAT_ACCEPTED);
rep[3] = cpu_to_be32(RPC_ACCEPTSTAT_SUCCESS);
rep[4] = 0;
rep[5] = 0;
msm_rpc_write(ept, rep, sizeof(rep));
}
static void process_audmgr_callback(struct audmgr *am,
struct rpc_audmgr_cb_func_ptr *args,
int len)
{
if (len < (sizeof(uint32_t) * 3))
return;
if (be32_to_cpu(args->set_to_one) != 1)
return;
switch (be32_to_cpu(args->status)) {
case RPC_AUDMGR_STATUS_READY:
if (len < sizeof(uint32_t) * 4)
break;
am->handle = be32_to_cpu(args->u.handle);
pr_info("audmgr: rpc READY handle=0x%08x\n", am->handle);
break;
case RPC_AUDMGR_STATUS_CODEC_CONFIG: {
uint32_t volume;
if (len < sizeof(uint32_t) * 4)
break;
volume = be32_to_cpu(args->u.volume);
pr_info("audmgr: rpc CODEC_CONFIG volume=0x%08x\n", volume);
am->state = STATE_ENABLED;
wake_up(&am->wait);
break;
}
case RPC_AUDMGR_STATUS_PENDING:
pr_err("audmgr: PENDING?\n");
break;
case RPC_AUDMGR_STATUS_SUSPEND:
pr_err("audmgr: SUSPEND?\n");
break;
case RPC_AUDMGR_STATUS_FAILURE:
pr_err("audmgr: FAILURE\n");
break;
case RPC_AUDMGR_STATUS_VOLUME_CHANGE:
pr_err("audmgr: VOLUME_CHANGE?\n");
break;
case RPC_AUDMGR_STATUS_DISABLED:
pr_err("audmgr: DISABLED\n");
am->state = STATE_DISABLED;
wake_up(&am->wait);
break;
case RPC_AUDMGR_STATUS_ERROR:
pr_err("audmgr: ERROR?\n");
am->state = STATE_ERROR;
wake_up(&am->wait);
break;
default:
break;
}
}
static void process_rpc_request(uint32_t proc, uint32_t xid,
void *data, int len, void *private)
{
struct audmgr *am = private;
uint32_t *x = data;
if (0) {
int n = len / 4;
pr_info("rpc_call proc %d:", proc);
while (n--)
printk(" %08x", be32_to_cpu(*x++));
printk("\n");
}
if (proc == AUDMGR_CB_FUNC_PTR)
process_audmgr_callback(am, data, len);
else
pr_err("audmgr: unknown rpc proc %d\n", proc);
rpc_ack(am->ept, xid);
}
#define RPC_TYPE_REQUEST 0
#define RPC_TYPE_REPLY 1
#define RPC_VERSION 2
#define RPC_COMMON_HDR_SZ (sizeof(uint32_t) * 2)
#define RPC_REQUEST_HDR_SZ (sizeof(struct rpc_request_hdr))
#define RPC_REPLY_HDR_SZ (sizeof(uint32_t) * 3)
#define RPC_REPLY_SZ (sizeof(uint32_t) * 6)
static int audmgr_rpc_thread(void *data)
{
struct audmgr *am = data;
struct rpc_request_hdr *hdr = NULL;
uint32_t type;
int len;
pr_info("audmgr_rpc_thread() start\n");
while (!kthread_should_stop()) {
if (hdr) {
kfree(hdr);
hdr = NULL;
}
len = msm_rpc_read(am->ept, (void **) &hdr, -1, -1);
if (len < 0) {
pr_err("audmgr: rpc read failed (%d)\n", len);
break;
}
if (len < RPC_COMMON_HDR_SZ)
continue;
type = be32_to_cpu(hdr->type);
if (type == RPC_TYPE_REPLY) {
struct rpc_reply_hdr *rep = (void *) hdr;
uint32_t status;
if (len < RPC_REPLY_HDR_SZ)
continue;
status = be32_to_cpu(rep->reply_stat);
if (status == RPCMSG_REPLYSTAT_ACCEPTED) {
status = be32_to_cpu(rep->data.acc_hdr.accept_stat);
pr_info("audmgr: rpc_reply status %d\n", status);
} else {
pr_info("audmgr: rpc_reply denied!\n");
}
/* process reply */
continue;
}
if (len < RPC_REQUEST_HDR_SZ)
continue;
process_rpc_request(be32_to_cpu(hdr->procedure),
be32_to_cpu(hdr->xid),
(void *) (hdr + 1),
len - sizeof(*hdr),
data);
}
pr_info("audmgr_rpc_thread() exit\n");
if (hdr) {
kfree(hdr);
hdr = NULL;
}
am->task = NULL;
wake_up(&am->wait);
return 0;
}
struct audmgr_enable_msg {
struct rpc_request_hdr hdr;
struct rpc_audmgr_enable_client_args args;
};
struct audmgr_disable_msg {
struct rpc_request_hdr hdr;
uint32_t handle;
};
int audmgr_open(struct audmgr *am)
{
int rc;
if (am->state != STATE_CLOSED)
return 0;
am->ept = msm_rpc_connect(AUDMGR_PROG,
AUDMGR_VERS,
MSM_RPC_UNINTERRUPTIBLE);
init_waitqueue_head(&am->wait);
if (IS_ERR(am->ept)) {
rc = PTR_ERR(am->ept);
am->ept = NULL;
pr_err("audmgr: failed to connect to audmgr svc\n");
return rc;
}
am->task = kthread_run(audmgr_rpc_thread, am, "audmgr_rpc");
if (IS_ERR(am->task)) {
rc = PTR_ERR(am->task);
am->task = NULL;
msm_rpc_close(am->ept);
am->ept = NULL;
return rc;
}
am->state = STATE_DISABLED;
return 0;
}
EXPORT_SYMBOL(audmgr_open);
int audmgr_close(struct audmgr *am)
{
return -EBUSY;
}
EXPORT_SYMBOL(audmgr_close);
int audmgr_enable(struct audmgr *am, struct audmgr_config *cfg)
{
struct audmgr_enable_msg msg;
int rc;
if (am->state == STATE_ENABLED)
return 0;
if (am->state == STATE_DISABLING)
pr_err("audmgr: state is DISABLING in enable?\n");
am->state = STATE_ENABLING;
msg.args.set_to_one = cpu_to_be32(1);
msg.args.tx_sample_rate = cpu_to_be32(cfg->tx_rate);
msg.args.rx_sample_rate = cpu_to_be32(cfg->rx_rate);
msg.args.def_method = cpu_to_be32(cfg->def_method);
msg.args.codec_type = cpu_to_be32(cfg->codec);
msg.args.snd_method = cpu_to_be32(cfg->snd_method);
msg.args.cb_func = cpu_to_be32(0x11111111);
msg.args.client_data = cpu_to_be32(0x11223344);
msm_rpc_setup_req(&msg.hdr, AUDMGR_PROG, msm_rpc_get_vers(am->ept),
AUDMGR_ENABLE_CLIENT);
rc = msm_rpc_write(am->ept, &msg, sizeof(msg));
if (rc < 0)
return rc;
rc = wait_event_timeout(am->wait, am->state != STATE_ENABLING, 15 * HZ);
if (rc == 0) {
pr_err("audmgr_enable: ARM9 did not reply to RPC am->state = %d\n", am->state);
BUG();
}
if (am->state == STATE_ENABLED)
return 0;
pr_err("audmgr: unexpected state %d while enabling?!\n", am->state);
return -ENODEV;
}
EXPORT_SYMBOL(audmgr_enable);
int audmgr_disable(struct audmgr *am)
{
struct audmgr_disable_msg msg;
int rc;
if (am->state == STATE_DISABLED)
return 0;
msm_rpc_setup_req(&msg.hdr, AUDMGR_PROG, msm_rpc_get_vers(am->ept),
AUDMGR_DISABLE_CLIENT);
msg.handle = cpu_to_be32(am->handle);
am->state = STATE_DISABLING;
rc = msm_rpc_write(am->ept, &msg, sizeof(msg));
if (rc < 0)
return rc;
rc = wait_event_timeout(am->wait, am->state != STATE_DISABLING, 15 * HZ);
if (rc == 0) {
pr_err("audmgr_disable: ARM9 did not reply to RPC am->state = %d\n", am->state);
BUG();
}
if (am->state == STATE_DISABLED)
return 0;
pr_err("audmgr: unexpected state %d while disabling?!\n", am->state);
return -ENODEV;
}
EXPORT_SYMBOL(audmgr_disable);
/* arch/arm/mach-msm/qdsp5/audmgr.h
*
* Copyright 2008 (c) QUALCOMM Incorporated.
* Copyright (C) 2008 Google, Inc.
*
* 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.
*
*/
#ifndef _ARCH_ARM_MACH_MSM_AUDMGR_H
#define _ARCH_ARM_MACH_MSM_AUDMGR_H
#if CONFIG_MSM_AMSS_VERSION==6350
#include "audmgr_new.h"
#else
enum rpc_aud_def_sample_rate_type {
RPC_AUD_DEF_SAMPLE_RATE_NONE,
RPC_AUD_DEF_SAMPLE_RATE_8000,
RPC_AUD_DEF_SAMPLE_RATE_11025,
RPC_AUD_DEF_SAMPLE_RATE_12000,
RPC_AUD_DEF_SAMPLE_RATE_16000,
RPC_AUD_DEF_SAMPLE_RATE_22050,
RPC_AUD_DEF_SAMPLE_RATE_24000,
RPC_AUD_DEF_SAMPLE_RATE_32000,
RPC_AUD_DEF_SAMPLE_RATE_44100,
RPC_AUD_DEF_SAMPLE_RATE_48000,
RPC_AUD_DEF_SAMPLE_RATE_MAX,
};
enum rpc_aud_def_method_type {
RPC_AUD_DEF_METHOD_NONE,
RPC_AUD_DEF_METHOD_KEY_BEEP,
RPC_AUD_DEF_METHOD_PLAYBACK,
RPC_AUD_DEF_METHOD_VOICE,
RPC_AUD_DEF_METHOD_RECORD,
RPC_AUD_DEF_METHOD_HOST_PCM,
RPC_AUD_DEF_METHOD_MIDI_OUT,
RPC_AUD_DEF_METHOD_RECORD_SBC,
RPC_AUD_DEF_METHOD_DTMF_RINGER,
RPC_AUD_DEF_METHOD_MAX,
};
enum rpc_aud_def_codec_type {
RPC_AUD_DEF_CODEC_NONE,
RPC_AUD_DEF_CODEC_DTMF,
RPC_AUD_DEF_CODEC_MIDI,
RPC_AUD_DEF_CODEC_MP3,
RPC_AUD_DEF_CODEC_PCM,
RPC_AUD_DEF_CODEC_AAC,
RPC_AUD_DEF_CODEC_WMA,
RPC_AUD_DEF_CODEC_RA,
RPC_AUD_DEF_CODEC_ADPCM,
RPC_AUD_DEF_CODEC_GAUDIO,
RPC_AUD_DEF_CODEC_VOC_EVRC,
RPC_AUD_DEF_CODEC_VOC_13K,
RPC_AUD_DEF_CODEC_VOC_4GV_NB,
RPC_AUD_DEF_CODEC_VOC_AMR,
RPC_AUD_DEF_CODEC_VOC_EFR,
RPC_AUD_DEF_CODEC_VOC_FR,
RPC_AUD_DEF_CODEC_VOC_HR,
RPC_AUD_DEF_CODEC_VOC,
RPC_AUD_DEF_CODEC_SBC,
RPC_AUD_DEF_CODEC_VOC_PCM,
RPC_AUD_DEF_CODEC_AMR_WB,
RPC_AUD_DEF_CODEC_AMR_WB_PLUS,
RPC_AUD_DEF_CODEC_MAX,
};
enum rpc_snd_method_type {
RPC_SND_METHOD_VOICE = 0,
RPC_SND_METHOD_KEY_BEEP,
RPC_SND_METHOD_MESSAGE,
RPC_SND_METHOD_RING,
RPC_SND_METHOD_MIDI,
RPC_SND_METHOD_AUX,
RPC_SND_METHOD_MAX,
};
enum rpc_voc_codec_type {
RPC_VOC_CODEC_DEFAULT,
RPC_VOC_CODEC_ON_CHIP_0 = RPC_VOC_CODEC_DEFAULT,
RPC_VOC_CODEC_ON_CHIP_1,
RPC_VOC_CODEC_STEREO_HEADSET,
RPC_VOC_CODEC_ON_CHIP_AUX,
RPC_VOC_CODEC_BT_OFF_BOARD,
RPC_VOC_CODEC_BT_A2DP,
RPC_VOC_CODEC_OFF_BOARD,
RPC_VOC_CODEC_SDAC,
RPC_VOC_CODEC_RX_EXT_SDAC_TX_INTERNAL,
RPC_VOC_CODEC_IN_STEREO_SADC_OUT_MONO_HANDSET,
RPC_VOC_CODEC_IN_STEREO_SADC_OUT_STEREO_HEADSET,
RPC_VOC_CODEC_TX_INT_SADC_RX_EXT_AUXPCM,
RPC_VOC_CODEC_EXT_STEREO_SADC_OUT_MONO_HANDSET,
RPC_VOC_CODEC_EXT_STEREO_SADC_OUT_STEREO_HEADSET,
RPC_VOC_CODEC_TTY_ON_CHIP_1,
RPC_VOC_CODEC_TTY_OFF_BOARD,
RPC_VOC_CODEC_TTY_VCO,
RPC_VOC_CODEC_TTY_HCO,
RPC_VOC_CODEC_ON_CHIP_0_DUAL_MIC,
RPC_VOC_CODEC_MAX,
RPC_VOC_CODEC_NONE,
};
enum rpc_audmgr_status_type {
RPC_AUDMGR_STATUS_READY,
RPC_AUDMGR_STATUS_CODEC_CONFIG,
RPC_AUDMGR_STATUS_PENDING,
RPC_AUDMGR_STATUS_SUSPEND,
RPC_AUDMGR_STATUS_FAILURE,
RPC_AUDMGR_STATUS_VOLUME_CHANGE,
RPC_AUDMGR_STATUS_DISABLED,
RPC_AUDMGR_STATUS_ERROR,
};
struct rpc_audmgr_enable_client_args {
uint32_t set_to_one;
uint32_t tx_sample_rate;
uint32_t rx_sample_rate;
uint32_t def_method;
uint32_t codec_type;
uint32_t snd_method;
uint32_t cb_func;
uint32_t client_data;
};
#define AUDMGR_ENABLE_CLIENT 2
#define AUDMGR_DISABLE_CLIENT 3
#define AUDMGR_SUSPEND_EVENT_RSP 4
#define AUDMGR_REGISTER_OPERATION_LISTENER 5
#define AUDMGR_UNREGISTER_OPERATION_LISTENER 6
#define AUDMGR_REGISTER_CODEC_LISTENER 7
#define AUDMGR_GET_RX_SAMPLE_RATE 8
#define AUDMGR_GET_TX_SAMPLE_RATE 9
#define AUDMGR_SET_DEVICE_MODE 10
#if CONFIG_MSM_AMSS_VERSION < 6220
#define AUDMGR_PROG_VERS "rs30000013:46255756"
#define AUDMGR_PROG 0x30000013
#define AUDMGR_VERS 0x46255756
#else
#define AUDMGR_PROG_VERS "rs30000013:e94e8f0c"
#define AUDMGR_PROG 0x30000013
#define AUDMGR_VERS 0xe94e8f0c
#endif
struct rpc_audmgr_cb_func_ptr {
uint32_t cb_id;
uint32_t set_to_one;
uint32_t status;
union {
uint32_t handle;
uint32_t volume;
} u;
};
#define AUDMGR_CB_FUNC_PTR 1
#define AUDMGR_OPR_LSTNR_CB_FUNC_PTR 2
#define AUDMGR_CODEC_LSTR_FUNC_PTR 3
#if CONFIG_MSM_AMSS_VERSION < 6220
#define AUDMGR_CB_PROG 0x31000013
#define AUDMGR_CB_VERS 0x5fa922a9
#else
#define AUDMGR_CB_PROG 0x31000013
#define AUDMGR_CB_VERS 0x21570ba7
#endif
struct audmgr {
wait_queue_head_t wait;
uint32_t handle;
struct msm_rpc_endpoint *ept;
struct task_struct *task;
int state;
};
struct audmgr_config {
uint32_t tx_rate;
uint32_t rx_rate;
uint32_t def_method;
uint32_t codec;
uint32_t snd_method;
};
int audmgr_open(struct audmgr *am);
int audmgr_close(struct audmgr *am);
int audmgr_enable(struct audmgr *am, struct audmgr_config *cfg);
int audmgr_disable(struct audmgr *am);
typedef void (*audpp_event_func)(void *private, unsigned id, uint16_t *msg);
int audpp_enable(int id, audpp_event_func func, void *private);
void audpp_disable(int id, void *private);
int audpp_send_queue1(void *cmd, unsigned len);
int audpp_send_queue2(void *cmd, unsigned len);
int audpp_send_queue3(void *cmd, unsigned len);
int audpp_pause(unsigned id, int pause);
int audpp_set_volume_and_pan(unsigned id, unsigned volume, int pan);
void audpp_avsync(int id, unsigned rate);
unsigned audpp_avsync_sample_count(int id);
unsigned audpp_avsync_byte_count(int id);
#endif
#endif
/* arch/arm/mach-msm/qdsp5/audmgr.h
*
* Copyright 2008 (c) QUALCOMM Incorporated.
* Copyright (C) 2008 Google, Inc.
*
* 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.
*
*/
#ifndef _ARCH_ARM_MACH_MSM_AUDMGR_NEW_H
#define _ARCH_ARM_MACH_MSM_AUDMGR_NEW_H
enum rpc_aud_def_sample_rate_type {
RPC_AUD_DEF_SAMPLE_RATE_NONE,
RPC_AUD_DEF_SAMPLE_RATE_8000,
RPC_AUD_DEF_SAMPLE_RATE_11025,
RPC_AUD_DEF_SAMPLE_RATE_12000,
RPC_AUD_DEF_SAMPLE_RATE_16000,
RPC_AUD_DEF_SAMPLE_RATE_22050,
RPC_AUD_DEF_SAMPLE_RATE_24000,
RPC_AUD_DEF_SAMPLE_RATE_32000,
RPC_AUD_DEF_SAMPLE_RATE_44100,
RPC_AUD_DEF_SAMPLE_RATE_48000,
RPC_AUD_DEF_SAMPLE_RATE_MAX,
};
enum rpc_aud_def_method_type {
RPC_AUD_DEF_METHOD_NONE,
RPC_AUD_DEF_METHOD_KEY_BEEP,
RPC_AUD_DEF_METHOD_PLAYBACK,
RPC_AUD_DEF_METHOD_VOICE,
RPC_AUD_DEF_METHOD_RECORD,
RPC_AUD_DEF_METHOD_HOST_PCM,
RPC_AUD_DEF_METHOD_MIDI_OUT,
RPC_AUD_DEF_METHOD_RECORD_SBC,
RPC_AUD_DEF_METHOD_DTMF_RINGER,
RPC_AUD_DEF_METHOD_MAX,
};
enum rpc_aud_def_codec_type {
RPC_AUD_DEF_CODEC_NONE,
RPC_AUD_DEF_CODEC_DTMF,
RPC_AUD_DEF_CODEC_MIDI,
RPC_AUD_DEF_CODEC_MP3,
RPC_AUD_DEF_CODEC_PCM,
RPC_AUD_DEF_CODEC_AAC,
RPC_AUD_DEF_CODEC_WMA,
RPC_AUD_DEF_CODEC_RA,
RPC_AUD_DEF_CODEC_ADPCM,
RPC_AUD_DEF_CODEC_GAUDIO,
RPC_AUD_DEF_CODEC_VOC_EVRC,
RPC_AUD_DEF_CODEC_VOC_13K,
RPC_AUD_DEF_CODEC_VOC_4GV_NB,
RPC_AUD_DEF_CODEC_VOC_AMR,
RPC_AUD_DEF_CODEC_VOC_EFR,
RPC_AUD_DEF_CODEC_VOC_FR,
RPC_AUD_DEF_CODEC_VOC_HR,
RPC_AUD_DEF_CODEC_VOC_CDMA,
RPC_AUD_DEF_CODEC_VOC_CDMA_WB,
RPC_AUD_DEF_CODEC_VOC_UMTS,
RPC_AUD_DEF_CODEC_VOC_UMTS_WB,
RPC_AUD_DEF_CODEC_SBC,
RPC_AUD_DEF_CODEC_VOC_PCM,
RPC_AUD_DEF_CODEC_AMR_WB,
RPC_AUD_DEF_CODEC_AMR_WB_PLUS,
RPC_AUD_DEF_CODEC_AAC_BSAC,
RPC_AUD_DEF_CODEC_MAX,
RPC_AUD_DEF_CODEC_AMR_NB,
RPC_AUD_DEF_CODEC_13K,
RPC_AUD_DEF_CODEC_EVRC,
RPC_AUD_DEF_CODEC_MAX_002,
};
enum rpc_snd_method_type {
RPC_SND_METHOD_VOICE = 0,
RPC_SND_METHOD_KEY_BEEP,
RPC_SND_METHOD_MESSAGE,
RPC_SND_METHOD_RING,
RPC_SND_METHOD_MIDI,
RPC_SND_METHOD_AUX,
RPC_SND_METHOD_MAX,
};
enum rpc_voc_codec_type {
RPC_VOC_CODEC_DEFAULT,
RPC_VOC_CODEC_ON_CHIP_0 = RPC_VOC_CODEC_DEFAULT,
RPC_VOC_CODEC_ON_CHIP_1,
RPC_VOC_CODEC_STEREO_HEADSET,
RPC_VOC_CODEC_ON_CHIP_AUX,
RPC_VOC_CODEC_BT_OFF_BOARD,
RPC_VOC_CODEC_BT_A2DP,
RPC_VOC_CODEC_OFF_BOARD,
RPC_VOC_CODEC_SDAC,
RPC_VOC_CODEC_RX_EXT_SDAC_TX_INTERNAL,
RPC_VOC_CODEC_IN_STEREO_SADC_OUT_MONO_HANDSET,
RPC_VOC_CODEC_IN_STEREO_SADC_OUT_STEREO_HEADSET,
RPC_VOC_CODEC_TX_INT_SADC_RX_EXT_AUXPCM,
RPC_VOC_CODEC_EXT_STEREO_SADC_OUT_MONO_HANDSET,
RPC_VOC_CODEC_EXT_STEREO_SADC_OUT_STEREO_HEADSET,
RPC_VOC_CODEC_TTY_ON_CHIP_1,
RPC_VOC_CODEC_TTY_OFF_BOARD,
RPC_VOC_CODEC_TTY_VCO,
RPC_VOC_CODEC_TTY_HCO,
RPC_VOC_CODEC_ON_CHIP_0_DUAL_MIC,
RPC_VOC_CODEC_MAX,
RPC_VOC_CODEC_NONE,
};
enum rpc_audmgr_status_type {
RPC_AUDMGR_STATUS_READY,
RPC_AUDMGR_STATUS_CODEC_CONFIG,
RPC_AUDMGR_STATUS_PENDING,
RPC_AUDMGR_STATUS_SUSPEND,
RPC_AUDMGR_STATUS_FAILURE,
RPC_AUDMGR_STATUS_VOLUME_CHANGE,
RPC_AUDMGR_STATUS_DISABLED,
RPC_AUDMGR_STATUS_ERROR,
};
struct rpc_audmgr_enable_client_args {
uint32_t set_to_one;
uint32_t tx_sample_rate;
uint32_t rx_sample_rate;
uint32_t def_method;
uint32_t codec_type;
uint32_t snd_method;
uint32_t cb_func;
uint32_t client_data;
};
#define AUDMGR_ENABLE_CLIENT 2
#define AUDMGR_DISABLE_CLIENT 3
#define AUDMGR_SUSPEND_EVENT_RSP 4
#define AUDMGR_REGISTER_OPERATION_LISTENER 5
#define AUDMGR_UNREGISTER_OPERATION_LISTENER 6
#define AUDMGR_REGISTER_CODEC_LISTENER 7
#define AUDMGR_GET_RX_SAMPLE_RATE 8
#define AUDMGR_GET_TX_SAMPLE_RATE 9
#define AUDMGR_SET_DEVICE_MODE 10
#define AUDMGR_PROG 0x30000013
#define AUDMGR_VERS MSM_RPC_VERS(1,0)
struct rpc_audmgr_cb_func_ptr {
uint32_t cb_id;
uint32_t status; /* Audmgr status */
uint32_t set_to_one; /* Pointer status (1 = valid, 0 = invalid) */
uint32_t disc;
/* disc = AUDMGR_STATUS_READY => data=handle
disc = AUDMGR_STATUS_CODEC_CONFIG => data = handle
disc = AUDMGR_STATUS_DISABLED => data =status_disabled
disc = AUDMGR_STATUS_VOLUME_CHANGE => data = volume-change */
union {
uint32_t handle;
uint32_t volume;
uint32_t status_disabled;
uint32_t volume_change;
} u;
};
#define AUDMGR_CB_FUNC_PTR 1
#define AUDMGR_OPR_LSTNR_CB_FUNC_PTR 2
#define AUDMGR_CODEC_LSTR_FUNC_PTR 3
#define AUDMGR_CB_PROG 0x31000013
#define AUDMGR_CB_VERS 0xf8e3e2d9
struct audmgr {
wait_queue_head_t wait;
uint32_t handle;
struct msm_rpc_endpoint *ept;
struct task_struct *task;
int state;
};
struct audmgr_config {
uint32_t tx_rate;
uint32_t rx_rate;
uint32_t def_method;
uint32_t codec;
uint32_t snd_method;
};
int audmgr_open(struct audmgr *am);
int audmgr_close(struct audmgr *am);
int audmgr_enable(struct audmgr *am, struct audmgr_config *cfg);
int audmgr_disable(struct audmgr *am);
typedef void (*audpp_event_func)(void *private, unsigned id, uint16_t *msg);
int audpp_enable(int id, audpp_event_func func, void *private);
void audpp_disable(int id, void *private);
int audpp_send_queue1(void *cmd, unsigned len);
int audpp_send_queue2(void *cmd, unsigned len);
int audpp_send_queue3(void *cmd, unsigned len);
int audpp_set_volume_and_pan(unsigned id, unsigned volume, int pan);
int audpp_pause(unsigned id, int pause);
int audpp_flush(unsigned id);
void audpp_avsync(int id, unsigned rate);
unsigned audpp_avsync_sample_count(int id);
unsigned audpp_avsync_byte_count(int id);
#endif
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment