static int _ipu_pixel_clk_div_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_clk_rate) { struct clk_di_div *di_div = to_clk_di_div(hw); struct ipu_soc *ipu = ipu_get_soc(di_div->ipu_id); u64 div, parent_rate; u64 remainder; parent_rate = (unsigned long long)parent_clk_rate * 16; div = parent_rate; div = do_udiv64(div, rate, &remainder); /* 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) pr_err("Overflow, di:%d, DI_BS_CLKGEN0 div:0x%x\n", di_div->di_id, (u32)div); _ipu_get(ipu); ipu_di_write(ipu, di_div->di_id, (u32)div, DI_BS_CLKGEN0); /* Setup pixel clock timing */ /* FIXME: needs to be more flexible */ /* Down time is half of period */ ipu_di_write(ipu, di_div->di_id, ((u32)div / 16) << 16, DI_BS_CLKGEN1); _ipu_put(ipu); return 0; }
static long _ipu_pixel_clk_div_round_rate(struct clk_hw *hw, unsigned long rate, unsigned long *parent_clk_rate) { u64 div, final_rate; u64 remainder; u64 parent_rate = (unsigned long long)(*parent_clk_rate) * 16; /* * Calculate divider * Fractional part is 4 bits, * so simply multiply by 2^4 to get fractional part. */ div = parent_rate; div = do_udiv64(div, rate, &remainder); /* 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; final_rate = udiv64(final_rate, div); return final_rate; }
static int printi(char **out, u32 *out_len, long long i, int b, int sg, int width, int flags, int letbase) { char print_buf[PRINT_BUF_LEN]; char *s; int neg = 0, pc = 0; u64 t; unsigned long long u = i; if (sg && b == 10 && i < 0) { neg = 1; u = -i; } s = print_buf + PRINT_BUF_LEN - 1; *s = '\0'; if (!u) { *--s = '0'; } else { while (u) { u = do_udiv64(u, b, &t); if (t >= 10) t += letbase - '0' - 10; *--s = t + '0'; } } if (flags & PAD_ALTERNATE) { if ((b == 16) && (letbase == 'A')) { *--s = 'X'; } else if ((b == 16) && (letbase == 'a')) { *--s = 'x'; } *--s = '0'; } if (neg) { if (width && (flags & PAD_ZERO)) { printc(out, out_len, '-'); ++pc; --width; } else { *--s = '-'; } } return pc + prints(out, out_len, s, width, flags); }