[Motorola Photon 4G] rrusek:
Kernel Patch used for EVO 4G

Can this patch be used on the kernels that are currenly out Photon?

---------------------------------

From 0ade273fbca96fc909aa4873ed0ec56b37adb8b0 Mon Sep 17 00:00:00 2001

From: Kraml Liu <kraml.liu@gmail.com>

Date: Wed, 16 Mar 2011 09:28:01 +0800

Subject: [PATCH] Add rVoix call line recording patch, see below URL for

detail

http://xdaforums.com/showthread.php?t=993793

---

arch/arm/mach-msm/qdsp6/pcm_in.c | 104 +++++++++++++++++++++++--------------

arch/arm/mach-msm/qdsp6/q6audio.c | 98 ++++++++++++++++++++++++++++++++++-

2 files changed, 160 insertions(+), 42 deletions(-)

diff --git a/arch/arm/mach-msm/qdsp6/pcm_in.c b/arch/arm/mach-msm/qdsp6/pcm_in.c

index 3b3d23b..b711f46 100644

--- a/arch/arm/mach-msm/qdsp6/pcm_in.c

+++ b/arch/arm/mach-msm/qdsp6/pcm_in.c

@@ -26,18 +26,30 @@

#include <mach/msm_qdsp6_audio.h>

-#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;

+struct msm_voicerec_mode {

+ uint32_t rec_mode;

+};

+

+

+#define AUDIO_SET_INCALL _IOW(AUDIO_IOCTL_MAGIC, 19, struct msm_voicerec_mode)

+#define AUDIO_FLAG_INCALL_MIXED 2

+

+struct pcm {

+	struct audio_client *ac;

+	uint32_t sample_rate;

+	uint32_t channel_count;

+	uint32_t buffer_size;

+	uint32_t rec_mode;

+};

+

+#define BUFSZ (256)

void audio_client_dump(struct audio_client *ac);

static long q6_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

{

+	struct pcm *pcm = file->private_data;

int rc = 0;

switch (cmd) {

@@ -61,17 +73,15 @@ static long q6_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

break;

}

-	mutex_lock(&pcm_in_lock);

-	if (file->private_data) {

+	if (pcm->ac) {

rc = -EBUSY;

} else {

-	file->private_data = q6audio_open_pcm(

-	buffer_size, sample_rate, channel_count,

-	AUDIO_FLAG_READ, acdb_id);

-	if (!file->private_data)

+	pcm->ac = q6audio_open_pcm(pcm->buffer_size,

+	pcm->sample_rate, pcm->channel_count,

+	pcm->rec_mode, acdb_id);

+	if (!pcm->ac)

rc = -ENOMEM;

}

-	mutex_unlock(&pcm_in_lock);

break;

}

case AUDIO_STOP:

@@ -96,17 +106,32 @@ static long q6_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

rc = -EINVAL;

break;

}

-	sample_rate = config.sample_rate;

-	channel_count = config.channel_count;

-	buffer_size = config.buffer_size;

+

+	pcm->sample_rate = config.sample_rate;

+	pcm->channel_count = config.channel_count;

+	pcm->buffer_size = config.buffer_size;

+	break;

+	}

+	case AUDIO_SET_INCALL: {

+	struct msm_voicerec_mode voicerec_mode;

+	if (copy_from_user(&voicerec_mode, (void *)arg,

+	sizeof(struct msm_voicerec_mode)))

+	return -EFAULT;

+	if (voicerec_mode.rec_mode != AUDIO_FLAG_READ &&

+	voicerec_mode.rec_mode != AUDIO_FLAG_INCALL_MIXED) {

+	pcm->rec_mode = AUDIO_FLAG_READ;

+	pr_err("invalid rec_mode\n");

+	rc = -EINVAL;

+	} else

+	pcm->rec_mode = voicerec_mode.rec_mode;

break;

}

