Skip to content

Commit

Permalink
drm/mgag200: Split PLL compute function for G200SE by rev
Browse files Browse the repository at this point in the history
The compute function for G200SE pixel PLLs handles two revisions with
different algorithms. Split it accordingly to make it readable. No
functional changes.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
Link: https://patchwork.freedesktop.org/patch/msgid/20210714142240.21979-9-tzimmermann@suse.de
  • Loading branch information
Thomas Zimmermann committed Aug 8, 2021
1 parent 35b36ff commit ac643cc
Showing 1 changed file with 96 additions and 70 deletions.
166 changes: 96 additions & 70 deletions drivers/gpu/drm/mgag200/mgag200_mode.c
Original file line number Diff line number Diff line change
Expand Up @@ -206,102 +206,117 @@ static void mgag200_set_pixpll_g200(struct mga_device *mdev,
WREG_DAC(MGA1064_PIX_PLLC_P, xpixpllcp);
}

static int mgag200_compute_pixpll_values_g200se(struct mga_device *mdev, long clock,
struct mgag200_pll_values *pixpllc)
static int mgag200_compute_pixpll_values_g200se_00(struct mga_device *mdev, long clock,
struct mgag200_pll_values *pixpllc)
{
static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};

u32 unique_rev_id = mdev->model.g200se.unique_rev_id;
unsigned int vcomax, vcomin, pllreffreq;
unsigned int delta, tmpdelta, permitteddelta;
unsigned int testp, testm, testn;
unsigned int p, m, n, s;
unsigned int computed;
unsigned int fvv;
unsigned int i;

m = n = p = s = 0;

if (unique_rev_id <= 0x03) {
vcomax = 320000;
vcomin = 160000;
pllreffreq = 25000;
delta = 0xffffffff;
permitteddelta = clock * 5 / 1000;
vcomax = 320000;
vcomin = 160000;
pllreffreq = 25000;
permitteddelta = clock * 5 / 1000;

for (testp = 8; testp > 0; testp /= 2) {
if (clock * testp > vcomax)
continue;
if (clock * testp < vcomin)
continue;
for (testp = 8; testp > 0; testp /= 2) {
if (clock * testp > vcomax)
continue;
if (clock * testp < vcomin)
continue;

for (testn = 17; testn < 256; testn++) {
for (testm = 1; testm < 32; testm++) {
computed = (pllreffreq * testn) /
(testm * testp);
if (computed > clock)
tmpdelta = computed - clock;
else
tmpdelta = clock - computed;
if (tmpdelta < delta) {
delta = tmpdelta;
m = testm;
n = testn;
p = testp;
}
for (testn = 17; testn < 256; testn++) {
for (testm = 1; testm < 32; testm++) {
computed = (pllreffreq * testn) / (testm * testp);
if (computed > clock)
tmpdelta = computed - clock;
else
tmpdelta = clock - computed;
if (tmpdelta < delta) {
delta = tmpdelta;
m = testm;
n = testn;
p = testp;
}
}
}
} else {
vcomax = 1600000;
vcomin = 800000;
pllreffreq = 25000;
}

if (clock < 25000)
clock = 25000;
if (delta > permitteddelta) {
pr_warn("PLL delta too large\n");
return -EINVAL;
}

clock = clock * 2;
pixpllc->m = m;
pixpllc->n = n;
pixpllc->p = p;
pixpllc->s = s;

delta = 0xFFFFFFFF;
/* Permited delta is 0.5% as VESA Specification */
permitteddelta = clock * 5 / 1000;
return 0;
}

for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
testp = pvalues_e4[i];
static int mgag200_compute_pixpll_values_g200se_04(struct mga_device *mdev, long clock,
struct mgag200_pll_values *pixpllc)
{
static const unsigned int pvalues_e4[] = {16, 14, 12, 10, 8, 6, 4, 2, 1};

if ((clock * testp) > vcomax)
continue;
if ((clock * testp) < vcomin)
continue;
unsigned int vcomax, vcomin, pllreffreq;
unsigned int delta, tmpdelta, permitteddelta;
unsigned int testp, testm, testn;
unsigned int p, m, n, s;
unsigned int computed;
unsigned int fvv;
unsigned int i;

for (testn = 50; testn <= 256; testn++) {
for (testm = 1; testm <= 32; testm++) {
computed = (pllreffreq * testn) /
(testm * testp);
if (computed > clock)
tmpdelta = computed - clock;
else
tmpdelta = clock - computed;
m = n = p = s = 0;
delta = 0xffffffff;

if (tmpdelta < delta) {
delta = tmpdelta;
m = testm;
n = testn;
p = testp;
}
vcomax = 1600000;
vcomin = 800000;
pllreffreq = 25000;

if (clock < 25000)
clock = 25000;
clock = clock * 2;

/* Permited delta is 0.5% as VESA Specification */
permitteddelta = clock * 5 / 1000;

for (i = 0 ; i < ARRAY_SIZE(pvalues_e4); i++) {
testp = pvalues_e4[i];

if ((clock * testp) > vcomax)
continue;
if ((clock * testp) < vcomin)
continue;

for (testn = 50; testn <= 256; testn++) {
for (testm = 1; testm <= 32; testm++) {
computed = (pllreffreq * testn) / (testm * testp);
if (computed > clock)
tmpdelta = computed - clock;
else
tmpdelta = clock - computed;

if (tmpdelta < delta) {
delta = tmpdelta;
m = testm;
n = testn;
p = testp;
}
}
}

fvv = pllreffreq * n / m;
fvv = (fvv - 800000) / 50000;
if (fvv > 15)
fvv = 15;
s = fvv << 1;

clock = clock / 2;
}

fvv = pllreffreq * n / m;
fvv = (fvv - 800000) / 50000;
if (fvv > 15)
fvv = 15;
s = fvv << 1;

if (delta > permitteddelta) {
pr_warn("PLL delta too large\n");
return -EINVAL;
Expand All @@ -315,6 +330,17 @@ static int mgag200_compute_pixpll_values_g200se(struct mga_device *mdev, long cl
return 0;
}

static int mgag200_compute_pixpll_values_g200se(struct mga_device *mdev, long clock,
struct mgag200_pll_values *pixpllc)
{
u32 unique_rev_id = mdev->model.g200se.unique_rev_id;

if (unique_rev_id >= 0x04)
return mgag200_compute_pixpll_values_g200se_04(mdev, clock, pixpllc);
else
return mgag200_compute_pixpll_values_g200se_00(mdev, clock, pixpllc);
}

static void mgag200_set_pixpll_g200se(struct mga_device *mdev,
const struct mgag200_pll_values *pixpllc)
{
Expand Down

0 comments on commit ac643cc

Please sign in to comment.