aml_audio_hal: Add more hal tests [1/1]

PD#TV-17788
PD#TV-18504
PD#SWPL-23836

Problem:
Need sample code to show audio HAL dap_settings,
output format config, speaker and ARC delay and
arc/earc output.

Solution:
Provide sample test code.

Verify:
Local on AB311 platform.

Change-Id: I99c2aa45c9a5dea3ef04a26279eb0a19d53a4bf9
diff --git a/src/test_arc.c b/src/test_arc.c
new file mode 100644
index 0000000..7bcadca
--- /dev/null
+++ b/src/test_arc.c
@@ -0,0 +1,422 @@
+

+#include <string.h>

+#include <fcntl.h>

+#include <stdio.h>

+#include <stdlib.h>

+#include <unistd.h>

+#include <stdbool.h>

+#include <stdint.h>

+#include <pthread.h>

+#include <sys/types.h>

+#include <sys/wait.h>

+#include <sys/stat.h>

+#include <sys/ioctl.h>

+#include <sys/poll.h>

+#include <sys/time.h>

+

+//#include</linux/amlogic/cec_common.h>

+#include "hdmi_tx_cec_20.h"

+#include "data.h"

+#include "audio_if.h"

+

+

+#define DEV_CEC			"/dev/cec"

+static int      Cec_fd = 0;

+#define HDR 0

+#define OPCODE 1

+#define OPERAND 2

+

+#define CEC_MSG_HDR_BROADCAST 0x0F

+#define CEC_MSG_HDR 0x05

+#define INITIATE_ARC                     0XC0

+#define	REPORT_ARC_INITIATED             0XC1

+#define REPORT_ARC_TERMINATED            0XC2

+#define	REQUEST_ARC_INITIATION           0XC3

+#define	REQUEST_ARC_TERMINATION          0XC4

+#define	TERMINATE_ARC                    0XC5

+char CEC_MSG_ARC_INITIATED[]={CEC_MSG_HDR,REPORT_ARC_INITIATED};

+

+static pthread_t CEC_Event_Thread;

+struct pollfd polling;

+static bool arc_not_initialised = true;

+static char cecmsg[16] ;

+static int stop =0;

+static char msg_to_send[16];

+

+/* Audio stuffs */

+

+

+#define TV_AUDIO_OUTPUT

+

+#ifdef TV_AUDIO_OUTPUT

+static struct audio_port_config source_;

+static struct audio_port_config sink_;

+static audio_patch_handle_t patch_h_;

+

+static void test_patch(audio_hw_device_t *device)

+{

+    int ret;

+    /* create mixer to device patch */

+    source_.id = 1;

+    source_.role = AUDIO_PORT_ROLE_SOURCE;

+    source_.type = AUDIO_PORT_TYPE_MIX;

+    source_.config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE |

+        AUDIO_PORT_CONFIG_FORMAT;

+    source_.sample_rate = 48000;

+    source_.format = AUDIO_FORMAT_PCM_16_BIT;

+

+    sink_.id = 2;

+    sink_.role = AUDIO_PORT_ROLE_SINK;

+    sink_.type = AUDIO_PORT_TYPE_DEVICE;

+    sink_.config_mask = AUDIO_PORT_CONFIG_SAMPLE_RATE |

+        AUDIO_PORT_CONFIG_FORMAT;

+    sink_.sample_rate = 48000;

+    sink_.format = AUDIO_FORMAT_PCM_16_BIT;

+    sink_.ext.device.type = AUDIO_DEVICE_OUT_HDMI_ARC;

+

+    printf("create mix --> ARC patch...");

+    ret = device->create_audio_patch(device, 1, &source_, 1, &sink_, &patch_h_);

+    if (ret) {

+        printf("fail ret:%d\n",ret);

+    } else {

+        printf("success\n");

+    }

+}

+

+static void destroy_patch(audio_hw_device_t *device)

+{

+    if (patch_h_) {

+        int ret;

+        printf("destroy patch...");

+        ret = device->release_audio_patch(device, patch_h_);

+        if (ret) {

+            printf("fail ret:%d\n",ret);

+        } else {

+            printf("success\n");

+        }

+    }

+}

+#endif

+static void test_vol(audio_hw_device_t *device, int gain)

+{

+    int ret;

+    float vol = 0;

+    ret = device->get_master_volume(device, &vol);

+    if (ret) {

+        printf("get_master_volume fail\n");

+    } else {

+        printf("cur master vol:%f\n", vol);

+    }

+    ret = device->set_master_volume(device, 0.5f);

+    if (ret) {

+        printf("set_master_volume fail\n");

+    } else {

+        printf("set master vol 0.5\n");

+        device->set_master_volume(device, vol);

+    }

+

+#ifdef  TV_AUDIO_OUTPUT

+    {

+        struct audio_port_config config;

+

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

+        config.id = 2;

+        config.role = AUDIO_PORT_ROLE_SINK;

+        config.type = AUDIO_PORT_TYPE_DEVICE;

+        config.config_mask = AUDIO_PORT_CONFIG_GAIN;

+        /* audio_hal use dB * 100 to keep the accuracy */

+        config.gain.values[0] = gain * 100;

+        printf("set gain to %ddB...\n", gain);

+        ret = device->set_audio_port_config(device, &config);

+        if (ret) {

+            printf("fail\n");

+        } else {

+            printf("success\n");

+        }

+    }

+#endif

+}

