diff options
author | Alan Cox <alan@linux.intel.com> | 2011-11-03 14:21:42 -0400 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2011-11-16 06:25:28 -0500 |
commit | f910b411053f04d5ccd6219a912eaea2b6f5ea6e (patch) | |
tree | bd026e22a686f321c47c66011441ef77339c4c82 /drivers/gpu | |
parent | bbbb262d375140a27ed9fe45a13f19a04a0c51b2 (diff) |
gma500: Add the glue to the various BIOS and firmware interfaces
Some of this should one day become a library shared by i915 and gma500 I
suspct. Best however to deal with that later once it is all nice and
stably merged.
Signed-off-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/gma500/intel_bios.c | 303 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/intel_bios.h | 430 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/intel_opregion.c | 80 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/mid_bios.c | 243 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/mid_bios.h | 21 |
5 files changed, 1077 insertions, 0 deletions
diff --git a/drivers/gpu/drm/gma500/intel_bios.c b/drivers/gpu/drm/gma500/intel_bios.c new file mode 100644 index 000000000000..096757f9bc89 --- /dev/null +++ b/drivers/gpu/drm/gma500/intel_bios.c | |||
@@ -0,0 +1,303 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006 Intel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
16 | * | ||
17 | * Authors: | ||
18 | * Eric Anholt <eric@anholt.net> | ||
19 | * | ||
20 | */ | ||
21 | #include <drm/drmP.h> | ||
22 | #include <drm/drm.h> | ||
23 | #include "psb_drm.h" | ||
24 | #include "psb_drv.h" | ||
25 | #include "psb_intel_drv.h" | ||
26 | #include "psb_intel_reg.h" | ||
27 | #include "intel_bios.h" | ||
28 | |||
29 | |||
30 | static void *find_section(struct bdb_header *bdb, int section_id) | ||
31 | { | ||
32 | u8 *base = (u8 *)bdb; | ||
33 | int index = 0; | ||
34 | u16 total, current_size; | ||
35 | u8 current_id; | ||
36 | |||
37 | /* skip to first section */ | ||
38 | index += bdb->header_size; | ||
39 | total = bdb->bdb_size; | ||
40 | |||
41 | /* walk the sections looking for section_id */ | ||
42 | while (index < total) { | ||
43 | current_id = *(base + index); | ||
44 | index++; | ||
45 | current_size = *((u16 *)(base + index)); | ||
46 | index += 2; | ||
47 | if (current_id == section_id) | ||
48 | return base + index; | ||
49 | index += current_size; | ||
50 | } | ||
51 | |||
52 | return NULL; | ||
53 | } | ||
54 | |||
55 | static void fill_detail_timing_data(struct drm_display_mode *panel_fixed_mode, | ||
56 | struct lvds_dvo_timing *dvo_timing) | ||
57 | { | ||
58 | panel_fixed_mode->hdisplay = (dvo_timing->hactive_hi << 8) | | ||
59 | dvo_timing->hactive_lo; | ||
60 | panel_fixed_mode->hsync_start = panel_fixed_mode->hdisplay + | ||
61 | ((dvo_timing->hsync_off_hi << 8) | dvo_timing->hsync_off_lo); | ||
62 | panel_fixed_mode->hsync_end = panel_fixed_mode->hsync_start + | ||
63 | dvo_timing->hsync_pulse_width; | ||
64 | panel_fixed_mode->htotal = panel_fixed_mode->hdisplay + | ||
65 | ((dvo_timing->hblank_hi << 8) | dvo_timing->hblank_lo); | ||
66 | |||
67 | panel_fixed_mode->vdisplay = (dvo_timing->vactive_hi << 8) | | ||
68 | dvo_timing->vactive_lo; | ||
69 | panel_fixed_mode->vsync_start = panel_fixed_mode->vdisplay + | ||
70 | dvo_timing->vsync_off; | ||
71 | panel_fixed_mode->vsync_end = panel_fixed_mode->vsync_start + | ||
72 | dvo_timing->vsync_pulse_width; | ||
73 | panel_fixed_mode->vtotal = panel_fixed_mode->vdisplay + | ||
74 | ((dvo_timing->vblank_hi << 8) | dvo_timing->vblank_lo); | ||
75 | panel_fixed_mode->clock = dvo_timing->clock * 10; | ||
76 | panel_fixed_mode->type = DRM_MODE_TYPE_PREFERRED; | ||
77 | |||
78 | /* Some VBTs have bogus h/vtotal values */ | ||
79 | if (panel_fixed_mode->hsync_end > panel_fixed_mode->htotal) | ||
80 | panel_fixed_mode->htotal = panel_fixed_mode->hsync_end + 1; | ||
81 | if (panel_fixed_mode->vsync_end > panel_fixed_mode->vtotal) | ||
82 | panel_fixed_mode->vtotal = panel_fixed_mode->vsync_end + 1; | ||
83 | |||
84 | drm_mode_set_name(panel_fixed_mode); | ||
85 | } | ||
86 | |||
87 | static void parse_backlight_data(struct drm_psb_private *dev_priv, | ||
88 | struct bdb_header *bdb) | ||
89 | { | ||
90 | struct bdb_lvds_backlight *vbt_lvds_bl = NULL; | ||
91 | struct bdb_lvds_backlight *lvds_bl; | ||
92 | u8 p_type = 0; | ||
93 | void *bl_start = NULL; | ||
94 | struct bdb_lvds_options *lvds_opts | ||
95 | = find_section(bdb, BDB_LVDS_OPTIONS); | ||
96 | |||
97 | dev_priv->lvds_bl = NULL; | ||
98 | |||
99 | if (lvds_opts) | ||
100 | p_type = lvds_opts->panel_type; | ||
101 | else | ||
102 | return; | ||
103 | |||
104 | bl_start = find_section(bdb, BDB_LVDS_BACKLIGHT); | ||
105 | vbt_lvds_bl = (struct bdb_lvds_backlight *)(bl_start + 1) + p_type; | ||
106 | |||
107 | lvds_bl = kzalloc(sizeof(*vbt_lvds_bl), GFP_KERNEL); | ||
108 | if (!lvds_bl) { | ||
109 | dev_err(dev_priv->dev->dev, "out of memory for backlight data\n"); | ||
110 | return; | ||
111 | } | ||
112 | memcpy(lvds_bl, vbt_lvds_bl, sizeof(*vbt_lvds_bl)); | ||
113 | dev_priv->lvds_bl = lvds_bl; | ||
114 | } | ||
115 | |||
116 | /* Try to find integrated panel data */ | ||
117 | static void parse_lfp_panel_data(struct drm_psb_private *dev_priv, | ||
118 | struct bdb_header *bdb) | ||
119 | { | ||
120 | struct bdb_lvds_options *lvds_options; | ||
121 | struct bdb_lvds_lfp_data *lvds_lfp_data; | ||
122 | struct bdb_lvds_lfp_data_entry *entry; | ||
123 | struct lvds_dvo_timing *dvo_timing; | ||
124 | struct drm_display_mode *panel_fixed_mode; | ||
125 | |||
126 | /* Defaults if we can't find VBT info */ | ||
127 | dev_priv->lvds_dither = 0; | ||
128 | dev_priv->lvds_vbt = 0; | ||
129 | |||
130 | lvds_options = find_section(bdb, BDB_LVDS_OPTIONS); | ||
131 | if (!lvds_options) | ||
132 | return; | ||
133 | |||
134 | dev_priv->lvds_dither = lvds_options->pixel_dither; | ||
135 | if (lvds_options->panel_type == 0xff) | ||
136 | return; | ||
137 | |||
138 | lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA); | ||
139 | if (!lvds_lfp_data) | ||
140 | return; | ||
141 | |||
142 | |||
143 | entry = &lvds_lfp_data->data[lvds_options->panel_type]; | ||
144 | dvo_timing = &entry->dvo_timing; | ||
145 | |||
146 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), | ||
147 | GFP_KERNEL); | ||
148 | if (panel_fixed_mode == NULL) { | ||
149 | dev_err(dev_priv->dev->dev, "out of memory for fixed panel mode\n"); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | dev_priv->lvds_vbt = 1; | ||
154 | fill_detail_timing_data(panel_fixed_mode, dvo_timing); | ||
155 | |||
156 | if (panel_fixed_mode->htotal > 0 && panel_fixed_mode->vtotal > 0) { | ||
157 | dev_priv->lfp_lvds_vbt_mode = panel_fixed_mode; | ||
158 | drm_mode_debug_printmodeline(panel_fixed_mode); | ||
159 | } else { | ||
160 | dev_dbg(dev_priv->dev->dev, "ignoring invalid LVDS VBT\n"); | ||
161 | dev_priv->lvds_vbt = 0; | ||
162 | kfree(panel_fixed_mode); | ||
163 | } | ||
164 | return; | ||
165 | } | ||
166 | |||
167 | /* Try to find sdvo panel data */ | ||
168 | static void parse_sdvo_panel_data(struct drm_psb_private *dev_priv, | ||
169 | struct bdb_header *bdb) | ||
170 | { | ||
171 | struct bdb_sdvo_lvds_options *sdvo_lvds_options; | ||
172 | struct lvds_dvo_timing *dvo_timing; | ||
173 | struct drm_display_mode *panel_fixed_mode; | ||
174 | |||
175 | dev_priv->sdvo_lvds_vbt_mode = NULL; | ||
176 | |||
177 | sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS); | ||
178 | if (!sdvo_lvds_options) | ||
179 | return; | ||
180 | |||
181 | dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS); | ||
182 | if (!dvo_timing) | ||
183 | return; | ||
184 | |||
185 | panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); | ||
186 | |||
187 | if (!panel_fixed_mode) | ||
188 | return; | ||
189 | |||
190 | fill_detail_timing_data(panel_fixed_mode, | ||
191 | dvo_timing + sdvo_lvds_options->panel_type); | ||
192 | |||
193 | dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode; | ||
194 | |||
195 | return; | ||
196 | } | ||
197 | |||
198 | static void parse_general_features(struct drm_psb_private *dev_priv, | ||
199 | struct bdb_header *bdb) | ||
200 | { | ||
201 | struct bdb_general_features *general; | ||
202 | |||
203 | /* Set sensible defaults in case we can't find the general block */ | ||
204 | dev_priv->int_tv_support = 1; | ||
205 | dev_priv->int_crt_support = 1; | ||
206 | |||
207 | general = find_section(bdb, BDB_GENERAL_FEATURES); | ||
208 | if (general) { | ||
209 | dev_priv->int_tv_support = general->int_tv_support; | ||
210 | dev_priv->int_crt_support = general->int_crt_support; | ||
211 | dev_priv->lvds_use_ssc = general->enable_ssc; | ||
212 | |||
213 | if (dev_priv->lvds_use_ssc) { | ||
214 | dev_priv->lvds_ssc_freq | ||
215 | = general->ssc_freq ? 100 : 96; | ||
216 | } | ||
217 | } | ||
218 | } | ||
219 | |||
220 | /** | ||
221 | * psb_intel_init_bios - initialize VBIOS settings & find VBT | ||
222 | * @dev: DRM device | ||
223 | * | ||
224 | * Loads the Video BIOS and checks that the VBT exists. Sets scratch registers | ||
225 | * to appropriate values. | ||
226 | * | ||
227 | * VBT existence is a sanity check that is relied on by other i830_bios.c code. | ||
228 | * Note that it would be better to use a BIOS call to get the VBT, as BIOSes may | ||
229 | * feed an updated VBT back through that, compared to what we'll fetch using | ||
230 | * this method of groping around in the BIOS data. | ||
231 | * | ||
232 | * Returns 0 on success, nonzero on failure. | ||
233 | */ | ||
234 | bool psb_intel_init_bios(struct drm_device *dev) | ||
235 | { | ||
236 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
237 | struct pci_dev *pdev = dev->pdev; | ||
238 | struct vbt_header *vbt = NULL; | ||
239 | struct bdb_header *bdb; | ||
240 | u8 __iomem *bios; | ||
241 | size_t size; | ||
242 | int i; | ||
243 | |||
244 | bios = pci_map_rom(pdev, &size); | ||
245 | if (!bios) | ||
246 | return -1; | ||
247 | |||
248 | /* Scour memory looking for the VBT signature */ | ||
249 | for (i = 0; i + 4 < size; i++) { | ||
250 | if (!memcmp(bios + i, "$VBT", 4)) { | ||
251 | vbt = (struct vbt_header *)(bios + i); | ||
252 | break; | ||
253 | } | ||
254 | } | ||
255 | |||
256 | if (!vbt) { | ||
257 | dev_err(dev->dev, "VBT signature missing\n"); | ||
258 | pci_unmap_rom(pdev, bios); | ||
259 | return -1; | ||
260 | } | ||
261 | |||
262 | bdb = (struct bdb_header *)(bios + i + vbt->bdb_offset); | ||
263 | |||
264 | /* Grab useful general definitions */ | ||
265 | parse_general_features(dev_priv, bdb); | ||
266 | parse_lfp_panel_data(dev_priv, bdb); | ||
267 | parse_sdvo_panel_data(dev_priv, bdb); | ||
268 | parse_backlight_data(dev_priv, bdb); | ||
269 | |||
270 | pci_unmap_rom(pdev, bios); | ||
271 | |||
272 | return 0; | ||
273 | } | ||
274 | |||
275 | /** | ||
276 | * Destroy and free VBT data | ||
277 | */ | ||
278 | void psb_intel_destroy_bios(struct drm_device *dev) | ||
279 | { | ||
280 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
281 | struct drm_display_mode *sdvo_lvds_vbt_mode = | ||
282 | dev_priv->sdvo_lvds_vbt_mode; | ||
283 | struct drm_display_mode *lfp_lvds_vbt_mode = | ||
284 | dev_priv->lfp_lvds_vbt_mode; | ||
285 | struct bdb_lvds_backlight *lvds_bl = | ||
286 | dev_priv->lvds_bl; | ||
287 | |||
288 | /*free sdvo panel mode*/ | ||
289 | if (sdvo_lvds_vbt_mode) { | ||
290 | dev_priv->sdvo_lvds_vbt_mode = NULL; | ||
291 | kfree(sdvo_lvds_vbt_mode); | ||
292 | } | ||
293 | |||
294 | if (lfp_lvds_vbt_mode) { | ||
295 | dev_priv->lfp_lvds_vbt_mode = NULL; | ||
296 | kfree(lfp_lvds_vbt_mode); | ||
297 | } | ||
298 | |||
299 | if (lvds_bl) { | ||
300 | dev_priv->lvds_bl = NULL; | ||
301 | kfree(lvds_bl); | ||
302 | } | ||
303 | } | ||
diff --git a/drivers/gpu/drm/gma500/intel_bios.h b/drivers/gpu/drm/gma500/intel_bios.h new file mode 100644 index 000000000000..70f1bf018183 --- /dev/null +++ b/drivers/gpu/drm/gma500/intel_bios.h | |||
@@ -0,0 +1,430 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2006 Intel Corporation | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify it | ||
5 | * under the terms and conditions of the GNU General Public License, | ||
6 | * version 2, as published by the Free Software Foundation. | ||
7 | * | ||
8 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
9 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
10 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
11 | * more details. | ||
12 | * | ||
13 | * You should have received a copy of the GNU General Public License along with | ||
14 | * this program; if not, write to the Free Software Foundation, Inc., | ||
15 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
16 | * | ||
17 | * Authors: | ||
18 | * Eric Anholt <eric@anholt.net> | ||
19 | * | ||
20 | */ | ||
21 | |||
22 | #ifndef _I830_BIOS_H_ | ||
23 | #define _I830_BIOS_H_ | ||
24 | |||
25 | #include <drm/drmP.h> | ||
26 | |||
27 | struct vbt_header { | ||
28 | u8 signature[20]; /**< Always starts with 'VBT$' */ | ||
29 | u16 version; /**< decimal */ | ||
30 | u16 header_size; /**< in bytes */ | ||
31 | u16 vbt_size; /**< in bytes */ | ||
32 | u8 vbt_checksum; | ||
33 | u8 reserved0; | ||
34 | u32 bdb_offset; /**< from beginning of VBT */ | ||
35 | u32 aim_offset[4]; /**< from beginning of VBT */ | ||
36 | } __attribute__((packed)); | ||
37 | |||
38 | |||
39 | struct bdb_header { | ||
40 | u8 signature[16]; /**< Always 'BIOS_DATA_BLOCK' */ | ||
41 | u16 version; /**< decimal */ | ||
42 | u16 header_size; /**< in bytes */ | ||
43 | u16 bdb_size; /**< in bytes */ | ||
44 | }; | ||
45 | |||
46 | /* strictly speaking, this is a "skip" block, but it has interesting info */ | ||
47 | struct vbios_data { | ||
48 | u8 type; /* 0 == desktop, 1 == mobile */ | ||
49 | u8 relstage; | ||
50 | u8 chipset; | ||
51 | u8 lvds_present:1; | ||
52 | u8 tv_present:1; | ||
53 | u8 rsvd2:6; /* finish byte */ | ||
54 | u8 rsvd3[4]; | ||
55 | u8 signon[155]; | ||
56 | u8 copyright[61]; | ||
57 | u16 code_segment; | ||
58 | u8 dos_boot_mode; | ||
59 | u8 bandwidth_percent; | ||
60 | u8 rsvd4; /* popup memory size */ | ||
61 | u8 resize_pci_bios; | ||
62 | u8 rsvd5; /* is crt already on ddc2 */ | ||
63 | } __attribute__((packed)); | ||
64 | |||
65 | /* | ||
66 | * There are several types of BIOS data blocks (BDBs), each block has | ||
67 | * an ID and size in the first 3 bytes (ID in first, size in next 2). | ||
68 | * Known types are listed below. | ||
69 | */ | ||
70 | #define BDB_GENERAL_FEATURES 1 | ||
71 | #define BDB_GENERAL_DEFINITIONS 2 | ||
72 | #define BDB_OLD_TOGGLE_LIST 3 | ||
73 | #define BDB_MODE_SUPPORT_LIST 4 | ||
74 | #define BDB_GENERIC_MODE_TABLE 5 | ||
75 | #define BDB_EXT_MMIO_REGS 6 | ||
76 | #define BDB_SWF_IO 7 | ||
77 | #define BDB_SWF_MMIO 8 | ||
78 | #define BDB_DOT_CLOCK_TABLE 9 | ||
79 | #define BDB_MODE_REMOVAL_TABLE 10 | ||
80 | #define BDB_CHILD_DEVICE_TABLE 11 | ||
81 | #define BDB_DRIVER_FEATURES 12 | ||
82 | #define BDB_DRIVER_PERSISTENCE 13 | ||
83 | #define BDB_EXT_TABLE_PTRS 14 | ||
84 | #define BDB_DOT_CLOCK_OVERRIDE 15 | ||
85 | #define BDB_DISPLAY_SELECT 16 | ||
86 | /* 17 rsvd */ | ||
87 | #define BDB_DRIVER_ROTATION 18 | ||
88 | #define BDB_DISPLAY_REMOVE 19 | ||
89 | #define BDB_OEM_CUSTOM 20 | ||
90 | #define BDB_EFP_LIST 21 /* workarounds for VGA hsync/vsync */ | ||
91 | #define BDB_SDVO_LVDS_OPTIONS 22 | ||
92 | #define BDB_SDVO_PANEL_DTDS 23 | ||
93 | #define BDB_SDVO_LVDS_PNP_IDS 24 | ||
94 | #define BDB_SDVO_LVDS_POWER_SEQ 25 | ||
95 | #define BDB_TV_OPTIONS 26 | ||
96 | #define BDB_LVDS_OPTIONS 40 | ||
97 | #define BDB_LVDS_LFP_DATA_PTRS 41 | ||
98 | #define BDB_LVDS_LFP_DATA 42 | ||
99 | #define BDB_LVDS_BACKLIGHT 43 | ||
100 | #define BDB_LVDS_POWER 44 | ||
101 | #define BDB_SKIP 254 /* VBIOS private block, ignore */ | ||
102 | |||
103 | struct bdb_general_features { | ||
104 | /* bits 1 */ | ||
105 | u8 panel_fitting:2; | ||
106 | u8 flexaim:1; | ||
107 | u8 msg_enable:1; | ||
108 | u8 clear_screen:3; | ||
109 | u8 color_flip:1; | ||
110 | |||
111 | /* bits 2 */ | ||
112 | u8 download_ext_vbt:1; | ||
113 | u8 enable_ssc:1; | ||
114 | u8 ssc_freq:1; | ||
115 | u8 enable_lfp_on_override:1; | ||
116 | u8 disable_ssc_ddt:1; | ||
117 | u8 rsvd8:3; /* finish byte */ | ||
118 | |||
119 | /* bits 3 */ | ||
120 | u8 disable_smooth_vision:1; | ||
121 | u8 single_dvi:1; | ||
122 | u8 rsvd9:6; /* finish byte */ | ||
123 | |||
124 | /* bits 4 */ | ||
125 | u8 legacy_monitor_detect; | ||
126 | |||
127 | /* bits 5 */ | ||
128 | u8 int_crt_support:1; | ||
129 | u8 int_tv_support:1; | ||
130 | u8 rsvd11:6; /* finish byte */ | ||
131 | } __attribute__((packed)); | ||
132 | |||
133 | struct bdb_general_definitions { | ||
134 | /* DDC GPIO */ | ||
135 | u8 crt_ddc_gmbus_pin; | ||
136 | |||
137 | /* DPMS bits */ | ||
138 | u8 dpms_acpi:1; | ||
139 | u8 skip_boot_crt_detect:1; | ||
140 | u8 dpms_aim:1; | ||
141 | u8 rsvd1:5; /* finish byte */ | ||
142 | |||
143 | /* boot device bits */ | ||
144 | u8 boot_display[2]; | ||
145 | u8 child_dev_size; | ||
146 | |||
147 | /* device info */ | ||
148 | u8 tv_or_lvds_info[33]; | ||
149 | u8 dev1[33]; | ||
150 | u8 dev2[33]; | ||
151 | u8 dev3[33]; | ||
152 | u8 dev4[33]; | ||
153 | /* may be another device block here on some platforms */ | ||
154 | }; | ||
155 | |||
156 | struct bdb_lvds_options { | ||
157 | u8 panel_type; | ||
158 | u8 rsvd1; | ||
159 | /* LVDS capabilities, stored in a dword */ | ||
160 | u8 pfit_mode:2; | ||
161 | u8 pfit_text_mode_enhanced:1; | ||
162 | u8 pfit_gfx_mode_enhanced:1; | ||
163 | u8 pfit_ratio_auto:1; | ||
164 | u8 pixel_dither:1; | ||
165 | u8 lvds_edid:1; | ||
166 | u8 rsvd2:1; | ||
167 | u8 rsvd4; | ||
168 | } __attribute__((packed)); | ||
169 | |||
170 | struct bdb_lvds_backlight { | ||
171 | u8 type:2; | ||
172 | u8 pol:1; | ||
173 | u8 gpio:3; | ||
174 | u8 gmbus:2; | ||
175 | u16 freq; | ||
176 | u8 minbrightness; | ||
177 | u8 i2caddr; | ||
178 | u8 brightnesscmd; | ||
179 | /*FIXME: more...*/ | ||
180 | } __attribute__((packed)); | ||
181 | |||
182 | /* LFP pointer table contains entries to the struct below */ | ||
183 | struct bdb_lvds_lfp_data_ptr { | ||
184 | u16 fp_timing_offset; /* offsets are from start of bdb */ | ||
185 | u8 fp_table_size; | ||
186 | u16 dvo_timing_offset; | ||
187 | u8 dvo_table_size; | ||
188 | u16 panel_pnp_id_offset; | ||
189 | u8 pnp_table_size; | ||
190 | } __attribute__((packed)); | ||
191 | |||
192 | struct bdb_lvds_lfp_data_ptrs { | ||
193 | u8 lvds_entries; /* followed by one or more lvds_data_ptr structs */ | ||
194 | struct bdb_lvds_lfp_data_ptr ptr[16]; | ||
195 | } __attribute__((packed)); | ||
196 | |||
197 | /* LFP data has 3 blocks per entry */ | ||
198 | struct lvds_fp_timing { | ||
199 | u16 x_res; | ||
200 | u16 y_res; | ||
201 | u32 lvds_reg; | ||
202 | u32 lvds_reg_val; | ||
203 | u32 pp_on_reg; | ||
204 | u32 pp_on_reg_val; | ||
205 | u32 pp_off_reg; | ||
206 | u32 pp_off_reg_val; | ||
207 | u32 pp_cycle_reg; | ||
208 | u32 pp_cycle_reg_val; | ||
209 | u32 pfit_reg; | ||
210 | u32 pfit_reg_val; | ||
211 | u16 terminator; | ||
212 | } __attribute__((packed)); | ||
213 | |||
214 | struct lvds_dvo_timing { | ||
215 | u16 clock; /**< In 10khz */ | ||
216 | u8 hactive_lo; | ||
217 | u8 hblank_lo; | ||
218 | u8 hblank_hi:4; | ||
219 | u8 hactive_hi:4; | ||
220 | u8 vactive_lo; | ||
221 | u8 vblank_lo; | ||
222 | u8 vblank_hi:4; | ||
223 | u8 vactive_hi:4; | ||
224 | u8 hsync_off_lo; | ||
225 | u8 hsync_pulse_width; | ||
226 | u8 vsync_pulse_width:4; | ||
227 | u8 vsync_off:4; | ||
228 | u8 rsvd0:6; | ||
229 | u8 hsync_off_hi:2; | ||
230 | u8 h_image; | ||
231 | u8 v_image; | ||
232 | u8 max_hv; | ||
233 | u8 h_border; | ||
234 | u8 v_border; | ||
235 | u8 rsvd1:3; | ||
236 | u8 digital:2; | ||
237 | u8 vsync_positive:1; | ||
238 | u8 hsync_positive:1; | ||
239 | u8 rsvd2:1; | ||
240 | } __attribute__((packed)); | ||
241 | |||
242 | struct lvds_pnp_id { | ||
243 | u16 mfg_name; | ||
244 | u16 product_code; | ||
245 | u32 serial; | ||
246 | u8 mfg_week; | ||
247 | u8 mfg_year; | ||
248 | } __attribute__((packed)); | ||
249 | |||
250 | struct bdb_lvds_lfp_data_entry { | ||
251 | struct lvds_fp_timing fp_timing; | ||
252 | struct lvds_dvo_timing dvo_timing; | ||
253 | struct lvds_pnp_id pnp_id; | ||
254 | } __attribute__((packed)); | ||
255 | |||
256 | struct bdb_lvds_lfp_data { | ||
257 | struct bdb_lvds_lfp_data_entry data[16]; | ||
258 | } __attribute__((packed)); | ||
259 | |||
260 | struct aimdb_header { | ||
261 | char signature[16]; | ||
262 | char oem_device[20]; | ||
263 | u16 aimdb_version; | ||
264 | u16 aimdb_header_size; | ||
265 | u16 aimdb_size; | ||
266 | } __attribute__((packed)); | ||
267 | |||
268 | struct aimdb_block { | ||
269 | u8 aimdb_id; | ||
270 | u16 aimdb_size; | ||
271 | } __attribute__((packed)); | ||
272 | |||
273 | struct vch_panel_data { | ||
274 | u16 fp_timing_offset; | ||
275 | u8 fp_timing_size; | ||
276 | u16 dvo_timing_offset; | ||
277 | u8 dvo_timing_size; | ||
278 | u16 text_fitting_offset; | ||
279 | u8 text_fitting_size; | ||
280 | u16 graphics_fitting_offset; | ||
281 | u8 graphics_fitting_size; | ||
282 | } __attribute__((packed)); | ||
283 | |||
284 | struct vch_bdb_22 { | ||
285 | struct aimdb_block aimdb_block; | ||
286 | struct vch_panel_data panels[16]; | ||
287 | } __attribute__((packed)); | ||
288 | |||
289 | struct bdb_sdvo_lvds_options { | ||
290 | u8 panel_backlight; | ||
291 | u8 h40_set_panel_type; | ||
292 | u8 panel_type; | ||
293 | u8 ssc_clk_freq; | ||
294 | u16 als_low_trip; | ||
295 | u16 als_high_trip; | ||
296 | u8 sclalarcoeff_tab_row_num; | ||
297 | u8 sclalarcoeff_tab_row_size; | ||
298 | u8 coefficient[8]; | ||
299 | u8 panel_misc_bits_1; | ||
300 | u8 panel_misc_bits_2; | ||
301 | u8 panel_misc_bits_3; | ||
302 | u8 panel_misc_bits_4; | ||
303 | } __attribute__((packed)); | ||
304 | |||
305 | |||
306 | extern bool psb_intel_init_bios(struct drm_device *dev); | ||
307 | extern void psb_intel_destroy_bios(struct drm_device *dev); | ||
308 | |||
309 | /* | ||
310 | * Driver<->VBIOS interaction occurs through scratch bits in | ||
311 | * GR18 & SWF*. | ||
312 | */ | ||
313 | |||
314 | /* GR18 bits are set on display switch and hotkey events */ | ||
315 | #define GR18_DRIVER_SWITCH_EN (1<<7) /* 0: VBIOS control, 1: driver control */ | ||
316 | #define GR18_HOTKEY_MASK 0x78 /* See also SWF4 15:0 */ | ||
317 | #define GR18_HK_NONE (0x0<<3) | ||
318 | #define GR18_HK_LFP_STRETCH (0x1<<3) | ||
319 | #define GR18_HK_TOGGLE_DISP (0x2<<3) | ||
320 | #define GR18_HK_DISP_SWITCH (0x4<<3) /* see SWF14 15:0 for what to enable */ | ||
321 | #define GR18_HK_POPUP_DISABLED (0x6<<3) | ||
322 | #define GR18_HK_POPUP_ENABLED (0x7<<3) | ||
323 | #define GR18_HK_PFIT (0x8<<3) | ||
324 | #define GR18_HK_APM_CHANGE (0xa<<3) | ||
325 | #define GR18_HK_MULTIPLE (0xc<<3) | ||
326 | #define GR18_USER_INT_EN (1<<2) | ||
327 | #define GR18_A0000_FLUSH_EN (1<<1) | ||
328 | #define GR18_SMM_EN (1<<0) | ||
329 | |||
330 | /* Set by driver, cleared by VBIOS */ | ||
331 | #define SWF00_YRES_SHIFT 16 | ||
332 | #define SWF00_XRES_SHIFT 0 | ||
333 | #define SWF00_RES_MASK 0xffff | ||
334 | |||
335 | /* Set by VBIOS at boot time and driver at runtime */ | ||
336 | #define SWF01_TV2_FORMAT_SHIFT 8 | ||
337 | #define SWF01_TV1_FORMAT_SHIFT 0 | ||
338 | #define SWF01_TV_FORMAT_MASK 0xffff | ||
339 | |||
340 | #define SWF10_VBIOS_BLC_I2C_EN (1<<29) | ||
341 | #define SWF10_GTT_OVERRIDE_EN (1<<28) | ||
342 | #define SWF10_LFP_DPMS_OVR (1<<27) /* override DPMS on display switch */ | ||
343 | #define SWF10_ACTIVE_TOGGLE_LIST_MASK (7<<24) | ||
344 | #define SWF10_OLD_TOGGLE 0x0 | ||
345 | #define SWF10_TOGGLE_LIST_1 0x1 | ||
346 | #define SWF10_TOGGLE_LIST_2 0x2 | ||
347 | #define SWF10_TOGGLE_LIST_3 0x3 | ||
348 | #define SWF10_TOGGLE_LIST_4 0x4 | ||
349 | #define SWF10_PANNING_EN (1<<23) | ||
350 | #define SWF10_DRIVER_LOADED (1<<22) | ||
351 | #define SWF10_EXTENDED_DESKTOP (1<<21) | ||
352 | #define SWF10_EXCLUSIVE_MODE (1<<20) | ||
353 | #define SWF10_OVERLAY_EN (1<<19) | ||
354 | #define SWF10_PLANEB_HOLDOFF (1<<18) | ||
355 | #define SWF10_PLANEA_HOLDOFF (1<<17) | ||
356 | #define SWF10_VGA_HOLDOFF (1<<16) | ||
357 | #define SWF10_ACTIVE_DISP_MASK 0xffff | ||
358 | #define SWF10_PIPEB_LFP2 (1<<15) | ||
359 | #define SWF10_PIPEB_EFP2 (1<<14) | ||
360 | #define SWF10_PIPEB_TV2 (1<<13) | ||
361 | #define SWF10_PIPEB_CRT2 (1<<12) | ||
362 | #define SWF10_PIPEB_LFP (1<<11) | ||
363 | #define SWF10_PIPEB_EFP (1<<10) | ||
364 | #define SWF10_PIPEB_TV (1<<9) | ||
365 | #define SWF10_PIPEB_CRT (1<<8) | ||
366 | #define SWF10_PIPEA_LFP2 (1<<7) | ||
367 | #define SWF10_PIPEA_EFP2 (1<<6) | ||
368 | #define SWF10_PIPEA_TV2 (1<<5) | ||
369 | #define SWF10_PIPEA_CRT2 (1<<4) | ||
370 | #define SWF10_PIPEA_LFP (1<<3) | ||
371 | #define SWF10_PIPEA_EFP (1<<2) | ||
372 | #define SWF10_PIPEA_TV (1<<1) | ||
373 | #define SWF10_PIPEA_CRT (1<<0) | ||
374 | |||
375 | #define SWF11_MEMORY_SIZE_SHIFT 16 | ||
376 | #define SWF11_SV_TEST_EN (1<<15) | ||
377 | #define SWF11_IS_AGP (1<<14) | ||
378 | #define SWF11_DISPLAY_HOLDOFF (1<<13) | ||
379 | #define SWF11_DPMS_REDUCED (1<<12) | ||
380 | #define SWF11_IS_VBE_MODE (1<<11) | ||
381 | #define SWF11_PIPEB_ACCESS (1<<10) /* 0 here means pipe a */ | ||
382 | #define SWF11_DPMS_MASK 0x07 | ||
383 | #define SWF11_DPMS_OFF (1<<2) | ||
384 | #define SWF11_DPMS_SUSPEND (1<<1) | ||
385 | #define SWF11_DPMS_STANDBY (1<<0) | ||
386 | #define SWF11_DPMS_ON 0 | ||
387 | |||
388 | #define SWF14_GFX_PFIT_EN (1<<31) | ||
389 | #define SWF14_TEXT_PFIT_EN (1<<30) | ||
390 | #define SWF14_LID_STATUS_CLOSED (1<<29) /* 0 here means open */ | ||
391 | #define SWF14_POPUP_EN (1<<28) | ||
392 | #define SWF14_DISPLAY_HOLDOFF (1<<27) | ||
393 | #define SWF14_DISP_DETECT_EN (1<<26) | ||
394 | #define SWF14_DOCKING_STATUS_DOCKED (1<<25) /* 0 here means undocked */ | ||
395 | #define SWF14_DRIVER_STATUS (1<<24) | ||
396 | #define SWF14_OS_TYPE_WIN9X (1<<23) | ||
397 | #define SWF14_OS_TYPE_WINNT (1<<22) | ||
398 | /* 21:19 rsvd */ | ||
399 | #define SWF14_PM_TYPE_MASK 0x00070000 | ||
400 | #define SWF14_PM_ACPI_VIDEO (0x4 << 16) | ||
401 | #define SWF14_PM_ACPI (0x3 << 16) | ||
402 | #define SWF14_PM_APM_12 (0x2 << 16) | ||
403 | #define SWF14_PM_APM_11 (0x1 << 16) | ||
404 | #define SWF14_HK_REQUEST_MASK 0x0000ffff /* see GR18 6:3 for event type */ | ||
405 | /* if GR18 indicates a display switch */ | ||
406 | #define SWF14_DS_PIPEB_LFP2_EN (1<<15) | ||
407 | #define SWF14_DS_PIPEB_EFP2_EN (1<<14) | ||
408 | #define SWF14_DS_PIPEB_TV2_EN (1<<13) | ||
409 | #define SWF14_DS_PIPEB_CRT2_EN (1<<12) | ||
410 | #define SWF14_DS_PIPEB_LFP_EN (1<<11) | ||
411 | #define SWF14_DS_PIPEB_EFP_EN (1<<10) | ||
412 | #define SWF14_DS_PIPEB_TV_EN (1<<9) | ||
413 | #define SWF14_DS_PIPEB_CRT_EN (1<<8) | ||
414 | #define SWF14_DS_PIPEA_LFP2_EN (1<<7) | ||
415 | #define SWF14_DS_PIPEA_EFP2_EN (1<<6) | ||
416 | #define SWF14_DS_PIPEA_TV2_EN (1<<5) | ||
417 | #define SWF14_DS_PIPEA_CRT2_EN (1<<4) | ||
418 | #define SWF14_DS_PIPEA_LFP_EN (1<<3) | ||
419 | #define SWF14_DS_PIPEA_EFP_EN (1<<2) | ||
420 | #define SWF14_DS_PIPEA_TV_EN (1<<1) | ||
421 | #define SWF14_DS_PIPEA_CRT_EN (1<<0) | ||
422 | /* if GR18 indicates a panel fitting request */ | ||
423 | #define SWF14_PFIT_EN (1<<0) /* 0 means disable */ | ||
424 | /* if GR18 indicates an APM change request */ | ||
425 | #define SWF14_APM_HIBERNATE 0x4 | ||
426 | #define SWF14_APM_SUSPEND 0x3 | ||
427 | #define SWF14_APM_STANDBY 0x1 | ||
428 | #define SWF14_APM_RESTORE 0x0 | ||
429 | |||
430 | #endif /* _I830_BIOS_H_ */ | ||
diff --git a/drivers/gpu/drm/gma500/intel_opregion.c b/drivers/gpu/drm/gma500/intel_opregion.c new file mode 100644 index 000000000000..d2e60376982f --- /dev/null +++ b/drivers/gpu/drm/gma500/intel_opregion.c | |||
@@ -0,0 +1,80 @@ | |||
1 | /* | ||
2 | * Copyright 2010 Intel Corporation | ||
3 | * | ||
4 | * Permission is hereby granted, free of charge, to any person obtaining a | ||
5 | * copy of this software and associated documentation files (the "Software"), | ||
6 | * to deal in the Software without restriction, including without limitation | ||
7 | * the rights to use, copy, modify, merge, publish, distribute, sublicense, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the next | ||
12 | * paragraph) shall be included in all copies or substantial portions of the | ||
13 | * Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
21 | * DEALINGS IN THE SOFTWARE. | ||
22 | * | ||
23 | */ | ||
24 | |||
25 | #include "psb_drv.h" | ||
26 | |||
27 | struct opregion_header { | ||
28 | u8 signature[16]; | ||
29 | u32 size; | ||
30 | u32 opregion_ver; | ||
31 | u8 bios_ver[32]; | ||
32 | u8 vbios_ver[16]; | ||
33 | u8 driver_ver[16]; | ||
34 | u32 mboxes; | ||
35 | u8 reserved[164]; | ||
36 | } __packed; | ||
37 | |||
38 | struct opregion_apci { | ||
39 | /*FIXME: add it later*/ | ||
40 | } __packed; | ||
41 | |||
42 | struct opregion_swsci { | ||
43 | /*FIXME: add it later*/ | ||
44 | } __packed; | ||
45 | |||
46 | struct opregion_acpi { | ||
47 | /*FIXME: add it later*/ | ||
48 | } __packed; | ||
49 | |||
50 | int gma_intel_opregion_init(struct drm_device *dev) | ||
51 | { | ||
52 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
53 | u32 opregion_phy; | ||
54 | void *base; | ||
55 | u32 *lid_state; | ||
56 | |||
57 | dev_priv->lid_state = NULL; | ||
58 | |||
59 | pci_read_config_dword(dev->pdev, 0xfc, &opregion_phy); | ||
60 | if (opregion_phy == 0) | ||
61 | return -ENOTSUPP; | ||
62 | |||
63 | base = ioremap(opregion_phy, 8*1024); | ||
64 | if (!base) | ||
65 | return -ENOMEM; | ||
66 | |||
67 | lid_state = base + 0x01ac; | ||
68 | |||
69 | dev_priv->lid_state = lid_state; | ||
70 | dev_priv->lid_last_state = readl(lid_state); | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | int gma_intel_opregion_exit(struct drm_device *dev) | ||
75 | { | ||
76 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
77 | if (dev_priv->lid_state) | ||
78 | iounmap(dev_priv->lid_state); | ||
79 | return 0; | ||
80 | } | ||
diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c new file mode 100644 index 000000000000..7115d1a7408f --- /dev/null +++ b/drivers/gpu/drm/gma500/mid_bios.c | |||
@@ -0,0 +1,243 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2011, Intel Corporation. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | * | ||
18 | **************************************************************************/ | ||
19 | |||
20 | /* TODO | ||
21 | * - Split functions by vbt type | ||
22 | * - Make them all take drm_device | ||
23 | * - Check ioremap failures | ||
24 | */ | ||
25 | |||
26 | #include <drm/drmP.h> | ||
27 | #include <drm/drm.h> | ||
28 | #include "psb_drm.h" | ||
29 | #include "psb_drv.h" | ||
30 | #include "mid_bios.h" | ||
31 | |||
32 | static void mid_get_fuse_settings(struct drm_device *dev) | ||
33 | { | ||
34 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
35 | struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0); | ||
36 | uint32_t fuse_value = 0; | ||
37 | uint32_t fuse_value_tmp = 0; | ||
38 | |||
39 | #define FB_REG06 0xD0810600 | ||
40 | #define FB_MIPI_DISABLE (1 << 11) | ||
41 | #define FB_REG09 0xD0810900 | ||
42 | #define FB_REG09 0xD0810900 | ||
43 | #define FB_SKU_MASK 0x7000 | ||
44 | #define FB_SKU_SHIFT 12 | ||
45 | #define FB_SKU_100 0 | ||
46 | #define FB_SKU_100L 1 | ||
47 | #define FB_SKU_83 2 | ||
48 | pci_write_config_dword(pci_root, 0xD0, FB_REG06); | ||
49 | pci_read_config_dword(pci_root, 0xD4, &fuse_value); | ||
50 | |||
51 | /* FB_MIPI_DISABLE doesn't mean LVDS on with Medfield */ | ||
52 | if (IS_MRST(dev)) | ||
53 | dev_priv->iLVDS_enable = fuse_value & FB_MIPI_DISABLE; | ||
54 | |||
55 | DRM_INFO("internal display is %s\n", | ||
56 | dev_priv->iLVDS_enable ? "LVDS display" : "MIPI display"); | ||
57 | |||
58 | /* Prevent runtime suspend at start*/ | ||
59 | if (dev_priv->iLVDS_enable) { | ||
60 | dev_priv->is_lvds_on = true; | ||
61 | dev_priv->is_mipi_on = false; | ||
62 | } else { | ||
63 | dev_priv->is_mipi_on = true; | ||
64 | dev_priv->is_lvds_on = false; | ||
65 | } | ||
66 | |||
67 | dev_priv->video_device_fuse = fuse_value; | ||
68 | |||
69 | pci_write_config_dword(pci_root, 0xD0, FB_REG09); | ||
70 | pci_read_config_dword(pci_root, 0xD4, &fuse_value); | ||
71 | |||
72 | dev_dbg(dev->dev, "SKU values is 0x%x.\n", fuse_value); | ||
73 | fuse_value_tmp = (fuse_value & FB_SKU_MASK) >> FB_SKU_SHIFT; | ||
74 | |||
75 | dev_priv->fuse_reg_value = fuse_value; | ||
76 | |||
77 | switch (fuse_value_tmp) { | ||
78 | case FB_SKU_100: | ||
79 | dev_priv->core_freq = 200; | ||
80 | break; | ||
81 | case FB_SKU_100L: | ||
82 | dev_priv->core_freq = 100; | ||
83 | break; | ||
84 | case FB_SKU_83: | ||
85 | dev_priv->core_freq = 166; | ||
86 | break; | ||
87 | default: | ||
88 | dev_warn(dev->dev, "Invalid SKU values, SKU value = 0x%08x\n", | ||
89 | fuse_value_tmp); | ||
90 | dev_priv->core_freq = 0; | ||
91 | } | ||
92 | dev_dbg(dev->dev, "LNC core clk is %dMHz.\n", dev_priv->core_freq); | ||
93 | pci_dev_put(pci_root); | ||
94 | } | ||
95 | |||
96 | /* | ||
97 | * Get the revison ID, B0:D2:F0;0x08 | ||
98 | */ | ||
99 | static void mid_get_pci_revID(struct drm_psb_private *dev_priv) | ||
100 | { | ||
101 | uint32_t platform_rev_id = 0; | ||
102 | struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); | ||
103 | |||
104 | pci_read_config_dword(pci_gfx_root, 0x08, &platform_rev_id); | ||
105 | dev_priv->platform_rev_id = (uint8_t) platform_rev_id; | ||
106 | pci_dev_put(pci_gfx_root); | ||
107 | dev_dbg(dev_priv->dev->dev, "platform_rev_id is %x\n", | ||
108 | dev_priv->platform_rev_id); | ||
109 | } | ||
110 | |||
111 | static void mid_get_vbt_data(struct drm_psb_private *dev_priv) | ||
112 | { | ||
113 | struct drm_device *dev = dev_priv->dev; | ||
114 | struct oaktrail_vbt *vbt = &dev_priv->vbt_data; | ||
115 | u32 addr; | ||
116 | u16 new_size; | ||
117 | u8 *vbt_virtual; | ||
118 | u8 bpi; | ||
119 | u8 number_desc = 0; | ||
120 | struct oaktrail_timing_info *dp_ti = &dev_priv->gct_data.DTD; | ||
121 | struct gct_r10_timing_info ti; | ||
122 | void *pGCT; | ||
123 | struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); | ||
124 | |||
125 | /* Get the address of the platform config vbt, B0:D2:F0;0xFC */ | ||
126 | pci_read_config_dword(pci_gfx_root, 0xFC, &addr); | ||
127 | pci_dev_put(pci_gfx_root); | ||
128 | |||
129 | dev_dbg(dev->dev, "drm platform config address is %x\n", addr); | ||
130 | |||
131 | /* check for platform config address == 0. */ | ||
132 | /* this means fw doesn't support vbt */ | ||
133 | |||
134 | if (addr == 0) { | ||
135 | vbt->size = 0; | ||
136 | return; | ||
137 | } | ||
138 | |||
139 | /* get the virtual address of the vbt */ | ||
140 | vbt_virtual = ioremap(addr, sizeof(*vbt)); | ||
141 | |||
142 | memcpy(vbt, vbt_virtual, sizeof(*vbt)); | ||
143 | iounmap(vbt_virtual); /* Free virtual address space */ | ||
144 | |||
145 | dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision); | ||
146 | |||
147 | switch (vbt->revision) { | ||
148 | case 0: | ||
149 | vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4, | ||
150 | vbt->size - sizeof(*vbt) + 4); | ||
151 | pGCT = vbt->oaktrail_gct; | ||
152 | bpi = ((struct oaktrail_gct_v1 *)pGCT)->PD.BootPanelIndex; | ||
153 | dev_priv->gct_data.bpi = bpi; | ||
154 | dev_priv->gct_data.pt = | ||
155 | ((struct oaktrail_gct_v1 *)pGCT)->PD.PanelType; | ||
156 | memcpy(&dev_priv->gct_data.DTD, | ||
157 | &((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].DTD, | ||
158 | sizeof(struct oaktrail_timing_info)); | ||
159 | dev_priv->gct_data.Panel_Port_Control = | ||
160 | ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control; | ||
161 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
162 | ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; | ||
163 | break; | ||
164 | case 1: | ||
165 | vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4, | ||
166 | vbt->size - sizeof(*vbt) + 4); | ||
167 | pGCT = vbt->oaktrail_gct; | ||
168 | bpi = ((struct oaktrail_gct_v2 *)pGCT)->PD.BootPanelIndex; | ||
169 | dev_priv->gct_data.bpi = bpi; | ||
170 | dev_priv->gct_data.pt = | ||
171 | ((struct oaktrail_gct_v2 *)pGCT)->PD.PanelType; | ||
172 | memcpy(&dev_priv->gct_data.DTD, | ||
173 | &((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].DTD, | ||
174 | sizeof(struct oaktrail_timing_info)); | ||
175 | dev_priv->gct_data.Panel_Port_Control = | ||
176 | ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control; | ||
177 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
178 | ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; | ||
179 | break; | ||
180 | case 0x10: | ||
181 | /*header definition changed from rev 01 (v2) to rev 10h. */ | ||
182 | /*so, some values have changed location*/ | ||
183 | new_size = vbt->checksum; /*checksum contains lo size byte*/ | ||
184 | /*LSB of oaktrail_gct contains hi size byte*/ | ||
185 | new_size |= ((0xff & (unsigned int)vbt->oaktrail_gct)) << 8; | ||
186 | |||
187 | vbt->checksum = vbt->size; /*size contains the checksum*/ | ||
188 | if (new_size > 0xff) | ||
189 | vbt->size = 0xff; /*restrict size to 255*/ | ||
190 | else | ||
191 | vbt->size = new_size; | ||
192 | |||
193 | /* number of descriptors defined in the GCT */ | ||
194 | number_desc = ((0xff00 & (unsigned int)vbt->oaktrail_gct)) >> 8; | ||
195 | bpi = ((0xff0000 & (unsigned int)vbt->oaktrail_gct)) >> 16; | ||
196 | vbt->oaktrail_gct = ioremap(addr + GCT_R10_HEADER_SIZE, | ||
197 | GCT_R10_DISPLAY_DESC_SIZE * number_desc); | ||
198 | pGCT = vbt->oaktrail_gct; | ||
199 | pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE); | ||
200 | dev_priv->gct_data.bpi = bpi; /*save boot panel id*/ | ||
201 | |||
202 | /*copy the GCT display timings into a temp structure*/ | ||
203 | memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info)); | ||
204 | |||
205 | /*now copy the temp struct into the dev_priv->gct_data*/ | ||
206 | dp_ti->pixel_clock = ti.pixel_clock; | ||
207 | dp_ti->hactive_hi = ti.hactive_hi; | ||
208 | dp_ti->hactive_lo = ti.hactive_lo; | ||
209 | dp_ti->hblank_hi = ti.hblank_hi; | ||
210 | dp_ti->hblank_lo = ti.hblank_lo; | ||
211 | dp_ti->hsync_offset_hi = ti.hsync_offset_hi; | ||
212 | dp_ti->hsync_offset_lo = ti.hsync_offset_lo; | ||
213 | dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi; | ||
214 | dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo; | ||
215 | dp_ti->vactive_hi = ti.vactive_hi; | ||
216 | dp_ti->vactive_lo = ti.vactive_lo; | ||
217 | dp_ti->vblank_hi = ti.vblank_hi; | ||
218 | dp_ti->vblank_lo = ti.vblank_lo; | ||
219 | dp_ti->vsync_offset_hi = ti.vsync_offset_hi; | ||
220 | dp_ti->vsync_offset_lo = ti.vsync_offset_lo; | ||
221 | dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi; | ||
222 | dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo; | ||
223 | |||
224 | /* Move the MIPI_Display_Descriptor data from GCT to dev priv */ | ||
225 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
226 | *((u8 *)pGCT + 0x0d); | ||
227 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor |= | ||
228 | (*((u8 *)pGCT + 0x0e)) << 8; | ||
229 | break; | ||
230 | default: | ||
231 | dev_err(dev->dev, "Unknown revision of GCT!\n"); | ||
232 | vbt->size = 0; | ||
233 | } | ||
234 | } | ||
235 | |||
236 | int mid_chip_setup(struct drm_device *dev) | ||
237 | { | ||
238 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
239 | mid_get_fuse_settings(dev); | ||
240 | mid_get_vbt_data(dev_priv); | ||
241 | mid_get_pci_revID(dev_priv); | ||
242 | return 0; | ||
243 | } | ||
diff --git a/drivers/gpu/drm/gma500/mid_bios.h b/drivers/gpu/drm/gma500/mid_bios.h new file mode 100644 index 000000000000..00e7d564b7eb --- /dev/null +++ b/drivers/gpu/drm/gma500/mid_bios.h | |||
@@ -0,0 +1,21 @@ | |||
1 | /************************************************************************** | ||
2 | * Copyright (c) 2011, Intel Corporation. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms and conditions of the GNU General Public License, | ||
7 | * version 2, as published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
12 | * more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License along with | ||
15 | * this program; if not, write to the Free Software Foundation, Inc., | ||
16 | * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. | ||
17 | * | ||
18 | **************************************************************************/ | ||
19 | |||
20 | extern int mid_chip_setup(struct drm_device *dev); | ||
21 | |||