]> rtime.felk.cvut.cz Git - hercules2020/nv-tegra/linux-4.4.git/commitdiff
asoc: codec: audience: support HRA audio
authorDara Ramesh <dramesh@nvidia.com>
Wed, 11 Mar 2015 05:20:52 +0000 (10:50 +0530)
committerRavindra Lokhande <rlokhande@nvidia.com>
Tue, 24 May 2016 06:45:47 +0000 (12:15 +0530)
Add DHWPT to support 24 bit (HRA) audio

bug 200086376

Change-Id: Ibdcd1af20150f2f1174a9c5e14a82f67ba6b05db
Signed-off-by: Dara Ramesh <dramesh@nvidia.com>
Reviewed-on: http://git-master/r/716142
Reviewed-by: Sumit Bhattacharya <sumitb@nvidia.com>
firmware/audience/es755/audience-es755-fw.bin
sound/soc/codecs/audience/es-d300-route.c
sound/soc/codecs/audience/es-d300-route.h
sound/soc/codecs/audience/es-d300.c
sound/soc/codecs/audience/es-d300.h
sound/soc/codecs/audience/es755.c
sound/soc/codecs/audience/es755.h

index f772fd4fa1ecde76e2eeba0f1f68f37cc857a320..40ee934b59d90c29307d7fb45a983efee4ff3a02 100644 (file)
Binary files a/firmware/audience/es755/audience-es755-fw.bin and b/firmware/audience/es755/audience-es755-fw.bin differ
index a63c0777681710c494d708d60494bd9e5a3c2e69..2cb7f968d94bc36b968e24c6bc43f1658fadd758 100644 (file)
@@ -266,6 +266,123 @@ struct es_mux_info es_pt_vp_mux_info = {
        .out_tbl = &es_pt_vp_out_route_tbl,
 };
 