+

+#define WRITE_UNIT 4096

+#define min(a, b) ((a) < (b) ? (a) : (b))

+static int test_stream(struct audio_stream_out *stream)

+{

+    int i, ret;

+    int len;

+    unsigned char *data;

+

+    ret = stream->set_volume(stream, 1.0f, 1.0f);

+    if (ret) {

+        fprintf(stderr, "%s %d, ret:%x\n", __func__, __LINE__, ret);

+        return -1;

+    }

+

+    printf("Start output to audio HAL\n");

+    for (i = 0; i < 10; i++) {

+        data = wav_data;

+        len = sizeof(wav_data);

+        while (len > 0) {

+            ssize_t s = stream->write(stream, data, min(len, WRITE_UNIT));

+            if (s < 0) {

+                fprintf(stderr, "stream writing error %d\n", s);

+                break;

+            }

+

+            len -= s;

+            data += s;

+        }

+    }

+

+    return 0;

+}

+

+#define HDMI_ARC_OUTPUT_DD

+

+static void test_output_stream(audio_hw_device_t *device)

+{

+    int ret;

+    struct audio_config config;

+    struct audio_stream_out *stream;

+    char cmd[32];

+

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

+    config.sample_rate = 48000;

+    config.channel_mask = AUDIO_CHANNEL_OUT_STEREO;

+    config.format = AUDIO_FORMAT_PCM_16_BIT;

+

+    printf("Tell audio HAL HDMI ARC is connected\n");

+    ret = device->set_parameters(device, "connect=0x40000");

+    if (ret) {

+        fprintf(stderr, "set_parameters HDMI connected failed\n");

+    }

+

+#ifdef HDMI_ARC_OUTPUT_DD

+    printf("Set HDMI ARC output format to AC3\n");

+    ret = device->set_parameters(device, "hdmi_format=4");

+    if (ret) {

+        fprintf(stderr, "set_parameters failed\n");

+    }

+#else

+    printf("Set HDMI ARC output format to PCM\n");

+    ret = device->set_parameters(device, "hdmi_format=0");

+    if (ret) {

+        fprintf(stderr, "set_parameters failed\n");

+    }

+#endif

+

+#ifdef HDMI_ARC_OUTPUT_DD

+    /*

+     * The following set_parameters calling sequence is needed

+     * to meet the audio HAL internal checking for ARC output:

+     * 1. "HDMI ARC Switch" key is used for UI control switch to enable

+     *    ARC output.

+     * 2. "connect" key is used to tell audio HAL the connection status

+     * 3. "speaker_mute" is also checked to make sure ARC output is

+     *    effective.

+     */

+    printf("Report UI settings for HDMI ARC enabled\n");

+    ret = device->set_parameters(device, "HDMI ARC Switch=1");

+    if (ret) {

+        fprintf(stderr, "set_parameters failed\n");

+    }

+

+    printf("Report HDMI ARC is connected\n");

+    snprintf(cmd, sizeof(cmd), "connect=%d", AUDIO_DEVICE_OUT_HDMI_ARC);

+    ret = device->set_parameters(device, cmd);

+    if (ret) {

+        fprintf(stderr, "set_parameters failed\n");

+    }

+

+    printf("Mute speaker output\n");

+    ret = device->set_parameters(device, "speaker_mute=1");

+    if (ret) {

+        fprintf(stderr, "set_parameters failed\n");

+    }

+#endif

+

+    printf("open output to HDMI_ARC with direct mode...\n");

+    ret = device->open_output_stream(device,

+            0, AUDIO_DEVICE_OUT_HDMI_ARC,

+            AUDIO_OUTPUT_FLAG_PRIMARY | AUDIO_OUTPUT_FLAG_DIRECT, &config,

+            &stream, NULL);

+    if (ret) {

+        printf("fail\n");

+        return;

+    } else {

+        printf("success\n");

+    }

+

+    test_stream(stream);

+

+    printf("close output speaker...\n");

+    device->close_output_stream(device, stream);

+}

+

+void process_cec_msg(char * cec_msg,int len)

