~ubuntu-branches/ubuntu/precise/linux-lowlatency/precise

« back to all changes in this revision

Viewing changes to drivers/video/vermilion/cr_pll.c

  • Committer: Package Import Robot
  • Author(s): Alessio Igor Bogani
  • Date: 2011-10-26 11:13:05 UTC
  • Revision ID: package-import@ubuntu.com-20111026111305-tz023xykf0i6eosh
Tags: upstream-3.2.0
ImportĀ upstreamĀ versionĀ 3.2.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) Intel Corp. 2007.
 
3
 * All Rights Reserved.
 
4
 *
 
5
 * Intel funded Tungsten Graphics (http://www.tungstengraphics.com) to
 
6
 * develop this driver.
 
7
 *
 
8
 * This file is part of the Carillo Ranch video subsystem driver.
 
9
 * The Carillo Ranch video subsystem driver is free software;
 
10
 * you can redistribute it and/or modify
 
11
 * it under the terms of the GNU General Public License as published by
 
12
 * the Free Software Foundation; either version 2 of the License, or
 
13
 * (at your option) any later version.
 
14
 *
 
15
 * The Carillo Ranch video subsystem driver is distributed
 
16
 * in the hope that it will be useful,
 
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
19
 * GNU General Public License for more details.
 
20
 *
 
21
 * You should have received a copy of the GNU General Public License
 
22
 * along with this driver; if not, write to the Free Software
 
23
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
24
 *
 
25
 * Authors:
 
26
 *   Thomas Hellstrom <thomas-at-tungstengraphics-dot-com>
 
27
 *   Alan Hourihane <alanh-at-tungstengraphics-dot-com>
 
28
 */
 
29
 
 
30
#include <linux/module.h>
 
31
#include <linux/kernel.h>
 
32
#include <linux/pci.h>
 
33
#include <linux/errno.h>
 
34
#include <linux/fb.h>
 
35
#include "vermilion.h"
 
36
 
 
37
/* The PLL Clock register sits on Host bridge */
 
38
#define CRVML_DEVICE_MCH   0x5001
 
39
#define CRVML_REG_MCHBAR   0x44
 
40
#define CRVML_REG_MCHEN    0x54
 
41
#define CRVML_MCHEN_BIT    (1 << 28)
 
42
#define CRVML_MCHMAP_SIZE  4096
 
43
#define CRVML_REG_CLOCK    0xc3c
 
44
#define CRVML_CLOCK_SHIFT  8
 
45
#define CRVML_CLOCK_MASK   0x00000f00
 
46
 
 
47
static struct pci_dev *mch_dev;
 
48
static u32 mch_bar;
 
49
static void __iomem *mch_regs_base;
 
50
static u32 saved_clock;
 
51
 
 
52
static const unsigned crvml_clocks[] = {
 
53
        6750,
 
54
        13500,
 
55
        27000,
 
56
        29700,
 
57
        37125,
 
58
        54000,
 
59
        59400,
 
60
        74250,
 
61
        120000
 
62
            /*
 
63
             * There are more clocks, but they are disabled on the CR board.
 
64
             */
 
65
};
 
66
 
 
67
static const u32 crvml_clock_bits[] = {
 
68
        0x0a,
 
69
        0x09,
 
70
        0x08,
 
71
        0x07,
 
72
        0x06,
 
73
        0x05,
 
74
        0x04,
 
75
        0x03,
 
76
        0x0b
 
77
};
 
78
 
 
79
static const unsigned crvml_num_clocks = ARRAY_SIZE(crvml_clocks);
 
80
 
 
81
static int crvml_sys_restore(struct vml_sys *sys)
 
82
{
 
83
        void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
 
84
 
 
85
        iowrite32(saved_clock, clock_reg);
 
86
        ioread32(clock_reg);
 
87
 
 
88
        return 0;
 
89
}
 
90
 
 
91
static int crvml_sys_save(struct vml_sys *sys)
 
92
{
 
93
        void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
 
94
 
 
95
        saved_clock = ioread32(clock_reg);
 
96
 
 
97
        return 0;
 
98
}
 
99
 
 
100
static int crvml_nearest_index(const struct vml_sys *sys, int clock)
 
101
{
 
102
        int i;
 
103
        int cur_index = 0;
 
104
        int cur_diff;
 
105
        int diff;
 
106
 
 
107
        cur_diff = clock - crvml_clocks[0];
 
108
        cur_diff = (cur_diff < 0) ? -cur_diff : cur_diff;
 
109
        for (i = 1; i < crvml_num_clocks; ++i) {
 
110
                diff = clock - crvml_clocks[i];
 
111
                diff = (diff < 0) ? -diff : diff;
 
112
                if (diff < cur_diff) {
 
113
                        cur_index = i;
 
114
                        cur_diff = diff;
 
115
                }
 
116
        }
 
117
        return cur_index;
 
118
}
 
119
 
 
120
static int crvml_nearest_clock(const struct vml_sys *sys, int clock)
 
121
{
 
122
        return crvml_clocks[crvml_nearest_index(sys, clock)];
 
123
}
 
124
 
 
125
static int crvml_set_clock(struct vml_sys *sys, int clock)
 
126
{
 
127
        void __iomem *clock_reg = mch_regs_base + CRVML_REG_CLOCK;
 
128
        int index;
 
129
        u32 clock_val;
 
130
 
 
131
        index = crvml_nearest_index(sys, clock);
 
132
 
 
133
        if (crvml_clocks[index] != clock)
 
134
                return -EINVAL;
 
135
 
 
136
        clock_val = ioread32(clock_reg) & ~CRVML_CLOCK_MASK;
 
137
        clock_val = crvml_clock_bits[index] << CRVML_CLOCK_SHIFT;
 
138
        iowrite32(clock_val, clock_reg);
 
139
        ioread32(clock_reg);
 
140
 
 
141
        return 0;
 
142
}
 
143
 
 
144
static struct vml_sys cr_pll_ops = {
 
145
        .name = "Carillo Ranch",
 
146
        .save = crvml_sys_save,
 
147
        .restore = crvml_sys_restore,
 
148
        .set_clock = crvml_set_clock,
 
149
        .nearest_clock = crvml_nearest_clock,
 
150
};
 
151
 
 
152
static int __init cr_pll_init(void)
 
153
{
 
154
        int err;
 
155
        u32 dev_en;
 
156
 
 
157
        mch_dev = pci_get_device(PCI_VENDOR_ID_INTEL,
 
158
                                        CRVML_DEVICE_MCH, NULL);
 
159
        if (!mch_dev) {
 
160
                printk(KERN_ERR
 
161
                       "Could not find Carillo Ranch MCH device.\n");
 
162
                return -ENODEV;
 
163
        }
 
164
 
 
165
        pci_read_config_dword(mch_dev, CRVML_REG_MCHEN, &dev_en);
 
166
        if (!(dev_en & CRVML_MCHEN_BIT)) {
 
167
                printk(KERN_ERR
 
168
                       "Carillo Ranch MCH device was not enabled.\n");
 
169
                pci_dev_put(mch_dev);
 
170
                return -ENODEV;
 
171
        }
 
172
 
 
173
        pci_read_config_dword(mch_dev, CRVML_REG_MCHBAR,
 
174
                              &mch_bar);
 
175
        mch_regs_base =
 
176
            ioremap_nocache(mch_bar, CRVML_MCHMAP_SIZE);
 
177
        if (!mch_regs_base) {
 
178
                printk(KERN_ERR
 
179
                       "Carillo Ranch MCH device was not enabled.\n");
 
180
                pci_dev_put(mch_dev);
 
181
                return -ENODEV;
 
182
        }
 
183
 
 
184
        err = vmlfb_register_subsys(&cr_pll_ops);
 
185
        if (err) {
 
186
                printk(KERN_ERR
 
187
                       "Carillo Ranch failed to initialize vml_sys.\n");
 
188
                pci_dev_put(mch_dev);
 
189
                return err;
 
190
        }
 
191
 
 
192
        return 0;
 
193
}
 
194
 
 
195
static void __exit cr_pll_exit(void)
 
196
{
 
197
        vmlfb_unregister_subsys(&cr_pll_ops);
 
198
 
 
199
        iounmap(mch_regs_base);
 
200
        pci_dev_put(mch_dev);
 
201
}
 
202
 
 
203
module_init(cr_pll_init);
 
204
module_exit(cr_pll_exit);
 
205
 
 
206
MODULE_AUTHOR("Tungsten Graphics Inc.");
 
207
MODULE_DESCRIPTION("Carillo Ranch PLL Driver");
 
208
MODULE_LICENSE("GPL");