gma500: being abstracting out devices a bit more
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / gma500 / mrst_device.c
blob5cd82838a052777c1067f096ee6a61d43cac90a2
1 /**************************************************************************
2 * Copyright (c) 2011, Intel Corporation.
3 * All Rights Reserved.
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.
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.
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.
18 **************************************************************************/
20 #include <drm/drmP.h>
21 #include <drm/drm.h>
22 #include "psb_drm.h"
23 #include "psb_drv.h"
24 #include "psb_reg.h"
25 #include "psb_intel_reg.h"
26 #include <asm/intel_scu_ipc.h>
28 /* IPC message and command defines used to enable/disable mipi panel voltages */
29 #define IPC_MSG_PANEL_ON_OFF 0xE9
30 #define IPC_CMD_PANEL_ON 1
31 #define IPC_CMD_PANEL_OFF 0
33 static int mrst_output_init(struct drm_device *dev)
35 struct drm_psb_private *dev_priv = dev->dev_private;
36 if (dev_priv->iLVDS_enable) {
37 mrst_lvds_init(dev, &dev_priv->mode_dev);
38 return 0;
40 dev_err(dev->dev, "DSI is not supported\n");
41 return -ENODEV;
45 * Provide the Moorestown specific chip logic and low level methods
48 static void mrst_init_pm(struct drm_device *dev)
52 /**
53 * mrst_save_display_registers - save registers lost on suspend
54 * @dev: our DRM device
56 * Save the state we need in order to be able to restore the interface
57 * upon resume from suspend
59 static int mrst_save_display_registers(struct drm_device *dev)
61 struct drm_psb_private *dev_priv = dev->dev_private;
62 struct drm_crtc *crtc;
63 struct drm_connector *connector;
65 /* Display arbitration control + watermarks */
66 dev_priv->saveDSPARB = PSB_RVDC32(DSPARB);
67 dev_priv->saveDSPFW1 = PSB_RVDC32(DSPFW1);
68 dev_priv->saveDSPFW2 = PSB_RVDC32(DSPFW2);
69 dev_priv->saveDSPFW3 = PSB_RVDC32(DSPFW3);
70 dev_priv->saveDSPFW4 = PSB_RVDC32(DSPFW4);
71 dev_priv->saveDSPFW5 = PSB_RVDC32(DSPFW5);
72 dev_priv->saveDSPFW6 = PSB_RVDC32(DSPFW6);
73 dev_priv->saveCHICKENBIT = PSB_RVDC32(DSPCHICKENBIT);
75 /* Save crtc and output state */
76 mutex_lock(&dev->mode_config.mutex);
77 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
78 if (drm_helper_crtc_in_use(crtc))
79 crtc->funcs->save(crtc);
82 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
83 connector->funcs->save(connector);
85 mutex_unlock(&dev->mode_config.mutex);
86 return 0;
89 /**
90 * mrst_restore_display_registers - restore lost register state
91 * @dev: our DRM device
93 * Restore register state that was lost during suspend and resume.
95 static int mrst_restore_display_registers(struct drm_device *dev)
97 struct drm_psb_private *dev_priv = dev->dev_private;
98 struct drm_crtc *crtc;
99 struct drm_connector *connector;
100 int pp_stat;
102 if (!dev_priv->iLVDS_enable) {
103 #ifdef CONFIG_X86_MRST
104 intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
105 IPC_CMD_PANEL_ON);
106 /* FIXME: can we avoid this delay ? */
107 msleep(2000); /* wait 2 seconds */
108 #endif
111 /* Display arbitration + watermarks */
112 PSB_WVDC32(dev_priv->saveDSPARB, DSPARB);
113 PSB_WVDC32(dev_priv->saveDSPFW1, DSPFW1);
114 PSB_WVDC32(dev_priv->saveDSPFW2, DSPFW2);
115 PSB_WVDC32(dev_priv->saveDSPFW3, DSPFW3);
116 PSB_WVDC32(dev_priv->saveDSPFW4, DSPFW4);
117 PSB_WVDC32(dev_priv->saveDSPFW5, DSPFW5);
118 PSB_WVDC32(dev_priv->saveDSPFW6, DSPFW6);
119 PSB_WVDC32(dev_priv->saveCHICKENBIT, DSPCHICKENBIT);
121 /*make sure VGA plane is off. it initializes to on after reset!*/
122 PSB_WVDC32(0x80000000, VGACNTRL);
124 mutex_lock(&dev->mode_config.mutex);
125 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
126 if (drm_helper_crtc_in_use(crtc))
127 crtc->funcs->restore(crtc);
129 list_for_each_entry(connector, &dev->mode_config.connector_list, head)
130 connector->funcs->restore(connector);
132 mutex_unlock(&dev->mode_config.mutex);
134 if (dev_priv->iLVDS_enable) {
135 /*shutdown the panel*/
136 PSB_WVDC32(0, PP_CONTROL);
137 do {
138 pp_stat = PSB_RVDC32(PP_STATUS);
139 } while (pp_stat & 0x80000000);
141 /* Turn off the plane */
142 PSB_WVDC32(0x58000000, DSPACNTR);
143 PSB_WVDC32(0, DSPASURF);/*trigger the plane disable*/
144 /* Wait ~4 ticks */
145 msleep(4);
146 /* Turn off pipe */
147 PSB_WVDC32(0x0, PIPEACONF);
148 /* Wait ~8 ticks */
149 msleep(8);
151 /* Turn off PLLs */
152 PSB_WVDC32(0, MRST_DPLL_A);
153 } else {
154 PSB_WVDC32(DPI_SHUT_DOWN, DPI_CONTROL_REG);
155 PSB_WVDC32(0x0, PIPEACONF);
156 PSB_WVDC32(0x2faf0000, BLC_PWM_CTL);
157 while (REG_READ(0x70008) & 0x40000000)
158 cpu_relax();
159 while ((PSB_RVDC32(GEN_FIFO_STAT_REG) & DPI_FIFO_EMPTY)
160 != DPI_FIFO_EMPTY)
161 cpu_relax();
162 PSB_WVDC32(0, DEVICE_READY_REG);
163 /* Turn off panel power */
164 #ifdef CONFIG_X86_MRST /* FIXME: kill define once modular */
165 intel_scu_ipc_simple_command(IPC_MSG_PANEL_ON_OFF,
166 IPC_CMD_PANEL_OFF);
167 #endif
169 return 0;
173 * mrst_power_down - power down the display island
174 * @dev: our DRM device
176 * Power down the display interface of our device
178 static int mrst_power_down(struct drm_device *dev)
180 struct drm_psb_private *dev_priv = dev->dev_private;
181 u32 pwr_mask ;
182 u32 pwr_sts;
184 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
185 outl(pwr_mask, dev_priv->ospm_base + PSB_PM_SSC);
187 while (true) {
188 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
189 if ((pwr_sts & pwr_mask) == pwr_mask)
190 break;
191 else
192 udelay(10);
194 return 0;
198 * mrst_power_up
200 * Restore power to the specified island(s) (powergating)
202 static int mrst_power_up(struct drm_device *dev)
204 struct drm_psb_private *dev_priv = dev->dev_private;
205 u32 pwr_mask = PSB_PWRGT_DISPLAY_MASK;
206 u32 pwr_sts, pwr_cnt;
208 pwr_cnt = inl(dev_priv->ospm_base + PSB_PM_SSC);
209 pwr_cnt &= ~pwr_mask;
210 outl(pwr_cnt, (dev_priv->ospm_base + PSB_PM_SSC));
212 while (true) {
213 pwr_sts = inl(dev_priv->ospm_base + PSB_PM_SSS);
214 if ((pwr_sts & pwr_mask) == 0)
215 break;
216 else
217 udelay(10);
219 return 0;
222 const struct psb_ops mrst_chip_ops = {
223 .output_init = mrst_output_init,
224 .init_pm = mrst_init_pm,
225 .save_regs = mrst_save_display_registers,
226 .restore_regs = mrst_restore_display_registers,
227 .power_down = mrst_power_down,
228 .power_up = mrst_power_up,