138 lines
3.2 KiB
C
138 lines
3.2 KiB
C
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
/*
|
|
* arch/arm/mach-rpc/include/mach/acornfb.h
|
|
*
|
|
* Copyright (C) 1999 Russell King
|
|
*
|
|
* AcornFB architecture specific code
|
|
*/
|
|
|
|
#define acornfb_bandwidth(var) ((var)->pixclock * 8 / (var)->bits_per_pixel)
|
|
|
|
static inline int
|
|
acornfb_valid_pixrate(struct fb_var_screeninfo *var)
|
|
{
|
|
u_long limit;
|
|
|
|
if (!var->pixclock)
|
|
return 0;
|
|
|
|
/*
|
|
* Limits below are taken from RISC OS bandwidthlimit file
|
|
*/
|
|
if (current_par.using_vram) {
|
|
if (current_par.vram_half_sam == 2048)
|
|
limit = 6578;
|
|
else
|
|
limit = 13157;
|
|
} else {
|
|
limit = 26315;
|
|
}
|
|
|
|
return acornfb_bandwidth(var) >= limit;
|
|
}
|
|
|
|
/*
|
|
* Try to find the best PLL parameters for the pixel clock.
|
|
* This algorithm seems to give best predictable results,
|
|
* and produces the same values as detailed in the VIDC20
|
|
* data sheet.
|
|
*/
|
|
static inline u_int
|
|
acornfb_vidc20_find_pll(u_int pixclk)
|
|
{
|
|
u_int r, best_r = 2, best_v = 2;
|
|
int best_d = 0x7fffffff;
|
|
|
|
for (r = 2; r <= 32; r++) {
|
|
u_int rr, v, p;
|
|
int d;
|
|
|
|
rr = 41667 * r;
|
|
|
|
v = (rr + pixclk / 2) / pixclk;
|
|
|
|
if (v > 32 || v < 2)
|
|
continue;
|
|
|
|
p = (rr + v / 2) / v;
|
|
|
|
d = pixclk - p;
|
|
|
|
if (d < 0)
|
|
d = -d;
|
|
|
|
if (d < best_d) {
|
|
best_d = d;
|
|
best_v = v - 1;
|
|
best_r = r - 1;
|
|
}
|
|
|
|
if (d == 0)
|
|
break;
|
|
}
|
|
|
|
return best_v << 8 | best_r;
|
|
}
|
|
|
|
static inline void
|
|
acornfb_vidc20_find_rates(struct vidc_timing *vidc,
|
|
struct fb_var_screeninfo *var)
|
|
{
|
|
u_int div;
|
|
|
|
/* Select pixel-clock divisor to keep PLL in range */
|
|
div = var->pixclock / 9090; /*9921*/
|
|
|
|
/* Limit divisor */
|
|
if (div == 0)
|
|
div = 1;
|
|
if (div > 8)
|
|
div = 8;
|
|
|
|
/* Encode divisor to VIDC20 setting */
|
|
switch (div) {
|
|
case 1: vidc->control |= VIDC20_CTRL_PIX_CK; break;
|
|
case 2: vidc->control |= VIDC20_CTRL_PIX_CK2; break;
|
|
case 3: vidc->control |= VIDC20_CTRL_PIX_CK3; break;
|
|
case 4: vidc->control |= VIDC20_CTRL_PIX_CK4; break;
|
|
case 5: vidc->control |= VIDC20_CTRL_PIX_CK5; break;
|
|
case 6: vidc->control |= VIDC20_CTRL_PIX_CK6; break;
|
|
case 7: vidc->control |= VIDC20_CTRL_PIX_CK7; break;
|
|
case 8: vidc->control |= VIDC20_CTRL_PIX_CK8; break;
|
|
}
|
|
|
|
/*
|
|
* With VRAM, the FIFO can be set to the highest possible setting
|
|
* because there are no latency considerations for other memory
|
|
* accesses. However, in 64 bit bus mode the FIFO preload value
|
|
* must not be set to VIDC20_CTRL_FIFO_28 because this will let
|
|
* the FIFO overflow. See VIDC20 manual page 33 (6.0 Setting the
|
|
* FIFO preload value).
|
|
*/
|
|
if (current_par.using_vram) {
|
|
if (current_par.vram_half_sam == 2048)
|
|
vidc->control |= VIDC20_CTRL_FIFO_24;
|
|
else
|
|
vidc->control |= VIDC20_CTRL_FIFO_28;
|
|
} else {
|
|
unsigned long bandwidth = acornfb_bandwidth(var);
|
|
|
|
/* Encode bandwidth as VIDC20 setting */
|
|
if (bandwidth > 33334) /* < 30.0MB/s */
|
|
vidc->control |= VIDC20_CTRL_FIFO_16;
|
|
else if (bandwidth > 26666) /* < 37.5MB/s */
|
|
vidc->control |= VIDC20_CTRL_FIFO_20;
|
|
else if (bandwidth > 22222) /* < 45.0MB/s */
|
|
vidc->control |= VIDC20_CTRL_FIFO_24;
|
|
else /* > 45.0MB/s */
|
|
vidc->control |= VIDC20_CTRL_FIFO_28;
|
|
}
|
|
|
|
/* Find the PLL values */
|
|
vidc->pll_ctl = acornfb_vidc20_find_pll(var->pixclock / div);
|
|
}
|
|
|
|
#define acornfb_default_control() (VIDC20_CTRL_PIX_VCLK)
|
|
#define acornfb_default_econtrol() (VIDC20_ECTL_DAC | VIDC20_ECTL_REG(3))
|