Lines Matching +full:mipi +full:- +full:ccs
1 // SPDX-License-Identifier: GPL-2.0-only
3 * drivers/media/i2c/ccs-pll.c
5 * Generic MIPI CCS/SMIA/SMIA++ PLL calculator
8 * Copyright (C) 2011--2012 Nokia Corporation
17 #include "ccs-pll.h"
55 dev_dbg(dev, "%s_%s out of bounds: %d (%d--%d)\n", prefix, in bounds_check()
58 return -EINVAL; in bounds_check()
85 { &pll->vt_fr, &pll->vt_bk, PLL_VT }, in print_pll()
86 { &pll->op_fr, &pll->op_bk, PLL_OP } in print_pll()
90 dev_dbg(dev, "ext_clk_freq_hz\t\t%u\n", pll->ext_clk_freq_hz); in print_pll()
93 const char *s = pll_string(br->which); in print_pll()
95 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL || in print_pll()
96 br->which == PLL_VT) { in print_pll()
98 br->fr->pre_pll_clk_div); in print_pll()
100 br->fr->pll_multiplier); in print_pll()
103 br->fr->pll_ip_clk_freq_hz); in print_pll()
105 br->fr->pll_op_clk_freq_hz); in print_pll()
108 if (!(pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) || in print_pll()
109 br->which == PLL_VT) { in print_pll()
111 br->bk->sys_clk_div); in print_pll()
113 br->bk->pix_clk_div); in print_pll()
116 br->bk->sys_clk_freq_hz); in print_pll()
118 br->bk->pix_clk_freq_hz); in print_pll()
123 pll->pixel_rate_pixel_array); in print_pll()
124 dev_dbg(dev, "pixel rate on CSI-2 bus:\t%u\n", in print_pll()
125 pll->pixel_rate_csi); in print_pll()
128 pll->flags & PLL_FL(LANE_SPEED_MODEL) ? " lane-speed" : "", in print_pll()
129 pll->flags & PLL_FL(LINK_DECOUPLED) ? " link-decoupled" : "", in print_pll()
130 pll->flags & PLL_FL(EXT_IP_PLL_DIVIDER) ? in print_pll()
131 " ext-ip-pll-divider" : "", in print_pll()
132 pll->flags & PLL_FL(FLEXIBLE_OP_PIX_CLK_DIV) ? in print_pll()
133 " flexible-op-pix-div" : "", in print_pll()
134 pll->flags & PLL_FL(FIFO_DERATING) ? " fifo-derating" : "", in print_pll()
135 pll->flags & PLL_FL(FIFO_OVERRATING) ? " fifo-overrating" : "", in print_pll()
136 pll->flags & PLL_FL(DUAL_PLL) ? " dual-pll" : "", in print_pll()
137 pll->flags & PLL_FL(OP_SYS_DDR) ? " op-sys-ddr" : "", in print_pll()
138 pll->flags & PLL_FL(OP_PIX_DDR) ? " op-pix-ddr" : ""); in print_pll()
161 lim_fr = &lim->op_fr; in check_fr_bounds()
162 pll_fr = &pll->op_fr; in check_fr_bounds()
164 lim_fr = &lim->vt_fr; in check_fr_bounds()
165 pll_fr = &pll->vt_fr; in check_fr_bounds()
168 rval = bounds_check(dev, pll_fr->pre_pll_clk_div, in check_fr_bounds()
169 lim_fr->min_pre_pll_clk_div, in check_fr_bounds()
170 lim_fr->max_pre_pll_clk_div, s, "pre_pll_clk_div"); in check_fr_bounds()
173 rval = bounds_check(dev, pll_fr->pll_ip_clk_freq_hz, in check_fr_bounds()
174 lim_fr->min_pll_ip_clk_freq_hz, in check_fr_bounds()
175 lim_fr->max_pll_ip_clk_freq_hz, in check_fr_bounds()
178 rval = bounds_check(dev, pll_fr->pll_multiplier, in check_fr_bounds()
179 lim_fr->min_pll_multiplier, in check_fr_bounds()
180 lim_fr->max_pll_multiplier, in check_fr_bounds()
183 rval = bounds_check(dev, pll_fr->pll_op_clk_freq_hz, in check_fr_bounds()
184 lim_fr->min_pll_op_clk_freq_hz, in check_fr_bounds()
185 lim_fr->max_pll_op_clk_freq_hz, in check_fr_bounds()
201 if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) in check_bk_bounds()
204 lim_bk = &lim->op_bk; in check_bk_bounds()
205 pll_bk = &pll->op_bk; in check_bk_bounds()
207 lim_bk = &lim->vt_bk; in check_bk_bounds()
208 pll_bk = &pll->vt_bk; in check_bk_bounds()
211 rval = bounds_check(dev, pll_bk->sys_clk_div, in check_bk_bounds()
212 lim_bk->min_sys_clk_div, in check_bk_bounds()
213 lim_bk->max_sys_clk_div, s, "op_sys_clk_div"); in check_bk_bounds()
215 rval = bounds_check(dev, pll_bk->sys_clk_freq_hz, in check_bk_bounds()
216 lim_bk->min_sys_clk_freq_hz, in check_bk_bounds()
217 lim_bk->max_sys_clk_freq_hz, in check_bk_bounds()
220 rval = bounds_check(dev, pll_bk->sys_clk_div, in check_bk_bounds()
221 lim_bk->min_sys_clk_div, in check_bk_bounds()
222 lim_bk->max_sys_clk_div, in check_bk_bounds()
225 rval = bounds_check(dev, pll_bk->pix_clk_freq_hz, in check_bk_bounds()
226 lim_bk->min_pix_clk_freq_hz, in check_bk_bounds()
227 lim_bk->max_pix_clk_freq_hz, in check_bk_bounds()
235 if (!(pll->flags & CCS_PLL_FLAG_FIFO_DERATING) && in check_ext_bounds()
236 pll->pixel_rate_pixel_array > pll->pixel_rate_csi) { in check_ext_bounds()
238 return -EINVAL; in check_ext_bounds()
241 if (!(pll->flags & CCS_PLL_FLAG_FIFO_OVERRATING) && in check_ext_bounds()
242 pll->pixel_rate_pixel_array < pll->pixel_rate_csi) { in check_ext_bounds()
244 return -EINVAL; in check_ext_bounds()
260 *min_sys_div = lim->vt_bk.min_sys_clk_div; in ccs_pll_find_vt_sys_div()
264 lim->vt_bk.max_pix_clk_div)); in ccs_pll_find_vt_sys_div()
267 pll_fr->pll_op_clk_freq_hz in ccs_pll_find_vt_sys_div()
268 / lim->vt_bk.max_sys_clk_freq_hz); in ccs_pll_find_vt_sys_div()
273 *max_sys_div = lim->vt_bk.max_sys_clk_div; in ccs_pll_find_vt_sys_div()
277 lim->vt_bk.min_pix_clk_div)); in ccs_pll_find_vt_sys_div()
280 DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, in ccs_pll_find_vt_sys_div()
281 lim->vt_bk.min_pix_clk_freq_hz)); in ccs_pll_find_vt_sys_div()
294 const struct ccs_pll_branch_limits_fr *lim_fr = &lim->vt_fr; in __ccs_pll_calculate_vt_tree()
295 const struct ccs_pll_branch_limits_bk *lim_bk = &lim->vt_bk; in __ccs_pll_calculate_vt_tree()
296 struct ccs_pll_branch_fr *pll_fr = &pll->vt_fr; in __ccs_pll_calculate_vt_tree()
297 struct ccs_pll_branch_bk *pll_bk = &pll->vt_bk; in __ccs_pll_calculate_vt_tree()
299 u16 best_pix_div = SHRT_MAX >> 1, best_div = lim_bk->max_sys_clk_div; in __ccs_pll_calculate_vt_tree()
302 pll_fr->pll_ip_clk_freq_hz = in __ccs_pll_calculate_vt_tree()
303 pll->ext_clk_freq_hz / pll_fr->pre_pll_clk_div; in __ccs_pll_calculate_vt_tree()
305 dev_dbg(dev, "vt_pll_ip_clk_freq_hz %u\n", pll_fr->pll_ip_clk_freq_hz); in __ccs_pll_calculate_vt_tree()
307 more_mul = one_or_more(DIV_ROUND_UP(lim_fr->min_pll_op_clk_freq_hz, in __ccs_pll_calculate_vt_tree()
308 pll_fr->pll_ip_clk_freq_hz * mul)); in __ccs_pll_calculate_vt_tree()
311 more_mul *= DIV_ROUND_UP(lim_fr->min_pll_multiplier, mul * more_mul); in __ccs_pll_calculate_vt_tree()
314 pll_fr->pll_multiplier = mul * more_mul; in __ccs_pll_calculate_vt_tree()
315 if (pll_fr->pll_multiplier > lim_fr->max_pll_multiplier) { in __ccs_pll_calculate_vt_tree()
317 pll_fr->pll_multiplier); in __ccs_pll_calculate_vt_tree()
318 return -EINVAL; in __ccs_pll_calculate_vt_tree()
321 if (pll_fr->pll_multiplier * pll_fr->pll_ip_clk_freq_hz > in __ccs_pll_calculate_vt_tree()
322 lim_fr->max_pll_op_clk_freq_hz) in __ccs_pll_calculate_vt_tree()
323 return -EINVAL; in __ccs_pll_calculate_vt_tree()
325 pll_fr->pll_op_clk_freq_hz = in __ccs_pll_calculate_vt_tree()
326 pll_fr->pll_ip_clk_freq_hz * pll_fr->pll_multiplier; in __ccs_pll_calculate_vt_tree()
338 sys_div += 2 - (sys_div & 1)) { in __ccs_pll_calculate_vt_tree()
346 if (pix_div < lim_bk->min_pix_clk_div || in __ccs_pll_calculate_vt_tree()
347 pix_div > lim_bk->max_pix_clk_div) { in __ccs_pll_calculate_vt_tree()
349 "pix_div %u too small or too big (%u--%u)\n", in __ccs_pll_calculate_vt_tree()
351 lim_bk->min_pix_clk_div, in __ccs_pll_calculate_vt_tree()
352 lim_bk->max_pix_clk_div); in __ccs_pll_calculate_vt_tree()
365 return -EINVAL; in __ccs_pll_calculate_vt_tree()
367 pll_bk->sys_clk_div = best_div / best_pix_div; in __ccs_pll_calculate_vt_tree()
368 pll_bk->pix_clk_div = best_pix_div; in __ccs_pll_calculate_vt_tree()
370 pll_bk->sys_clk_freq_hz = in __ccs_pll_calculate_vt_tree()
371 pll_fr->pll_op_clk_freq_hz / pll_bk->sys_clk_div; in __ccs_pll_calculate_vt_tree()
372 pll_bk->pix_clk_freq_hz = in __ccs_pll_calculate_vt_tree()
373 pll_bk->sys_clk_freq_hz / pll_bk->pix_clk_div; in __ccs_pll_calculate_vt_tree()
375 pll->pixel_rate_pixel_array = in __ccs_pll_calculate_vt_tree()
376 pll_bk->pix_clk_freq_hz * pll->vt_lanes; in __ccs_pll_calculate_vt_tree()
385 const struct ccs_pll_branch_limits_fr *lim_fr = &lim->vt_fr; in ccs_pll_calculate_vt_tree()
386 struct ccs_pll_branch_fr *pll_fr = &pll->vt_fr; in ccs_pll_calculate_vt_tree()
387 u16 min_pre_pll_clk_div = lim_fr->min_pre_pll_clk_div; in ccs_pll_calculate_vt_tree()
388 u16 max_pre_pll_clk_div = lim_fr->max_pre_pll_clk_div; in ccs_pll_calculate_vt_tree()
391 pre_div = gcd(pll->pixel_rate_csi, in ccs_pll_calculate_vt_tree()
392 pll->ext_clk_freq_hz * pll->vt_lanes); in ccs_pll_calculate_vt_tree()
393 pre_mul = pll->pixel_rate_csi / pre_div; in ccs_pll_calculate_vt_tree()
394 pre_div = pll->ext_clk_freq_hz * pll->vt_lanes / pre_div; in ccs_pll_calculate_vt_tree()
399 DIV_ROUND_UP(pll->ext_clk_freq_hz, in ccs_pll_calculate_vt_tree()
400 lim_fr->min_pll_ip_clk_freq_hz)); in ccs_pll_calculate_vt_tree()
403 pll->ext_clk_freq_hz / in ccs_pll_calculate_vt_tree()
404 lim_fr->max_pll_ip_clk_freq_hz); in ccs_pll_calculate_vt_tree()
405 if (!(pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER)) in ccs_pll_calculate_vt_tree()
411 for (pll_fr->pre_pll_clk_div = min_pre_pll_clk_div; in ccs_pll_calculate_vt_tree()
412 pll_fr->pre_pll_clk_div <= max_pre_pll_clk_div; in ccs_pll_calculate_vt_tree()
413 pll_fr->pre_pll_clk_div += in ccs_pll_calculate_vt_tree()
414 (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : in ccs_pll_calculate_vt_tree()
415 2 - (pll_fr->pre_pll_clk_div & 1)) { in ccs_pll_calculate_vt_tree()
419 div = gcd(pre_mul * pll_fr->pre_pll_clk_div, pre_div); in ccs_pll_calculate_vt_tree()
420 mul = pre_mul * pll_fr->pre_pll_clk_div / div; in ccs_pll_calculate_vt_tree()
423 dev_dbg(dev, "vt pre-div/mul/div: %u,%u,%u\n", in ccs_pll_calculate_vt_tree()
424 pll_fr->pre_pll_clk_div, mul, div); in ccs_pll_calculate_vt_tree()
442 return -EINVAL; in ccs_pll_calculate_vt_tree()
458 if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) in ccs_pll_calculate_vt()
465 if (!(pll->flags & CCS_PLL_FLAG_FIFO_DERATING)) { in ccs_pll_calculate_vt()
467 op_pll_bk->sys_clk_div * op_pll_bk->pix_clk_div in ccs_pll_calculate_vt()
468 * pll->vt_lanes * phy_const / pll->op_lanes in ccs_pll_calculate_vt()
469 / (PHY_CONST_DIV << op_pix_ddr(pll->flags)); in ccs_pll_calculate_vt()
478 if (lim->min_line_length_pck_bin > lim->min_line_length_pck in ccs_pll_calculate_vt()
479 / pll->binning_horizontal) in ccs_pll_calculate_vt()
480 vt_op_binning_div = pll->binning_horizontal; in ccs_pll_calculate_vt()
490 * enough to accommodate the CSI-2 sync codes. in ccs_pll_calculate_vt()
496 dev_dbg(dev, "scale_m: %u\n", pll->scale_m); in ccs_pll_calculate_vt()
498 DIV_ROUND_UP(pll->bits_per_pixel in ccs_pll_calculate_vt()
499 * op_pll_bk->sys_clk_div * pll->scale_n in ccs_pll_calculate_vt()
500 * pll->vt_lanes * phy_const, in ccs_pll_calculate_vt()
501 (pll->flags & in ccs_pll_calculate_vt()
503 pll->csi2.lanes : 1) in ccs_pll_calculate_vt()
504 * vt_op_binning_div * pll->scale_m in ccs_pll_calculate_vt()
505 * PHY_CONST_DIV << op_pix_ddr(pll->flags)); in ccs_pll_calculate_vt()
511 DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, in ccs_pll_calculate_vt()
512 lim->vt_bk.max_pix_clk_freq_hz)); in ccs_pll_calculate_vt()
515 min_vt_div = max_t(u16, min_vt_div, lim->vt_bk.min_pix_clk_div in ccs_pll_calculate_vt()
516 * lim->vt_bk.min_sys_clk_div); in ccs_pll_calculate_vt()
519 max_vt_div = lim->vt_bk.max_sys_clk_div * lim->vt_bk.max_pix_clk_div; in ccs_pll_calculate_vt()
522 DIV_ROUND_UP(pll_fr->pll_op_clk_freq_hz, in ccs_pll_calculate_vt()
523 lim->vt_bk.min_pix_clk_freq_hz)); in ccs_pll_calculate_vt()
539 sys_div += 2 - (sys_div & 1)) { in ccs_pll_calculate_vt()
545 if (pix_div < lim->vt_bk.min_pix_clk_div in ccs_pll_calculate_vt()
546 || pix_div > lim->vt_bk.max_pix_clk_div) { in ccs_pll_calculate_vt()
548 "pix_div %u too small or too big (%u--%u)\n", in ccs_pll_calculate_vt()
550 lim->vt_bk.min_pix_clk_div, in ccs_pll_calculate_vt()
551 lim->vt_bk.max_pix_clk_div); in ccs_pll_calculate_vt()
569 pll->vt_bk.sys_clk_div = DIV_ROUND_UP(vt_div, best_pix_div); in ccs_pll_calculate_vt()
570 pll->vt_bk.pix_clk_div = best_pix_div; in ccs_pll_calculate_vt()
572 pll->vt_bk.sys_clk_freq_hz = in ccs_pll_calculate_vt()
573 pll_fr->pll_op_clk_freq_hz / pll->vt_bk.sys_clk_div; in ccs_pll_calculate_vt()
574 pll->vt_bk.pix_clk_freq_hz = in ccs_pll_calculate_vt()
575 pll->vt_bk.sys_clk_freq_hz / pll->vt_bk.pix_clk_div; in ccs_pll_calculate_vt()
578 pll->pixel_rate_pixel_array = in ccs_pll_calculate_vt()
579 pll->vt_bk.pix_clk_freq_hz * pll->vt_lanes; in ccs_pll_calculate_vt()
616 dev_dbg(dev, "op_pre_pll_clk_div %u\n", op_pll_fr->pre_pll_clk_div); in ccs_pll_calculate_op()
619 more_mul_max = op_lim_fr->max_pll_multiplier / mul; in ccs_pll_calculate_op()
626 op_lim_fr->max_pll_op_clk_freq_hz in ccs_pll_calculate_op()
627 / (pll->ext_clk_freq_hz / in ccs_pll_calculate_op()
628 op_pll_fr->pre_pll_clk_div * mul)); in ccs_pll_calculate_op()
633 op_lim_bk->max_sys_clk_div * op_pll_fr->pre_pll_clk_div in ccs_pll_calculate_op()
638 more_mul_max = min(more_mul_max, op_lim_fr->max_pll_multiplier / mul); in ccs_pll_calculate_op()
643 more_mul_min = DIV_ROUND_UP(op_lim_fr->min_pll_op_clk_freq_hz, in ccs_pll_calculate_op()
644 pll->ext_clk_freq_hz / in ccs_pll_calculate_op()
645 op_pll_fr->pre_pll_clk_div * mul); in ccs_pll_calculate_op()
650 DIV_ROUND_UP(op_lim_fr->min_pll_multiplier, mul)); in ccs_pll_calculate_op()
657 return -EINVAL; in ccs_pll_calculate_op()
660 more_mul_factor = lcm(div, op_pll_fr->pre_pll_clk_div) / div; in ccs_pll_calculate_op()
662 more_mul_factor = lcm(more_mul_factor, op_lim_bk->min_sys_clk_div); in ccs_pll_calculate_op()
672 return -EINVAL; in ccs_pll_calculate_op()
675 op_pll_fr->pll_multiplier = mul * i; in ccs_pll_calculate_op()
676 op_pll_bk->sys_clk_div = div * i / op_pll_fr->pre_pll_clk_div; in ccs_pll_calculate_op()
677 dev_dbg(dev, "op_sys_clk_div: %u\n", op_pll_bk->sys_clk_div); in ccs_pll_calculate_op()
679 op_pll_fr->pll_ip_clk_freq_hz = pll->ext_clk_freq_hz in ccs_pll_calculate_op()
680 / op_pll_fr->pre_pll_clk_div; in ccs_pll_calculate_op()
682 op_pll_fr->pll_op_clk_freq_hz = op_pll_fr->pll_ip_clk_freq_hz in ccs_pll_calculate_op()
683 * op_pll_fr->pll_multiplier; in ccs_pll_calculate_op()
685 if (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL) in ccs_pll_calculate_op()
686 op_pll_bk->pix_clk_div = in ccs_pll_calculate_op()
687 (pll->bits_per_pixel in ccs_pll_calculate_op()
688 * pll->op_lanes * (phy_const << op_sys_ddr(pll->flags)) in ccs_pll_calculate_op()
689 / PHY_CONST_DIV / pll->csi2.lanes / l) in ccs_pll_calculate_op()
690 >> op_pix_ddr(pll->flags); in ccs_pll_calculate_op()
692 op_pll_bk->pix_clk_div = in ccs_pll_calculate_op()
693 (pll->bits_per_pixel in ccs_pll_calculate_op()
694 * (phy_const << op_sys_ddr(pll->flags)) in ccs_pll_calculate_op()
695 / PHY_CONST_DIV / l) >> op_pix_ddr(pll->flags); in ccs_pll_calculate_op()
697 op_pll_bk->pix_clk_freq_hz = in ccs_pll_calculate_op()
698 (op_sys_clk_freq_hz_sdr >> op_pix_ddr(pll->flags)) in ccs_pll_calculate_op()
699 / op_pll_bk->pix_clk_div; in ccs_pll_calculate_op()
700 op_pll_bk->sys_clk_freq_hz = in ccs_pll_calculate_op()
701 op_sys_clk_freq_hz_sdr >> op_sys_ddr(pll->flags); in ccs_pll_calculate_op()
703 dev_dbg(dev, "op_pix_clk_div: %u\n", op_pll_bk->pix_clk_div); in ccs_pll_calculate_op()
715 bool cphy = pll->bus_type == CCS_PLL_BUS_TYPE_CSI2_CPHY; in ccs_pll_calculate()
721 u32 l = (!pll->op_bits_per_lane || in ccs_pll_calculate()
722 pll->op_bits_per_lane >= pll->bits_per_pixel) ? 1 : 2; in ccs_pll_calculate()
724 int rval = -EINVAL; in ccs_pll_calculate()
726 if (!(pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL)) { in ccs_pll_calculate()
727 pll->op_lanes = 1; in ccs_pll_calculate()
728 pll->vt_lanes = 1; in ccs_pll_calculate()
731 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) { in ccs_pll_calculate()
732 op_lim_fr = &lim->op_fr; in ccs_pll_calculate()
733 op_lim_bk = &lim->op_bk; in ccs_pll_calculate()
734 op_pll_fr = &pll->op_fr; in ccs_pll_calculate()
735 op_pll_bk = &pll->op_bk; in ccs_pll_calculate()
736 } else if (pll->flags & CCS_PLL_FLAG_NO_OP_CLOCKS) { in ccs_pll_calculate()
742 op_lim_fr = &lim->vt_fr; in ccs_pll_calculate()
743 op_lim_bk = &lim->vt_bk; in ccs_pll_calculate()
744 op_pll_fr = &pll->vt_fr; in ccs_pll_calculate()
745 op_pll_bk = &pll->vt_bk; in ccs_pll_calculate()
747 op_lim_fr = &lim->vt_fr; in ccs_pll_calculate()
748 op_lim_bk = &lim->op_bk; in ccs_pll_calculate()
749 op_pll_fr = &pll->vt_fr; in ccs_pll_calculate()
750 op_pll_bk = &pll->op_bk; in ccs_pll_calculate()
753 if (!pll->op_lanes || !pll->vt_lanes || !pll->bits_per_pixel || in ccs_pll_calculate()
754 !pll->ext_clk_freq_hz || !pll->link_freq || !pll->scale_m || in ccs_pll_calculate()
755 !op_lim_fr->min_pll_ip_clk_freq_hz || in ccs_pll_calculate()
756 !op_lim_fr->max_pll_ip_clk_freq_hz || in ccs_pll_calculate()
757 !op_lim_fr->min_pll_op_clk_freq_hz || in ccs_pll_calculate()
758 !op_lim_fr->max_pll_op_clk_freq_hz || in ccs_pll_calculate()
759 !op_lim_bk->max_sys_clk_div || !op_lim_fr->max_pll_multiplier) in ccs_pll_calculate()
760 return -EINVAL; in ccs_pll_calculate()
763 * Make sure op_pix_clk_div will be integer --- unless flexible in ccs_pll_calculate()
766 if (!(pll->flags & CCS_PLL_FLAG_FLEXIBLE_OP_PIX_CLK_DIV) && in ccs_pll_calculate()
767 (pll->bits_per_pixel * pll->op_lanes) % in ccs_pll_calculate()
768 (pll->csi2.lanes * l << op_pix_ddr(pll->flags))) { in ccs_pll_calculate()
770 pll->bits_per_pixel, pll->op_lanes, pll->csi2.lanes, l); in ccs_pll_calculate()
771 return -EINVAL; in ccs_pll_calculate()
774 dev_dbg(dev, "vt_lanes: %u\n", pll->vt_lanes); in ccs_pll_calculate()
775 dev_dbg(dev, "op_lanes: %u\n", pll->op_lanes); in ccs_pll_calculate()
777 dev_dbg(dev, "binning: %ux%u\n", pll->binning_horizontal, in ccs_pll_calculate()
778 pll->binning_vertical); in ccs_pll_calculate()
780 switch (pll->bus_type) { in ccs_pll_calculate()
783 op_sys_clk_freq_hz_sdr = pll->link_freq * 2 in ccs_pll_calculate()
784 * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? in ccs_pll_calculate()
785 1 : pll->csi2.lanes); in ccs_pll_calculate()
788 return -EINVAL; in ccs_pll_calculate()
791 pll->pixel_rate_csi = in ccs_pll_calculate()
793 * (pll->flags & CCS_PLL_FLAG_LANE_SPEED_MODEL ? in ccs_pll_calculate()
794 pll->csi2.lanes : 1) * PHY_CONST_DIV, in ccs_pll_calculate()
795 phy_const * pll->bits_per_pixel * l); in ccs_pll_calculate()
797 /* Figure out limits for OP pre-pll divider based on extclk */ in ccs_pll_calculate()
799 op_lim_fr->min_pre_pll_clk_div, op_lim_fr->max_pre_pll_clk_div); in ccs_pll_calculate()
801 min_t(u16, op_lim_fr->max_pre_pll_clk_div, in ccs_pll_calculate()
802 DIV_ROUND_UP(pll->ext_clk_freq_hz, in ccs_pll_calculate()
803 op_lim_fr->min_pll_ip_clk_freq_hz)); in ccs_pll_calculate()
805 max_t(u16, op_lim_fr->min_pre_pll_clk_div, in ccs_pll_calculate()
807 DIV_ROUND_UP(pll->ext_clk_freq_hz, in ccs_pll_calculate()
808 op_lim_fr->max_pll_ip_clk_freq_hz))); in ccs_pll_calculate()
809 dev_dbg(dev, "pre-pll check: min / max op_pre_pll_clk_div: %u / %u\n", in ccs_pll_calculate()
813 pll->ext_clk_freq_hz << op_pix_ddr(pll->flags)); in ccs_pll_calculate()
815 div = (pll->ext_clk_freq_hz << op_pix_ddr(pll->flags)) / i; in ccs_pll_calculate()
823 DIV_ROUND_UP(op_lim_fr->max_pll_op_clk_freq_hz, in ccs_pll_calculate()
824 pll->ext_clk_freq_hz)))); in ccs_pll_calculate()
825 if (!(pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER)) in ccs_pll_calculate()
830 for (op_pll_fr->pre_pll_clk_div = min_op_pre_pll_clk_div; in ccs_pll_calculate()
831 op_pll_fr->pre_pll_clk_div <= max_op_pre_pll_clk_div; in ccs_pll_calculate()
832 op_pll_fr->pre_pll_clk_div += in ccs_pll_calculate()
833 (pll->flags & CCS_PLL_FLAG_EXT_IP_PLL_DIVIDER) ? 1 : in ccs_pll_calculate()
834 2 - (op_pll_fr->pre_pll_clk_div & 1)) { in ccs_pll_calculate()
843 pll->flags & CCS_PLL_FLAG_DUAL_PLL ? in ccs_pll_calculate()
852 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) in ccs_pll_calculate()
874 if (pll->flags & CCS_PLL_FLAG_DUAL_PLL) { in ccs_pll_calculate()
888 MODULE_DESCRIPTION("Generic MIPI CCS/SMIA/SMIA++ PLL calculator");