+static const u16 pwm_freq_cksel0[16] = {
+ 1024, 512, 341, 256, 205, 171, 146, 128,
+ 85, 64, 32, 16, 8, 4, 2, 1
+};
+
+static unsigned int pwm_freq_from_reg(u8 reg, u16 clkin)
+{
+ unsigned long base_clock;
+
+ if (reg & 0x80) {
+ base_clock = clkin * 1000 / ((clkin == 48000) ? 384 : 256);
+ return base_clock / ((reg & 0x7f) + 1);
+ } else
+ return pwm_freq_cksel0[reg & 0x0f];
+}
+
+static u8 pwm_freq_to_reg(unsigned long val, u16 clkin)
+{
+ unsigned long base_clock;
+ u8 reg0, reg1;
+ unsigned long best0, best1;
+
+ /* Best fit for cksel = 0 */
+ for (reg0 = 0; reg0 < ARRAY_SIZE(pwm_freq_cksel0) - 1; reg0++) {
+ if (val > (pwm_freq_cksel0[reg0] +
+ pwm_freq_cksel0[reg0 + 1]) / 2)
+ break;
+ }
+ if (val < 375) /* cksel = 1 can't beat this */
+ return reg0;
+ best0 = pwm_freq_cksel0[reg0];
+
+ /* Best fit for cksel = 1 */
+ base_clock = clkin * 1000 / ((clkin == 48000) ? 384 : 256);
+ reg1 = SENSORS_LIMIT(DIV_ROUND_CLOSEST(base_clock, val), 1, 128);
+ best1 = base_clock / reg1;
+ reg1 = 0x80 | (reg1 - 1);
+
+ /* Choose the closest one */
+ if (abs(val - best0) > abs(val - best1))
+ return reg1;
+ else
+ return reg0;
+}