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)); clk->rate = (u64)(clk->parent->rate * 16) / div; return 0; }
static void ipu_pixel_clk_recalc(struct clk *clk) { u32 div = __raw_readl(DI_BS_CLKGEN0(clk->id)); if (div == 0) clk->rate = 0; else clk->rate = (clk->parent->rate * 16) / div; }
static int ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate) { u32 div = (clk->parent->rate * 16) / rate; __raw_writel(div, DI_BS_CLKGEN0(clk->id)); /* Setup pixel clock timing */ __raw_writel((div / 16) << 16, DI_BS_CLKGEN1(clk->id)); clk->rate = (clk->parent->rate * 16) / div; return 0; }
static int ipu_pixel_clk_set_rate(struct clk *clk, unsigned long rate) { u32 div = (clk->parent->rate * 16) / rate; __raw_writel(div, DI_BS_CLKGEN0(clk->id)); /* Setup pixel clock timing */ /* Shift the pixel clock a little bit (1/4 - 3/4) */ __raw_writel( ((div * 3 / 32) << 16) | (div / 32), DI_BS_CLKGEN1(clk->id) ); clk->rate = (clk->parent->rate * 16) / div; return 0; }
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; } }