ASoC: davinci-mcasp: Implement configurable dismod handling
authorPeter Ujfalusi <peter.ujfalusi@ti.com>
Fri, 16 Nov 2018 13:41:41 +0000 (15:41 +0200)
committerMark Brown <broonie@kernel.org>
Wed, 28 Nov 2018 12:41:31 +0000 (12:41 +0000)
If the dismod is specified in the DT node, use the specified custom value
to configure the drive on state of the inactive TX slots.

If the dismod is not present or booted in legacy mode, the dismod is set
to low as it was the original behavior.

Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
include/linux/platform_data/davinci_asp.h
sound/soc/davinci/davinci-mcasp.c
sound/soc/davinci/davinci-mcasp.h

index 85ad68f9206ae929b4cc3ec571735c651134be09..7fe80f1c7e081c0cad5b0ba4ce2db562f249edc8 100644 (file)
@@ -79,6 +79,7 @@ struct davinci_mcasp_pdata {
        /* McASP specific fields */
        int tdm_slots;
        u8 op_mode;
+       u8 dismod;
        u8 num_serializer;
        u8 *serial_dir;
        u8 version;
index 0f3911be1c8e0280d893a89994242d8dd1206ce6..40d3a916fb74baa3655a7d31f220f6f74edd7b7a 100644 (file)
@@ -85,6 +85,7 @@ struct davinci_mcasp {
        u32     tdm_mask[2];
        int     slot_width;
        u8      op_mode;
+       u8      dismod;
        u8      num_serializer;
        u8      *serial_dir;
        u8      version;
@@ -834,7 +835,7 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
                if (mcasp->serial_dir[i] == TX_MODE &&
                                        tx_ser < max_active_serializers) {
                        mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
-                                      DISMOD_LOW, DISMOD_MASK);
+                                      mcasp->dismod, DISMOD_MASK);
                        set_bit(PIN_BIT_AXR(i), &mcasp->pdir);
                        tx_ser++;
                } else if (mcasp->serial_dir[i] == RX_MODE &&
@@ -847,6 +848,8 @@ static int mcasp_common_hw_param(struct davinci_mcasp *mcasp, int stream,
                        clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
                } else if (mcasp->serial_dir[i] == TX_MODE) {
                        /* Unused TX pins, clear PDIR  */
+                       mcasp_mod_bits(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
+                                      mcasp->dismod, DISMOD_MASK);
                        clear_bit(PIN_BIT_AXR(i), &mcasp->pdir);
                }
        }
@@ -1709,6 +1712,7 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
 
        if (pdev->dev.platform_data) {
                pdata = pdev->dev.platform_data;
+               pdata->dismod = DISMOD_LOW;
                return pdata;
        } else if (match) {
                pdata = devm_kmemdup(&pdev->dev, match->data, sizeof(*pdata),
@@ -1798,6 +1802,18 @@ static struct davinci_mcasp_pdata *davinci_mcasp_set_pdata_from_of(
        if (ret >= 0)
                pdata->sram_size_capture = val;
 
+       ret = of_property_read_u32(np, "dismod", &val);
+       if (ret >= 0) {
+               if (val == 0 || val == 2 || val == 3) {
+                       pdata->dismod = DISMOD_VAL(val);
+               } else {
+                       dev_warn(&pdev->dev, "Invalid dismod value: %u\n", val);
+                       pdata->dismod = DISMOD_LOW;
+               }
+       } else {
+               pdata->dismod = DISMOD_LOW;
+       }
+
        return  pdata;
 
 nodata:
@@ -1973,6 +1989,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        mcasp->version = pdata->version;
        mcasp->txnumevt = pdata->txnumevt;
        mcasp->rxnumevt = pdata->rxnumevt;
+       mcasp->dismod = pdata->dismod;
 
        mcasp->dev = &pdev->dev;
 
index acb024ab6a9d15e37d9ed8bd3e7d2d1885140aa2..5e4060d8fe56a0867e185a1a3332bea58a3858a7 100644 (file)
 #define DISMOD_3STATE  (0x0)
 #define DISMOD_LOW     (0x2 << 2)
 #define DISMOD_HIGH    (0x3 << 2)
+#define DISMOD_VAL(x)  ((x) << 2)
 #define DISMOD_MASK    DISMOD_HIGH
 #define TXSTATE                BIT(4)
 #define RXSTATE                BIT(5)