linux/arch/arm/mach-rpc/include/mach/acornfb.h
<<
>>
Prefs
   1/*
   2 *  arch/arm/mach-rpc/include/mach/acornfb.h
   3 *
   4 *  Copyright (C) 1999 Russell King
   5 *
   6 * This program is free software; you can redistribute it and/or modify
   7 * it under the terms of the GNU General Public License version 2 as
   8 * published by the Free Software Foundation.
   9 *
  10 *  AcornFB architecture specific code
  11 */
  12
  13#define acornfb_bandwidth(var) ((var)->pixclock * 8 / (var)->bits_per_pixel)
  14
  15static inline int
  16acornfb_valid_pixrate(struct fb_var_screeninfo *var)
  17{
  18        u_long limit;
  19
  20        if (!var->pixclock)
  21                return 0;
  22
  23        /*
  24         * Limits below are taken from RISC OS bandwidthlimit file
  25         */
  26        if (current_par.using_vram) {
  27                if (current_par.vram_half_sam == 2048)
  28                        limit = 6578;
  29                else
  30                        limit = 13157;
  31        } else {
  32                limit = 26315;
  33        }
  34
  35        return acornfb_bandwidth(var) >= limit;
  36}
  37
  38/*
  39 * Try to find the best PLL parameters for the pixel clock.
  40 * This algorithm seems to give best predictable results,
  41 * and produces the same values as detailed in the VIDC20
  42 * data sheet.
  43 */
  44static inline u_int
  45acornfb_vidc20_find_pll(u_int pixclk)
  46{
  47        u_int r, best_r = 2, best_v = 2;
  48        int best_d = 0x7fffffff;
  49
  50        for (r = 2; r <= 32; r++) {
  51                u_int rr, v, p;
  52                int d;
  53
  54                rr = 41667 * r;
  55
  56                v = (rr + pixclk / 2) / pixclk;
  57
  58                if (v > 32 || v < 2)
  59                        continue;
  60
  61                p = (rr + v / 2) / v;
  62
  63                d = pixclk - p;
  64
  65                if (d < 0)
  66                        d = -d;
  67
  68                if (d < best_d) {
  69                        best_d = d;
  70                        best_v = v - 1;
  71                        best_r = r - 1;
  72                }
  73
  74                if (d == 0)
  75                        break;
  76        }
  77
  78        return best_v << 8 | best_r;
  79}
  80
  81static inline void
  82acornfb_vidc20_find_rates(struct vidc_timing *vidc,
  83                          struct fb_var_screeninfo *var)
  84{
  85        u_int div;
  86
  87        /* Select pixel-clock divisor to keep PLL in range */
  88        div = var->pixclock / 9090; /*9921*/
  89
  90        /* Limit divisor */
  91        if (div == 0)
  92                div = 1;
  93        if (div > 8)
  94                div = 8;
  95
  96        /* Encode divisor to VIDC20 setting */
  97        switch (div) {
  98        case 1: vidc->control |= VIDC20_CTRL_PIX_CK;  break;
  99        case 2: vidc->control |= VIDC20_CTRL_PIX_CK2; break;
 100        case 3: vidc->control |= VIDC20_CTRL_PIX_CK3; break;
 101        case 4: vidc->control |= VIDC20_CTRL_PIX_CK4; break;
 102        case 5: vidc->control |= VIDC20_CTRL_PIX_CK5; break;
 103        case 6: vidc->control |= VIDC20_CTRL_PIX_CK6; break;
 104        case 7: vidc->control |= VIDC20_CTRL_PIX_CK7; break;
 105        case 8: vidc->control |= VIDC20_CTRL_PIX_CK8; break;
 106        }
 107
 108        /*
 109         * With VRAM, the FIFO can be set to the highest possible setting
 110         * because there are no latency considerations for other memory
 111         * accesses. However, in 64 bit bus mode the FIFO preload value
 112         * must not be set to VIDC20_CTRL_FIFO_28 because this will let
 113         * the FIFO overflow. See VIDC20 manual page 33 (6.0 Setting the
 114         * FIFO preload value).
 115         */
 116        if (current_par.using_vram) {
 117                if (current_par.vram_half_sam == 2048)
 118                        vidc->control |= VIDC20_CTRL_FIFO_24;
 119                else
 120                        vidc->control |= VIDC20_CTRL_FIFO_28;
 121        } else {
 122                unsigned long bandwidth = acornfb_bandwidth(var);
 123
 124                /* Encode bandwidth as VIDC20 setting */
 125                if (bandwidth > 33334)          /* < 30.0MB/s */
 126                        vidc->control |= VIDC20_CTRL_FIFO_16;
 127                else if (bandwidth > 26666)     /* < 37.5MB/s */
 128                        vidc->control |= VIDC20_CTRL_FIFO_20;
 129                else if (bandwidth > 22222)     /* < 45.0MB/s */
 130                        vidc->control |= VIDC20_CTRL_FIFO_24;
 131                else                            /* > 45.0MB/s */
 132                        vidc->control |= VIDC20_CTRL_FIFO_28;
 133        }
 134
 135        /* Find the PLL values */
 136        vidc->pll_ctl = acornfb_vidc20_find_pll(var->pixclock / div);
 137}
 138
 139#define acornfb_default_control()       (VIDC20_CTRL_PIX_VCLK)
 140#define acornfb_default_econtrol()      (VIDC20_ECTL_DAC | VIDC20_ECTL_REG(3))
 141