case AUDIO_GET_CONFIG: {

struct msm_audio_config config;

-	config.buffer_size = buffer_size;

+	config.buffer_size = pcm->buffer_size;

config.buffer_count = 2;

-	config.sample_rate = sample_rate;

-	config.channel_count = channel_count;

+	config.sample_rate = pcm->sample_rate;

+	config.channel_count = pcm->channel_count;

config.unused[0] = 0;

config.unused[1] = 0;

config.unused[2] = 0;

@@ -123,32 +148,33 @@ static long q6_in_ioctl(struct file *file, unsigned int cmd, unsigned long arg)

static int q6_in_open(struct inode *inode, struct file *file)

{

-	int rc;

+	struct pcm *pcm;

pr_info("pcm_in: open\n");

-	mutex_lock(&pcm_in_lock);

-	if (pcm_in_opened) {

-	pr_err("pcm_in: busy\n");

-	rc = -EBUSY;

-	} else {

-	pcm_in_opened = 1;

-	rc = 0;

-	}

-	mutex_unlock(&pcm_in_lock);

-	return rc;

+	pcm = kzalloc(sizeof(struct pcm), GFP_KERNEL);

+

+	if (!pcm)

+	return -ENOMEM;

+

+	pcm->channel_count = 1;

+	pcm->sample_rate = 8000;

+	pcm->buffer_size = BUFSZ;

+	pcm->rec_mode = AUDIO_FLAG_READ;

+	file->private_data = pcm;

+	return 0;

}

static ssize_t q6_in_read(struct file *file, char __user *buf,

size_t count, loff_t *pos)

{

+	struct pcm *pcm = file->private_data;

struct audio_client *ac;

struct audio_buffer *ab;

const char __user *start = buf;

int xfer;

int res;

-	mutex_lock(&pcm_in_lock);

-	ac = file->private_data;

+	ac = pcm->ac;

if (!ac) {

res = -ENODEV;

goto fail;

@@ -181,20 +207,18 @@ static ssize_t q6_in_read(struct file *file, char __user *buf,

}

fail:

res = buf - start;

-	mutex_unlock(&pcm_in_lock);

-

return res;

}

static int q6_in_release(struct inode *inode, struct file *file)

{

+

int rc = 0;

-	mutex_lock(&pcm_in_lock);

-	if (file->private_data)

-	rc = q6audio_close(file->private_data);

-	pcm_in_opened = 0;

-	mutex_unlock(&pcm_in_lock);

-	pr_info("pcm_in: release\n");

+	struct pcm *pcm = file->private_data;

+	if (pcm->ac)

+	rc = q6audio_close(pcm->ac);

+	kfree(pcm);

+	pr_info("pcm_out: release\n");

return rc;

}

diff --git a/arch/arm/mach-msm/qdsp6/q6audio.c b/arch/arm/mach-msm/qdsp6/q6audio.c

index 2df5b24..444710d 100644

--- a/arch/arm/mach-msm/qdsp6/q6audio.c

+++ b/arch/arm/mach-msm/qdsp6/q6audio.c

@@ -393,6 +393,7 @@ static int audio_out_open(struct audio_client *ac, uint32_t bufsz,

return audio_ioctl(ac, &rpc, sizeof(rpc));

}

+#if 0

static int audio_in_open(struct audio_client *ac, uint32_t bufsz,

uint32_t rate, uint32_t channels)

{

@@ -415,6 +416,34 @@ static int audio_in_open(struct audio_client *ac, uint32_t bufsz,

TRACE("%p: open in\n", ac);

return audio_ioctl(ac, &rpc, sizeof(rpc));

}

+#else

+static int audio_in_open(struct audio_client *ac, uint32_t bufsz,

+ uint32_t flags, uint32_t rate, uint32_t channels)

+{

+ struct adsp_open_command rpc;

+

+ memset(&rpc, 0, sizeof(rpc));

+

+ rpc.format.standard.format = ADSP_AUDIO_FORMAT_PCM;

+ rpc.format.standard.channels = channels;

+ rpc.format.standard.bits_per_sample = 16;

+ rpc.format.standard.sampling_rate = rate;

+ rpc.format.standard.is_signed = 1;

+ rpc.format.standard.is_interleaved = 1;

+

+ rpc.hdr.opcode = ADSP_AUDIO_IOCTL_CMD_OPEN_READ;

+ rpc.device = ADSP_AUDIO_DEVICE_ID_DEFAULT;

+ if (flags == AUDIO_FLAG_READ)

+ rpc.stream_context = ADSP_AUDIO_DEVICE_CONTEXT_RECORD;

+ else

+ rpc.stream_context = ADSP_AUDIO_DEVICE_CONTEXT_MIXED_RECORD;

+

+ rpc.buf_max_size = bufsz;

+

+ TRACE("%p: open in\n", ac);

+ return audio_ioctl(ac, &rpc, sizeof(rpc));

+}

+#endif

static int audio_mp3_open(struct audio_client *ac, uint32_t bufsz,

uint32_t rate, uint32_t channels)

@@ -1565,6 +1594,31 @@ done:

return 0;

}

+static void adie_rx_path_enable(uint32_t acdb_id)

+{

+ if (audio_rx_path_id) {

+ adie_enable();

+ adie_set_path(adie, audio_rx_path_id, ADIE_PATH_RX);

+ adie_set_path_freq_plan(adie, ADIE_PATH_RX, 48000);

+

+ adie_proceed_to_stage(adie, ADIE_PATH_RX,

+ ADIE_STAGE_DIGITAL_READY);

+ adie_proceed_to_stage(adie, ADIE_PATH_RX,

+ ADIE_STAGE_DIGITAL_ANALOG_READY);

+ }

+}

+

+static void q6_rx_path_enable(int reconf, uint32_t acdb_id)

+{

+ audio_update_acdb(audio_rx_device_id, acdb_id);

+ if (!reconf)

+ qdsp6_devchg_notify(ac_control, ADSP_AUDIO_RX_DEVICE, audio_rx_device_id);

+ qdsp6_standby(ac_control);

+ qdsp6_start(ac_control);

+}

+

+

+

struct audio_client *q6audio_open_pcm(uint32_t bufsz, uint32_t rate,

uint32_t channels, uint32_t flags, uint32_t acdb_id)

{

@@ -1581,7 +1635,7 @@ struct audio_client *q6audio_open_pcm(uint32_t bufsz, uint32_t rate,

ac->flags = flags;

mutex_lock(&audio_path_lock);

-

+#if 0

if (ac->flags & AUDIO_FLAG_WRITE) {

audio_rx_path_refcount++;

if (audio_rx_path_refcount == 1) {

@@ -1626,7 +1680,47 @@ struct audio_client *q6audio_open_pcm(uint32_t bufsz, uint32_t rate,

audio_rx_analog_enable(1);

}

}

-

+#else

+ if (ac->flags & AUDIO_FLAG_WRITE) {

+ audio_rx_path_refcount++;

+ if (audio_rx_path_refcount == 1) {

+ _audio_rx_clk_enable();

+ q6_rx_path_enable(0, acdb_id);

+ adie_rx_path_enable(acdb_id);

+ }

+ } else {

+ /* TODO: consider concurrency with voice call */

+ if (audio_tx_path_refcount > 0) {

+ tx_clk_freq = 8000;

+ } else {

+ tx_clk_freq = rate;

+ }

+ audio_tx_path_refcount++;

+ if (audio_tx_path_refcount == 1) {

+ tx_clk_freq = rate;

+ _audio_tx_clk_enable();

+ _audio_tx_path_enable(0, acdb_id);

+ }

+ }

+

+ for (retry = 5;;retry--) {

+ if (ac->flags & AUDIO_FLAG_WRITE)

+ rc = audio_out_open(ac, bufsz, rate, channels);

+ else

+ rc = audio_in_open(ac, bufsz, flags, rate, channels);

+ if (rc == 0)

+ break;

+ if (retry == 0)

+ BUG();

+ pr_err("q6audio: open pcm error %d, retrying\n", rc);

+ msleep(1);

+ }

+

+ if (ac->flags & AUDIO_FLAG_WRITE) {

+ if (audio_rx_path_refcount == 1)

+ audio_rx_analog_enable(1);

+ }

+#endif

mutex_unlock(&audio_path_lock);

for (retry = 5;;retry--) {

--

1.7.5.4