aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/gma500/oaktrail.h6
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_crtc.c8
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_device.c2
-rw-r--r--drivers/gpu/drm/gma500/oaktrail_hdmi.c365
4 files changed, 365 insertions, 16 deletions
diff --git a/drivers/gpu/drm/gma500/oaktrail.h b/drivers/gpu/drm/gma500/oaktrail.h
index f2f9f38a5362..30adbbe23024 100644
--- a/drivers/gpu/drm/gma500/oaktrail.h
+++ b/drivers/gpu/drm/gma500/oaktrail.h
@@ -249,3 +249,9 @@ extern void oaktrail_hdmi_i2c_exit(struct pci_dev *dev);
249extern void oaktrail_hdmi_save(struct drm_device *dev); 249extern void oaktrail_hdmi_save(struct drm_device *dev);
250extern void oaktrail_hdmi_restore(struct drm_device *dev); 250extern void oaktrail_hdmi_restore(struct drm_device *dev);
251extern void oaktrail_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev); 251extern void oaktrail_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev);
252extern int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc, struct drm_display_mode *mode,
253 struct drm_display_mode *adjusted_mode, int x, int y,
254 struct drm_framebuffer *old_fb);
255extern void oaktrail_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode);
256
257
diff --git a/drivers/gpu/drm/gma500/oaktrail_crtc.c b/drivers/gpu/drm/gma500/oaktrail_crtc.c
index cdafd2acc72f..4ec2962f7635 100644
--- a/drivers/gpu/drm/gma500/oaktrail_crtc.c
+++ b/drivers/gpu/drm/gma500/oaktrail_crtc.c
@@ -168,6 +168,11 @@ static void oaktrail_crtc_dpms(struct drm_crtc *crtc, int mode)
168 const struct psb_offset *map = &dev_priv->regmap[pipe]; 168 const struct psb_offset *map = &dev_priv->regmap[pipe];
169 u32 temp; 169 u32 temp;
170 170
171 if (pipe == 1) {
172 oaktrail_crtc_hdmi_dpms(crtc, mode);
173 return;
174 }
175
171 if (!gma_power_begin(dev, true)) 176 if (!gma_power_begin(dev, true))
172 return; 177 return;
173 178
@@ -302,6 +307,9 @@ static int oaktrail_crtc_mode_set(struct drm_crtc *crtc,
302 uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN; 307 uint64_t scalingType = DRM_MODE_SCALE_FULLSCREEN;
303 struct drm_connector *connector; 308 struct drm_connector *connector;
304 309
310 if (pipe == 1)
311 return oaktrail_crtc_hdmi_mode_set(crtc, mode, adjusted_mode, x, y, old_fb);
312
305 if (!gma_power_begin(dev, true)) 313 if (!gma_power_begin(dev, true))
306 return 0; 314 return 0;
307 315
diff --git a/drivers/gpu/drm/gma500/oaktrail_device.c b/drivers/gpu/drm/gma500/oaktrail_device.c
index 010b820744a5..08747fd7105c 100644
--- a/drivers/gpu/drm/gma500/oaktrail_device.c
+++ b/drivers/gpu/drm/gma500/oaktrail_device.c
@@ -544,7 +544,7 @@ const struct psb_ops oaktrail_chip_ops = {
544 .accel_2d = 1, 544 .accel_2d = 1,
545 .pipes = 2, 545 .pipes = 2,
546 .crtcs = 2, 546 .crtcs = 2,
547 .hdmi_mask = (1 << 0), 547 .hdmi_mask = (1 << 1),
548 .lvds_mask = (1 << 0), 548 .lvds_mask = (1 << 0),
549 .cursor_needs_phys = 0, 549 .cursor_needs_phys = 0,
550 .sgx_offset = MRST_SGX_OFFSET, 550 .sgx_offset = MRST_SGX_OFFSET,
diff --git a/drivers/gpu/drm/gma500/oaktrail_hdmi.c b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
index 69e51e903f35..f036f1fc161e 100644
--- a/drivers/gpu/drm/gma500/oaktrail_hdmi.c
+++ b/drivers/gpu/drm/gma500/oaktrail_hdmi.c
@@ -155,6 +155,345 @@ static void oaktrail_hdmi_audio_disable(struct drm_device *dev)
155 HDMI_READ(HDMI_HCR); 155 HDMI_READ(HDMI_HCR);
156} 156}
157 157
158static void wait_for_vblank(struct drm_device *dev)
159{
160 /* Wait for 20ms, i.e. one cycle at 50hz. */
161 mdelay(20);
162}
163
164static unsigned int htotal_calculate(struct drm_display_mode *mode)
165{
166 u32 htotal, new_crtc_htotal;
167
168 htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16);
169
170 /*
171 * 1024 x 768 new_crtc_htotal = 0x1024;
172 * 1280 x 1024 new_crtc_htotal = 0x0c34;
173 */
174 new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock;
175
176 DRM_DEBUG_KMS("new crtc htotal 0x%4x\n", new_crtc_htotal);
177 return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16);
178}
179
180static void oaktrail_hdmi_find_dpll(struct drm_crtc *crtc, int target,
181 int refclk, struct oaktrail_hdmi_clock *best_clock)
182{
183 int np_min, np_max, nr_min, nr_max;
184 int np, nr, nf;
185
186 np_min = DIV_ROUND_UP(oaktrail_hdmi_limit.vco.min, target * 10);
187 np_max = oaktrail_hdmi_limit.vco.max / (target * 10);
188 if (np_min < oaktrail_hdmi_limit.np.min)
189 np_min = oaktrail_hdmi_limit.np.min;
190 if (np_max > oaktrail_hdmi_limit.np.max)
191 np_max = oaktrail_hdmi_limit.np.max;
192
193 nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max));
194 nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min));
195 if (nr_min < oaktrail_hdmi_limit.nr.min)
196 nr_min = oaktrail_hdmi_limit.nr.min;
197 if (nr_max > oaktrail_hdmi_limit.nr.max)
198 nr_max = oaktrail_hdmi_limit.nr.max;
199
200 np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max));
201 nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np));
202 nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk);
203 DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf);
204
205 /*
206 * 1024 x 768 np = 1; nr = 0x26; nf = 0x0fd8000;
207 * 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000;
208 */
209 best_clock->np = np;
210 best_clock->nr = nr - 1;
211 best_clock->nf = (nf << 14);
212}
213
214static void scu_busy_loop(void __iomem *scu_base)
215{
216 u32 status = 0;
217 u32 loop_count = 0;
218
219 status = readl(scu_base + 0x04);
220 while (status & 1) {
221 udelay(1); /* scu processing time is in few u secods */
222 status = readl(scu_base + 0x04);
223 loop_count++;
224 /* break if scu doesn't reset busy bit after huge retry */
225 if (loop_count > 1000) {
226 DRM_DEBUG_KMS("SCU IPC timed out");
227 return;
228 }
229 }
230}
231
232/*
233 * You don't want to know, you really really don't want to know....
234 *
235 * This is magic. However it's safe magic because of the way the platform
236 * works and it is necessary magic.
237 */
238static void oaktrail_hdmi_reset(struct drm_device *dev)
239{
240 void __iomem *base;
241 unsigned long scu_ipc_mmio = 0xff11c000UL;
242 int scu_len = 1024;
243
244 base = ioremap((resource_size_t)scu_ipc_mmio, scu_len);
245 if (base == NULL) {
246 DRM_ERROR("failed to map scu mmio\n");
247 return;
248 }
249
250 /* scu ipc: assert hdmi controller reset */
251 writel(0xff11d118, base + 0x0c);
252 writel(0x7fffffdf, base + 0x80);
253 writel(0x42005, base + 0x0);
254 scu_busy_loop(base);
255
256 /* scu ipc: de-assert hdmi controller reset */
257 writel(0xff11d118, base + 0x0c);
258 writel(0x7fffffff, base + 0x80);
259 writel(0x42005, base + 0x0);
260 scu_busy_loop(base);
261
262 iounmap(base);
263}
264
265int oaktrail_crtc_hdmi_mode_set(struct drm_crtc *crtc,
266 struct drm_display_mode *mode,
267 struct drm_display_mode *adjusted_mode,
268 int x, int y,
269 struct drm_framebuffer *old_fb)
270{
271 struct drm_device *dev = crtc->dev;
272 struct drm_psb_private *dev_priv = dev->dev_private;
273 struct oaktrail_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
274 int pipe = 1;
275 int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
276 int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
277 int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
278 int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
279 int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
280 int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
281 int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
282 int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
283 int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
284 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
285 int refclk;
286 struct oaktrail_hdmi_clock clock;
287 u32 dspcntr, pipeconf, dpll, temp;
288 int dspcntr_reg = DSPBCNTR;
289
290 if (!gma_power_begin(dev, true))
291 return 0;
292
293 /* Disable the VGA plane that we never use */
294 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
295
296 /* Disable dpll if necessary */
297 dpll = REG_READ(DPLL_CTRL);
298 if ((dpll & DPLL_PWRDN) == 0) {
299 REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET));
300 REG_WRITE(DPLL_DIV_CTRL, 0x00000000);
301 REG_WRITE(DPLL_STATUS, 0x1);
302 }
303 udelay(150);
304
305 /* Reset controller */
306 oaktrail_hdmi_reset(dev);
307
308 /* program and enable dpll */
309 refclk = 25000;
310 oaktrail_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock);
311
312 /* Set the DPLL */
313 dpll = REG_READ(DPLL_CTRL);
314 dpll &= ~DPLL_PDIV_MASK;
315 dpll &= ~(DPLL_PWRDN | DPLL_RESET);
316 REG_WRITE(DPLL_CTRL, 0x00000008);
317 REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr));
318 REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1));
319 REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN));
320 REG_WRITE(DPLL_UPDATE, 0x80000000);
321 REG_WRITE(DPLL_CLK_ENABLE, 0x80050102);
322 udelay(150);
323
324 /* configure HDMI */
325 HDMI_WRITE(0x1004, 0x1fd);
326 HDMI_WRITE(0x2000, 0x1);
327 HDMI_WRITE(0x2008, 0x0);
328 HDMI_WRITE(0x3130, 0x8);
329 HDMI_WRITE(0x101c, 0x1800810);
330
331 temp = htotal_calculate(adjusted_mode);
332 REG_WRITE(htot_reg, temp);
333 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
334 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
335 REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
336 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
337 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
338 REG_WRITE(pipesrc_reg, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
339
340 REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16));
341 REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
342 REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
343 REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
344 REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
345 REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
346 REG_WRITE(PCH_PIPEBSRC, ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
347
348 temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
349 HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) | temp);
350
351 REG_WRITE(dspsize_reg, ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
352 REG_WRITE(dsppos_reg, 0);
353
354 /* Flush the plane changes */
355 {
356 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
357 crtc_funcs->mode_set_base(crtc, x, y, old_fb);
358 }
359
360 /* Set up the display plane register */
361 dspcntr = REG_READ(dspcntr_reg);
362 dspcntr |= DISPPLANE_GAMMA_ENABLE;
363 dspcntr |= DISPPLANE_SEL_PIPE_B;
364 dspcntr |= DISPLAY_PLANE_ENABLE;
365
366 /* setup pipeconf */
367 pipeconf = REG_READ(pipeconf_reg);
368 pipeconf |= PIPEACONF_ENABLE;
369
370 REG_WRITE(pipeconf_reg, pipeconf);
371 REG_READ(pipeconf_reg);
372
373 REG_WRITE(PCH_PIPEBCONF, pipeconf);
374 REG_READ(PCH_PIPEBCONF);
375 wait_for_vblank(dev);
376
377 REG_WRITE(dspcntr_reg, dspcntr);
378 wait_for_vblank(dev);
379
380 gma_power_end(dev);
381
382 return 0;
383}
384
385void oaktrail_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode)
386{
387 struct drm_device *dev = crtc->dev;
388 u32 temp;
389
390 DRM_DEBUG_KMS("%s %d\n", __func__, mode);
391
392 switch (mode) {
393 case DRM_MODE_DPMS_OFF:
394 REG_WRITE(VGACNTRL, 0x80000000);
395
396 /* Disable plane */
397 temp = REG_READ(DSPBCNTR);
398 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
399 REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
400 REG_READ(DSPBCNTR);
401 /* Flush the plane changes */
402 REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
403 REG_READ(DSPBSURF);
404 }
405
406 /* Disable pipe B */
407 temp = REG_READ(PIPEBCONF);
408 if ((temp & PIPEACONF_ENABLE) != 0) {
409 REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE);
410 REG_READ(PIPEBCONF);
411 }
412
413 /* Disable LNW Pipes, etc */
414 temp = REG_READ(PCH_PIPEBCONF);
415 if ((temp & PIPEACONF_ENABLE) != 0) {
416 REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE);
417 REG_READ(PCH_PIPEBCONF);
418 }
419
420 /* wait for pipe off */
421 udelay(150);
422
423 /* Disable dpll */
424 temp = REG_READ(DPLL_CTRL);
425 if ((temp & DPLL_PWRDN) == 0) {
426 REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET));
427 REG_WRITE(DPLL_STATUS, 0x1);
428 }
429
430 /* wait for dpll off */
431 udelay(150);
432
433 break;
434 case DRM_MODE_DPMS_ON:
435 case DRM_MODE_DPMS_STANDBY:
436 case DRM_MODE_DPMS_SUSPEND:
437 /* Enable dpll */
438 temp = REG_READ(DPLL_CTRL);
439 if ((temp & DPLL_PWRDN) != 0) {
440 REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET));
441 temp = REG_READ(DPLL_CLK_ENABLE);
442 REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI);
443 REG_READ(DPLL_CLK_ENABLE);
444 }
445 /* wait for dpll warm up */
446 udelay(150);
447
448 /* Enable pipe B */
449 temp = REG_READ(PIPEBCONF);
450 if ((temp & PIPEACONF_ENABLE) == 0) {
451 REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE);
452 REG_READ(PIPEBCONF);
453 }
454
455 /* Enable LNW Pipe B */
456 temp = REG_READ(PCH_PIPEBCONF);
457 if ((temp & PIPEACONF_ENABLE) == 0) {
458 REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE);
459 REG_READ(PCH_PIPEBCONF);
460 }
461
462 wait_for_vblank(dev);
463
464 /* Enable plane */
465 temp = REG_READ(DSPBCNTR);
466 if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
467 REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
468 /* Flush the plane changes */
469 REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
470 REG_READ(DSPBSURF);
471 }
472
473 psb_intel_crtc_load_lut(crtc);
474 }
475
476 /* DSPARB */
477 REG_WRITE(DSPARB, 0x00003fbf);
478
479 /* FW1 */
480 REG_WRITE(0x70034, 0x3f880a0a);
481
482 /* FW2 */
483 REG_WRITE(0x70038, 0x0b060808);
484
485 /* FW4 */
486 REG_WRITE(0x70050, 0x08030404);
487
488 /* FW5 */
489 REG_WRITE(0x70054, 0x04040404);
490
491 /* LNC Chicken Bits - Squawk! */
492 REG_WRITE(0x70400, 0x4000);
493
494 return;
495}
496
158static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode) 497static void oaktrail_hdmi_dpms(struct drm_encoder *encoder, int mode)
159{ 498{
160 static int dpms_mode = -1; 499 static int dpms_mode = -1;
@@ -233,13 +572,15 @@ static const unsigned char raw_edid[] = {
233 572
234static int oaktrail_hdmi_get_modes(struct drm_connector *connector) 573static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
235{ 574{
236 struct drm_device *dev = connector->dev;
237 struct drm_psb_private *dev_priv = dev->dev_private;
238 struct i2c_adapter *i2c_adap; 575 struct i2c_adapter *i2c_adap;
239 struct edid *edid; 576 struct edid *edid;
240 struct drm_display_mode *mode, *t; 577 int ret = 0;
241 int i = 0, ret = 0;
242 578
579 /*
580 * FIXME: We need to figure this lot out. In theory we can
581 * read the EDID somehow but I've yet to find working reference
582 * code.
583 */
243 i2c_adap = i2c_get_adapter(3); 584 i2c_adap = i2c_get_adapter(3);
244 if (i2c_adap == NULL) { 585 if (i2c_adap == NULL) {
245 DRM_ERROR("No ddc adapter available!\n"); 586 DRM_ERROR("No ddc adapter available!\n");
@@ -253,17 +594,7 @@ static int oaktrail_hdmi_get_modes(struct drm_connector *connector)
253 drm_mode_connector_update_edid_property(connector, edid); 594 drm_mode_connector_update_edid_property(connector, edid);
254 ret = drm_add_edid_modes(connector, edid); 595 ret = drm_add_edid_modes(connector, edid);
255 } 596 }
256 597 return ret;
257 /*
258 * prune modes that require frame buffer bigger than stolen mem
259 */
260 list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
261 if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) {
262 i++;
263 drm_mode_remove(connector, mode);
264 }
265 }
266 return ret - i;
267} 598}
268 599
269static void oaktrail_hdmi_mode_set(struct drm_encoder *encoder, 600static void oaktrail_hdmi_mode_set(struct drm_encoder *encoder,
@@ -349,6 +680,7 @@ void oaktrail_hdmi_init(struct drm_device *dev,
349 connector->interlace_allowed = false; 680 connector->interlace_allowed = false;
350 connector->doublescan_allowed = false; 681 connector->doublescan_allowed = false;
351 drm_sysfs_connector_add(connector); 682 drm_sysfs_connector_add(connector);
683 dev_info(dev->dev, "HDMI initialised.\n");
352 684
353 return; 685 return;
354 686
@@ -403,6 +735,9 @@ void oaktrail_hdmi_setup(struct drm_device *dev)
403 735
404 dev_priv->hdmi_priv = hdmi_dev; 736 dev_priv->hdmi_priv = hdmi_dev;
405 oaktrail_hdmi_audio_disable(dev); 737 oaktrail_hdmi_audio_disable(dev);
738
739 dev_info(dev->dev, "HDMI hardware present.\n");
740
406 return; 741 return;
407 742
408free: 743free: