Skip to content

Commit 41db462

Browse files
aford173vinodkoul
authored andcommitted
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 <[email protected]> Signed-off-by: Adam Ford <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Vinod Koul <[email protected]>
1 parent be79213 commit 41db462

File tree

1 file changed

+41
-65
lines changed

1 file changed

+41
-65
lines changed

drivers/phy/freescale/phy-fsl-samsung-hdmi.c

Lines changed: 41 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,8 @@ static int fsl_samsung_hdmi_phy_configure(struct fsl_samsung_hdmi_phy *phy,
456456
int i, ret;
457457
u8 val;
458458

459+
phy->cur_cfg = cfg;
460+
459461
/* HDMI PHY init */
460462
writeb(REG33_FIX_DA, phy->regs + PHY_REG(33));
461463

@@ -521,18 +523,9 @@ static void fsl_samsung_hdmi_calculate_phy(struct phy_config *cal_phy, unsigned
521523
/* pll_div_regs 3-6 are fixed and pre-defined already */
522524
}
523525

524-
static u32 fsl_samsung_hdmi_phy_get_closest_rate(unsigned long rate,
525-
u32 int_div_clk, u32 frac_div_clk)
526-
{
527-
/* Calculate the absolute value of the differences and return whichever is closest */
528-
if (abs((long)rate - (long)int_div_clk) < abs((long)(rate - (long)frac_div_clk)))
529-
return int_div_clk;
530-
531-
return frac_div_clk;
532-
}
533-
534-
static long fsl_samsung_hdmi_phy_clk_round_rate(struct clk_hw *hw,
535-
unsigned long rate, unsigned long *parent_rate)
526+
static
527+
const struct phy_config *fsl_samsung_hdmi_phy_find_settings(struct fsl_samsung_hdmi_phy *phy,
528+
unsigned long rate)
536529
{
537530
const struct phy_config *fract_div_phy;
538531
u32 int_div_clk;
@@ -541,83 +534,66 @@ static long fsl_samsung_hdmi_phy_clk_round_rate(struct clk_hw *hw,
541534

542535
/* If the clock is out of range return error instead of searching */
543536
if (rate > 297000000 || rate < 22250000)
544-
return -EINVAL;
537+
return NULL;
545538

546539
/* Search the fractional divider lookup table */
547540
fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate(rate);
541+
if (fract_div_phy->pixclk == rate) {
542+
dev_dbg(phy->dev, "fractional divider match = %u\n", fract_div_phy->pixclk);
543+
return fract_div_phy;
544+
}
548545

549-
/* If the rate is an exact match, return that value */
550-
if (rate == fract_div_phy->pixclk)
551-
return fract_div_phy->pixclk;
552-
553-
/* If the exact match isn't found, calculate the integer divider */
546+
/* Calculate the integer divider */
554547
int_div_clk = fsl_samsung_hdmi_phy_find_pms(rate, &p, &m, &s);
548+
fsl_samsung_hdmi_calculate_phy(&calculated_phy_pll_cfg, int_div_clk, p, m, s);
549+
if (int_div_clk == rate) {
550+
dev_dbg(phy->dev, "integer divider match = %u\n", calculated_phy_pll_cfg.pixclk);
551+
return &calculated_phy_pll_cfg;
552+
}
555553

556-
/* If the int_div_clk rate is an exact match, return that value */
557-
if (int_div_clk == rate)
558-
return int_div_clk;
554+
/* Calculate the absolute value of the differences and return whichever is closest */
555+
if (abs((long)rate - (long)int_div_clk) <
556+
abs((long)rate - (long)fract_div_phy->pixclk)) {
557+
dev_dbg(phy->dev, "integer divider = %u\n", calculated_phy_pll_cfg.pixclk);
558+
return &calculated_phy_pll_cfg;
559+
}
559560

560-
/* If neither rate is an exact match, use the value from the LUT */
561-
return fract_div_phy->pixclk;
562-
}
561+
dev_dbg(phy->dev, "fractional divider = %u\n", phy->cur_cfg->pixclk);
563562

564-
static int phy_use_fract_div(struct fsl_samsung_hdmi_phy *phy, const struct phy_config *fract_div_phy)
565-
{
566-
phy->cur_cfg = fract_div_phy;
567-
dev_dbg(phy->dev, "fsl_samsung_hdmi_phy: using fractional divider rate = %u\n",
568-
phy->cur_cfg->pixclk);
569-
return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
563+
return fract_div_phy;
570564
}
571565

572-
static int phy_use_integer_div(struct fsl_samsung_hdmi_phy *phy,
573-
const struct phy_config *int_div_clk)
566+
static long fsl_samsung_hdmi_phy_clk_round_rate(struct clk_hw *hw,
567+
unsigned long rate, unsigned long *parent_rate)
574568
{
575-
phy->cur_cfg = &calculated_phy_pll_cfg;
576-
dev_dbg(phy->dev, "fsl_samsung_hdmi_phy: integer divider rate = %u\n",
577-
phy->cur_cfg->pixclk);
578-
return fsl_samsung_hdmi_phy_configure(phy, phy->cur_cfg);
569+
struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
570+
const struct phy_config *target_settings = fsl_samsung_hdmi_phy_find_settings(phy, rate);
571+
572+
if (target_settings == NULL)
573+
return -EINVAL;
574+
575+
dev_dbg(phy->dev, "round_rate, closest rate = %u\n", target_settings->pixclk);
576+
return target_settings->pixclk;
579577
}
580578

581-
static int phy_clk_set_rate(struct clk_hw *hw,
579+
static int fsl_samsung_hdmi_phy_clk_set_rate(struct clk_hw *hw,
582580
unsigned long rate, unsigned long parent_rate)
583581
{
584582
struct fsl_samsung_hdmi_phy *phy = to_fsl_samsung_hdmi_phy(hw);
585-
const struct phy_config *fract_div_phy;
586-
u32 int_div_clk;
587-
u16 m;
588-
u8 p, s;
589-
590-
/* Search the fractional divider lookup table */
591-
fract_div_phy = fsl_samsung_hdmi_phy_lookup_rate(rate);
583+
const struct phy_config *target_settings = fsl_samsung_hdmi_phy_find_settings(phy, rate);
592584

593-
/* If the rate is an exact match, use that value */
594-
if (fract_div_phy->pixclk == rate)
595-
return phy_use_fract_div(phy, fract_div_phy);
585+
if (target_settings == NULL)
586+
return -EINVAL;
596587

597-
/*
598-
* If the rate from the fractional divider is not exact, check the integer divider,
599-
* and use it if that value is an exact match.
600-
*/
601-
int_div_clk = fsl_samsung_hdmi_phy_find_pms(rate, &p, &m, &s);
602-
fsl_samsung_hdmi_calculate_phy(&calculated_phy_pll_cfg, int_div_clk, p, m, s);
603-
if (int_div_clk == rate)
604-
return phy_use_integer_div(phy, &calculated_phy_pll_cfg);
588+
dev_dbg(phy->dev, "set_rate, closest rate = %u\n", target_settings->pixclk);
605589

606-
/*
607-
* Compare the difference between the integer clock and the fractional clock against
608-
* the desired clock and which whichever is closest.
609-
*/
610-
if (fsl_samsung_hdmi_phy_get_closest_rate(rate, int_div_clk,
611-
fract_div_phy->pixclk) == fract_div_phy->pixclk)
612-
return phy_use_fract_div(phy, fract_div_phy);
613-
else
614-
return phy_use_integer_div(phy, &calculated_phy_pll_cfg);
590+
return fsl_samsung_hdmi_phy_configure(phy, target_settings);
615591
}
616592

617593
static const struct clk_ops phy_clk_ops = {
618594
.recalc_rate = phy_clk_recalc_rate,
619595
.round_rate = fsl_samsung_hdmi_phy_clk_round_rate,
620-
.set_rate = phy_clk_set_rate,
596+
.set_rate = fsl_samsung_hdmi_phy_clk_set_rate,
621597
};
622598

623599
static int phy_clk_register(struct fsl_samsung_hdmi_phy *phy)

0 commit comments

Comments
 (0)