Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

phy: freescale: fsl-samsung-hdmi: Refactor finding PHY settings

There are two functions, round_rate and set_rate that duplicate
a lot of the same work, so simplify the code by creating a helper
function that will identify the phy settings for a desired clock
rate and return the structure with the corresponding settings.
>From this structure, the round_rate and set_rate can both get what
they need to achieve the clock setting closest to the desired rate
as possible while minimizing the duplicated code.

Also rename phy_clk_set_rate to fsl_samsung_hdmi_phy_clk_set_rate.

Suggested-by: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Signed-off-by: Adam Ford <aford173@gmail.com>

Link: https://lore.kernel.org/r/20250504204043.418924-2-aford173@gmail.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>

authored by

Adam Ford and committed by
Vinod Koul
41db4623 be79213b

+42 -66
+42 -66
drivers/phy/freescale/phy-fsl-samsung-hdmi.c
··· 456 456 int i, ret; 457 457 u8 val; 458 458 459 + phy->cur_cfg = cfg; 460 + 459 461 /* HDMI PHY init */ 460 462 writeb(REG33_FIX_DA, phy->regs + PHY_REG(33)); 461 463 ··· 523 521 /* pll_div_regs 3-6 are fixed and pre-defined already */ 524 522 } 525 523 526 - static u32 fsl_samsung_hdmi_phy_get_closest_rate(unsigned long rate, 527 - u32 int_div_clk, u32 frac_div_clk) 528 - { 529 - /* Calculate the absolute value of the differences and return whichever is closest */ 530 - if (abs((long)rate - (long)int_div_clk) < abs((long)(rate - (long)frac_div_clk))) 531 - return int_div_clk; 532 - 533 - return frac_div_clk; 534 - } 535 - 536 - static long fsl_samsung_hdmi_phy_clk_round_rate(struct clk_hw *hw, 537 - unsigned long rate, unsigned long *parent_rate) 524 + static 525 + const struct phy_config *fsl_samsung_hdmi_phy_find_settings(struct fsl_samsung_hdmi_phy *phy, 526 + unsigned long rate) 538 527 { 539 528 const struct phy_config *fract_div_phy; 540 529 u32 int_div_clk; ··· 534 541 535 542 /* If the clock is out of range return error instead of searching */ 536 543 if (rate > 297000000 || rate < 22250000) 537 - return -EINVAL; 544 + return NULL; 538 545 539 546 /* Search the fractional divider lookup table */ 540 547 fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate(rate); 548 + if (fract_div_phy->pixclk == rate) { 549 + dev_dbg(phy->dev, "fractional divider match = %u\n", fract_div_phy->pixclk); 550 + return fract_div_phy; 551 + } 541 552 542 - /* If the rate is an exact match, return that value */ 543 - if (rate == fract_div_phy->pixclk) 544 - return fract_div_phy->pixclk; 545 - 546 - /* If the exact match isn't found, calculate the integer divider */ 553 + /* Calculate the integer divider */ 547 554 int_div_clk = fsl_samsung_hdmi_phy_find_pms(rate, &p, &m, &s); 555 + fsl_samsung_hdmi_calculate_phy(&calculated_phy_pll_cfg, int_div_clk, p, m, s); 556 + if (int_div_clk == rate) { 557 + dev_dbg(phy->dev, "integer divider match = %u\n", calculated_phy_pll_cfg.pixclk); 558 + return &calculated_phy_pll_cfg; 559 + } 548 560 549 - /* If the int_div_clk rate is an exact match, return that value */ 550 - if (int_div_clk == rate) 551 - return int_div_clk; 561 + /* Calculate the absolute value of the differences and return whichever is closest */ 562 + if (abs((long)rate - (long)int_div_clk) < 563 + abs((long)rate - (long)fract_div_phy->pixclk)) { 564 + dev_dbg(phy->dev, "integer divider = %u\n", calculated_phy_pll_cfg.pixclk); 565 + return &calculated_phy_pll_cfg; 566 + } 552 567 553 - /* If neither rate is an exact match, use the value from the LUT */ 554 - return fract_div_phy->pixclk; 568 + dev_dbg(phy->dev, "fractional divider = %u\n", phy->cur_cfg->pixclk); 569 + 570 + return fract_div_phy; 555 571 } 556 572 557 - static int phy_use_fract_div(struct fsl_samsung_hdmi_phy *phy, const struct phy_config *fract_div_phy) 573 + static long fsl_samsung_hdmi_phy_clk_round_rate(struct clk_hw *hw, 574 + unsigned long rate, unsigned long *parent_rate) 558 575 { 559 - phy->cur_cfg = fract_div_phy; 560 - dev_dbg(phy->dev, "fsl_samsung_hdmi_phy: using fractional divider rate = %u\n", 561 - phy->cur_cfg->pixclk); 562 - return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg); 576 + struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw); 577 + const struct phy_config *target_settings = fsl_samsung_hdmi_phy_find_settings(phy, rate); 578 + 579 + if (target_settings == NULL) 580 + return -EINVAL; 581 + 582 + dev_dbg(phy->dev, "round_rate, closest rate = %u\n", target_settings->pixclk); 583 + return target_settings->pixclk; 563 584 } 564 585 565 - static int phy_use_integer_div(struct fsl_samsung_hdmi_phy *phy, 566 - const struct phy_config *int_div_clk) 567 - { 568 - phy->cur_cfg = &calculated_phy_pll_cfg; 569 - dev_dbg(phy->dev, "fsl_samsung_hdmi_phy: integer divider rate = %u\n", 570 - phy->cur_cfg->pixclk); 571 - return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg); 572 - } 573 - 574 - static int phy_clk_set_rate(struct clk_hw *hw, 586 + static int fsl_samsung_hdmi_phy_clk_set_rate(struct clk_hw *hw, 575 587 unsigned long rate, unsigned long parent_rate) 576 588 { 577 589 struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw); 578 - const struct phy_config *fract_div_phy; 579 - u32 int_div_clk; 580 - u16 m; 581 - u8 p, s; 590 + const struct phy_config *target_settings = fsl_samsung_hdmi_phy_find_settings(phy, rate); 582 591 583 - /* Search the fractional divider lookup table */ 584 - fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate(rate); 592 + if (target_settings == NULL) 593 + return -EINVAL; 585 594 586 - /* If the rate is an exact match, use that value */ 587 - if (fract_div_phy->pixclk == rate) 588 - return phy_use_fract_div(phy, fract_div_phy); 595 + dev_dbg(phy->dev, "set_rate, closest rate = %u\n", target_settings->pixclk); 589 596 590 - /* 591 - * If the rate from the fractional divider is not exact, check the integer divider, 592 - * and use it if that value is an exact match. 593 - */ 594 - int_div_clk = fsl_samsung_hdmi_phy_find_pms(rate, &p, &m, &s); 595 - fsl_samsung_hdmi_calculate_phy(&calculated_phy_pll_cfg, int_div_clk, p, m, s); 596 - if (int_div_clk == rate) 597 - return phy_use_integer_div(phy, &calculated_phy_pll_cfg); 598 - 599 - /* 600 - * Compare the difference between the integer clock and the fractional clock against 601 - * the desired clock and which whichever is closest. 602 - */ 603 - if (fsl_samsung_hdmi_phy_get_closest_rate(rate, int_div_clk, 604 - fract_div_phy->pixclk) == fract_div_phy->pixclk) 605 - return phy_use_fract_div(phy, fract_div_phy); 606 - else 607 - return phy_use_integer_div(phy, &calculated_phy_pll_cfg); 597 + return fsl_samsung_hdmi_phy_configure(phy, target_settings); 608 598 } 609 599 610 600 static const struct clk_ops phy_clk_ops = { 611 601 .recalc_rate = phy_clk_recalc_rate, 612 602 .round_rate = fsl_samsung_hdmi_phy_clk_round_rate, 613 - .set_rate = phy_clk_set_rate, 603 + .set_rate = fsl_samsung_hdmi_phy_clk_set_rate, 614 604 }; 615 605 616 606 static int phy_clk_register(struct fsl_samsung_hdmi_phy *phy)