aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2011-07-15 12:34:41 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2011-07-15 13:05:08 -0400
commit1e585b52fd8ea59792634bc31d227eb3456af22e (patch)
treeb291fd77abd0622ec9a671158b8ef979ca233f2d
parent80e2f055e05b62d1132eadc934f83c6d81c7cfa4 (diff)
gma500: Add the Oaktrail HDMI support
This differs enough from the Cedarview HDMI sufficiently to want to keep them separated. We need to sort out the power management for Oaktrail/Moorestown in order to plumb this lot into the register handling logic. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/staging/gma500/Makefile4
-rw-r--r--drivers/staging/gma500/mrst.h35
-rw-r--r--drivers/staging/gma500/mrst_device.c246
-rw-r--r--drivers/staging/gma500/mrst_hdmi.c852
-rw-r--r--drivers/staging/gma500/mrst_hdmi_i2c.c327
-rw-r--r--drivers/staging/gma500/psb_drv.c2
-rw-r--r--drivers/staging/gma500/psb_drv.h4
7 files changed, 1401 insertions, 69 deletions
diff --git a/drivers/staging/gma500/Makefile b/drivers/staging/gma500/Makefile
index e515edfb1d27..fe34f1831415 100644
--- a/drivers/staging/gma500/Makefile
+++ b/drivers/staging/gma500/Makefile
@@ -32,7 +32,9 @@ psb_gfx-$(CONFIG_DRM_PSB_CDV) += cdv_device.o \
32 32
33psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \ 33psb_gfx-$(CONFIG_DRM_PSB_MRST) += mrst_device.o \
34 mrst_crtc.o \ 34 mrst_crtc.o \
35 mrst_lvds.o 35 mrst_lvds.o \
36 mrst_hdmi.o \
37 mrst_hdmi_i2c.o
36 38
37psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \ 39psb_gfx-$(CONFIG_DRM_PSB_MFLD) += mdfld_device.o \
38 mdfld_output.o \ 40 mdfld_output.o \
diff --git a/drivers/staging/gma500/mrst.h b/drivers/staging/gma500/mrst.h
index 7bacb9a0083a..b563dbc73104 100644
--- a/drivers/staging/gma500/mrst.h
+++ b/drivers/staging/gma500/mrst.h
@@ -215,3 +215,38 @@ struct mrst_gct_data {
215 215
216#define GCT_R10_HEADER_SIZE 16 216#define GCT_R10_HEADER_SIZE 16
217#define GCT_R10_DISPLAY_DESC_SIZE 28 217#define GCT_R10_DISPLAY_DESC_SIZE 28
218
219/*
220 * Moorestown HDMI interfaces
221 */
222
223struct mrst_hdmi_dev {
224 struct pci_dev *dev;
225 void __iomem *regs;
226 unsigned int mmio, mmio_len;
227 int dpms_mode;
228 struct hdmi_i2c_dev *i2c_dev;
229
230 /* register state */
231 u32 saveDPLL_CTRL;
232 u32 saveDPLL_DIV_CTRL;
233 u32 saveDPLL_ADJUST;
234 u32 saveDPLL_UPDATE;
235 u32 saveDPLL_CLK_ENABLE;
236 u32 savePCH_HTOTAL_B;
237 u32 savePCH_HBLANK_B;
238 u32 savePCH_HSYNC_B;
239 u32 savePCH_VTOTAL_B;
240 u32 savePCH_VBLANK_B;
241 u32 savePCH_VSYNC_B;
242 u32 savePCH_PIPEBCONF;
243 u32 savePCH_PIPEBSRC;
244};
245
246extern void mrst_hdmi_setup(struct drm_device *dev);
247extern void mrst_hdmi_teardown(struct drm_device *dev);
248extern int mrst_hdmi_i2c_init(struct pci_dev *dev);
249extern void mrst_hdmi_i2c_exit(struct pci_dev *dev);
250extern void mrst_hdmi_save(struct drm_device *dev);
251extern void mrst_hdmi_restore(struct drm_device *dev);
252extern void mrst_hdmi_init(struct drm_device *dev, struct psb_intel_mode_device *mode_dev);
diff --git a/drivers/staging/gma500/mrst_device.c b/drivers/staging/gma500/mrst_device.c
index 3d525a032135..20677f9a2bde 100644
--- a/drivers/staging/gma500/mrst_device.c
+++ b/drivers/staging/gma500/mrst_device.c
@@ -38,12 +38,13 @@ static const struct psb_ops oaktrail_chip_ops;
38static int mrst_output_init(struct drm_device *dev) 38static int mrst_output_init(struct drm_device *dev)
39{ 39{
40 struct drm_psb_private *dev_priv = dev->dev_private; 40 struct drm_psb_private *dev_priv = dev->dev_private;
41 if (dev_priv->iLVDS_enable) { 41 if (dev_priv->iLVDS_enable)
42 mrst_lvds_init(dev, &dev_priv->mode_dev); 42 mrst_lvds_init(dev, &dev_priv->mode_dev);
43 return 0; 43 else
44 } 44 dev_err(dev->dev, "DSI is not supported\n");
45 dev_err(dev->dev, "DSI is not supported\n"); 45 if (dev_priv->hdmi_priv)
46 return -ENODEV; 46 mrst_hdmi_init(dev, &dev_priv->mode_dev);
47 return 0;
47} 48}
48 49
49/* 50/*
@@ -195,8 +196,8 @@ static void mrst_init_pm(struct drm_device *dev)
195static int mrst_save_display_registers(struct drm_device *dev) 196static int mrst_save_display_registers(struct drm_device *dev)
196{ 197{
197 struct drm_psb_private *dev_priv = dev->dev_private; 198 struct drm_psb_private *dev_priv = dev->dev_private;
198 struct drm_crtc *crtc; 199 int i;
199 struct drm_connector *connector; 200 u32 pp_stat;
200 201
201 /* Display arbitration control + watermarks */ 202 /* Display arbitration control + watermarks */
202 dev_priv->saveDSPARB = PSB_RVDC32(DSPARB); 203 dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
@@ -208,17 +209,91 @@ static int mrst_save_display_registers(struct drm_device *dev)
208 dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6); 209 dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
209 dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT); 210 dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
210 211
211 /* Save crtc and output state */ 212 /* Pipe & plane A info */
212 mutex_lock(&dev->mode_config.mutex); 213 dev_priv->savePIPEACONF = PSB_RVDC32(PIPEACONF);
213 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 214 dev_priv->savePIPEASRC = PSB_RVDC32(PIPEASRC);
214 if (drm_helper_crtc_in_use(crtc)) 215 dev_priv->saveFPA0 = PSB_RVDC32(MRST_FPA0);
215 crtc->funcs->save(crtc); 216 dev_priv->saveFPA1 = PSB_RVDC32(MRST_FPA1);
216 } 217 dev_priv->saveDPLL_A = PSB_RVDC32(MRST_DPLL_A);
218 dev_priv->saveHTOTAL_A = PSB_RVDC32(HTOTAL_A);
219 dev_priv->saveHBLANK_A = PSB_RVDC32(HBLANK_A);
220 dev_priv->saveHSYNC_A = PSB_RVDC32(HSYNC_A);
221 dev_priv->saveVTOTAL_A = PSB_RVDC32(VTOTAL_A);
222 dev_priv->saveVBLANK_A = PSB_RVDC32(VBLANK_A);
223 dev_priv->saveVSYNC_A = PSB_RVDC32(VSYNC_A);
224 dev_priv->saveBCLRPAT_A = PSB_RVDC32(BCLRPAT_A);
225 dev_priv->saveDSPACNTR = PSB_RVDC32(DSPACNTR);
226 dev_priv->saveDSPASTRIDE = PSB_RVDC32(DSPASTRIDE);
227 dev_priv->saveDSPAADDR = PSB_RVDC32(DSPABASE);
228 dev_priv->saveDSPASURF = PSB_RVDC32(DSPASURF);
229 dev_priv->saveDSPALINOFF = PSB_RVDC32(DSPALINOFF);
230 dev_priv->saveDSPATILEOFF = PSB_RVDC32(DSPATILEOFF);
231
232 /* Save cursor regs */
233 dev_priv->saveDSPACURSOR_CTRL = PSB_RVDC32(CURACNTR);
234 dev_priv->saveDSPACURSOR_BASE = PSB_RVDC32(CURABASE);
235 dev_priv->saveDSPACURSOR_POS = PSB_RVDC32(CURAPOS);
236
237 /* Save palette (gamma) */
238 for (i = 0; i < 256; i++)
239 dev_priv->save_palette_a[i] = PSB_RVDC32(PALETTE_A + (i << 2));
240
241 if (dev_priv->hdmi_priv)
242 mrst_hdmi_save(dev);
243
244 /* Save performance state */
245 dev_priv->savePERF_MODE = PSB_RVDC32(MRST_PERF_MODE);
246
247 /* LVDS state */
248 dev_priv->savePP_CONTROL = PSB_RVDC32(PP_CONTROL);
249 dev_priv->savePFIT_PGM_RATIOS = PSB_RVDC32(PFIT_PGM_RATIOS);
250 dev_priv->savePFIT_AUTO_RATIOS = PSB_RVDC32(PFIT_AUTO_RATIOS);
251 dev_priv->saveBLC_PWM_CTL = PSB_RVDC32(BLC_PWM_CTL);
252 dev_priv->saveBLC_PWM_CTL2 = PSB_RVDC32(BLC_PWM_CTL2);
253 dev_priv->saveLVDS = PSB_RVDC32(LVDS);
254 dev_priv->savePFIT_CONTROL = PSB_RVDC32(PFIT_CONTROL);
255 dev_priv->savePP_ON_DELAYS = PSB_RVDC32(LVDSPP_ON);
256 dev_priv->savePP_OFF_DELAYS = PSB_RVDC32(LVDSPP_OFF);
257 dev_priv->savePP_DIVISOR = PSB_RVDC32(PP_CYCLE);
258
259 /* HW overlay */
260 dev_priv->saveOV_OVADD = PSB_RVDC32(OV_OVADD);
261 dev_priv->saveOV_OGAMC0 = PSB_RVDC32(OV_OGAMC0);
262 dev_priv->saveOV_OGAMC1 = PSB_RVDC32(OV_OGAMC1);
263 dev_priv->saveOV_OGAMC2 = PSB_RVDC32(OV_OGAMC2);
264 dev_priv->saveOV_OGAMC3 = PSB_RVDC32(OV_OGAMC3);
265 dev_priv->saveOV_OGAMC4 = PSB_RVDC32(OV_OGAMC4);
266 dev_priv->saveOV_OGAMC5 = PSB_RVDC32(OV_OGAMC5);
267
268 /* DPST registers */
269 dev_priv->saveHISTOGRAM_INT_CONTROL_REG = PSB_RVDC32(HISTOGRAM_INT_CONTROL);
270 dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG = PSB_RVDC32(HISTOGRAM_LOGIC_CONTROL);
271 dev_priv->savePWM_CONTROL_LOGIC = PSB_RVDC32(PWM_CONTROL_LOGIC);
272
273 if (dev_priv->iLVDS_enable) {
274 /* Shut down the panel */
275 PSB_WVDC32(0, PP_CONTROL);
217 276
218 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 277 do {
219 connector->funcs->save(connector); 278 pp_stat = PSB_RVDC32(PP_STATUS);
279 } while (pp_stat & 0x80000000);
220 280
221 mutex_unlock(&dev->mode_config.mutex); 281 /* Turn off the plane */
282 PSB_WVDC32(0x58000000, DSPACNTR);
283 /* Trigger the plane disable */
284 PSB_WVDC32(0, DSPASURF);
285
286 /* Wait ~4 ticks */
287 msleep(4);
288
289 /* Turn off pipe */
290 PSB_WVDC32(0x0, PIPEACONF);
291 /* Wait ~8 ticks */
292 msleep(8);
293
294 /* Turn off PLLs */
295 PSB_WVDC32(0, MRST_DPLL_A);
296 }
222 return 0; 297 return 0;
223} 298}
224 299
@@ -231,18 +306,8 @@ static int mrst_save_display_registers(struct drm_device *dev)
231static int mrst_restore_display_registers(struct drm_device *dev) 306static int mrst_restore_display_registers(struct drm_device *dev)
232{ 307{
233 struct drm_psb_private *dev_priv = dev->dev_private; 308 struct drm_psb_private *dev_priv = dev->dev_private;
234 struct drm_crtc *crtc; 309 u32 pp_stat;
235 struct drm_connector *connector; 310 int i;
236 int pp_stat;
237
238 if (!dev_priv->iLVDS_enable) {
239#ifdef CONFIG_X86_MRST
240 intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
241 IPC_CMD_PANEL_ON);
242 /* FIXME: can we avoid this delay ? */
243 msleep(2000); /* wait 2 seconds */
244#endif
245 }
246 311
247 /* Display arbitration + watermarks */ 312 /* Display arbitration + watermarks */
248 PSB_WVDC32(dev_priv->saveDSPARB, DSPARB); 313 PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
@@ -254,54 +319,92 @@ static int mrst_restore_display_registers(struct drm_device *dev)
254 PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6); 319 PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
255 PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT); 320 PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
256 321
257 /*make sure VGA plane is off. it initializes to on after reset!*/ 322 /* Make sure VGA plane is off. it initializes to on after reset!*/
258 PSB_WVDC32(0x80000000, VGACNTRL); 323 PSB_WVDC32(0x80000000, VGACNTRL);
259 324
260 mutex_lock(&dev->mode_config.mutex); 325 /* set the plls */
261 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) 326 PSB_WVDC32(dev_priv->saveFPA0, MRST_FPA0);
262 if (drm_helper_crtc_in_use(crtc)) 327 PSB_WVDC32(dev_priv->saveFPA1, MRST_FPA1);
263 crtc->funcs->restore(crtc);
264 328
265 list_for_each_entry(connector, &dev->mode_config.connector_list, head) 329 /* Actually enable it */
266 connector->funcs->restore(connector); 330 PSB_WVDC32(dev_priv->saveDPLL_A, MRST_DPLL_A);
331 DRM_UDELAY(150);
267 332
268 mutex_unlock(&dev->mode_config.mutex); 333 /* Restore mode */
334 PSB_WVDC32(dev_priv->saveHTOTAL_A, HTOTAL_A);
335 PSB_WVDC32(dev_priv->saveHBLANK_A, HBLANK_A);
336 PSB_WVDC32(dev_priv->saveHSYNC_A, HSYNC_A);
337 PSB_WVDC32(dev_priv->saveVTOTAL_A, VTOTAL_A);
338 PSB_WVDC32(dev_priv->saveVBLANK_A, VBLANK_A);
339 PSB_WVDC32(dev_priv->saveVSYNC_A, VSYNC_A);
340 PSB_WVDC32(dev_priv->savePIPEASRC, PIPEASRC);
341 PSB_WVDC32(dev_priv->saveBCLRPAT_A, BCLRPAT_A);
269 342
270 if (dev_priv->iLVDS_enable) { 343 /* Restore performance mode*/
271 /*shutdown the panel*/ 344 PSB_WVDC32(dev_priv->savePERF_MODE, MRST_PERF_MODE);
272 PSB_WVDC32(0, PP_CONTROL);
273 do {
274 pp_stat = PSB_RVDC32(PP_STATUS);
275 } while (pp_stat & 0x80000000);
276 345
277 /* Turn off the plane */ 346 /* Enable the pipe*/
278 PSB_WVDC32(0x58000000, DSPACNTR); 347 if (dev_priv->iLVDS_enable)
279 PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/ 348 PSB_WVDC32(dev_priv->savePIPEACONF, PIPEACONF);
280 /* Wait ~4 ticks */
281 msleep(4);
282 /* Turn off pipe */
283 PSB_WVDC32(0x0, PIPEACONF);
284 /* Wait ~8 ticks */
285 msleep(8);
286 349
287 /* Turn off PLLs */ 350 /* Set up the plane*/
288 PSB_WVDC32(0, MRST_DPLL_A); 351 PSB_WVDC32(dev_priv->saveDSPALINOFF, DSPALINOFF);
289 } else { 352 PSB_WVDC32(dev_priv->saveDSPASTRIDE, DSPASTRIDE);
290 PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG); 353 PSB_WVDC32(dev_priv->saveDSPATILEOFF, DSPATILEOFF);
291 PSB_WVDC32(0x0, PIPEACONF); 354
292 PSB_WVDC32(0x2faf0000, BLC_PWM_CTL); 355 /* Enable the plane */
293 while (REG_READ(0x70008) & 0x40000000) 356 PSB_WVDC32(dev_priv->saveDSPACNTR, DSPACNTR);
294 cpu_relax(); 357 PSB_WVDC32(dev_priv->saveDSPASURF, DSPASURF);
295 while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY) 358
296 != DPI_FIFO_EMPTY) 359 /* Enable Cursor A */
297 cpu_relax(); 360 PSB_WVDC32(dev_priv->saveDSPACURSOR_CTRL, CURACNTR);
298 PSB_WVDC32(0, DEVICE_READY_REG); 361 PSB_WVDC32(dev_priv->saveDSPACURSOR_POS, CURAPOS);
299 /* Turn off panel power */ 362 PSB_WVDC32(dev_priv->saveDSPACURSOR_BASE, CURABASE);
300#ifdef CONFIG_X86_MRST /* FIXME: kill define once modular */ 363
301 intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF, 364 /* Restore palette (gamma) */
302 IPC_CMD_PANEL_OFF); 365 for (i = 0; i < 256; i++)
303#endif 366 PSB_WVDC32(dev_priv->save_palette_a[i], PALETTE_A + (i << 2));
367
368 if (dev_priv->hdmi_priv)
369 mrst_hdmi_restore(dev);
370
371 if (dev_priv->iLVDS_enable) {
372 PSB_WVDC32(dev_priv->saveBLC_PWM_CTL2, BLC_PWM_CTL2);
373 PSB_WVDC32(dev_priv->saveLVDS, LVDS); /*port 61180h*/
374 PSB_WVDC32(dev_priv->savePFIT_CONTROL, PFIT_CONTROL);
375 PSB_WVDC32(dev_priv->savePFIT_PGM_RATIOS, PFIT_PGM_RATIOS);
376 PSB_WVDC32(dev_priv->savePFIT_AUTO_RATIOS, PFIT_AUTO_RATIOS);
377 PSB_WVDC32(dev_priv->saveBLC_PWM_CTL, BLC_PWM_CTL);
378 PSB_WVDC32(dev_priv->savePP_ON_DELAYS, LVDSPP_ON);
379 PSB_WVDC32(dev_priv->savePP_OFF_DELAYS, LVDSPP_OFF);
380 PSB_WVDC32(dev_priv->savePP_DIVISOR, PP_CYCLE);
381 PSB_WVDC32(dev_priv->savePP_CONTROL, PP_CONTROL);
304 } 382 }
383
384 /* Wait for cycle delay */
385 do {
386 pp_stat = PSB_RVDC32(PP_STATUS);
387 } while (pp_stat & 0x08000000);
388
389 /* Wait for panel power up */
390 do {
391 pp_stat = PSB_RVDC32(PP_STATUS);
392 } while (pp_stat & 0x10000000);
393
394 /* Restore HW overlay */
395 PSB_WVDC32(dev_priv->saveOV_OVADD, OV_OVADD);
396 PSB_WVDC32(dev_priv->saveOV_OGAMC0, OV_OGAMC0);
397 PSB_WVDC32(dev_priv->saveOV_OGAMC1, OV_OGAMC1);
398 PSB_WVDC32(dev_priv->saveOV_OGAMC2, OV_OGAMC2);
399 PSB_WVDC32(dev_priv->saveOV_OGAMC3, OV_OGAMC3);
400 PSB_WVDC32(dev_priv->saveOV_OGAMC4, OV_OGAMC4);
401 PSB_WVDC32(dev_priv->saveOV_OGAMC5, OV_OGAMC5);
402
403 /* DPST registers */
404 PSB_WVDC32(dev_priv->saveHISTOGRAM_INT_CONTROL_REG, HISTOGRAM_INT_CONTROL);
405 PSB_WVDC32(dev_priv->saveHISTOGRAM_LOGIC_CONTROL_REG, HISTOGRAM_LOGIC_CONTROL);
406 PSB_WVDC32(dev_priv->savePWM_CONTROL_LOGIC, PWM_CONTROL_LOGIC);
407
305 return 0; 408 return 0;
306} 409}
307 410
@@ -364,9 +467,15 @@ static int mrst_chip_setup(struct drm_device *dev)
364 return mid_chip_setup(dev); 467 return mid_chip_setup(dev);
365#endif 468#endif
366 dev_priv->ops = &oaktrail_chip_ops; 469 dev_priv->ops = &oaktrail_chip_ops;
470 mrst_hdmi_setup(dev);
367 /* Check - may be better to go via BIOS paths ? */ 471 /* Check - may be better to go via BIOS paths ? */
368 return mid_chip_setup(dev); 472 return mid_chip_setup(dev);
369} 473}
474
475static void oaktrail_teardown(struct drm_device *dev)
476{
477 mrst_hdmi_teardown(dev);
478}
370 479
371const struct psb_ops mrst_chip_ops = { 480const struct psb_ops mrst_chip_ops = {
372 .name = "Moorestown", 481 .name = "Moorestown",
@@ -400,6 +509,7 @@ static const struct psb_ops oaktrail_chip_ops = {
400 .sgx_offset = MRST_SGX_OFFSET, 509 .sgx_offset = MRST_SGX_OFFSET,
401 510
402 .chip_setup = mid_chip_setup, 511 .chip_setup = mid_chip_setup,
512 .chip_teardown = oaktrail_teardown,
403 .crtc_helper = &mrst_helper_funcs, 513 .crtc_helper = &mrst_helper_funcs,
404 .crtc_funcs = &psb_intel_crtc_funcs, 514 .crtc_funcs = &psb_intel_crtc_funcs,
405 515
diff --git a/drivers/staging/gma500/mrst_hdmi.c b/drivers/staging/gma500/mrst_hdmi.c
new file mode 100644
index 000000000000..d6a517971ba8
--- /dev/null
+++ b/drivers/staging/gma500/mrst_hdmi.c
@@ -0,0 +1,852 @@
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 * Authors:
24 * Li Peng <peng.li@intel.com>
25 */
26
27#include <drm/drmP.h>
28#include <drm/drm.h>
29#include "psb_intel_drv.h"
30#include "psb_intel_reg.h"
31#include "psb_drv.h"
32
33#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))
34#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg))
35
36#define HDMI_HCR 0x1000
37#define HCR_ENABLE_HDCP (1 << 5)
38#define HCR_ENABLE_AUDIO (1 << 2)
39#define HCR_ENABLE_PIXEL (1 << 1)
40#define HCR_ENABLE_TMDS (1 << 0)
41
42#define HDMI_HICR 0x1004
43#define HDMI_HSR 0x1008
44#define HDMI_HISR 0x100C
45#define HDMI_DETECT_HDP (1 << 0)
46
47#define HDMI_VIDEO_REG 0x3000
48#define HDMI_UNIT_EN (1 << 7)
49#define HDMI_MODE_OUTPUT (1 << 0)
50#define HDMI_HBLANK_A 0x3100
51
52#define HDMI_AUDIO_CTRL 0x4000
53#define HDMI_ENABLE_AUDIO (1 << 0)
54
55#define PCH_HTOTAL_B 0x3100
56#define PCH_HBLANK_B 0x3104
57#define PCH_HSYNC_B 0x3108
58#define PCH_VTOTAL_B 0x310C
59#define PCH_VBLANK_B 0x3110
60#define PCH_VSYNC_B 0x3114
61#define PCH_PIPEBSRC 0x311C
62
63#define PCH_PIPEB_DSL 0x3800
64#define PCH_PIPEB_SLC 0x3804
65#define PCH_PIPEBCONF 0x3808
66#define PCH_PIPEBSTAT 0x3824
67
68#define CDVO_DFT 0x5000
69#define CDVO_SLEWRATE 0x5004
70#define CDVO_STRENGTH 0x5008
71#define CDVO_RCOMP 0x500C
72
73#define DPLL_CTRL 0x6000
74#define DPLL_PDIV_SHIFT 16
75#define DPLL_PDIV_MASK (0xf << 16)
76#define DPLL_PWRDN (1 << 4)
77#define DPLL_RESET (1 << 3)
78#define DPLL_FASTEN (1 << 2)
79#define DPLL_ENSTAT (1 << 1)
80#define DPLL_DITHEN (1 << 0)
81
82#define DPLL_DIV_CTRL 0x6004
83#define DPLL_CLKF_MASK 0xffffffc0
84#define DPLL_CLKR_MASK (0x3f)
85
86#define DPLL_CLK_ENABLE 0x6008
87#define DPLL_EN_DISP (1 << 31)
88#define DPLL_SEL_HDMI (1 << 8)
89#define DPLL_EN_HDMI (1 << 1)
90#define DPLL_EN_VGA (1 << 0)
91
92#define DPLL_ADJUST 0x600C
93#define DPLL_STATUS 0x6010
94#define DPLL_UPDATE 0x6014
95#define DPLL_DFT 0x6020
96
97struct intel_range {
98 int min, max;
99};
100
101struct mrst_hdmi_limit {
102 struct intel_range vco, np, nr, nf;
103};
104
105struct mrst_hdmi_clock {
106 int np;
107 int nr;
108 int nf;
109 int dot;
110};
111
112#define VCO_MIN 320000
113#define VCO_MAX 1650000
114#define NP_MIN 1
115#define NP_MAX 15
116#define NR_MIN 1
117#define NR_MAX 64
118#define NF_MIN 2
119#define NF_MAX 4095
120
121static const struct mrst_hdmi_limit mrst_hdmi_limit = {
122 .vco = { .min = VCO_MIN, .max = VCO_MAX },
123 .np = { .min = NP_MIN, .max = NP_MAX },
124 .nr = { .min = NR_MIN, .max = NR_MAX },
125 .nf = { .min = NF_MIN, .max = NF_MAX },
126};
127
128static void wait_for_vblank(struct drm_device *dev)
129{
130 /* FIXME: Can we do this as a sleep ? */
131 /* Wait for 20ms, i.e. one cycle at 50hz. */
132 udelay(20000);
133}
134
135static void scu_busy_loop(void *scu_base)
136{
137 u32 status = 0;
138 u32 loop_count = 0;
139
140 status = readl(scu_base + 0x04);
141 while (status & 1) {
142 udelay(1); /* scu processing time is in few u secods */
143 status = readl(scu_base + 0x04);
144 loop_count++;
145 /* break if scu doesn't reset busy bit after huge retry */
146 if (loop_count > 1000) {
147 DRM_DEBUG_KMS("SCU IPC timed out");
148 return;
149 }
150 }
151}
152
153static void mrst_hdmi_reset(struct drm_device *dev)
154{
155 void *base;
156 /* FIXME: at least make these defines */
157 unsigned int scu_ipc_mmio = 0xff11c000;
158 int scu_len = 1024;
159
160 base = ioremap((resource_size_t)scu_ipc_mmio, scu_len);
161 if (base == NULL) {
162 DRM_ERROR("failed to map SCU mmio\n");
163 return;
164 }
165
166 /* scu ipc: assert hdmi controller reset */
167 writel(0xff11d118, base + 0x0c);
168 writel(0x7fffffdf, base + 0x80);
169 writel(0x42005, base + 0x0);
170 scu_busy_loop(base);
171
172 /* scu ipc: de-assert hdmi controller reset */
173 writel(0xff11d118, base + 0x0c);
174 writel(0x7fffffff, base + 0x80);
175 writel(0x42005, base + 0x0);
176 scu_busy_loop(base);
177
178 iounmap(base);
179}
180
181static void mrst_hdmi_audio_enable(struct drm_device *dev)
182{
183 struct drm_psb_private *dev_priv = dev->dev_private;
184 struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
185
186 HDMI_WRITE(HDMI_HCR, 0x67);
187 HDMI_READ(HDMI_HCR);
188
189 HDMI_WRITE(0x51a8, 0x10);
190 HDMI_READ(0x51a8);
191
192 HDMI_WRITE(HDMI_AUDIO_CTRL, 0x1);
193 HDMI_READ(HDMI_AUDIO_CTRL);
194}
195
196static void mrst_hdmi_audio_disable(struct drm_device *dev)
197{
198 struct drm_psb_private *dev_priv = dev->dev_private;
199 struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
200
201 HDMI_WRITE(0x51a8, 0x0);
202 HDMI_READ(0x51a8);
203
204 HDMI_WRITE(HDMI_AUDIO_CTRL, 0x0);
205 HDMI_READ(HDMI_AUDIO_CTRL);
206
207 HDMI_WRITE(HDMI_HCR, 0x47);
208 HDMI_READ(HDMI_HCR);
209}
210
211void mrst_crtc_hdmi_dpms(struct drm_crtc *crtc, int mode)
212{
213 struct drm_device *dev = crtc->dev;
214 u32 temp;
215
216 switch (mode) {
217 case DRM_MODE_DPMS_OFF:
218 /* Disable VGACNTRL */
219 REG_WRITE(VGACNTRL, 0x80000000);
220
221 /* Disable plane */
222 temp = REG_READ(DSPBCNTR);
223 if ((temp & DISPLAY_PLANE_ENABLE) != 0) {
224 REG_WRITE(DSPBCNTR, temp & ~DISPLAY_PLANE_ENABLE);
225 REG_READ(DSPBCNTR);
226 /* Flush the plane changes */
227 REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
228 REG_READ(DSPBSURF);
229 }
230
231 /* Disable pipe B */
232 temp = REG_READ(PIPEBCONF);
233 if ((temp & PIPEACONF_ENABLE) != 0) {
234 REG_WRITE(PIPEBCONF, temp & ~PIPEACONF_ENABLE);
235 REG_READ(PIPEBCONF);
236 }
237
238 /* Disable LNW Pipes, etc */
239 temp = REG_READ(PCH_PIPEBCONF);
240 if ((temp & PIPEACONF_ENABLE) != 0) {
241 REG_WRITE(PCH_PIPEBCONF, temp & ~PIPEACONF_ENABLE);
242 REG_READ(PCH_PIPEBCONF);
243 }
244 /* wait for pipe off */
245 udelay(150);
246 /* Disable dpll */
247 temp = REG_READ(DPLL_CTRL);
248 if ((temp & DPLL_PWRDN) == 0) {
249 REG_WRITE(DPLL_CTRL, temp | (DPLL_PWRDN | DPLL_RESET));
250 REG_WRITE(DPLL_STATUS, 0x1);
251 }
252 /* wait for dpll off */
253 udelay(150);
254 break;
255 case DRM_MODE_DPMS_ON:
256 case DRM_MODE_DPMS_STANDBY:
257 case DRM_MODE_DPMS_SUSPEND:
258 /* Enable dpll */
259 temp = REG_READ(DPLL_CTRL);
260 if ((temp & DPLL_PWRDN) != 0) {
261 REG_WRITE(DPLL_CTRL, temp & ~(DPLL_PWRDN | DPLL_RESET));
262 temp = REG_READ(DPLL_CLK_ENABLE);
263 REG_WRITE(DPLL_CLK_ENABLE, temp | DPLL_EN_DISP | DPLL_SEL_HDMI | DPLL_EN_HDMI);
264 REG_READ(DPLL_CLK_ENABLE);
265 }
266 /* wait for dpll warm up */
267 udelay(150);
268
269 /* Enable pipe B */
270 temp = REG_READ(PIPEBCONF);
271 if ((temp & PIPEACONF_ENABLE) == 0) {
272 REG_WRITE(PIPEBCONF, temp | PIPEACONF_ENABLE);
273 REG_READ(PIPEBCONF);
274 }
275
276 /* Enable LNW Pipe B */
277 temp = REG_READ(PCH_PIPEBCONF);
278 if ((temp & PIPEACONF_ENABLE) == 0) {
279 REG_WRITE(PCH_PIPEBCONF, temp | PIPEACONF_ENABLE);
280 REG_READ(PCH_PIPEBCONF);
281 }
282 wait_for_vblank(dev);
283
284 /* Enable plane */
285 temp = REG_READ(DSPBCNTR);
286 if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
287 REG_WRITE(DSPBCNTR, temp | DISPLAY_PLANE_ENABLE);
288 /* Flush the plane changes */
289 REG_WRITE(DSPBSURF, REG_READ(DSPBSURF));
290 REG_READ(DSPBSURF);
291 }
292 psb_intel_crtc_load_lut(crtc);
293 }
294 /* DSPARB */
295 REG_WRITE(DSPARB, 0x00003fbf);
296 /* FW1 */
297 REG_WRITE(0x70034, 0x3f880a0a);
298 /* FW2 */
299 REG_WRITE(0x70038, 0x0b060808);
300 /* FW4 */
301 REG_WRITE(0x70050, 0x08030404);
302 /* FW5 */
303 REG_WRITE(0x70054, 0x04040404);
304 /* LNC Chicken Bits */
305 REG_WRITE(0x70400, 0x4000);
306}
307
308
309static void mrst_hdmi_dpms(struct drm_encoder *encoder, int mode)
310{
311 static int dpms_mode = -1;
312
313 struct drm_device *dev = encoder->dev;
314 struct drm_psb_private *dev_priv = dev->dev_private;
315 struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
316 u32 temp;
317
318 if (dpms_mode == mode)
319 return;
320
321 if (mode != DRM_MODE_DPMS_ON)
322 temp = 0x0;
323 else
324 temp = 0x99;
325
326 dpms_mode = mode;
327 HDMI_WRITE(HDMI_VIDEO_REG, temp);
328}
329
330static unsigned int htotal_calculate(struct drm_display_mode *mode)
331{
332 u32 htotal, new_crtc_htotal;
333
334 htotal = (mode->crtc_hdisplay - 1) | ((mode->crtc_htotal - 1) << 16);
335
336 /*
337 * 1024 x 768 new_crtc_htotal = 0x1024;
338 * 1280 x 1024 new_crtc_htotal = 0x0c34;
339 */
340 new_crtc_htotal = (mode->crtc_htotal - 1) * 200 * 1000 / mode->clock;
341
342 return (mode->crtc_hdisplay - 1) | (new_crtc_htotal << 16);
343}
344
345static void mrst_hdmi_find_dpll(struct drm_crtc *crtc, int target,
346 int refclk, struct mrst_hdmi_clock *best_clock)
347{
348 int np_min, np_max, nr_min, nr_max;
349 int np, nr, nf;
350
351 np_min = DIV_ROUND_UP(mrst_hdmi_limit.vco.min, target * 10);
352 np_max = mrst_hdmi_limit.vco.max / (target * 10);
353 if (np_min < mrst_hdmi_limit.np.min)
354 np_min = mrst_hdmi_limit.np.min;
355 if (np_max > mrst_hdmi_limit.np.max)
356 np_max = mrst_hdmi_limit.np.max;
357
358 nr_min = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_max));
359 nr_max = DIV_ROUND_UP((refclk * 1000), (target * 10 * np_min));
360 if (nr_min < mrst_hdmi_limit.nr.min)
361 nr_min = mrst_hdmi_limit.nr.min;
362 if (nr_max > mrst_hdmi_limit.nr.max)
363 nr_max = mrst_hdmi_limit.nr.max;
364
365 np = DIV_ROUND_UP((refclk * 1000), (target * 10 * nr_max));
366 nr = DIV_ROUND_UP((refclk * 1000), (target * 10 * np));
367 nf = DIV_ROUND_CLOSEST((target * 10 * np * nr), refclk);
368 DRM_DEBUG_KMS("np, nr, nf %d %d %d\n", np, nr, nf);
369
370 /*
371 * 1024 x 768 np = 1; nr = 0x26; nf = 0x0fd8000;
372 * 1280 x 1024 np = 1; nr = 0x17; nf = 0x1034000;
373 */
374 best_clock->np = np;
375 best_clock->nr = nr - 1;
376 best_clock->nf = (nf << 14);
377}
378
379int mrst_crtc_hdmi_mode_set(struct drm_crtc *crtc,
380 struct drm_display_mode *mode,
381 struct drm_display_mode *adjusted_mode,
382 int x, int y,
383 struct drm_framebuffer *old_fb)
384{
385 struct drm_device *dev = crtc->dev;
386 struct drm_psb_private *dev_priv = dev->dev_private;
387 struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
388 int pipe = 1;
389 int htot_reg = (pipe == 0) ? HTOTAL_A : HTOTAL_B;
390 int hblank_reg = (pipe == 0) ? HBLANK_A : HBLANK_B;
391 int hsync_reg = (pipe == 0) ? HSYNC_A : HSYNC_B;
392 int vtot_reg = (pipe == 0) ? VTOTAL_A : VTOTAL_B;
393 int vblank_reg = (pipe == 0) ? VBLANK_A : VBLANK_B;
394 int vsync_reg = (pipe == 0) ? VSYNC_A : VSYNC_B;
395 int dspsize_reg = (pipe == 0) ? DSPASIZE : DSPBSIZE;
396 int dsppos_reg = (pipe == 0) ? DSPAPOS : DSPBPOS;
397 int pipesrc_reg = (pipe == 0) ? PIPEASRC : PIPEBSRC;
398 int pipeconf_reg = (pipe == 0) ? PIPEACONF : PIPEBCONF;
399 int refclk;
400 struct mrst_hdmi_clock clock;
401 u32 dspcntr, pipeconf, dpll, temp;
402 int dspcntr_reg = DSPBCNTR;
403
404 /* Disable the VGA plane that we never use */
405 REG_WRITE(VGACNTRL, VGA_DISP_DISABLE);
406
407 /* XXX: Disable the panel fitter if it was on our pipe */
408
409 /* Disable dpll if necessary */
410 dpll = REG_READ(DPLL_CTRL);
411 if ((dpll & DPLL_PWRDN) == 0) {
412 REG_WRITE(DPLL_CTRL, dpll | (DPLL_PWRDN | DPLL_RESET));
413 REG_WRITE(DPLL_DIV_CTRL, 0x00000000);
414 REG_WRITE(DPLL_STATUS, 0x1);
415 }
416 udelay(150);
417
418 /* reset controller: FIXME - can we sort out the ioremap mess ? */
419 iounmap(hdmi_dev->regs);
420 mrst_hdmi_reset(dev);
421
422 /* program and enable dpll */
423 refclk = 25000;
424 mrst_hdmi_find_dpll(crtc, adjusted_mode->clock, refclk, &clock);
425
426 /* Setting DPLL */
427 dpll = REG_READ(DPLL_CTRL);
428 dpll &= ~DPLL_PDIV_MASK;
429 dpll &= ~(DPLL_PWRDN | DPLL_RESET);
430 REG_WRITE(DPLL_CTRL, 0x00000008);
431 REG_WRITE(DPLL_DIV_CTRL, ((clock.nf << 6) | clock.nr));
432 REG_WRITE(DPLL_ADJUST, ((clock.nf >> 14) - 1));
433 REG_WRITE(DPLL_CTRL, (dpll | (clock.np << DPLL_PDIV_SHIFT) | DPLL_ENSTAT | DPLL_DITHEN));
434 REG_WRITE(DPLL_UPDATE, 0x80000000);
435 REG_WRITE(DPLL_CLK_ENABLE, 0x80050102);
436 udelay(150);
437
438 hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
439 if (hdmi_dev->regs == NULL) {
440 DRM_ERROR("failed to do hdmi mmio mapping\n");
441 return -ENOMEM;
442 }
443
444 /* configure HDMI */
445 HDMI_WRITE(0x1004, 0x1fd);
446 HDMI_WRITE(0x2000, 0x1);
447 HDMI_WRITE(0x2008, 0x0);
448 HDMI_WRITE(0x3130, 0x8);
449 HDMI_WRITE(0x101c, 0x1800810);
450
451 temp = htotal_calculate(adjusted_mode);
452 REG_WRITE(htot_reg, temp);
453 REG_WRITE(hblank_reg, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
454 REG_WRITE(hsync_reg, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
455 REG_WRITE(vtot_reg, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
456 REG_WRITE(vblank_reg, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
457 REG_WRITE(vsync_reg, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
458 REG_WRITE(pipesrc_reg,
459 ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
460
461 REG_WRITE(PCH_HTOTAL_B, (adjusted_mode->crtc_hdisplay - 1) | ((adjusted_mode->crtc_htotal - 1) << 16));
462 REG_WRITE(PCH_HBLANK_B, (adjusted_mode->crtc_hblank_start - 1) | ((adjusted_mode->crtc_hblank_end - 1) << 16));
463 REG_WRITE(PCH_HSYNC_B, (adjusted_mode->crtc_hsync_start - 1) | ((adjusted_mode->crtc_hsync_end - 1) << 16));
464 REG_WRITE(PCH_VTOTAL_B, (adjusted_mode->crtc_vdisplay - 1) | ((adjusted_mode->crtc_vtotal - 1) << 16));
465 REG_WRITE(PCH_VBLANK_B, (adjusted_mode->crtc_vblank_start - 1) | ((adjusted_mode->crtc_vblank_end - 1) << 16));
466 REG_WRITE(PCH_VSYNC_B, (adjusted_mode->crtc_vsync_start - 1) | ((adjusted_mode->crtc_vsync_end - 1) << 16));
467 REG_WRITE(PCH_PIPEBSRC,
468 ((mode->crtc_hdisplay - 1) << 16) | (mode->crtc_vdisplay - 1));
469
470 temp = adjusted_mode->crtc_hblank_end - adjusted_mode->crtc_hblank_start;
471 HDMI_WRITE(HDMI_HBLANK_A, ((adjusted_mode->crtc_hdisplay - 1) << 16) | temp);
472
473 REG_WRITE(dspsize_reg,
474 ((mode->vdisplay - 1) << 16) | (mode->hdisplay - 1));
475 REG_WRITE(dsppos_reg, 0);
476
477 /* Flush the plane changes */
478 {
479 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
480 crtc_funcs->mode_set_base(crtc, x, y, old_fb);
481 }
482
483 /* Set up the display plane register */
484 dspcntr = REG_READ(dspcntr_reg);
485 dspcntr |= DISPPLANE_GAMMA_ENABLE;
486 dspcntr |= DISPPLANE_SEL_PIPE_B;
487 dspcntr |= DISPLAY_PLANE_ENABLE;
488
489 /* setup pipeconf */
490 pipeconf = REG_READ(pipeconf_reg);
491 pipeconf |= PIPEACONF_ENABLE;
492
493 REG_WRITE(pipeconf_reg, pipeconf);
494 REG_READ(pipeconf_reg);
495
496 REG_WRITE(PCH_PIPEBCONF, pipeconf);
497 REG_READ(PCH_PIPEBCONF);
498 wait_for_vblank(dev);
499
500 REG_WRITE(dspcntr_reg, dspcntr);
501 wait_for_vblank(dev);
502
503 return 0;
504}
505
506static int mrst_hdmi_mode_valid(struct drm_connector *connector,
507 struct drm_display_mode *mode)
508{
509 if (mode->clock > 165000)
510 return MODE_CLOCK_HIGH;
511 if (mode->clock < 20000)
512 return MODE_CLOCK_LOW;
513
514 if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
515 return MODE_NO_DBLESCAN;
516
517 return MODE_OK;
518}
519
520static bool mrst_hdmi_mode_fixup(struct drm_encoder *encoder,
521 struct drm_display_mode *mode,
522 struct drm_display_mode *adjusted_mode)
523{
524 return true;
525}
526
527static enum drm_connector_status
528mrst_hdmi_detect(struct drm_connector *connector, bool force)
529{
530 enum drm_connector_status status;
531 struct drm_device *dev = connector->dev;
532 struct drm_psb_private *dev_priv = dev->dev_private;
533 struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
534 u32 temp;
535
536 temp = HDMI_READ(HDMI_HSR);
537 DRM_DEBUG_KMS("HDMI_HSR %x\n", temp);
538
539 if ((temp & HDMI_DETECT_HDP) != 0)
540 status = connector_status_connected;
541 else
542 status = connector_status_disconnected;
543
544 return status;
545}
546
547static const unsigned char raw_edid[] = {
548 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x10, 0xac, 0x2f, 0xa0,
549 0x53, 0x55, 0x33, 0x30, 0x16, 0x13, 0x01, 0x03, 0x0e, 0x3a, 0x24, 0x78,
550 0xea, 0xe9, 0xf5, 0xac, 0x51, 0x30, 0xb4, 0x25, 0x11, 0x50, 0x54, 0xa5,
551 0x4b, 0x00, 0x81, 0x80, 0xa9, 0x40, 0x71, 0x4f, 0xb3, 0x00, 0x01, 0x01,
552 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x28, 0x3c, 0x80, 0xa0, 0x70, 0xb0,
553 0x23, 0x40, 0x30, 0x20, 0x36, 0x00, 0x46, 0x6c, 0x21, 0x00, 0x00, 0x1a,
554 0x00, 0x00, 0x00, 0xff, 0x00, 0x47, 0x4e, 0x37, 0x32, 0x31, 0x39, 0x35,
555 0x52, 0x30, 0x33, 0x55, 0x53, 0x0a, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x44,
556 0x45, 0x4c, 0x4c, 0x20, 0x32, 0x37, 0x30, 0x39, 0x57, 0x0a, 0x20, 0x20,
557 0x00, 0x00, 0x00, 0xfd, 0x00, 0x38, 0x4c, 0x1e, 0x53, 0x11, 0x00, 0x0a,
558 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x8d
559};
560
561static int mrst_hdmi_get_modes(struct drm_connector *connector)
562{
563 struct drm_device *dev = connector->dev;
564 struct drm_psb_private *dev_priv = dev->dev_private;
565 struct i2c_adapter *i2c_adap;
566 struct edid *edid;
567 struct drm_display_mode *mode, *t;
568 int i = 0, ret = 0;
569
570 i2c_adap = i2c_get_adapter(3);
571 if (i2c_adap == NULL) {
572 DRM_ERROR("No ddc adapter available!\n");
573 edid = (struct edid *)raw_edid;
574 } else {
575 edid = (struct edid *)raw_edid;
576 /* FIXME ? edid = drm_get_edid(connector, i2c_adap); */
577 }
578
579 if (edid) {
580 drm_mode_connector_update_edid_property(connector, edid);
581 ret = drm_add_edid_modes(connector, edid);
582 connector->display_info.raw_edid = NULL;
583 }
584
585 /*
586 * prune modes that require frame buffer bigger than stolen mem
587 */
588 list_for_each_entry_safe(mode, t, &connector->probed_modes, head) {
589 if ((mode->hdisplay * mode->vdisplay * 4) >= dev_priv->vram_stolen_size) {
590 i++;
591 drm_mode_remove(connector, mode);
592 }
593 }
594 return ret - i;
595}
596
597static void mrst_hdmi_mode_set(struct drm_encoder *encoder,
598 struct drm_display_mode *mode,
599 struct drm_display_mode *adjusted_mode)
600{
601 struct drm_device *dev = encoder->dev;
602
603 mrst_hdmi_audio_enable(dev);
604 return;
605}
606
607static void mrst_hdmi_destroy(struct drm_connector *connector)
608{
609 return;
610}
611
612static const struct drm_encoder_helper_funcs mrst_hdmi_helper_funcs = {
613 .dpms = mrst_hdmi_dpms,
614 .mode_fixup = mrst_hdmi_mode_fixup,
615 .prepare = psb_intel_encoder_prepare,
616 .mode_set = mrst_hdmi_mode_set,
617 .commit = psb_intel_encoder_commit,
618};
619
620static const struct drm_connector_helper_funcs
621 mrst_hdmi_connector_helper_funcs = {
622 .get_modes = mrst_hdmi_get_modes,
623 .mode_valid = mrst_hdmi_mode_valid,
624 .best_encoder = psb_intel_best_encoder,
625};
626
627static const struct drm_connector_funcs mrst_hdmi_connector_funcs = {
628 .dpms = drm_helper_connector_dpms,
629 .detect = mrst_hdmi_detect,
630 .fill_modes = drm_helper_probe_single_connector_modes,
631 .destroy = mrst_hdmi_destroy,
632};
633
634static void mrst_hdmi_enc_destroy(struct drm_encoder *encoder)
635{
636 drm_encoder_cleanup(encoder);
637}
638
639static const struct drm_encoder_funcs mrst_hdmi_enc_funcs = {
640 .destroy = mrst_hdmi_enc_destroy,
641};
642
643void mrst_hdmi_init(struct drm_device *dev,
644 struct psb_intel_mode_device *mode_dev)
645{
646 struct psb_intel_output *psb_intel_output;
647 struct drm_connector *connector;
648 struct drm_encoder *encoder;
649
650 psb_intel_output = kzalloc(sizeof(struct psb_intel_output), GFP_KERNEL);
651 if (!psb_intel_output)
652 return;
653
654 psb_intel_output->mode_dev = mode_dev;
655 connector = &psb_intel_output->base;
656 encoder = &psb_intel_output->enc;
657 drm_connector_init(dev, &psb_intel_output->base,
658 &mrst_hdmi_connector_funcs,
659 DRM_MODE_CONNECTOR_DVID);
660
661 drm_encoder_init(dev, &psb_intel_output->enc,
662 &mrst_hdmi_enc_funcs,
663 DRM_MODE_ENCODER_TMDS);
664
665 drm_mode_connector_attach_encoder(&psb_intel_output->base,
666 &psb_intel_output->enc);
667
668 psb_intel_output->type = INTEL_OUTPUT_HDMI;
669 drm_encoder_helper_add(encoder, &mrst_hdmi_helper_funcs);
670 drm_connector_helper_add(connector, &mrst_hdmi_connector_helper_funcs);
671
672 connector->display_info.subpixel_order = SubPixelHorizontalRGB;
673 connector->interlace_allowed = false;
674 connector->doublescan_allowed = false;
675 drm_sysfs_connector_add(connector);
676
677 return;
678}
679
680static DEFINE_PCI_DEVICE_TABLE(hdmi_ids) = {
681 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x080d) },
682 {}
683};
684
685void mrst_hdmi_setup(struct drm_device *dev)
686{
687 struct drm_psb_private *dev_priv = dev->dev_private;
688 struct pci_dev *pdev;
689 struct mrst_hdmi_dev *hdmi_dev;
690 int ret;
691
692 pdev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x080d, NULL);
693 if (!pdev)
694 return;
695
696 hdmi_dev = kzalloc(sizeof(struct mrst_hdmi_dev), GFP_KERNEL);
697 if (!hdmi_dev) {
698 dev_err(dev->dev, "failed to allocate memory\n");
699 goto out;
700 }
701
702
703 ret = pci_enable_device(pdev);
704 if (ret) {
705 dev_err(dev->dev, "failed to enable hdmi controller\n");
706 goto free;
707 }
708
709 hdmi_dev->mmio = pci_resource_start(pdev, 0);
710 hdmi_dev->mmio_len = pci_resource_len(pdev, 0);
711 hdmi_dev->regs = ioremap(hdmi_dev->mmio, hdmi_dev->mmio_len);
712 if (!hdmi_dev->regs) {
713 dev_err(dev->dev, "failed to map hdmi mmio\n");
714 goto free;
715 }
716
717 hdmi_dev->dev = pdev;
718 pci_set_drvdata(pdev, hdmi_dev);
719
720 /* Initialize i2c controller */
721 ret = mrst_hdmi_i2c_init(hdmi_dev->dev);
722 if (ret)
723 dev_err(dev->dev, "HDMI I2C initialization failed\n");
724
725 dev_priv->hdmi_priv = hdmi_dev;
726 mrst_hdmi_audio_disable(dev);
727 return;
728
729free:
730 kfree(hdmi_dev);
731out:
732 return;
733}
734
735void mrst_hdmi_teardown(struct drm_device *dev)
736{
737 struct drm_psb_private *dev_priv = dev->dev_private;
738 struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
739 struct pci_dev *pdev;
740
741 if (hdmi_dev) {
742 pdev = hdmi_dev->dev;
743 pci_set_drvdata(pdev, NULL);
744 mrst_hdmi_i2c_exit(pdev);
745 iounmap(hdmi_dev->regs);
746 kfree(hdmi_dev);
747 pci_dev_put(pdev);
748 }
749}
750
751/* save HDMI register state */
752void mrst_hdmi_save(struct drm_device *dev)
753{
754 struct drm_psb_private *dev_priv = dev->dev_private;
755 struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
756 int i;
757
758 /* dpll */
759 hdmi_dev->saveDPLL_CTRL = PSB_RVDC32(DPLL_CTRL);
760 hdmi_dev->saveDPLL_DIV_CTRL = PSB_RVDC32(DPLL_DIV_CTRL);
761 hdmi_dev->saveDPLL_ADJUST = PSB_RVDC32(DPLL_ADJUST);
762 hdmi_dev->saveDPLL_UPDATE = PSB_RVDC32(DPLL_UPDATE);
763 hdmi_dev->saveDPLL_CLK_ENABLE = PSB_RVDC32(DPLL_CLK_ENABLE);
764
765 /* pipe B */
766 dev_priv->savePIPEBCONF = PSB_RVDC32(PIPEBCONF);
767 dev_priv->savePIPEBSRC = PSB_RVDC32(PIPEBSRC);
768 dev_priv->saveHTOTAL_B = PSB_RVDC32(HTOTAL_B);
769 dev_priv->saveHBLANK_B = PSB_RVDC32(HBLANK_B);
770 dev_priv->saveHSYNC_B = PSB_RVDC32(HSYNC_B);
771 dev_priv->saveVTOTAL_B = PSB_RVDC32(VTOTAL_B);
772 dev_priv->saveVBLANK_B = PSB_RVDC32(VBLANK_B);
773 dev_priv->saveVSYNC_B = PSB_RVDC32(VSYNC_B);
774
775 hdmi_dev->savePCH_PIPEBCONF = PSB_RVDC32(PCH_PIPEBCONF);
776 hdmi_dev->savePCH_PIPEBSRC = PSB_RVDC32(PCH_PIPEBSRC);
777 hdmi_dev->savePCH_HTOTAL_B = PSB_RVDC32(PCH_HTOTAL_B);
778 hdmi_dev->savePCH_HBLANK_B = PSB_RVDC32(PCH_HBLANK_B);
779 hdmi_dev->savePCH_HSYNC_B = PSB_RVDC32(PCH_HSYNC_B);
780 hdmi_dev->savePCH_VTOTAL_B = PSB_RVDC32(PCH_VTOTAL_B);
781 hdmi_dev->savePCH_VBLANK_B = PSB_RVDC32(PCH_VBLANK_B);
782 hdmi_dev->savePCH_VSYNC_B = PSB_RVDC32(PCH_VSYNC_B);
783
784 /* plane */
785 dev_priv->saveDSPBCNTR = PSB_RVDC32(DSPBCNTR);
786 dev_priv->saveDSPBSTRIDE = PSB_RVDC32(DSPBSTRIDE);
787 dev_priv->saveDSPBADDR = PSB_RVDC32(DSPBBASE);
788 dev_priv->saveDSPBSURF = PSB_RVDC32(DSPBSURF);
789 dev_priv->saveDSPBLINOFF = PSB_RVDC32(DSPBLINOFF);
790 dev_priv->saveDSPBTILEOFF = PSB_RVDC32(DSPBTILEOFF);
791
792 /* cursor B */
793 dev_priv->saveDSPBCURSOR_CTRL = PSB_RVDC32(CURBCNTR);
794 dev_priv->saveDSPBCURSOR_BASE = PSB_RVDC32(CURBBASE);
795 dev_priv->saveDSPBCURSOR_POS = PSB_RVDC32(CURBPOS);
796
797 /* save palette */
798 for (i = 0; i < 256; i++)
799 dev_priv->save_palette_b[i] = PSB_RVDC32(PALETTE_B + (i << 2));
800}
801
802/* restore HDMI register state */
803void mrst_hdmi_restore(struct drm_device *dev)
804{
805 struct drm_psb_private *dev_priv = dev->dev_private;
806 struct mrst_hdmi_dev *hdmi_dev = dev_priv->hdmi_priv;
807 int i;
808
809 /* dpll */
810 PSB_WVDC32(hdmi_dev->saveDPLL_CTRL, DPLL_CTRL);
811 PSB_WVDC32(hdmi_dev->saveDPLL_DIV_CTRL, DPLL_DIV_CTRL);
812 PSB_WVDC32(hdmi_dev->saveDPLL_ADJUST, DPLL_ADJUST);
813 PSB_WVDC32(hdmi_dev->saveDPLL_UPDATE, DPLL_UPDATE);
814 PSB_WVDC32(hdmi_dev->saveDPLL_CLK_ENABLE, DPLL_CLK_ENABLE);
815 DRM_UDELAY(150);
816
817 /* pipe */
818 PSB_WVDC32(dev_priv->savePIPEBSRC, PIPEBSRC);
819 PSB_WVDC32(dev_priv->saveHTOTAL_B, HTOTAL_B);
820 PSB_WVDC32(dev_priv->saveHBLANK_B, HBLANK_B);
821 PSB_WVDC32(dev_priv->saveHSYNC_B, HSYNC_B);
822 PSB_WVDC32(dev_priv->saveVTOTAL_B, VTOTAL_B);
823 PSB_WVDC32(dev_priv->saveVBLANK_B, VBLANK_B);
824 PSB_WVDC32(dev_priv->saveVSYNC_B, VSYNC_B);
825
826 PSB_WVDC32(hdmi_dev->savePCH_PIPEBSRC, PCH_PIPEBSRC);
827 PSB_WVDC32(hdmi_dev->savePCH_HTOTAL_B, PCH_HTOTAL_B);
828 PSB_WVDC32(hdmi_dev->savePCH_HBLANK_B, PCH_HBLANK_B);
829 PSB_WVDC32(hdmi_dev->savePCH_HSYNC_B, PCH_HSYNC_B);
830 PSB_WVDC32(hdmi_dev->savePCH_VTOTAL_B, PCH_VTOTAL_B);
831 PSB_WVDC32(hdmi_dev->savePCH_VBLANK_B, PCH_VBLANK_B);
832 PSB_WVDC32(hdmi_dev->savePCH_VSYNC_B, PCH_VSYNC_B);
833
834 PSB_WVDC32(dev_priv->savePIPEBCONF, PIPEBCONF);
835 PSB_WVDC32(hdmi_dev->savePCH_PIPEBCONF, PCH_PIPEBCONF);
836
837 /* plane */
838 PSB_WVDC32(dev_priv->saveDSPBLINOFF, DSPBLINOFF);
839 PSB_WVDC32(dev_priv->saveDSPBSTRIDE, DSPBSTRIDE);
840 PSB_WVDC32(dev_priv->saveDSPBTILEOFF, DSPBTILEOFF);
841 PSB_WVDC32(dev_priv->saveDSPBCNTR, DSPBCNTR);
842 PSB_WVDC32(dev_priv->saveDSPBSURF, DSPBSURF);
843
844 /* cursor B */
845 PSB_WVDC32(dev_priv->saveDSPBCURSOR_CTRL, CURBCNTR);
846 PSB_WVDC32(dev_priv->saveDSPBCURSOR_POS, CURBPOS);
847 PSB_WVDC32(dev_priv->saveDSPBCURSOR_BASE, CURBBASE);
848
849 /* restore palette */
850 for (i = 0; i < 256; i++)
851 PSB_WVDC32(dev_priv->save_palette_b[i], PALETTE_B + (i << 2));
852}
diff --git a/drivers/staging/gma500/mrst_hdmi_i2c.c b/drivers/staging/gma500/mrst_hdmi_i2c.c
new file mode 100644
index 000000000000..351b9d897b9f
--- /dev/null
+++ b/drivers/staging/gma500/mrst_hdmi_i2c.c
@@ -0,0 +1,327 @@
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 * Authors:
24 * Li Peng <peng.li@intel.com>
25 */
26
27#include <linux/mutex.h>
28#include <linux/pci.h>
29#include <linux/i2c.h>
30#include <linux/interrupt.h>
31#include <linux/delay.h>
32#include "psb_drv.h"
33
34#define HDMI_READ(reg) readl(hdmi_dev->regs + (reg))
35#define HDMI_WRITE(reg, val) writel(val, hdmi_dev->regs + (reg))
36
37#define HDMI_HCR 0x1000
38#define HCR_DETECT_HDP (1 << 6)
39#define HCR_ENABLE_HDCP (1 << 5)
40#define HCR_ENABLE_AUDIO (1 << 2)
41#define HCR_ENABLE_PIXEL (1 << 1)
42#define HCR_ENABLE_TMDS (1 << 0)
43#define HDMI_HICR 0x1004
44#define HDMI_INTR_I2C_ERROR (1 << 4)
45#define HDMI_INTR_I2C_FULL (1 << 3)
46#define HDMI_INTR_I2C_DONE (1 << 2)
47#define HDMI_INTR_HPD (1 << 0)
48#define HDMI_HSR 0x1008
49#define HDMI_HISR 0x100C
50#define HDMI_HI2CRDB0 0x1200
51#define HDMI_HI2CHCR 0x1240
52#define HI2C_HDCP_WRITE (0 << 2)
53#define HI2C_HDCP_RI_READ (1 << 2)
54#define HI2C_HDCP_READ (2 << 2)
55#define HI2C_EDID_READ (3 << 2)
56#define HI2C_READ_CONTINUE (1 << 1)
57#define HI2C_ENABLE_TRANSACTION (1 << 0)
58
59#define HDMI_ICRH 0x1100
60#define HDMI_HI2CTDR0 0x1244
61#define HDMI_HI2CTDR1 0x1248
62
63#define I2C_STAT_INIT 0
64#define I2C_READ_DONE 1
65#define I2C_TRANSACTION_DONE 2
66
67struct hdmi_i2c_dev {
68 struct i2c_adapter *adap;
69 struct mutex i2c_lock;
70 struct completion complete;
71 int status;
72 struct i2c_msg *msg;
73 int buf_offset;
74};
75
76static void hdmi_i2c_irq_enable(struct mrst_hdmi_dev *hdmi_dev)
77{
78 u32 temp;
79
80 temp = HDMI_READ(HDMI_HICR);
81 temp |= (HDMI_INTR_I2C_ERROR | HDMI_INTR_I2C_FULL | HDMI_INTR_I2C_DONE);
82 HDMI_WRITE(HDMI_HICR, temp);
83 HDMI_READ(HDMI_HICR);
84}
85
86static void hdmi_i2c_irq_disable(struct mrst_hdmi_dev *hdmi_dev)
87{
88 HDMI_WRITE(HDMI_HICR, 0x0);
89 HDMI_READ(HDMI_HICR);
90}
91
92static int xfer_read(struct i2c_adapter *adap, struct i2c_msg *pmsg)
93{
94 struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
95 struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
96 u32 temp;
97
98 i2c_dev->status = I2C_STAT_INIT;
99 i2c_dev->msg = pmsg;
100 i2c_dev->buf_offset = 0;
101 INIT_COMPLETION(i2c_dev->complete);
102
103 /* Enable I2C transaction */
104 temp = ((pmsg->len) << 20) | HI2C_EDID_READ | HI2C_ENABLE_TRANSACTION;
105 HDMI_WRITE(HDMI_HI2CHCR, temp);
106 HDMI_READ(HDMI_HI2CHCR);
107
108 while (i2c_dev->status != I2C_TRANSACTION_DONE)
109 wait_for_completion_interruptible_timeout(&i2c_dev->complete,
110 10 * HZ);
111
112 return 0;
113}
114
115static int xfer_write(struct i2c_adapter *adap, struct i2c_msg *pmsg)
116{
117 /*
118 * XXX: i2c write seems isn't useful for EDID probe, don't do anything
119 */
120 return 0;
121}
122
123static int mrst_hdmi_i2c_access(struct i2c_adapter *adap,
124 struct i2c_msg *pmsg,
125 int num)
126{
127 struct mrst_hdmi_dev *hdmi_dev = i2c_get_adapdata(adap);
128 struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
129 int i, err = 0;
130
131 mutex_lock(&i2c_dev->i2c_lock);
132
133 /* Enable i2c unit */
134 HDMI_WRITE(HDMI_ICRH, 0x00008760);
135
136 /* Enable irq */
137 hdmi_i2c_irq_enable(hdmi_dev);
138 for (i = 0; i < num; i++) {
139 if (pmsg->len && pmsg->buf) {
140 if (pmsg->flags & I2C_M_RD)
141 err = xfer_read(adap, pmsg);
142 else
143 err = xfer_write(adap, pmsg);
144 }
145 pmsg++; /* next message */
146 }
147
148 /* Disable irq */
149 hdmi_i2c_irq_disable(hdmi_dev);
150
151 mutex_unlock(&i2c_dev->i2c_lock);
152
153 return i;
154}
155
156static u32 mrst_hdmi_i2c_func(struct i2c_adapter *adapter)
157{
158 return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR;
159}
160
161static const struct i2c_algorithm mrst_hdmi_i2c_algorithm = {
162 .master_xfer = mrst_hdmi_i2c_access,
163 .functionality = mrst_hdmi_i2c_func,
164};
165
166static struct i2c_adapter mrst_hdmi_i2c_adapter = {
167 .name = "mrst_hdmi_i2c",
168 .nr = 3,
169 .owner = THIS_MODULE,
170 .class = I2C_CLASS_DDC,
171 .algo = &mrst_hdmi_i2c_algorithm,
172};
173
174static void hdmi_i2c_read(struct mrst_hdmi_dev *hdmi_dev)
175{
176 struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
177 struct i2c_msg *msg = i2c_dev->msg;
178 u8 *buf = msg->buf;
179 u32 temp;
180 int i, offset;
181
182 offset = i2c_dev->buf_offset;
183 for (i = 0; i < 0x10; i++) {
184 temp = HDMI_READ(HDMI_HI2CRDB0 + (i * 4));
185 memcpy(buf + (offset + i * 4), &temp, 4);
186 }
187 i2c_dev->buf_offset += (0x10 * 4);
188
189 /* clearing read buffer full intr */
190 temp = HDMI_READ(HDMI_HISR);
191 HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_FULL);
192 HDMI_READ(HDMI_HISR);
193
194 /* continue read transaction */
195 temp = HDMI_READ(HDMI_HI2CHCR);
196 HDMI_WRITE(HDMI_HI2CHCR, temp | HI2C_READ_CONTINUE);
197 HDMI_READ(HDMI_HI2CHCR);
198
199 i2c_dev->status = I2C_READ_DONE;
200 return;
201}
202
203static void hdmi_i2c_transaction_done(struct mrst_hdmi_dev *hdmi_dev)
204{
205 struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
206 u32 temp;
207
208 /* clear transaction done intr */
209 temp = HDMI_READ(HDMI_HISR);
210 HDMI_WRITE(HDMI_HISR, temp | HDMI_INTR_I2C_DONE);
211 HDMI_READ(HDMI_HISR);
212
213
214 temp = HDMI_READ(HDMI_HI2CHCR);
215 HDMI_WRITE(HDMI_HI2CHCR, temp & ~HI2C_ENABLE_TRANSACTION);
216 HDMI_READ(HDMI_HI2CHCR);
217
218 i2c_dev->status = I2C_TRANSACTION_DONE;
219 return;
220}
221
222static irqreturn_t mrst_hdmi_i2c_handler(int this_irq, void *dev)
223{
224 struct mrst_hdmi_dev *hdmi_dev = dev;
225 struct hdmi_i2c_dev *i2c_dev = hdmi_dev->i2c_dev;
226 u32 stat;
227
228 stat = HDMI_READ(HDMI_HISR);
229
230 if (stat & HDMI_INTR_HPD) {
231 HDMI_WRITE(HDMI_HISR, stat | HDMI_INTR_HPD);
232 HDMI_READ(HDMI_HISR);
233 }
234
235 if (stat & HDMI_INTR_I2C_FULL)
236 hdmi_i2c_read(hdmi_dev);
237
238 if (stat & HDMI_INTR_I2C_DONE)
239 hdmi_i2c_transaction_done(hdmi_dev);
240
241 complete(&i2c_dev->complete);
242
243 return IRQ_HANDLED;
244}
245
246/*
247 * choose alternate function 2 of GPIO pin 52, 53,
248 * which is used by HDMI I2C logic
249 */
250static void mrst_hdmi_i2c_gpio_fix(void)
251{
252 void *base;
253 unsigned int gpio_base = 0xff12c000;
254 int gpio_len = 0x1000;
255 u32 temp;
256
257 base = ioremap((resource_size_t)gpio_base, gpio_len);
258 if (base == NULL) {
259 DRM_ERROR("gpio ioremap fail\n");
260 return;
261 }
262
263 temp = readl(base + 0x44);
264 DRM_DEBUG_DRIVER("old gpio val %x\n", temp);
265 writel((temp | 0x00000a00), (base + 0x44));
266 temp = readl(base + 0x44);
267 DRM_DEBUG_DRIVER("new gpio val %x\n", temp);
268
269 iounmap(base);
270}
271
272int mrst_hdmi_i2c_init(struct pci_dev *dev)
273{
274 struct mrst_hdmi_dev *hdmi_dev;
275 struct hdmi_i2c_dev *i2c_dev;
276 int ret;
277
278 hdmi_dev = pci_get_drvdata(dev);
279
280 i2c_dev = kzalloc(sizeof(struct hdmi_i2c_dev), GFP_KERNEL);
281 if (i2c_dev == NULL) {
282 DRM_ERROR("Can't allocate interface\n");
283 ret = -ENOMEM;
284 goto exit;
285 }
286
287 i2c_dev->adap = &mrst_hdmi_i2c_adapter;
288 i2c_dev->status = I2C_STAT_INIT;
289 init_completion(&i2c_dev->complete);
290 mutex_init(&i2c_dev->i2c_lock);
291 i2c_set_adapdata(&mrst_hdmi_i2c_adapter, hdmi_dev);
292 hdmi_dev->i2c_dev = i2c_dev;
293
294 /* Enable HDMI I2C function on gpio */
295 mrst_hdmi_i2c_gpio_fix();
296
297 /* request irq */
298 ret = request_irq(dev->irq, mrst_hdmi_i2c_handler, IRQF_SHARED,
299 mrst_hdmi_i2c_adapter.name, hdmi_dev);
300 if (ret) {
301 DRM_ERROR("Failed to request IRQ for I2C controller\n");
302 goto err;
303 }
304
305 /* Adapter registration */
306 ret = i2c_add_numbered_adapter(&mrst_hdmi_i2c_adapter);
307 return ret;
308
309err:
310 kfree(i2c_dev);
311exit:
312 return ret;
313}
314
315void mrst_hdmi_i2c_exit(struct pci_dev *dev)
316{
317 struct mrst_hdmi_dev *hdmi_dev;
318 struct hdmi_i2c_dev *i2c_dev;
319
320 hdmi_dev = pci_get_drvdata(dev);
321 if (i2c_del_adapter(&mrst_hdmi_i2c_adapter))
322 DRM_DEBUG_DRIVER("Failed to delete hdmi-i2c adapter\n");
323
324 i2c_dev = hdmi_dev->i2c_dev;
325 kfree(i2c_dev);
326 free_irq(dev->irq, hdmi_dev);
327}
diff --git a/drivers/staging/gma500/psb_drv.c b/drivers/staging/gma500/psb_drv.c
index 6b03951ebd04..4b740aac2a42 100644
--- a/drivers/staging/gma500/psb_drv.c
+++ b/drivers/staging/gma500/psb_drv.c
@@ -261,6 +261,8 @@ static int psb_driver_unload(struct drm_device *dev)
261 psb_lid_timer_takedown(dev_priv); 261 psb_lid_timer_takedown(dev_priv);
262 gma_intel_opregion_exit(dev); 262 gma_intel_opregion_exit(dev);
263 263
264 if (dev_priv->ops->chip_teardown)
265 dev_priv->ops->chip_teardown(dev);
264 psb_do_takedown(dev); 266 psb_do_takedown(dev);
265 267
266 268
diff --git a/drivers/staging/gma500/psb_drv.h b/drivers/staging/gma500/psb_drv.h
index 8184c2349d14..25275f7d7895 100644
--- a/drivers/staging/gma500/psb_drv.h
+++ b/drivers/staging/gma500/psb_drv.h
@@ -375,6 +375,9 @@ struct drm_psb_private {
375 bool dbi_panel_on2; /* The DBI panel power is on */ 375 bool dbi_panel_on2; /* The DBI panel power is on */
376 u32 dsr_fb_update; /* DSR FB update counter */ 376 u32 dsr_fb_update; /* DSR FB update counter */
377 377
378 /* Moorestown HDMI state */
379 struct mrst_hdmi_dev *hdmi_priv;
380
378 /* Moorestown pipe config register value cache */ 381 /* Moorestown pipe config register value cache */
379 uint32_t pipeconf; 382 uint32_t pipeconf;
380 uint32_t pipeconf1; 383 uint32_t pipeconf1;
@@ -631,6 +634,7 @@ struct psb_ops {
631 634
632 /* Setup hooks */ 635 /* Setup hooks */
633 int (*chip_setup)(struct drm_device *dev); 636 int (*chip_setup)(struct drm_device *dev);
637 void (*chip_teardown)(struct drm_device *dev);
634 638
635 /* Display management hooks */ 639 /* Display management hooks */
636 int (*output_init)(struct drm_device *dev); 640 int (*output_init)(struct drm_device *dev);