+enum {
+ Lcpll = 2700,
+ Lcpll2k = Lcpll * 2000,
+};
+
+static int
+wrbudget(int freq)
+{
+ static int b[] = {
+ 25175000,0, 25200000,0, 27000000,0, 27027000,0,
+ 37762500,0, 37800000,0, 40500000,0, 40541000,0,
+ 54000000,0, 54054000,0, 59341000,0, 59400000,0,
+ 72000000,0, 74176000,0, 74250000,0, 81000000,0,
+ 81081000,0, 89012000,0, 89100000,0, 108000000,0,
+ 108108000,0, 111264000,0, 111375000,0, 148352000,0,
+ 148500000,0, 162000000,0, 162162000,0, 222525000,0,
+ 222750000,0, 296703000,0, 297000000,0, 233500000,1500,
+ 245250000,1500, 247750000,1500, 253250000,1500, 298000000,1500,
+ 169128000,2000, 169500000,2000, 179500000,2000, 202000000,2000,
+ 256250000,4000, 262500000,4000, 270000000,4000, 272500000,4000,
+ 273750000,4000, 280750000,4000, 281250000,4000, 286000000,4000,
+ 291750000,4000, 267250000,5000, 268500000,5000
+ };
+ int *i;
+
+ for(i=b; i<b+nelem(b); i+=2)
+ if(i[0] == freq)
+ return i[1];
+ return 1000;
+}
+
+static void
+genwrpll(int freq, int *n2, int *p, int *r2)
+{
+ int budget, N2, P, R2;
+ vlong f2k, a, b, c, d, Δ, bestΔ;
+
+ f2k = freq / 100;
+ if(f2k == Lcpll2k){ /* bypass wrpll entirely and use lcpll */
+ *n2 = 2;
+ *p = 1;
+ *r2 = 2;
+ return;
+ }
+ budget = wrbudget(freq);
+ *p = 0;
+ for(R2=Lcpll*2/400+1; R2<=Lcpll*2/48; R2++)
+ for(N2=2400*R2/Lcpll+1; N2<=4800*R2/Lcpll; N2++)
+ for(P=2; P<=64; P+=2){
+ if(*p == 0){
+ *n2 = N2;
+ *p = P;
+ *r2 = R2;
+ continue;
+ }
+ Δ = f2k * P * R2;
+ Δ -= N2 * Lcpll2k;
+ if(Δ < 0)
+ Δ = -Δ;
+ bestΔ = f2k * *p * *r2;
+ bestΔ -= *n2 * Lcpll2k;
+ if(bestΔ < 0)
+ bestΔ = -bestΔ;
+ a = f2k * budget;
+ b = a;
+ a *= P * R2;
+ b *= *p * *r2;
+ c = Δ * MHz;
+ d = bestΔ * MHz;
+ if(a < c && b < d && *p * *r2 * Δ < P * R2 * bestΔ
+ || a >= c && b < d
+ || a >= c && b >= d && N2 * *r2 * *r2 > *n2 * R2 * R2){
+ *n2 = N2;
+ *p = P;
+ *r2 = R2;
+ }
+ }
+}
+