+{

+    int i=0;

+

+    switch (cec_msg[OPCODE]) {

+       case INITIATE_ARC :

+           printf("Got the Initiate ARC message Amplifeir requesting to start ARC\n");

+           arc_not_initialised = false;

+           write(Cec_fd,CEC_MSG_ARC_INITIATED,2);

+           printf("Sending the ARC initiated message to the Amplifier\n");

+           stop =1;

+           break;

+

+       case CEC_OC_GIVE_PHYSICAL_ADDRESS :

+           printf("CEC_OC_GIVE_PHYSICAL_ADDRESS\n");

+           msg_to_send[0] = CEC_MSG_HDR_BROADCAST;

+           msg_to_send[1] = CEC_OC_REPORT_PHYSICAL_ADDRESS;

+           msg_to_send[2] = 0x00;

+           msg_to_send[3] = 0x00;

+           msg_to_send[4] = 0x00;

+           write(Cec_fd,msg_to_send,5);

+           printf("Sending CEC_OC_REPORT_PHYSICAL_ADDRESS\n");

+           break;

+       default:

+          {

+               printf("CEC msg is ");

+               for(i=0;i< len;i++) {

+                   printf(" 0x%x ",cec_msg[i]);

+               }

+          }

+          printf("\n###################");

+          break;

+    }

+}

+

+void* CEC_event_read_fn (void *data)

+{

+    int timeout = -1;

+    unsigned int mask = 0;

+    int read_len =0;

+

+    polling.fd= Cec_fd;

+    polling.events = POLLIN;

+

+    while (!stop) { 

+        mask = poll(&polling,1,timeout);

+

+        if (mask & POLLIN || mask & POLLRDNORM) {

+            read_len= read(Cec_fd, &cecmsg, 1);

+            process_cec_msg(cecmsg,read_len);

+        }

+    }

+}

+

+static void sighandler(int sig)

+{

+    printf("Interrupted by signal %d\n", sig);

+    stop= 1;

+    printf("sighandler! Done\n");

+}

+

+int main(int argc, char *argv[]) 

+{

+    char msg[16];

+    int ret=0;

+    audio_hw_device_t *device;

+    int test_earc = 0;

+

+    if (argc > 1) {

+        test_earc = atoi(argv[1]);

+        if (test_earc) {

+            printf("Test EARC output, CEC communicatin will be skipped\n");

+        }

+    }

+

+    if (!test_earc) {

+        Cec_fd = open (DEV_CEC, O_RDWR);

+

+        if (Cec_fd < 0) {

+            printf ("%s CEC_device opening returned %d",DEV_CEC);

+            return -1;

+        }

+

+        ret = pthread_create(&CEC_Event_Thread, NULL, CEC_event_read_fn, NULL);

+        if (ret) {

+            printf("Unable to create decoder event thread\n");

+        }

+

+        /* setup the signal handler for CTRL-C */

+        signal(SIGINT, sighandler);

+        /*kill -USR1 pid */

+        signal(SIGUSR1, sighandler);

+

+        ioctl(Cec_fd, CEC_IOC_SET_OPTION_SYS_CTRL, 0x8);

+	

+        ioctl(Cec_fd, CEC_IOC_ADD_LOGICAL_ADDR, 0x0);

+        msg[HDR]=CEC_MSG_HDR;

+        msg[OPCODE]=REQUEST_ARC_INITIATION;

+        write(Cec_fd,msg,2);

+        printf("sending ARC initialisation \n");

+    }

+

+    ret = audio_hw_load_interface(&device);

+    if (ret) {

+        printf("%s %d error:%d\n", __func__, __LINE__, ret);

+        return ret;

+    }

+    printf("hw version: %x\n", device->common.version);

+    printf("hal api version: %x\n", device->common.module->hal_api_version);

+    printf("module id: %s\n", device->common.module->id);

+    printf("module name: %s\n", device->common.module->name);

+

+    if (device->get_supported_devices) {

+        uint32_t support_dev = 0;

+        support_dev = device->get_supported_devices(device);

+        printf("supported device: %x\n", support_dev);

+    }

+

+    int inited = device->init_check(device);

+    if (inited) {

+        printf("device not inited, quit\n");

+        goto exit;

+    }

+

+    if (!test_earc) {

+        while (!stop) {

+            if (arc_not_initialised) {

+                printf("TV sending Request ARC initialisation to Amplifier \n");

+                write(Cec_fd,msg,2);

+            }

+            sleep(1);

+        }

+    }

+

+    sleep(2);

+

+    #ifdef TV_AUDIO_OUTPUT

+    test_patch(device);

+    #endif

+

+    test_output_stream(device);

+	  

+    if (!test_earc) {

+        ret = pthread_join(CEC_Event_Thread, NULL);

+        if (ret != 0) {

+            printf("CEC_Event_Thread returned error\n");

+        }

+

+        ioctl(Cec_fd, CEC_IOC_CLR_LOGICAL_ADDR, 0x0);

+        ioctl(Cec_fd, CEC_IOC_SET_OPTION_SYS_CTRL, 0x0);

+	

+        close(Cec_fd);

+    }

+

+    /* Audio clean up */

+#ifdef TV_AUDIO_OUTPUT

+    destroy_patch(device);

+#endif

+

+exit:

+    device->common.close(&device->common);

+    audio_hw_unload_interface(device);

+    return 0;

+	

+}

+

+

+