diff options
Diffstat (limited to 'drivers/gpu/drm/gma500/mid_bios.c')
-rw-r--r-- | drivers/gpu/drm/gma500/mid_bios.c | 295 |
1 files changed, 185 insertions, 110 deletions
diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c index 5eee9ad80da4..b2a790bd9899 100644 --- a/drivers/gpu/drm/gma500/mid_bios.c +++ b/drivers/gpu/drm/gma500/mid_bios.c | |||
@@ -118,139 +118,214 @@ static void mid_get_pci_revID(struct drm_psb_private *dev_priv) | |||
118 | dev_priv->platform_rev_id); | 118 | dev_priv->platform_rev_id); |
119 | } | 119 | } |
120 | 120 | ||
121 | struct vbt_header { | ||
122 | u32 signature; | ||
123 | u8 revision; | ||
124 | } __packed; | ||
125 | |||
126 | /* The same for r0 and r1 */ | ||
127 | struct vbt_r0 { | ||
128 | struct vbt_header vbt_header; | ||
129 | u8 size; | ||
130 | u8 checksum; | ||
131 | } __packed; | ||
132 | |||
133 | struct vbt_r10 { | ||
134 | struct vbt_header vbt_header; | ||
135 | u8 checksum; | ||
136 | u16 size; | ||
137 | u8 panel_count; | ||
138 | u8 primary_panel_idx; | ||
139 | u8 secondary_panel_idx; | ||
140 | u8 __reserved[5]; | ||
141 | } __packed; | ||
142 | |||
143 | static int read_vbt_r0(u32 addr, struct vbt_r0 *vbt) | ||
144 | { | ||
145 | void __iomem *vbt_virtual; | ||
146 | |||
147 | vbt_virtual = ioremap(addr, sizeof(*vbt)); | ||
148 | if (vbt_virtual == NULL) | ||
149 | return -1; | ||
150 | |||
151 | memcpy_fromio(vbt, vbt_virtual, sizeof(*vbt)); | ||
152 | iounmap(vbt_virtual); | ||
153 | |||
154 | return 0; | ||
155 | } | ||
156 | |||
157 | static int read_vbt_r10(u32 addr, struct vbt_r10 *vbt) | ||
158 | { | ||
159 | void __iomem *vbt_virtual; | ||
160 | |||
161 | vbt_virtual = ioremap(addr, sizeof(*vbt)); | ||
162 | if (!vbt_virtual) | ||
163 | return -1; | ||
164 | |||
165 | memcpy_fromio(vbt, vbt_virtual, sizeof(*vbt)); | ||
166 | iounmap(vbt_virtual); | ||
167 | |||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | static int mid_get_vbt_data_r0(struct drm_psb_private *dev_priv, u32 addr) | ||
172 | { | ||
173 | struct vbt_r0 vbt; | ||
174 | void __iomem *gct_virtual; | ||
175 | struct gct_r0 gct; | ||
176 | u8 bpi; | ||
177 | |||
178 | if (read_vbt_r0(addr, &vbt)) | ||
179 | return -1; | ||
180 | |||
181 | gct_virtual = ioremap(addr + sizeof(vbt), vbt.size - sizeof(vbt)); | ||
182 | if (!gct_virtual) | ||
183 | return -1; | ||
184 | memcpy_fromio(&gct, gct_virtual, sizeof(gct)); | ||
185 | iounmap(gct_virtual); | ||
186 | |||
187 | bpi = gct.PD.BootPanelIndex; | ||
188 | dev_priv->gct_data.bpi = bpi; | ||
189 | dev_priv->gct_data.pt = gct.PD.PanelType; | ||
190 | dev_priv->gct_data.DTD = gct.panel[bpi].DTD; | ||
191 | dev_priv->gct_data.Panel_Port_Control = | ||
192 | gct.panel[bpi].Panel_Port_Control; | ||
193 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
194 | gct.panel[bpi].Panel_MIPI_Display_Descriptor; | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int mid_get_vbt_data_r1(struct drm_psb_private *dev_priv, u32 addr) | ||
200 | { | ||
201 | struct vbt_r0 vbt; | ||
202 | void __iomem *gct_virtual; | ||
203 | struct gct_r1 gct; | ||
204 | u8 bpi; | ||
205 | |||
206 | if (read_vbt_r0(addr, &vbt)) | ||
207 | return -1; | ||
208 | |||
209 | gct_virtual = ioremap(addr + sizeof(vbt), vbt.size - sizeof(vbt)); | ||
210 | if (!gct_virtual) | ||
211 | return -1; | ||
212 | memcpy_fromio(&gct, gct_virtual, sizeof(gct)); | ||
213 | iounmap(gct_virtual); | ||
214 | |||
215 | bpi = gct.PD.BootPanelIndex; | ||
216 | dev_priv->gct_data.bpi = bpi; | ||
217 | dev_priv->gct_data.pt = gct.PD.PanelType; | ||
218 | dev_priv->gct_data.DTD = gct.panel[bpi].DTD; | ||
219 | dev_priv->gct_data.Panel_Port_Control = | ||
220 | gct.panel[bpi].Panel_Port_Control; | ||
221 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
222 | gct.panel[bpi].Panel_MIPI_Display_Descriptor; | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int mid_get_vbt_data_r10(struct drm_psb_private *dev_priv, u32 addr) | ||
228 | { | ||
229 | struct vbt_r10 vbt; | ||
230 | void __iomem *gct_virtual; | ||
231 | struct gct_r10 *gct; | ||
232 | struct oaktrail_timing_info *dp_ti = &dev_priv->gct_data.DTD; | ||
233 | struct gct_r10_timing_info *ti; | ||
234 | int ret = -1; | ||
235 | |||
236 | if (read_vbt_r10(addr, &vbt)) | ||
237 | return -1; | ||
238 | |||
239 | gct = kmalloc(sizeof(*gct) * vbt.panel_count, GFP_KERNEL); | ||
240 | if (!gct) | ||
241 | return -1; | ||
242 | |||
243 | gct_virtual = ioremap(addr + sizeof(vbt), | ||
244 | sizeof(*gct) * vbt.panel_count); | ||
245 | if (!gct_virtual) | ||
246 | goto out; | ||
247 | memcpy_fromio(gct, gct_virtual, sizeof(*gct)); | ||
248 | iounmap(gct_virtual); | ||
249 | |||
250 | dev_priv->gct_data.bpi = vbt.primary_panel_idx; | ||
251 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
252 | gct[vbt.primary_panel_idx].Panel_MIPI_Display_Descriptor; | ||
253 | |||
254 | ti = &gct[vbt.primary_panel_idx].DTD; | ||
255 | dp_ti->pixel_clock = ti->pixel_clock; | ||
256 | dp_ti->hactive_hi = ti->hactive_hi; | ||
257 | dp_ti->hactive_lo = ti->hactive_lo; | ||
258 | dp_ti->hblank_hi = ti->hblank_hi; | ||
259 | dp_ti->hblank_lo = ti->hblank_lo; | ||
260 | dp_ti->hsync_offset_hi = ti->hsync_offset_hi; | ||
261 | dp_ti->hsync_offset_lo = ti->hsync_offset_lo; | ||
262 | dp_ti->hsync_pulse_width_hi = ti->hsync_pulse_width_hi; | ||
263 | dp_ti->hsync_pulse_width_lo = ti->hsync_pulse_width_lo; | ||
264 | dp_ti->vactive_hi = ti->vactive_hi; | ||
265 | dp_ti->vactive_lo = ti->vactive_lo; | ||
266 | dp_ti->vblank_hi = ti->vblank_hi; | ||
267 | dp_ti->vblank_lo = ti->vblank_lo; | ||
268 | dp_ti->vsync_offset_hi = ti->vsync_offset_hi; | ||
269 | dp_ti->vsync_offset_lo = ti->vsync_offset_lo; | ||
270 | dp_ti->vsync_pulse_width_hi = ti->vsync_pulse_width_hi; | ||
271 | dp_ti->vsync_pulse_width_lo = ti->vsync_pulse_width_lo; | ||
272 | |||
273 | ret = 0; | ||
274 | out: | ||
275 | kfree(gct); | ||
276 | return ret; | ||
277 | } | ||
278 | |||
121 | static void mid_get_vbt_data(struct drm_psb_private *dev_priv) | 279 | static void mid_get_vbt_data(struct drm_psb_private *dev_priv) |
122 | { | 280 | { |
123 | struct drm_device *dev = dev_priv->dev; | 281 | struct drm_device *dev = dev_priv->dev; |
124 | struct oaktrail_vbt *vbt = &dev_priv->vbt_data; | ||
125 | u32 addr; | 282 | u32 addr; |
126 | u16 new_size; | 283 | u8 __iomem *vbt_virtual; |
127 | u8 *vbt_virtual; | 284 | struct vbt_header vbt_header; |
128 | u8 bpi; | ||
129 | u8 number_desc = 0; | ||
130 | struct oaktrail_timing_info *dp_ti = &dev_priv->gct_data.DTD; | ||
131 | struct gct_r10_timing_info ti; | ||
132 | void *pGCT; | ||
133 | struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); | 285 | struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0)); |
286 | int ret = -1; | ||
134 | 287 | ||
135 | /* Get the address of the platform config vbt, B0:D2:F0;0xFC */ | 288 | /* Get the address of the platform config vbt */ |
136 | pci_read_config_dword(pci_gfx_root, 0xFC, &addr); | 289 | pci_read_config_dword(pci_gfx_root, 0xFC, &addr); |
137 | pci_dev_put(pci_gfx_root); | 290 | pci_dev_put(pci_gfx_root); |
138 | 291 | ||
139 | dev_dbg(dev->dev, "drm platform config address is %x\n", addr); | 292 | dev_dbg(dev->dev, "drm platform config address is %x\n", addr); |
140 | 293 | ||
141 | /* check for platform config address == 0. */ | 294 | if (!addr) |
142 | /* this means fw doesn't support vbt */ | 295 | goto out; |
143 | |||
144 | if (addr == 0) { | ||
145 | vbt->size = 0; | ||
146 | return; | ||
147 | } | ||
148 | 296 | ||
149 | /* get the virtual address of the vbt */ | 297 | /* get the virtual address of the vbt */ |
150 | vbt_virtual = ioremap(addr, sizeof(*vbt)); | 298 | vbt_virtual = ioremap(addr, sizeof(vbt_header)); |
151 | if (vbt_virtual == NULL) { | 299 | if (!vbt_virtual) |
152 | vbt->size = 0; | 300 | goto out; |
153 | return; | ||
154 | } | ||
155 | 301 | ||
156 | memcpy(vbt, vbt_virtual, sizeof(*vbt)); | 302 | memcpy_fromio(&vbt_header, vbt_virtual, sizeof(vbt_header)); |
157 | iounmap(vbt_virtual); /* Free virtual address space */ | 303 | iounmap(vbt_virtual); |
158 | 304 | ||
159 | /* No matching signature don't process the data */ | 305 | if (memcmp(&vbt_header.signature, "$GCT", 4)) |
160 | if (memcmp(vbt->signature, "$GCT", 4)) { | 306 | goto out; |
161 | vbt->size = 0; | 307 | |
162 | return; | 308 | dev_dbg(dev->dev, "GCT revision is %02x\n", vbt_header.revision); |
163 | } | ||
164 | 309 | ||
165 | dev_dbg(dev->dev, "GCT revision is %x\n", vbt->revision); | 310 | switch (vbt_header.revision) { |
166 | 311 | case 0x00: | |
167 | switch (vbt->revision) { | 312 | ret = mid_get_vbt_data_r0(dev_priv, addr); |
168 | case 0: | ||
169 | vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4, | ||
170 | vbt->size - sizeof(*vbt) + 4); | ||
171 | pGCT = vbt->oaktrail_gct; | ||
172 | bpi = ((struct oaktrail_gct_v1 *)pGCT)->PD.BootPanelIndex; | ||
173 | dev_priv->gct_data.bpi = bpi; | ||
174 | dev_priv->gct_data.pt = | ||
175 | ((struct oaktrail_gct_v1 *)pGCT)->PD.PanelType; | ||
176 | memcpy(&dev_priv->gct_data.DTD, | ||
177 | &((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].DTD, | ||
178 | sizeof(struct oaktrail_timing_info)); | ||
179 | dev_priv->gct_data.Panel_Port_Control = | ||
180 | ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_Port_Control; | ||
181 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
182 | ((struct oaktrail_gct_v1 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; | ||
183 | break; | 313 | break; |
184 | case 1: | 314 | case 0x01: |
185 | vbt->oaktrail_gct = ioremap(addr + sizeof(*vbt) - 4, | 315 | ret = mid_get_vbt_data_r1(dev_priv, addr); |
186 | vbt->size - sizeof(*vbt) + 4); | ||
187 | pGCT = vbt->oaktrail_gct; | ||
188 | bpi = ((struct oaktrail_gct_v2 *)pGCT)->PD.BootPanelIndex; | ||
189 | dev_priv->gct_data.bpi = bpi; | ||
190 | dev_priv->gct_data.pt = | ||
191 | ((struct oaktrail_gct_v2 *)pGCT)->PD.PanelType; | ||
192 | memcpy(&dev_priv->gct_data.DTD, | ||
193 | &((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].DTD, | ||
194 | sizeof(struct oaktrail_timing_info)); | ||
195 | dev_priv->gct_data.Panel_Port_Control = | ||
196 | ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_Port_Control; | ||
197 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
198 | ((struct oaktrail_gct_v2 *)pGCT)->panel[bpi].Panel_MIPI_Display_Descriptor; | ||
199 | break; | 316 | break; |
200 | case 0x10: | 317 | case 0x10: |
201 | /*header definition changed from rev 01 (v2) to rev 10h. */ | 318 | ret = mid_get_vbt_data_r10(dev_priv, addr); |
202 | /*so, some values have changed location*/ | ||
203 | new_size = vbt->checksum; /*checksum contains lo size byte*/ | ||
204 | /*LSB of oaktrail_gct contains hi size byte*/ | ||
205 | new_size |= ((0xff & (unsigned int)(long)vbt->oaktrail_gct)) << 8; | ||
206 | |||
207 | vbt->checksum = vbt->size; /*size contains the checksum*/ | ||
208 | if (new_size > 0xff) | ||
209 | vbt->size = 0xff; /*restrict size to 255*/ | ||
210 | else | ||
211 | vbt->size = new_size; | ||
212 | |||
213 | /* number of descriptors defined in the GCT */ | ||
214 | number_desc = ((0xff00 & (unsigned int)(long)vbt->oaktrail_gct)) >> 8; | ||
215 | bpi = ((0xff0000 & (unsigned int)(long)vbt->oaktrail_gct)) >> 16; | ||
216 | vbt->oaktrail_gct = ioremap(addr + GCT_R10_HEADER_SIZE, | ||
217 | GCT_R10_DISPLAY_DESC_SIZE * number_desc); | ||
218 | pGCT = vbt->oaktrail_gct; | ||
219 | pGCT = (u8 *)pGCT + (bpi*GCT_R10_DISPLAY_DESC_SIZE); | ||
220 | dev_priv->gct_data.bpi = bpi; /*save boot panel id*/ | ||
221 | |||
222 | /*copy the GCT display timings into a temp structure*/ | ||
223 | memcpy(&ti, pGCT, sizeof(struct gct_r10_timing_info)); | ||
224 | |||
225 | /*now copy the temp struct into the dev_priv->gct_data*/ | ||
226 | dp_ti->pixel_clock = ti.pixel_clock; | ||
227 | dp_ti->hactive_hi = ti.hactive_hi; | ||
228 | dp_ti->hactive_lo = ti.hactive_lo; | ||
229 | dp_ti->hblank_hi = ti.hblank_hi; | ||
230 | dp_ti->hblank_lo = ti.hblank_lo; | ||
231 | dp_ti->hsync_offset_hi = ti.hsync_offset_hi; | ||
232 | dp_ti->hsync_offset_lo = ti.hsync_offset_lo; | ||
233 | dp_ti->hsync_pulse_width_hi = ti.hsync_pulse_width_hi; | ||
234 | dp_ti->hsync_pulse_width_lo = ti.hsync_pulse_width_lo; | ||
235 | dp_ti->vactive_hi = ti.vactive_hi; | ||
236 | dp_ti->vactive_lo = ti.vactive_lo; | ||
237 | dp_ti->vblank_hi = ti.vblank_hi; | ||
238 | dp_ti->vblank_lo = ti.vblank_lo; | ||
239 | dp_ti->vsync_offset_hi = ti.vsync_offset_hi; | ||
240 | dp_ti->vsync_offset_lo = ti.vsync_offset_lo; | ||
241 | dp_ti->vsync_pulse_width_hi = ti.vsync_pulse_width_hi; | ||
242 | dp_ti->vsync_pulse_width_lo = ti.vsync_pulse_width_lo; | ||
243 | |||
244 | /* Move the MIPI_Display_Descriptor data from GCT to dev priv */ | ||
245 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor = | ||
246 | *((u8 *)pGCT + 0x0d); | ||
247 | dev_priv->gct_data.Panel_MIPI_Display_Descriptor |= | ||
248 | (*((u8 *)pGCT + 0x0e)) << 8; | ||
249 | break; | 319 | break; |
250 | default: | 320 | default: |
251 | dev_err(dev->dev, "Unknown revision of GCT!\n"); | 321 | dev_err(dev->dev, "Unknown revision of GCT!\n"); |
252 | vbt->size = 0; | ||
253 | } | 322 | } |
323 | |||
324 | out: | ||
325 | if (ret) | ||
326 | dev_err(dev->dev, "Unable to read GCT!"); | ||
327 | else | ||
328 | dev_priv->has_gct = true; | ||
254 | } | 329 | } |
255 | 330 | ||
256 | int mid_chip_setup(struct drm_device *dev) | 331 | int mid_chip_setup(struct drm_device *dev) |