From 5206840c7d959e501fa15cd3be8f2878dfa55ddc Mon Sep 17 00:00:00 2001 From: Harendra Gautam Date: Wed, 13 Sep 2023 10:59:58 +0530 Subject: [PATCH] audio-kernel:swr: Add dynamic SWRM clk support - Add support to load dynamic soundwire master clk from devicetree file. Change-Id: I59527f42aa7d3a7b00a0b161c3867c16aaecb263 Signed-off-by: Harendra Gautam --- include/soc/soundwire.h | 6 +++ include/soc/swr-wcd.h | 1 + soc/swr-mstr-ctrl.c | 92 ++++++++++++++++++++++++++++++----------- 3 files changed, 76 insertions(+), 23 deletions(-) diff --git a/include/soc/soundwire.h b/include/soc/soundwire.h index a8c5ec83e9e2..dffb4db05491 100644 --- a/include/soc/soundwire.h +++ b/include/soc/soundwire.h @@ -18,6 +18,12 @@ #define SWR_CLK_RATE_4P8MHZ 4800000 #define SWR_CLK_RATE_9P6MHZ 9600000 #define SWR_CLK_RATE_11P2896MHZ 11289600 +#define SWR_CLK_RATE_0P384MHZ 384000 +#define SWR_CLK_RATE_0P768MHZ 768000 +#define SWR_CLK_RATE_1P536MHZ 1536000 +#define SWR_CLK_RATE_3P072MHZ 3072000 +#define SWR_CLK_RATE_6P144MHZ 6144000 +#define SWR_CLK_RATE_12P288MHZ 12288000 extern struct bus_type soundwire_type; struct swr_device; diff --git a/include/soc/swr-wcd.h b/include/soc/swr-wcd.h index 8ed9f0a05e3b..140d4eecd81d 100644 --- a/include/soc/swr-wcd.h +++ b/include/soc/swr-wcd.h @@ -34,6 +34,7 @@ struct swr_mstr_port { #define MCLK_FREQ 9600000 #define MCLK_FREQ_LP 600000 #define MCLK_FREQ_NATIVE 11289600 +#define MCLK_FREQ_12P288MHZ 12288000 #if (IS_ENABLED(CONFIG_SOUNDWIRE_WCD_CTRL) || \ IS_ENABLED(CONFIG_SOUNDWIRE_MSTR_CTRL)) diff --git a/soc/swr-mstr-ctrl.c b/soc/swr-mstr-ctrl.c index 098f2fe1c36c..b1209a68dcac 100644 --- a/soc/swr-mstr-ctrl.c +++ b/soc/swr-mstr-ctrl.c @@ -1160,8 +1160,8 @@ static void swrm_switch_frame_shape(struct swr_mstr_ctrl *swrm, int mclk_freq) } else { n_col = SWR_MIN_COL; col = SWRM_COL_02; - n_row = SWR_ROW_50; - row = SWRM_ROW_50; + n_row = (mclk_freq == MCLK_FREQ_12P288MHZ) ? SWR_ROW_64 : SWR_ROW_50; + row = (mclk_freq == MCLK_FREQ_12P288MHZ) ? SWRM_ROW_64 : SWRM_ROW_50; frame_sync = SWRM_FRAME_SYNC_SEL; } @@ -1222,16 +1222,25 @@ int swrm_get_clk_div_rate(int mclk_freq, int bus_clk_freq) if (mclk_freq == SWR_CLK_RATE_9P6MHZ) { if (bus_clk_freq <= SWR_CLK_RATE_0P6MHZ) bus_clk_freq = SWR_CLK_RATE_0P6MHZ; - else if (bus_clk_freq <= SWR_CLK_RATE_1P2MHZ) - bus_clk_freq = SWR_CLK_RATE_4P8MHZ; - else if (bus_clk_freq <= SWR_CLK_RATE_2P4MHZ) - bus_clk_freq = SWR_CLK_RATE_4P8MHZ; - else if(bus_clk_freq <= SWR_CLK_RATE_4P8MHZ) + else if ((bus_clk_freq <= SWR_CLK_RATE_1P2MHZ) || + (bus_clk_freq <= SWR_CLK_RATE_2P4MHZ) || + (bus_clk_freq <= SWR_CLK_RATE_4P8MHZ)) bus_clk_freq = SWR_CLK_RATE_4P8MHZ; else if(bus_clk_freq <= SWR_CLK_RATE_9P6MHZ) bus_clk_freq = SWR_CLK_RATE_9P6MHZ; else bus_clk_freq = SWR_CLK_RATE_9P6MHZ; + } else if (mclk_freq == SWR_CLK_RATE_12P288MHZ) { + if (bus_clk_freq <= SWR_CLK_RATE_0P768MHZ) + bus_clk_freq = SWR_CLK_RATE_0P768MHZ; + else if ((bus_clk_freq <= SWR_CLK_RATE_1P536MHZ) || + (bus_clk_freq <= SWR_CLK_RATE_3P072MHZ) || + (bus_clk_freq <= SWR_CLK_RATE_6P144MHZ)) + bus_clk_freq = SWR_CLK_RATE_6P144MHZ; + else if(bus_clk_freq <= SWR_CLK_RATE_12P288MHZ) + bus_clk_freq = SWR_CLK_RATE_12P288MHZ; + else + bus_clk_freq = SWR_CLK_RATE_12P288MHZ; } else if (mclk_freq == SWR_CLK_RATE_11P2896MHZ) bus_clk_freq = SWR_CLK_RATE_11P2896MHZ; @@ -1368,12 +1377,14 @@ static void swrm_get_device_frame_shape(struct swr_mstr_ctrl *swrm, if ((swrm->master_id == MASTER_ID_TX) && (swrm->use_custom_phy_addr) && - ((swrm->bus_clk == SWR_CLK_RATE_9P6MHZ) || + ((swrm->bus_clk == SWR_CLK_RATE_12P288MHZ) || + (swrm->bus_clk == SWR_CLK_RATE_9P6MHZ) || (swrm->bus_clk == SWR_CLK_RATE_0P6MHZ) || (swrm->bus_clk == SWR_CLK_RATE_4P8MHZ))) { dev_num = swrm_get_device_id(swrm, port_req->dev_num); port_id = port_req->slave_port_id; - if (swrm->bus_clk == SWR_CLK_RATE_9P6MHZ) + if ((swrm->bus_clk == SWR_CLK_RATE_12P288MHZ) || + (swrm->bus_clk == SWR_CLK_RATE_9P6MHZ)) pp_dev = swrdev_frame_params_9p6MHz[dev_num].pp; else if (swrm->bus_clk == SWR_CLK_RATE_0P6MHZ) pp_dev = swrdev_frame_params_0p6MHz[dev_num].pp; @@ -1681,7 +1692,8 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable) /* set col = 16 */ n_col = SWR_MAX_COL; col = SWRM_COL_16; - if (swrm->bus_clk == MCLK_FREQ_LP) { + if ((swrm->bus_clk == MCLK_FREQ_LP) || + (swrm->bus_clk == SWR_CLK_RATE_0P768MHZ)) { n_col = SWR_MIN_COL; col = SWRM_COL_02; } @@ -1699,16 +1711,15 @@ static int swrm_slvdev_datapath_control(struct swr_master *master, bool enable) } /* Use default 50 * x, frame shape. Change based on mclk */ if (swrm->mclk_freq == MCLK_FREQ_NATIVE) { - dev_dbg(swrm->dev, "setting 64 x %d frameshape\n", col); n_row = SWR_ROW_64; row = SWRM_ROW_64; frame_sync = SWRM_FRAME_SYNC_SEL_NATIVE; } else { - dev_dbg(swrm->dev, "setting 50 x %d frameshape\n", col); - n_row = SWR_ROW_50; - row = SWRM_ROW_50; + n_row = (swrm->mclk_freq == MCLK_FREQ_12P288MHZ) ? SWR_ROW_64 : SWR_ROW_50; + row = (swrm->mclk_freq == MCLK_FREQ_12P288MHZ) ? SWRM_ROW_64 : SWRM_ROW_50; frame_sync = SWRM_FRAME_SYNC_SEL; } + dev_dbg(swrm->dev, "setting %d x %d frameshape\n", row, col); ssp_period = swrm_get_ssp_period(swrm, row, col, frame_sync); bus_clk_div_factor = swrm_get_clk_div(swrm->mclk_freq, swrm->bus_clk); dev_dbg(swrm->dev, "%s: ssp_period: %d, bus_clk_div:%d \n", __func__, @@ -2450,14 +2461,28 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) { int ret = 0, i = 0; u32 val; - u8 row_ctrl = SWR_ROW_50; - u8 col_ctrl = SWR_MIN_COL; + u8 row_ctrl = 0, row = 0; + u8 col_ctrl = SWR_MIN_COL, col = SWRM_COL_02; u8 ssp_period = 1; u8 retry_cmd_num = 3; u32 reg[SWRM_MAX_INIT_REG]; u32 value[SWRM_MAX_INIT_REG]; u32 temp = 0; int len = 0; + int frame_sync = SWRM_FRAME_SYNC_SEL; + + if (swrm->mclk_freq == MCLK_FREQ_NATIVE) { + row_ctrl = SWR_ROW_64; + row = SWRM_ROW_64; + frame_sync = SWRM_FRAME_SYNC_SEL_NATIVE; + + } else { + row_ctrl = (swrm->mclk_freq == MCLK_FREQ_12P288MHZ) ? + SWR_ROW_64 : SWR_ROW_50; + row = (swrm->mclk_freq == MCLK_FREQ_12P288MHZ) ? + SWRM_ROW_64 : SWRM_ROW_50; + frame_sync = SWRM_FRAME_SYNC_SEL; + } /* Change no of retry counts to 1 for wsa to avoid underflow */ if (swrm->master_id == MASTER_ID_WSA) @@ -2475,8 +2500,7 @@ static int swrm_master_init(struct swr_mstr_ctrl *swrm) __func__, temp); } } - ssp_period = swrm_get_ssp_period(swrm, SWRM_ROW_50, - SWRM_COL_02, SWRM_FRAME_SYNC_SEL); + ssp_period = swrm_get_ssp_period(swrm, row, col, frame_sync); dev_dbg(swrm->dev, "%s: ssp_period: %d\n", __func__, ssp_period); /* Clear Rows and Cols */ @@ -2595,7 +2619,7 @@ static int swrm_probe(struct platform_device *pdev) { struct swr_mstr_ctrl *swrm; struct swr_ctrl_platform_data *pdata; - u32 i, num_ports, port_num, port_type, ch_mask, swrm_hctl_reg = 0; + u32 i, num_ports, port_num, port_type, ch_mask, swrm_hctl_reg = 0, mclk_freq = 0; u32 *temp, map_size, map_length, ch_iter = 0, old_port_num = 0; int ret = 0; struct clk *lpass_core_hw_vote = NULL; @@ -2830,8 +2854,6 @@ static int swrm_probe(struct platform_device *pdev) swrm->num_rx_chs = 0; swrm->clk_ref_count = 0; swrm->swr_irq_wakeup_capable = 0; - swrm->mclk_freq = MCLK_FREQ; - swrm->bus_clk = MCLK_FREQ; swrm->dev_up = true; swrm->state = SWR_MSTR_UP; swrm->ipc_wakeup = false; @@ -2861,6 +2883,17 @@ static int swrm_probe(struct platform_device *pdev) for (i = 0 ; i < SWR_MSTR_PORT_LEN; i++) INIT_LIST_HEAD(&swrm->mport_cfg[i].port_req_list); + ret = of_property_read_u32(pdev->dev.of_node, "qcom,swrm-mclk-clk-rate", + &mclk_freq); + if (ret) { + swrm->mclk_freq = MCLK_FREQ; + dev_dbg(&pdev->dev, "%s SWRM MCLK not specified, using default: %d,\n", + __func__, swrm->mclk_freq); + } else { + swrm->mclk_freq = mclk_freq; + } + swrm->bus_clk = swrm->mclk_freq; + if (of_property_read_u32(pdev->dev.of_node, "qcom,disable-div2-clk-switch", &swrm->disable_div2_clk_switch)) { @@ -3092,6 +3125,12 @@ static int swrm_runtime_resume(struct device *dev) struct swr_master *mstr = &swrm->master; struct swr_device *swr_dev; u32 temp = 0; + u8 row_ctrl = SWR_ROW_50; + u8 col_ctrl = SWR_MIN_COL; + + if ((swrm->mclk_freq == MCLK_FREQ_NATIVE) || + (swrm->mclk_freq == MCLK_FREQ_12P288MHZ)) + row_ctrl = SWR_ROW_64; dev_dbg(dev, "%s: pm_runtime: resume, state:%d\n", __func__, swrm->state); @@ -3178,7 +3217,7 @@ static int swrm_runtime_resume(struct device *dev) SWRS_SCP_INT_STATUS_MASK_1); if (swrm->state == SWR_MSTR_SSR) { mutex_unlock(&swrm->reslock); - enable_bank_switch(swrm, 0, SWR_ROW_50, SWR_MIN_COL); + enable_bank_switch(swrm, 0, row_ctrl, col_ctrl); mutex_lock(&swrm->reslock); } } else { @@ -3235,6 +3274,13 @@ static int swrm_runtime_suspend(struct device *dev) int current_state = 0; struct irq_data *irq_data = NULL; + u8 row_ctrl = SWR_ROW_50; + u8 col_ctrl = SWR_MIN_COL; + + if ((swrm->mclk_freq == MCLK_FREQ_NATIVE) || + (swrm->mclk_freq == MCLK_FREQ_12P288MHZ)) + row_ctrl = SWR_ROW_64; + dev_dbg(dev, "%s: pm_runtime: suspend state: %d\n", __func__, swrm->state); if (swrm->state == SWR_MSTR_SSR_RESET) { @@ -3268,7 +3314,7 @@ static int swrm_runtime_suspend(struct device *dev) dev_err(dev, "%s: clk stop mode not supported or SSR entry\n", __func__); mutex_unlock(&swrm->reslock); - enable_bank_switch(swrm, 0, SWR_ROW_50, SWR_MIN_COL); + enable_bank_switch(swrm, 0, row_ctrl, col_ctrl); mutex_lock(&swrm->reslock); swrm_clk_pause(swrm); swr_master_write(swrm, SWRM_COMP_CFG, 0x00);