diff --git a/src/drivers/intel/cavs/mn.c b/src/drivers/intel/cavs/mn.c index 1f03f47ee..9586e6504 100644 --- a/src/drivers/intel/cavs/mn.c +++ b/src/drivers/intel/cavs/mn.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include #include @@ -53,14 +54,16 @@ struct mn { struct mn mn; -void mn_init(void) +void mn_init(struct sof *sof) { int i; - for (i = 0; i < ARRAY_SIZE(mn.bclk_sources); i++) - mn.bclk_sources[i] = MN_BCLK_SOURCE_NONE; + sof->mn = &mn; - spinlock_init(&mn.lock); + for (i = 0; i < ARRAY_SIZE(sof->mn->bclk_sources); i++) + sof->mn->bclk_sources[i] = MN_BCLK_SOURCE_NONE; + + spinlock_init(&sof->mn->lock); } /** @@ -70,10 +73,11 @@ void mn_init(void) */ static inline bool is_mclk_source_in_use(void) { + struct mn *mn = mn_get(); int i; - for (i = 0; i < ARRAY_SIZE(mn.mclk_sources_used); i++) - if (mn.mclk_sources_used[i]) + for (i = 0; i < ARRAY_SIZE(mn->mclk_sources_used); i++) + if (mn->mclk_sources_used[i]) return true; return false; } @@ -87,6 +91,7 @@ static inline bool is_mclk_source_in_use(void) */ static inline int setup_initial_mclk_source(uint32_t mclk_rate) { + struct mn *mn = mn_get(); int i; int clk_index = -1; uint32_t mdivc = mn_reg_read(MN_MDIVCTRL); @@ -106,7 +111,7 @@ static inline int setup_initial_mclk_source(uint32_t mclk_rate) return -EINVAL; } - mn.mclk_source_clock = clk_index; + mn->mclk_source_clock = clk_index; /* enable MCLK divider */ mdivc |= MN_MDIVCTRL_M_DIV_ENABLE; @@ -125,9 +130,11 @@ static inline int setup_initial_mclk_source(uint32_t mclk_rate) */ static inline int check_current_mclk_source(uint32_t mclk_rate) { - if (ssp_freq[mn.mclk_source_clock].freq % mclk_rate != 0) { + struct mn *mn = mn_get(); + + if (ssp_freq[mn->mclk_source_clock].freq % mclk_rate != 0) { trace_mn_error("error: MCLK %d, no valid configuration for already selected source = %d", - mclk_rate, mn.mclk_source_clock); + mclk_rate, mn->mclk_source_clock); return -EINVAL; } return 0; @@ -167,6 +174,7 @@ static inline int set_mclk_divider(uint16_t mclk_id, uint32_t mdivr_val) int mn_set_mclk(uint16_t mclk_id, uint32_t mclk_rate) { + struct mn *mn = mn_get(); int ret = 0; if (mclk_id >= DAI_NUM_SSP_MCLK) { @@ -175,9 +183,9 @@ int mn_set_mclk(uint16_t mclk_id, uint32_t mclk_rate) return -EINVAL; } - spin_lock(&mn.lock); + spin_lock(&mn->lock); - mn.mclk_sources_used[mclk_id] = false; + mn->mclk_sources_used[mclk_id] = false; if (is_mclk_source_in_use()) ret = check_current_mclk_source(mclk_rate); @@ -187,22 +195,25 @@ int mn_set_mclk(uint16_t mclk_id, uint32_t mclk_rate) if (ret < 0) goto out; - mn.mclk_sources_used[mclk_id] = true; + mn->mclk_sources_used[mclk_id] = true; ret = set_mclk_divider(mclk_id, - ssp_freq[mn.mclk_source_clock].freq / mclk_rate); + ssp_freq[mn->mclk_source_clock].freq / + mclk_rate); out: - spin_unlock(&mn.lock); + spin_unlock(&mn->lock); return ret; } void mn_release_mclk(uint32_t mclk_id) { - spin_lock(&mn.lock); - mn.mclk_sources_used[mclk_id] = false; - spin_unlock(&mn.lock); + struct mn *mn = mn_get(); + + spin_lock(&mn->lock); + mn->mclk_sources_used[mclk_id] = false; + spin_unlock(&mn->lock); } /** @@ -299,10 +310,11 @@ static int find_bclk_source(uint32_t bclk, */ static inline bool is_bclk_source_in_use(enum bclk_source clk_src) { + struct mn *mn = mn_get(); int i; - for (i = 0; i < ARRAY_SIZE(mn.bclk_sources); i++) - if (mn.bclk_sources[i] == clk_src) + for (i = 0; i < ARRAY_SIZE(mn->bclk_sources); i++) + if (mn->bclk_sources[i] == clk_src) return true; return false; } @@ -320,6 +332,7 @@ static inline bool is_bclk_source_in_use(enum bclk_source clk_src) static inline int setup_initial_bclk_mn_source(uint32_t bclk, uint32_t *scr_div, uint32_t *m, uint32_t *n) { + struct mn *mn = mn_get(); int clk_index = find_bclk_source(bclk, scr_div, m, n); if (clk_index < 0) { @@ -327,7 +340,7 @@ static inline int setup_initial_bclk_mn_source(uint32_t bclk, uint32_t *scr_div, return -EINVAL; } - mn.bclk_source_mn_clock = clk_index; + mn->bclk_source_mn_clock = clk_index; mn_reg_write(MN_MDIVCTRL, (mn_reg_read(MN_MDIVCTRL) | MNDSS(ssp_freq_sources[clk_index]))); @@ -346,13 +359,15 @@ static inline int setup_initial_bclk_mn_source(uint32_t bclk, uint32_t *scr_div, static inline int setup_current_bclk_mn_source(uint32_t bclk, uint32_t *scr_div, uint32_t *m, uint32_t *n) { + struct mn *mn = mn_get(); + /* source for M/N is already set, no need to do it */ - if (find_mn(ssp_freq[mn.bclk_source_mn_clock].freq, bclk, scr_div, m, + if (find_mn(ssp_freq[mn->bclk_source_mn_clock].freq, bclk, scr_div, m, n)) return 0; trace_mn_error("error: BCLK %d, no valid configuration for already selected source = %d", - bclk, mn.bclk_source_mn_clock); + bclk, mn->bclk_source_mn_clock); return -EINVAL; } @@ -376,6 +391,7 @@ static inline bool check_bclk_xtal_source(uint32_t bclk, bool mn_in_use, static inline bool check_bclk_xtal_source(uint32_t bclk, bool mn_in_use, uint32_t *scr_div) { + struct mn *mn = mn_get(); int i; for (i = 0; i <= MAX_SSP_FREQ_INDEX; i++) { @@ -393,7 +409,7 @@ static inline bool check_bclk_xtal_source(uint32_t bclk, bool mn_in_use, /* if M/N is already set up for desired clock, * we can quit and let M/N logic handle it */ - if (!mn_in_use || mn.bclk_source_mn_clock == i) + if (!mn_in_use || mn->bclk_source_mn_clock == i) return false; } @@ -404,19 +420,20 @@ static inline bool check_bclk_xtal_source(uint32_t bclk, bool mn_in_use, int mn_set_bclk(uint32_t dai_index, uint32_t bclk_rate, uint32_t *out_scr_div, bool *out_need_ecs) { + struct mn *mn = mn_get(); uint32_t m = 1; uint32_t n = 1; int ret = 0; bool mn_in_use; - spin_lock(&mn.lock); + spin_lock(&mn->lock); - mn.bclk_sources[dai_index] = MN_BCLK_SOURCE_NONE; + mn->bclk_sources[dai_index] = MN_BCLK_SOURCE_NONE; mn_in_use = is_bclk_source_in_use(MN_BCLK_SOURCE_MN); if (check_bclk_xtal_source(bclk_rate, mn_in_use, out_scr_div)) { - mn.bclk_sources[dai_index] = MN_BCLK_SOURCE_XTAL; + mn->bclk_sources[dai_index] = MN_BCLK_SOURCE_XTAL; *out_need_ecs = false; goto out; } @@ -431,29 +448,33 @@ int mn_set_bclk(uint32_t dai_index, uint32_t bclk_rate, out_scr_div, &m, &n); if (ret >= 0) { - mn.bclk_sources[dai_index] = MN_BCLK_SOURCE_MN; + mn->bclk_sources[dai_index] = MN_BCLK_SOURCE_MN; mn_reg_write(MN_MDIV_M_VAL(dai_index), m); mn_reg_write(MN_MDIV_N_VAL(dai_index), n); } out: - spin_unlock(&mn.lock); + spin_unlock(&mn->lock); return ret; } void mn_release_bclk(uint32_t dai_index) { - spin_lock(&mn.lock); - mn.bclk_sources[dai_index] = MN_BCLK_SOURCE_NONE; - spin_unlock(&mn.lock); + struct mn *mn = mn_get(); + + spin_lock(&mn->lock); + mn->bclk_sources[dai_index] = MN_BCLK_SOURCE_NONE; + spin_unlock(&mn->lock); } void mn_reset_bclk_divider(uint32_t dai_index) { - spin_lock(&mn.lock); + struct mn *mn = mn_get(); + + spin_lock(&mn->lock); mn_reg_write(MN_MDIV_M_VAL(dai_index), 1); mn_reg_write(MN_MDIV_N_VAL(dai_index), 1); - spin_unlock(&mn.lock); + spin_unlock(&mn->lock); } diff --git a/src/include/sof/drivers/mn.h b/src/include/sof/drivers/mn.h index 27598528a..3e383d34f 100644 --- a/src/include/sof/drivers/mn.h +++ b/src/include/sof/drivers/mn.h @@ -8,6 +8,7 @@ #ifndef __SOF_DRIVERS_MN_H__ #define __SOF_DRIVERS_MN_H__ +#include #include #include @@ -29,7 +30,7 @@ /** * \brief Initializes MN driver. */ -void mn_init(void); +void mn_init(struct sof *sof); /** * \brief Finds and sets valid combination of MCLK source and divider to @@ -77,4 +78,13 @@ void mn_release_bclk(uint32_t dai_index); */ void mn_reset_bclk_divider(uint32_t dai_index); +/** + * \brief Retrieves M/N dividers structure. + * \return Pointer to M/N dividers structure. + */ +static inline struct mn *mn_get(void) +{ + return sof_get()->mn; +} + #endif /* __SOF_DRIVERS_MN_H__ */ diff --git a/src/include/sof/sof.h b/src/include/sof/sof.h index ce7bb5db8..69fb66ef5 100644 --- a/src/include/sof/sof.h +++ b/src/include/sof/sof.h @@ -21,6 +21,7 @@ struct dma_trace_data; struct ipc; struct ll_schedule_domain; struct mm; +struct mn; struct notify_data; struct pm_runtime_data; struct sa; @@ -87,6 +88,9 @@ struct sof { /* list of registered component drivers */ struct comp_driver_list *comp_drivers; + /* M/N dividers */ + struct mn *mn; + __aligned(PLATFORM_DCACHE_ALIGN) int alignment[0]; } __aligned(PLATFORM_DCACHE_ALIGN); diff --git a/src/platform/intel/cavs/lib/dai.c b/src/platform/intel/cavs/lib/dai.c index d93e387f8..eb405ccf8 100644 --- a/src/platform/intel/cavs/lib/dai.c +++ b/src/platform/intel/cavs/lib/dai.c @@ -155,7 +155,7 @@ int dai_init(struct sof *sof) #endif #if CONFIG_CAVS_MN - mn_init(); + mn_init(sof); #endif dai = cache_to_uncache((struct dai *)hda);