+/* DHWPT Mux ENUM */
+enum {
+       DHWPT_PASSIN1_MUX,
+       DHWPT_PASSIN2_MUX,
+       DHWPT_PRIMARY_MUX,
+       DHWPT_SECONDARY_MUX,
+       DHWPT_FEIN_MUX,
+       DHWPT_IN_MUX_LEN,
+};
+enum {
+       DHWPT_PASSOUT1_MUX,
+       DHWPT_PASSOUT2_MUX,
+       DHWPT_CSOUT1_MUX,
+       DHWPT_FEOUT1_MUX,
+       DHWPT_AO1_MUX,
+       DHWPT_MO2_MUX,
+       DHWPT_OUT_MUX_LEN,
+};
+
+static struct route_tbl es_dhwpt_in_route_tbl[DHWPT_IN_MUX_LEN] = {
+       [DHWPT_PASSIN1_MUX] = {
+               .cmd[0] = ES_API_WORD(0xB05A, 0x3FF3),
+               .mux_type = ES_PASSIN1_MUX,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(RXCHMGR3),
+       },
+       [DHWPT_PASSIN2_MUX] = {
+               .cmd[0] = ES_API_WORD(0xB05A, 0x3FF4),
+               .mux_type = ES_PASSIN2_MUX,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(RXCHMGR4),
+       },
+       [DHWPT_PRIMARY_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, RXCHMGR0)),
+               .mux_type = ES_PRIMARY_MUX,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(RXCHMGR0),
+       },
+       [DHWPT_SECONDARY_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, RXCHMGR1)),
+               .cmd[1] = ES_API_WORD(0xB05B, 0x0101),
+               .cmd[2] = ES_API_WORD(0xB064, 0x0048),
+               .cmd[3] = ES_API_WORD(0xB064, 0x0132),
+               .cmd[4] = ES_API_WORD(0xB063, 0x0104),
+               .cmd[5] = ES_API_WORD(0xB068, 0x0400),
+               .mux_type = ES_SECONDARY_MUX,
+               .cmd_len = 6,
+               .chn_mgr_mask = BIT(RXCHMGR1),
+       },
+       [DHWPT_FEIN_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, RXCHMGR2)),
+               .cmd[1] = ES_API_WORD(0xB05B, 0x0203),
+               .cmd[2] = ES_API_WORD(0xB064, 0x0058),
+               .cmd[3] = ES_API_WORD(0xB064, 0x0130),
+               .cmd[4] = ES_API_WORD(0xB063, 0x0105),
+               .cmd[5] = ES_API_WORD(0xB068, 0x0500),
+               .mux_type = ES_FEIN_MUX,
+               .cmd_len = 6,
+               .chn_mgr_mask = BIT(RXCHMGR2),
+       },
+};
+
+static struct route_tbl es_dhwpt_out_route_tbl[DHWPT_OUT_MUX_LEN] = {
+       [DHWPT_PASSOUT1_MUX] = {
+               .cmd[0] = ES_API_WORD(0xB05A, 0x3FFA),
+               .mux_type = PASS_AUDOUT1,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR0),
+       },
+       [DHWPT_PASSOUT2_MUX] = {
+               .cmd[0] = ES_API_WORD(0xB05A, 0x3FFB),
+               .mux_type = PASS_AUDOUT2,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR1),
+       },
+       [DHWPT_CSOUT1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR2)),
+               .mux_type = VP_CSOUT1,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR2),
+       },
+       [DHWPT_FEOUT1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR3)),
+               .mux_type = VP_FEOUT1,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR3),
+       },
+       [DHWPT_AO1_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR4)),
+               .mux_type = PASS_AO1,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR4),
+       },
+       [DHWPT_MO2_MUX] = {
+               .cmd[0] = ES_API_WORD(ES_SET_MUX_CMD,
+                               ES300_DATA_PATH(0, 0, TXCHMGR5)),
+               .mux_type = PASS_MO2,
+               .cmd_len = 1,
+               .chn_mgr_mask = BIT(TXCHMGR5),
+       },
+};
+
+struct es_mux_info es_dhwpt_mux_info = {
+       .in_mux_start = DHWPT_PASSIN1_MUX,
+       .in_mux_len = DHWPT_IN_MUX_LEN,
+       .out_mux_start = DHWPT_PASSOUT1_MUX,
+       .out_mux_len = DHWPT_OUT_MUX_LEN,
+       .in_tbl = &es_dhwpt_in_route_tbl,
+       .out_tbl = &es_dhwpt_out_route_tbl,
+};
+
 void prepare_mux_cmd(int mux, u32 *msg, u32 *msg_len,
                u16 *chn_mgr_mask, struct es_mux_info *mux_info, int type)
 {
index 73821fd25b0f80fe7fdea99313afadbce429ec26..e298260d3d8e84ce093da04f016d1c8e54c7d4ad 100644 (file)
@@ -73,6 +73,7 @@ enum {
 };
 #endif
 /* MUX info structure for each base route */
+extern struct es_mux_info es_dhwpt_mux_info;
 extern struct es_mux_info es_pt_vp_mux_info;
 extern struct es_mux_info es_vp_mux_info;
 
index c87203e5aa3b8697a7702d581a5b6f1ffd1b0a4d..7c2b4b2b257d44ceb25f9f1227acb4b4daf8b49b 100644 (file)
@@ -212,6 +212,7 @@ static const u32 es_base_route_preset[ALGO_MAX] = {
        [MM] = 0x90311772,
        [PASSTHRU] = 0x9031177D,
 #endif
+       [DHWPT] = 0x9031178F,
 };
 
 static const struct es_ch_mgr_max es_chn_mgr_max[ALGO_MAX] = {
@@ -230,6 +231,10 @@ static const struct es_ch_mgr_max es_chn_mgr_max[ALGO_MAX] = {
        [PASSTHRU_VP] = {
                .tx = PT_VP_TXCHMGR_MAX,
        },
+       [DHWPT] = {
+               .rx = DHWPT_RXCHMGR_MAX,
+               .tx = DHWPT_TXCHMGR_MAX,
+       },
 };
 
 static u32 switch_arr[] = {
@@ -440,6 +445,19 @@ static int convert_input_mux_to_cmd(struct escore_priv *escore, int reg)
                update_chmgr_mask = 0;
                break;
 
+       case DHWPT:
+               /* Unused channel managers in base route 6031 */
+               chn_mgr_mask[escore->algo_type] |= BIT(RXCHMGR5);
+               prepare_mux_cmd(reg, msg, &msg_len,
+                               &chn_mgr_mask[escore->algo_type],
+                               &es_dhwpt_mux_info, CMD_INPUT);
+               if (reg != ES_PASSIN1_MUX && reg != ES_PASSIN2_MUX) {
+                       msg[0] |= value;
+                       update_chmgr_mask = 0;
+               } else {
+                       goto done;
+               }
+               break;
        case PASSTHRU_VP:
                prepare_mux_cmd(reg, msg, &msg_len,
                                &chn_mgr_mask[escore->algo_type],
@@ -456,7 +474,7 @@ static int convert_input_mux_to_cmd(struct escore_priv *escore, int reg)
 
        if (update_chmgr_mask)
                chn_mgr_mask[escore->algo_type] |= 1 << ch_mgr;
-
+done:
        return escore_queue_msg_to_list(escore, (char *)msg, msg_len);
 }
 
@@ -513,6 +531,21 @@ static int convert_output_mux_to_cmd(struct escore_priv *escore, int reg)
                update_chmgr_mask = 0;
                update_msgs = 0;
                break;
+       case DHWPT:
+               prepare_mux_cmd(mux, msg, &msg_len,
+                               &chn_mgr_mask[escore->algo_type],
+                               &es_dhwpt_mux_info, CMD_OUTPUT);
+               for (i = 0; i < ARRAY_SIZE(es_out_mux_map); i++) {
+                       if (es_out_mux_map[i].mux_id == reg) {
+                               if (mux != PASS_AUDOUT1 && mux != PASS_AUDOUT2)
+                                       msg[0] |= es_out_mux_map[i].port_desc;
+                               else
+                                       goto done;
+                       }
+               }
+               update_chmgr_mask = 0;
+               update_msgs = 0;
+               break;
        }
 
        port = (msg[0] >> 9) & 0x1f;
@@ -527,7 +560,7 @@ static int convert_output_mux_to_cmd(struct escore_priv *escore, int reg)
 
        if (update_chmgr_mask)
                chn_mgr_mask[escore->algo_type] |= 1 << ch_mgr;
-
+done:
        return escore_queue_msg_to_list(escore, (char *)msg, msg_len);
 }
 
@@ -572,6 +605,11 @@ static int add_algo_base_route(struct escore_priv *escore)
        escore->current_preset =  msg & 0xFFFF;
        rc = escore_queue_msg_to_list(escore, (char *)&msg, sizeof(msg));
 
+       if (!rc && escore->algo_type == DHWPT) {
+               msg = escore->dhwpt_cmd;
+               rc = escore_queue_msg_to_list(escore,
+                               (char *)&msg, sizeof(msg));
+       }
        /* Configure command completion mode */
        if (escore->cmd_compl_mode == ES_CMD_COMP_INTR) {
                cmd |= escore->pdata->gpio_a_irq_type;
@@ -716,7 +754,8 @@ static int es_set_final_route(struct escore_priv *escore)
        escore->capture_mode = 0;
        escore->output_mode = 0;
        for (i = ES_DAC0_0_MUX; i <= ES_SBUSTX5_MUX; i++) {
-               if (escore->algo_type == PASSTHRU_VP) {
+               if (escore->algo_type == PASSTHRU_VP
+                               || escore->algo_type == DHWPT) {
                        int mux = cachedcmd_list[escore->algo_type][i].reg;
                        switch (mux) {
                        case PASS_AO1:
@@ -760,7 +799,7 @@ static int es_set_final_route(struct escore_priv *escore)
                        sizeof(prev_cmdlist));
 
        /* Do necessary switch settings */
-       if (escore->algo_type == PASSTHRU_VP) {
+       if (escore->algo_type == PASSTHRU_VP || escore->algo_type == DHWPT) {
                int pri, fein;
 
                pri = cachedcmd_list[escore->algo_type][ES_PRIMARY_MUX].reg;
@@ -1356,6 +1395,9 @@ static int es300_put_algo_state(struct snd_kcontrol *kcontrol,
        case ES_ALGORITHM_AZ:
                algo_type = AUDIOZOOM;
                break;
+       case ES_ALGORITHM_DHWPT:
+               algo_type = DHWPT;
+               break;
        default:
                pr_err("%s(): Algo type not implemented: %d\n", __func__, reg);
                ret = -EINVAL;
@@ -1947,6 +1989,10 @@ static const struct soc_enum az_algorithm_enum =
        SOC_ENUM_SINGLE(ES_ALGORITHM_AZ, 0,
                        ARRAY_SIZE(algorithm_texts),
                        algorithm_texts);
+static const struct soc_enum dhwpt_algorithm_enum =
+       SOC_ENUM_SINGLE(ES_ALGORITHM_DHWPT, 0,
+                       ARRAY_SIZE(algorithm_texts),
+                       algorithm_texts);
 
 static const char * const es755_algo_rates_text[] = {
        "None", "SR_8k", "SR_16k", "SR_24k", "SR_48k", "SR_96k", "SR_192k",
@@ -2029,6 +2075,8 @@ static const struct snd_kcontrol_new es_d300_snd_controls[] = {
                         es300_get_algo_state, es300_put_algo_state),
        SOC_ENUM_EXT("AZ Algorithm", az_algorithm_enum,
                         es300_get_algo_state, es300_put_algo_state),
+       SOC_ENUM_EXT("DHWPT Algorithm", dhwpt_algorithm_enum,
+                        es300_get_algo_state, es300_put_algo_state),
 
        SOC_ENUM_EXT("Algorithm Rate", algorithm_rate_enum,
                         get_control_enum, es300_put_algo_rate),
index 1936ed03c6dfa0baeb4c759a57af5588bbb6faf4..cfe4474b277e46762905d4a58ab2b848e47a79cf 100644 (file)
@@ -66,7 +66,8 @@ enum {
 #define VP_MM_TXCHMGR_MAX 5
 #define PT_VP_RXCHMGR_MAX 6
 #define PT_VP_TXCHMGR_MAX 6
-
+#define DHWPT_RXCHMGR_MAX 6
+#define DHWPT_TXCHMGR_MAX 6
 enum {
        ES_VP_NONE,
        ES_VP_RX_INIT, /* VP RX Initialized */
@@ -88,6 +89,7 @@ enum {
        PASSTHRU_VP_MM,
        PASSTHRU_AZ,
        VOICEQ,
+       DHWPT,
        NONE,
        ALGO_MAX,
 };
index 7fa8dd1528dc2b0fc686426e834d1f706371d719..3b0afd2e4d21d9ab4cddc9cb1b72d679901cf8d5 100644 (file)
@@ -570,7 +570,14 @@ static void es755_shutdown(struct snd_pcm_substream *substream,
 static int es755_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
 {
        struct snd_soc_codec *codec = dai->codec;
+       struct escore_priv *escore = snd_soc_codec_get_drvdata(codec);
+       struct escore_api_access *api_access;
+       int data_justification;
        int id = DAI_INDEX(dai->id);
+       u8 pcm_port[] = { ES755_PCM_PORT_A,
+               ES755_PCM_PORT_B,
+               ES755_PCM_PORT_C };
+       int rc;
 
        dev_dbg(codec->dev, "%s(): dai->name = %s, dai->id = %d, fmt = %x\n",
                __func__, dai->name, dai->id, fmt);
@@ -609,6 +616,7 @@ static int es755_hw_params(struct snd_pcm_substream *substream,
        int bps = 0;
        int rate = 0;
        int id = DAI_INDEX(dai->id);
+       int port_map = 0;
        u16 clock_control = 0;
        u8 pcm_port[] = { ES755_PCM_PORT_A,
                ES755_PCM_PORT_B,
@@ -752,25 +760,22 @@ static int es755_hw_params(struct snd_pcm_substream *substream,
         */
        escore->can_mpsleep = (rate == 48) && (bps == 0x1F) && (channels == 2);
 
-       if (escore->can_mpsleep) {
-               int port_map = 0;
-               switch (dai->id) {
-               case ES_I2S_PORTA:
-                       port_map = PORT_A_TO_D;
-                       break;
-               case ES_I2S_PORTB:
-                       port_map = PORT_B_TO_D;
-                       break;
-               case ES_I2S_PORTC:
-                       port_map = PORT_C_TO_D;
-                       break;
-               }
-               BUG_ON(!port_map);
+       switch (dai->id) {
+       case ES_I2S_PORTA:
+               port_map = PORT_A_TO_D;
+               break;
+       case ES_I2S_PORTB:
+               port_map = PORT_B_TO_D;
+               break;
+       case ES_I2S_PORTC:
+               port_map = PORT_C_TO_D;
+               break;
+       }
+
+       if (escore->can_mpsleep || escore->algo_type == DHWPT)
                escore->dhwpt_cmd = (ES_DHWPT_CMD << 16) | port_map;
-       } else {
-               /* Clear the DHWPT command */
+       else
                escore->dhwpt_cmd = 0;
-       }
 
        dev_dbg(codec->dev, "%s(): params_channels(params) = %d\n", __func__,
                channels);
index 3c964132bcbfd009c0689115be41d08b294cf402..2a507e9df61cfc5d8eb625337546bba393600218 100644 (file)
 #define ES755_PCM_PORT_B               0xB
 #define ES755_PCM_PORT_C               0xC
 
-/* Digital Hardware Passthrough Mapping for PCM ports */
-#define PORT_A_TO_D    0x00CC
-#define PORT_B_TO_D    0x00DD
-#define PORT_C_TO_D    0x00EE
+/* Unidirectional Digital Hardware Passthrough Mapping for PCM ports */
+#define PORT_A_TO_D    0x01CC
+#define PORT_B_TO_D    0x01DD
+#define PORT_C_TO_D    0x01EE
 
 union es755_accdet_status_reg {
        u16 value;
@@ -177,6 +177,7 @@ enum {
        ES_ALGORITHM_PT,
        ES_ALGORITHM_PT_VP,
        ES_ALGORITHM_AZ,
+       ES_ALGORITHM_DHWPT,
 
        /* PCM Port Parameters*/
        ES_PCM_PORT,