In preparation for CCF migration for IPUv3 separate existing clock code to legacy files. These will be used by i.MX5 that currently does not support the CCF. No functional change.
Signed-off-by: Brian Ruley <[email protected]> --- drivers/video/imx/Kconfig | 7 + drivers/video/imx/Makefile | 1 + drivers/video/imx/ipu.h | 60 +++++- drivers/video/imx/ipu_clk_legacy.c | 310 +++++++++++++++++++++++++++ drivers/video/imx/ipu_common.c | 322 +---------------------------- 5 files changed, 376 insertions(+), 324 deletions(-) create mode 100644 drivers/video/imx/ipu_clk_legacy.c diff --git a/drivers/video/imx/Kconfig b/drivers/video/imx/Kconfig index b35ba965efc..c25f209629e 100644 --- a/drivers/video/imx/Kconfig +++ b/drivers/video/imx/Kconfig @@ -15,6 +15,13 @@ config IMX_HDMI bool "Enable HDMI support in IPUv3" depends on VIDEO_IPUV3 +config IPU_CLK_LEGACY + bool "Use legacy clock management for IPU" + depends on VIDEO_IPUV3 && !CLK + default y + help + Use legacy clock management instead of Common Clock Framework. + config IMX_LDB bool "Freescale i.MX8MP LDB bridge" depends on VIDEO_BRIDGE diff --git a/drivers/video/imx/Makefile b/drivers/video/imx/Makefile index 1edf5a6bdf0..0e7f71a9f93 100644 --- a/drivers/video/imx/Makefile +++ b/drivers/video/imx/Makefile @@ -4,5 +4,6 @@ # Wolfgang Denk, DENX Software Engineering, [email protected]. obj-$(CONFIG_VIDEO_IPUV3) += mxc_ipuv3_fb.o ipu_common.o ipu_disp.o +obj-$(CONFIG_IPU_CLK_LEGACY) += ipu_clk_legacy.o obj-$(CONFIG_IMX_LDB) += ldb.o obj-$(CONFIG_IMX_LCDIF) += lcdif.o diff --git a/drivers/video/imx/ipu.h b/drivers/video/imx/ipu.h index 62827dc480d..ae40e20bc28 100644 --- a/drivers/video/imx/ipu.h +++ b/drivers/video/imx/ipu.h @@ -18,14 +18,23 @@ #ifndef __ASM_ARCH_IPU_H__ #define __ASM_ARCH_IPU_H__ +#if !CONFIG_IS_ENABLED(IPU_CLK_LEGACY) +#include <clk.h> +#endif #include <ipu_pixfmt.h> #include <linux/types.h> +#define IPUV3_CLK_MX51 133000000 +#define IPUV3_CLK_MX53 200000000 +#define IPUV3_CLK_MX6Q 264000000 +#define IPUV3_CLK_MX6DL 198000000 + #define IDMA_CHAN_INVALID 0xFF #define HIGH_RESOLUTION_WIDTH 1024 struct ipu_ctx; -struct ipu_di_config; + +#if CONFIG_IS_ENABLED(IPU_CLK_LEGACY) struct clk { const char *name; @@ -75,6 +84,46 @@ struct clk { int (*set_parent)(struct clk *clk, struct clk *parent); }; +/* Legacy clock API functions */ +void clk_enable(struct clk *clk); +void clk_disable(struct clk *clk); +int clk_get_usecount(struct clk *clk); +u32 clk_get_rate(struct clk *clk); +struct clk *clk_get_parent(struct clk *clk); +int clk_set_rate(struct clk *clk, unsigned long rate); +long clk_round_rate(struct clk *clk, unsigned long rate); +int clk_set_parent(struct clk *clk, struct clk *parent); + +/* IPU clock initialization */ +int ipu_clk_init_legacy(struct ipu_ctx *ctx); +int ipu_ldb_clk_init_legacy(struct ipu_ctx *ctx); +int ipu_pixel_clk_init_legacy(struct ipu_ctx *ctx, int id); + +#else + +static inline int clk_get_usecount(struct clk *clk) +{ + return clk->enable_count; +} + +/* Stub functions for non-legacy builds */ +static inline int ipu_clk_init_legacy(struct ipu_ctx *ctx) +{ + return -ENOSYS; +} + +static inline int ipu_ldb_clk_init_legacy(struct ipu_ctx *ctx) +{ + return -ENOSYS; +} + +static inline int ipu_pixel_clk_init_legacy(struct ipu_ctx *ctx, int id) +{ + return -ENOSYS; +} + +#endif /* CONFIG_IS_ENABLED(IPU_CLK_LEGACY) */ + struct udevice; /* @@ -298,15 +347,6 @@ int32_t ipu_disp_set_color_key(ipu_channel_t channel, unsigned char enable, u32 bytes_per_pixel(u32 fmt); -void clk_enable(struct clk *clk); -void clk_disable(struct clk *clk); -u32 clk_get_rate(struct clk *clk); -int clk_set_rate(struct clk *clk, unsigned long rate); -long clk_round_rate(struct clk *clk, unsigned long rate); -int clk_set_parent(struct clk *clk, struct clk *parent); -int clk_get_usecount(struct clk *clk); -struct clk *clk_get_parent(struct clk *clk); - void ipu_dump_registers(void); struct ipu_ctx *ipu_probe(struct udevice *dev); bool ipu_clk_enabled(struct ipu_ctx *ctx); diff --git a/drivers/video/imx/ipu_clk_legacy.c b/drivers/video/imx/ipu_clk_legacy.c new file mode 100644 index 00000000000..8aaafa2a080 --- /dev/null +++ b/drivers/video/imx/ipu_clk_legacy.c @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Legacy IPU clock management for i.MX5/6 without Common Clock Framework + * + * (C) Copyright 2026 + * Brian Ruley, GE HealthCare, [email protected] + */ + +#include "ipu.h" +#include "ipu_regs.h" +#include <asm/arch/crm_regs.h> +#include <asm/arch/sys_proto.h> +#include <asm/io.h> +#include <div64.h> +#include <dm/devres.h> +#include <linux/err.h> +#include <log.h> + +extern struct mxc_ccm_reg *mxc_ccm; + +void clk_enable(struct clk *clk) +{ + if (clk) { + if (clk->usecount++ == 0) + clk->enable(clk); + } +} + +void clk_disable(struct clk *clk) +{ + if (clk) { + if (!(--clk->usecount)) { + if (clk->disable) + clk->disable(clk); + } + } +} + +int clk_get_usecount(struct clk *clk) +{ + if (clk == NULL) + return 0; + + return clk->usecount; +} + +u32 clk_get_rate(struct clk *clk) +{ + if (!clk) + return 0; + + return clk->rate; +} + +struct clk *clk_get_parent(struct clk *clk) +{ + if (!clk) + return 0; + + return clk->parent; +} + +int clk_set_rate(struct clk *clk, unsigned long rate) +{ + if (!clk) + return 0; + + if (clk->set_rate) + clk->set_rate(clk, rate); + + return clk->rate; +} + +long clk_round_rate(struct clk *clk, unsigned long rate) +{ + if (clk == NULL || !clk->round_rate) + return 0; + + return clk->round_rate(clk, rate); +} + +int clk_set_parent(struct clk *clk, struct clk *parent) +{ + clk->parent = parent; + if (clk->set_parent) + return clk->set_parent(clk, parent); + return 0; +} + +static int clk_ipu_enable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg |= MXC_CCM_CCGR_CG_MASK << clk->enable_shift; + __raw_writel(reg, clk->enable_reg); + +#if CONFIG_IS_ENABLED(MX51) || CONFIG_IS_ENABLED(MX53) + reg = __raw_readl(&mxc_ccm->ccdr); + reg &= ~MXC_CCM_CCDR_IPU_HS_MASK; + __raw_writel(reg, &mxc_ccm->ccdr); + + reg = __raw_readl(&mxc_ccm->clpcr); + reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; + __raw_writel(reg, &mxc_ccm->clpcr); +#endif + return 0; +} + +static void clk_ipu_disable(struct clk *clk) +{ + u32 reg; + + reg = __raw_readl(clk->enable_reg); + reg &= ~(MXC_CCM_CCGR_CG_MASK << clk->enable_shift); + __raw_writel(reg, clk->enable_reg); + +#if CONFIG_IS_ENABLED(MX51) || CONFIG_IS_ENABLED(MX53) + reg = __raw_readl(&mxc_ccm->ccdr); + reg |= MXC_CCM_CCDR_IPU_HS_MASK; + __raw_writel(reg, &mxc_ccm->ccdr); + + reg = __raw_readl(&mxc_ccm->clpcr); + reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; + __raw_writel(reg, &mxc_ccm->clpcr); +#endif +} + +static void ipu_pixel_clk_recalc(struct clk *clk) +{ + u32 div; + u64 final_rate = (unsigned long long)clk->parent->rate * 16; + + div = __raw_readl(DI_BS_CLKGEN0(clk->id)); + debug("read BS_CLKGEN0 div:%d, final_rate:%lld, prate:%ld\n", div, + final_rate, clk->parent->rate); + + clk->rate = 0; + if (div != 0) { + do_div(final_rate, div); + clk->rate = final_rate; + } +} + +static unsigned long ipu_pixel_clk_round_rate(struct clk *clk, + unsigned long rate) +{ + u64 div, final_rate; + u32 remainder; + u64 parent_rate = (unsigned long long)clk->parent->rate * 16; + + div = parent_rate; + remainder = do_div(div, rate); + if (remainder > (rate / 2)) + div++; + if (div < 0x10) + div = 0x10; + if (div & ~0xFEF) + div &= 0xFF8; + else { + if ((div & 0xC) == 0xC) { + div += 0x10; + div &= ~0xF; + } + } + final_rate = parent_rate; + do_div(final_rate, div); + + return final_rate; +} + +static int ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate) +{ + u64 div, parent_rate; + u32 remainder; + + parent_rate = (unsigned long long)clk->parent->rate * 16; + div = parent_rate; + remainder = do_div(div, rate); + if (remainder > (rate / 2)) + div++; + + if ((div & 0xC) == 0xC) { + div += 0x10; + div &= ~0xF; + } + if (div > 0x1000) + debug("Overflow, DI_BS_CLKGEN0 div:0x%x\n", (u32)div); + + __raw_writel(div, DI_BS_CLKGEN0(clk->id)); + __raw_writel((div / 16) << 16, DI_BS_CLKGEN1(clk->id)); + + do_div(parent_rate, div); + clk->rate = parent_rate; + + return 0; +} + +static int ipu_pixel_clk_enable(struct clk *clk) +{ + u32 disp_gen = __raw_readl(IPU_DISP_GEN); + disp_gen |= clk->id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE; + __raw_writel(disp_gen, IPU_DISP_GEN); + + return 0; +} + +static void ipu_pixel_clk_disable(struct clk *clk) +{ + u32 disp_gen = __raw_readl(IPU_DISP_GEN); + disp_gen &= clk->id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE; + __raw_writel(disp_gen, IPU_DISP_GEN); +} + +static int ipu_pixel_clk_set_parent(struct clk *clk, struct clk *parent) +{ + u32 di_gen = __raw_readl(DI_GENERAL(clk->id)); + struct ipu_ctx *ctx = clk->ctx; + + if (parent == ctx->ipu_clk) + di_gen &= ~DI_GEN_DI_CLK_EXT; + else if (!IS_ERR(ctx->di_clk[clk->id]) && parent == ctx->ldb_clk) + di_gen |= DI_GEN_DI_CLK_EXT; + else + return -EINVAL; + + __raw_writel(di_gen, DI_GENERAL(clk->id)); + ipu_pixel_clk_recalc(clk); + return 0; +} + +int ipu_pixel_clk_init_legacy(struct ipu_ctx *ctx, int id) +{ + struct clk *pixel_clk; + + pixel_clk = devm_kzalloc(ctx->dev, sizeof(*pixel_clk), GFP_KERNEL); + if (!pixel_clk) + return -ENOMEM; + + pixel_clk->name = "pixel_clk"; + pixel_clk->id = id; + pixel_clk->ctx = ctx; + pixel_clk->recalc = ipu_pixel_clk_recalc; + pixel_clk->set_rate = ipu_pixel_clk_set_rate; + pixel_clk->round_rate = ipu_pixel_clk_round_rate; + pixel_clk->set_parent = ipu_pixel_clk_set_parent; + pixel_clk->enable = ipu_pixel_clk_enable; + pixel_clk->disable = ipu_pixel_clk_disable; + pixel_clk->usecount = 0; + + ctx->pixel_clk[id] = pixel_clk; + return 0; +} + +int ipu_clk_init_legacy(struct ipu_ctx *ctx) +{ + struct clk *ipu_clk; + + ipu_clk = devm_kzalloc(ctx->dev, sizeof(*ipu_clk), GFP_KERNEL); + if (!ipu_clk) + return -ENOMEM; + + ipu_clk->name = "ipu_clk"; + ipu_clk->ctx = ctx; +#if CONFIG_IS_ENABLED(MX51) || CONFIG_IS_ENABLED(MX53) + ipu_clk->enable_reg = + (u32 *)(CCM_BASE_ADDR + offsetof(struct mxc_ccm_reg, CCGR5)); + ipu_clk->enable_shift = MXC_CCM_CCGR5_IPU_OFFSET; +#else + ipu_clk->enable_reg = + (u32 *)(CCM_BASE_ADDR + offsetof(struct mxc_ccm_reg, CCGR3)); + ipu_clk->enable_shift = MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET; +#endif + + ipu_clk->enable = clk_ipu_enable; + ipu_clk->disable = clk_ipu_disable; + ipu_clk->usecount = 0; + +#if CONFIG_IS_ENABLED(MX51) + ipu_clk->rate = IPUV3_CLK_MX51; +#elif CONFIG_IS_ENABLED(MX53) + ipu_clk->rate = IPUV3_CLK_MX53; +#else + ipu_clk->rate = is_mx6sdl() ? IPUV3_CLK_MX6DL : IPUV3_CLK_MX6Q; +#endif + + ctx->ipu_clk = ipu_clk; + return 0; +} + +#if !defined CFG_SYS_LDB_CLOCK +#define CFG_SYS_LDB_CLOCK 65000000 +#endif + +int ipu_ldb_clk_init_legacy(struct ipu_ctx *ctx) +{ + struct clk *ldb_clk; + + ldb_clk = devm_kzalloc(ctx->dev, sizeof(*ldb_clk), GFP_KERNEL); + if (!ldb_clk) + return -ENOMEM; + + ldb_clk->name = "ldb_clk"; + ldb_clk->ctx = ctx; + ldb_clk->rate = CFG_SYS_LDB_CLOCK; + ldb_clk->usecount = 0; + + ctx->ldb_clk = ldb_clk; + return 0; +} diff --git a/drivers/video/imx/ipu_common.c b/drivers/video/imx/ipu_common.c index e9897ee79d2..d994053394f 100644 --- a/drivers/video/imx/ipu_common.c +++ b/drivers/video/imx/ipu_common.c @@ -31,8 +31,8 @@ #include <linux/types.h> #include <log.h> -extern struct mxc_ccm_reg *mxc_ccm; -extern u32 *ipu_cpmem_base; +u32 *ipu_cpmem_base; +u32 *ipu_dc_tmpl_reg; struct ipu_ch_param_word { u32 data[5]; @@ -92,126 +92,6 @@ struct ipu_ch_param { #define IPU_SW_RST_TOUT_USEC (10000) -#define IPUV3_CLK_MX51 133000000 -#define IPUV3_CLK_MX53 200000000 -#define IPUV3_CLK_MX6Q 264000000 -#define IPUV3_CLK_MX6DL 198000000 - -void clk_enable(struct clk *clk) -{ - if (clk) { - if (clk->usecount++ == 0) - clk->enable(clk); - } -} - -void clk_disable(struct clk *clk) -{ - if (clk) { - if (!(--clk->usecount)) { - if (clk->disable) - clk->disable(clk); - } - } -} - -int clk_get_usecount(struct clk *clk) -{ - if (clk == NULL) - return 0; - - return clk->usecount; -} - -u32 clk_get_rate(struct clk *clk) -{ - if (!clk) - return 0; - - return clk->rate; -} - -struct clk *clk_get_parent(struct clk *clk) -{ - if (!clk) - return 0; - - return clk->parent; -} - -int clk_set_rate(struct clk *clk, unsigned long rate) -{ - if (!clk) - return 0; - - if (clk->set_rate) - clk->set_rate(clk, rate); - - return clk->rate; -} - -long clk_round_rate(struct clk *clk, unsigned long rate) -{ - if (clk == NULL || !clk->round_rate) - return 0; - - return clk->round_rate(clk, rate); -} - -int clk_set_parent(struct clk *clk, struct clk *parent) -{ - clk->parent = parent; - if (clk->set_parent) - return clk->set_parent(clk, parent); - return 0; -} - -static int clk_ipu_enable(struct clk *clk) -{ - u32 reg; - - reg = __raw_readl(clk->enable_reg); - reg |= MXC_CCM_CCGR_CG_MASK << clk->enable_shift; - __raw_writel(reg, clk->enable_reg); - -#if CONFIG_IS_ENABLED(MX51) || CONFIG_IS_ENABLED(MX53) - /* Handshake with IPU when certain clock rates are changed. */ - reg = __raw_readl(&mxc_ccm->ccdr); - reg &= ~MXC_CCM_CCDR_IPU_HS_MASK; - __raw_writel(reg, &mxc_ccm->ccdr); - - /* Handshake with IPU when LPM is entered as its enabled. */ - reg = __raw_readl(&mxc_ccm->clpcr); - reg &= ~MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; - __raw_writel(reg, &mxc_ccm->clpcr); -#endif - return 0; -} - -static void clk_ipu_disable(struct clk *clk) -{ - u32 reg; - - reg = __raw_readl(clk->enable_reg); - reg &= ~(MXC_CCM_CCGR_CG_MASK << clk->enable_shift); - __raw_writel(reg, clk->enable_reg); - -#if CONFIG_IS_ENABLED(MX51) || CONFIG_IS_ENABLED(MX53) - /* - * No handshake with IPU whe dividers are changed - * as its not enabled. - */ - reg = __raw_readl(&mxc_ccm->ccdr); - reg |= MXC_CCM_CCDR_IPU_HS_MASK; - __raw_writel(reg, &mxc_ccm->ccdr); - - /* No handshake with IPU when LPM is entered as its not enabled. */ - reg = __raw_readl(&mxc_ccm->clpcr); - reg |= MXC_CCM_CLPCR_BYPASS_IPU_LPM_HS; - __raw_writel(reg, &mxc_ccm->clpcr); -#endif -} - /* * Function to initialize the ipu clock * @@ -221,43 +101,8 @@ static void clk_ipu_disable(struct clk *clk) */ static int ipu_clk_init(struct ipu_ctx *ctx) { - struct clk *ipu_clk; - - ipu_clk = devm_kzalloc(ctx->dev, sizeof(*ipu_clk), GFP_KERNEL); - if (!ipu_clk) - return -ENOMEM; - - ipu_clk->name = "ipu_clk"; - ipu_clk->ctx = ctx; -#if CONFIG_IS_ENABLED(MX51) || CONFIG_IS_ENABLED(MX53) - ipu_clk->enable_reg = - (u32 *)(CCM_BASE_ADDR + offsetof(struct mxc_ccm_reg, CCGR5)); - ipu_clk->enable_shift = MXC_CCM_CCGR5_IPU_OFFSET; -#else - ipu_clk->enable_reg = - (u32 *)(CCM_BASE_ADDR + offsetof(struct mxc_ccm_reg, CCGR3)); - ipu_clk->enable_shift = MXC_CCM_CCGR3_IPU1_IPU_DI0_OFFSET; -#endif - - ipu_clk->enable = clk_ipu_enable; - ipu_clk->disable = clk_ipu_disable; - ipu_clk->usecount = 0; - -#if CONFIG_IS_ENABLED(MX51) - ipu_clk->rate = IPUV3_CLK_MX51; -#elif CONFIG_IS_ENABLED(MX53) - ipu_clk->rate = IPUV3_CLK_MX53; -#else - ipu_clk->rate = is_mx6sdl() ? IPUV3_CLK_MX6DL : IPUV3_CLK_MX6Q; -#endif - - ctx->ipu_clk = ipu_clk; - return 0; -}; - -#if !defined CFG_SYS_LDB_CLOCK -#define CFG_SYS_LDB_CLOCK 65000000 -#endif + return ipu_clk_init_legacy(ctx); +} /* * Function to initialize the ldb dummy clock @@ -268,23 +113,8 @@ static int ipu_clk_init(struct ipu_ctx *ctx) */ static int ipu_ldb_clk_init(struct ipu_ctx *ctx) { - struct clk *ldb_clk; - - ldb_clk = devm_kzalloc(ctx->dev, sizeof(*ldb_clk), GFP_KERNEL); - if (!ldb_clk) - return -ENOMEM; - - ldb_clk->name = "ldb_clk"; - ldb_clk->ctx = ctx; - ldb_clk->rate = CFG_SYS_LDB_CLOCK; - ldb_clk->usecount = 0; - - ctx->ldb_clk = ldb_clk; - return 0; -}; - -u32 *ipu_cpmem_base; -u32 *ipu_dc_tmpl_reg; + return ipu_ldb_clk_init_legacy(ctx); +} /* Static functions */ @@ -320,124 +150,6 @@ static inline void ipu_ch_param_set_buffer(u32 ch, int buf_num, #define idma_mask(ch) (idma_is_valid(ch) ? (1UL << (ch & 0x1F)) : 0) #define idma_is_set(reg, dma) (__raw_readl(reg(dma)) & idma_mask(dma)) -static void ipu_pixel_clk_recalc(struct clk *clk) -{ - u32 div; - u64 final_rate = (unsigned long long)clk->parent->rate * 16; - - div = __raw_readl(DI_BS_CLKGEN0(clk->id)); - debug("read BS_CLKGEN0 div:%d, final_rate:%lld, prate:%ld\n", div, - final_rate, clk->parent->rate); - - clk->rate = 0; - if (div != 0) { - do_div(final_rate, div); - clk->rate = final_rate; - } -} - -static unsigned long ipu_pixel_clk_round_rate(struct clk *clk, - unsigned long rate) -{ - u64 div, final_rate; - u32 remainder; - u64 parent_rate = (unsigned long long)clk->parent->rate * 16; - - /* - * Calculate divider - * Fractional part is 4 bits, - * so simply multiply by 2^4 to get fractional part. - */ - div = parent_rate; - remainder = do_div(div, rate); - /* Round the divider value */ - if (remainder > (rate / 2)) - div++; - if (div < 0x10) /* Min DI disp clock divider is 1 */ - div = 0x10; - if (div & ~0xFEF) - div &= 0xFF8; - else { - /* Round up divider if it gets us closer to desired pix clk */ - if ((div & 0xC) == 0xC) { - div += 0x10; - div &= ~0xF; - } - } - final_rate = parent_rate; - do_div(final_rate, div); - - return final_rate; -} - -static int ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate) -{ - u64 div, parent_rate; - u32 remainder; - - parent_rate = (unsigned long long)clk->parent->rate * 16; - div = parent_rate; - remainder = do_div(div, rate); - /* Round the divider value */ - if (remainder > (rate / 2)) - div++; - - /* Round up divider if it gets us closer to desired pix clk */ - if ((div & 0xC) == 0xC) { - div += 0x10; - div &= ~0xF; - } - if (div > 0x1000) - debug("Overflow, DI_BS_CLKGEN0 div:0x%x\n", (u32)div); - - __raw_writel(div, DI_BS_CLKGEN0(clk->id)); - - /* - * Setup pixel clock timing - * Down time is half of period - */ - __raw_writel((div / 16) << 16, DI_BS_CLKGEN1(clk->id)); - - do_div(parent_rate, div); - - clk->rate = parent_rate; - - return 0; -} - -static int ipu_pixel_clk_enable(struct clk *clk) -{ - u32 disp_gen = __raw_readl(IPU_DISP_GEN); - disp_gen |= clk->id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE; - __raw_writel(disp_gen, IPU_DISP_GEN); - - return 0; -} - -static void ipu_pixel_clk_disable(struct clk *clk) -{ - u32 disp_gen = __raw_readl(IPU_DISP_GEN); - disp_gen &= clk->id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE; - __raw_writel(disp_gen, IPU_DISP_GEN); -} - -static int ipu_pixel_clk_set_parent(struct clk *clk, struct clk *parent) -{ - u32 di_gen = __raw_readl(DI_GENERAL(clk->id)); - struct ipu_ctx *ctx = clk->ctx; - - if (parent == ctx->ipu_clk) - di_gen &= ~DI_GEN_DI_CLK_EXT; - else if (!IS_ERR(ctx->di_clk[clk->id]) && parent == ctx->ldb_clk) - di_gen |= DI_GEN_DI_CLK_EXT; - else - return -EINVAL; - - __raw_writel(di_gen, DI_GENERAL(clk->id)); - ipu_pixel_clk_recalc(clk); - return 0; -} - /* * Function to initialize the pixel clock * @@ -447,26 +159,8 @@ static int ipu_pixel_clk_set_parent(struct clk *clk, struct clk *parent) */ static int ipu_pixel_clk_init(struct ipu_ctx *ctx, int id) { - struct clk *pixel_clk; - - pixel_clk = devm_kzalloc(ctx->dev, sizeof(*pixel_clk), GFP_KERNEL); - if (!pixel_clk) - return -ENOMEM; - - pixel_clk->name = "pixel_clk"; - pixel_clk->id = id; - pixel_clk->ctx = ctx; - pixel_clk->recalc = ipu_pixel_clk_recalc; - pixel_clk->set_rate = ipu_pixel_clk_set_rate; - pixel_clk->round_rate = ipu_pixel_clk_round_rate; - pixel_clk->set_parent = ipu_pixel_clk_set_parent; - pixel_clk->enable = ipu_pixel_clk_enable; - pixel_clk->disable = ipu_pixel_clk_disable; - pixel_clk->usecount = 0; - - ctx->pixel_clk[id] = pixel_clk; - return 0; -}; + return ipu_pixel_clk_init_legacy(ctx, id); +} /* * This function resets IPU -- 2.39.5

