audit: complex interfield comparison helper
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / gma500 / mdfld_tpo_cmd.c
blobc7f7c9c19bc1f73247e1f48bad02be649ad368b7
1 /*
2 * Copyright (c) 2010 Intel Corporation
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, sublicensen
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:
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.
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.
23 * Authors:
24 * Thomas Eaton <thomas.g.eaton@intel.com>
25 * Scott Rowe <scott.m.rowe@intel.com>
28 #include "mdfld_dsi_dbi.h"
29 #include "mdfld_dsi_dpi.h"
30 #include "mdfld_dsi_output.h"
31 #include "mdfld_output.h"
32 #include "mdfld_dsi_dbi_dpu.h"
33 #include "mdfld_dsi_pkg_sender.h"
35 #include "displays/tpo_cmd.h"
37 static struct drm_display_mode *tpo_cmd_get_config_mode(struct drm_device *dev)
39 struct drm_display_mode *mode;
40 struct drm_psb_private *dev_priv = dev->dev_private;
41 struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
42 bool use_gct = false;
44 mode = kzalloc(sizeof(*mode), GFP_KERNEL);
45 if (!mode)
46 return NULL;
48 if (use_gct) {
49 dev_dbg(dev->dev, "gct find MIPI panel.\n");
51 mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
52 mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
53 mode->hsync_start = mode->hdisplay + \
54 ((ti->hsync_offset_hi << 8) | \
55 ti->hsync_offset_lo);
56 mode->hsync_end = mode->hsync_start + \
57 ((ti->hsync_pulse_width_hi << 8) | \
58 ti->hsync_pulse_width_lo);
59 mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
60 ti->hblank_lo);
61 mode->vsync_start = \
62 mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
63 ti->vsync_offset_lo);
64 mode->vsync_end = \
65 mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
66 ti->vsync_pulse_width_lo);
67 mode->vtotal = mode->vdisplay + \
68 ((ti->vblank_hi << 8) | ti->vblank_lo);
69 mode->clock = ti->pixel_clock * 10;
71 dev_dbg(dev->dev, "hdisplay is %d\n", mode->hdisplay);
72 dev_dbg(dev->dev, "vdisplay is %d\n", mode->vdisplay);
73 dev_dbg(dev->dev, "HSS is %d\n", mode->hsync_start);
74 dev_dbg(dev->dev, "HSE is %d\n", mode->hsync_end);
75 dev_dbg(dev->dev, "htotal is %d\n", mode->htotal);
76 dev_dbg(dev->dev, "VSS is %d\n", mode->vsync_start);
77 dev_dbg(dev->dev, "VSE is %d\n", mode->vsync_end);
78 dev_dbg(dev->dev, "vtotal is %d\n", mode->vtotal);
79 dev_dbg(dev->dev, "clock is %d\n", mode->clock);
80 } else {
81 mode->hdisplay = 864;
82 mode->vdisplay = 480;
83 mode->hsync_start = 872;
84 mode->hsync_end = 876;
85 mode->htotal = 884;
86 mode->vsync_start = 482;
87 mode->vsync_end = 494;
88 mode->vtotal = 486;
89 mode->clock = 25777;
92 drm_mode_set_name(mode);
93 drm_mode_set_crtcinfo(mode, 0);
95 mode->type |= DRM_MODE_TYPE_PREFERRED;
97 return mode;
100 static bool mdfld_dsi_dbi_mode_fixup(struct drm_encoder *encoder,
101 struct drm_display_mode *mode,
102 struct drm_display_mode *adjusted_mode)
104 struct drm_device *dev = encoder->dev;
105 struct drm_display_mode *fixed_mode = tpo_cmd_get_config_mode(dev);
107 if (fixed_mode) {
108 adjusted_mode->hdisplay = fixed_mode->hdisplay;
109 adjusted_mode->hsync_start = fixed_mode->hsync_start;
110 adjusted_mode->hsync_end = fixed_mode->hsync_end;
111 adjusted_mode->htotal = fixed_mode->htotal;
112 adjusted_mode->vdisplay = fixed_mode->vdisplay;
113 adjusted_mode->vsync_start = fixed_mode->vsync_start;
114 adjusted_mode->vsync_end = fixed_mode->vsync_end;
115 adjusted_mode->vtotal = fixed_mode->vtotal;
116 adjusted_mode->clock = fixed_mode->clock;
117 drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V);
118 kfree(fixed_mode);
120 return true;
123 static void mdfld_dsi_dbi_set_power(struct drm_encoder *encoder, bool on)
125 int ret = 0;
126 struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
127 struct mdfld_dsi_dbi_output *dbi_output =
128 MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
129 struct mdfld_dsi_config *dsi_config =
130 mdfld_dsi_encoder_get_config(dsi_encoder);
131 struct mdfld_dsi_pkg_sender *sender =
132 mdfld_dsi_encoder_get_pkg_sender(dsi_encoder);
133 struct drm_device *dev = encoder->dev;
134 struct drm_psb_private *dev_priv = dev->dev_private;
135 u32 reg_offset = 0;
136 int pipe = (dbi_output->channel_num == 0) ? 0 : 2;
137 u32 data = 0;
139 dev_dbg(dev->dev, "pipe %d : %s, panel on: %s\n",
140 pipe, on ? "On" : "Off",
141 dbi_output->dbi_panel_on ? "True" : "False");
143 if (pipe == 2) {
144 if (on)
145 dev_priv->dual_mipi = true;
146 else
147 dev_priv->dual_mipi = false;
148 reg_offset = MIPIC_REG_OFFSET;
149 } else {
150 if (!on)
151 dev_priv->dual_mipi = false;
154 if (!gma_power_begin(dev, true)) {
155 dev_err(dev->dev, "hw begin failed\n");
156 return;
159 if (on) {
160 if (dbi_output->dbi_panel_on)
161 goto out_err;
163 ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_ON);
164 if (ret) {
165 dev_err(dev->dev, "power on error\n");
166 goto out_err;
169 dbi_output->dbi_panel_on = true;
171 if (pipe == 2)
172 dev_priv->dbi_panel_on2 = true;
173 else
174 dev_priv->dbi_panel_on = true;
175 mdfld_enable_te(dev, pipe);
176 } else {
177 if (!dbi_output->dbi_panel_on && !dbi_output->first_boot)
178 goto out_err;
180 dbi_output->dbi_panel_on = false;
181 dbi_output->first_boot = false;
183 if (pipe == 2)
184 dev_priv->dbi_panel_on2 = false;
185 else
186 dev_priv->dbi_panel_on = false;
188 mdfld_disable_te(dev, pipe);
190 ret = mdfld_dsi_dbi_update_power(dbi_output, DRM_MODE_DPMS_OFF);
191 if (ret) {
192 dev_err(dev->dev, "power on error\n");
193 goto out_err;
198 * FIXME: this is a WA for TPO panel crash on DPMS on & off around
199 * 83 times. the root cause of this issue is that Booster in
200 * drvIC crashed. Add this WA so that we can resume the driver IC
201 * once we found that booster has a fault
203 mdfld_dsi_get_power_mode(dsi_config,
204 &data,
205 MDFLD_DSI_HS_TRANSMISSION);
207 if (on && data && !(data & (1 << 7))) {
208 /* Soft reset */
209 mdfld_dsi_send_dcs(sender,
210 DCS_SOFT_RESET,
211 NULL,
213 CMD_DATA_SRC_PIPE,
214 MDFLD_DSI_SEND_PACKAGE);
216 /* Init drvIC */
217 if (dbi_output->p_funcs->drv_ic_init)
218 dbi_output->p_funcs->drv_ic_init(dsi_config,
219 pipe);
222 out_err:
223 gma_power_end(dev);
224 if (ret)
225 dev_err(dev->dev, "failed\n");
229 static void mdfld_dsi_dbi_mode_set(struct drm_encoder *encoder,
230 struct drm_display_mode *mode,
231 struct drm_display_mode *adjusted_mode)
233 int ret = 0;
234 struct drm_device *dev = encoder->dev;
235 struct drm_psb_private *dev_priv = dev->dev_private;
236 struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
237 struct mdfld_dsi_dbi_output *dsi_output =
238 MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
239 struct mdfld_dsi_config *dsi_config =
240 mdfld_dsi_encoder_get_config(dsi_encoder);
241 struct mdfld_dsi_connector *dsi_connector = dsi_config->connector;
242 int pipe = dsi_connector->pipe;
243 u8 param = 0;
245 /* Regs */
246 u32 mipi_reg = MIPI;
247 u32 dspcntr_reg = DSPACNTR;
248 u32 pipeconf_reg = PIPEACONF;
249 u32 reg_offset = 0;
251 /* Values */
252 u32 dspcntr_val = dev_priv->dspcntr;
253 u32 pipeconf_val = dev_priv->pipeconf;
254 u32 h_active_area = mode->hdisplay;
255 u32 v_active_area = mode->vdisplay;
256 u32 mipi_val;
258 mipi_val = (PASS_FROM_SPHY_TO_AFE | SEL_FLOPPED_HSTX |
259 TE_TRIGGER_GPIO_PIN);
261 dev_dbg(dev->dev, "mipi_val =0x%x\n", mipi_val);
263 dev_dbg(dev->dev, "type %s\n", (pipe == 2) ? "MIPI2" : "MIPI");
264 dev_dbg(dev->dev, "h %d v %d\n", mode->hdisplay, mode->vdisplay);
266 if (pipe == 2) {
267 mipi_reg = MIPI_C;
268 dspcntr_reg = DSPCCNTR;
269 pipeconf_reg = PIPECCONF;
271 reg_offset = MIPIC_REG_OFFSET;
273 dspcntr_val = dev_priv->dspcntr2;
274 pipeconf_val = dev_priv->pipeconf2;
275 } else {
276 mipi_val |= 0x2; /*two lanes for port A and C respectively*/
279 if (!gma_power_begin(dev, true)) {
280 dev_err(dev->dev, "hw begin failed\n");
281 return;
284 REG_WRITE(dspcntr_reg, dspcntr_val);
285 REG_READ(dspcntr_reg);
287 /* 20ms delay before sending exit_sleep_mode */
288 msleep(20);
290 /* Send exit_sleep_mode DCS */
291 ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_EXIT_SLEEP_MODE,
292 NULL, 0, CMD_DATA_SRC_SYSTEM_MEM);
293 if (ret) {
294 dev_err(dev->dev, "sent exit_sleep_mode faild\n");
295 goto out_err;
298 /* Send set_tear_on DCS */
299 ret = mdfld_dsi_dbi_send_dcs(dsi_output, DCS_SET_TEAR_ON,
300 &param, 1, CMD_DATA_SRC_SYSTEM_MEM);
301 if (ret) {
302 dev_err(dev->dev, "%s - sent set_tear_on faild\n", __func__);
303 goto out_err;
306 /* Do some init stuff */
307 REG_WRITE(pipeconf_reg, pipeconf_val | PIPEACONF_DSR);
308 REG_READ(pipeconf_reg);
310 /* TODO: this looks ugly, try to move it to CRTC mode setting*/
311 if (pipe == 2)
312 dev_priv->pipeconf2 |= PIPEACONF_DSR;
313 else
314 dev_priv->pipeconf |= PIPEACONF_DSR;
316 dev_dbg(dev->dev, "pipeconf %x\n", REG_READ(pipeconf_reg));
318 ret = mdfld_dsi_dbi_update_area(dsi_output, 0, 0,
319 h_active_area - 1, v_active_area - 1);
320 if (ret) {
321 dev_err(dev->dev, "update area failed\n");
322 goto out_err;
325 out_err:
326 gma_power_end(dev);
328 if (ret)
329 dev_err(dev->dev, "mode set failed\n");
332 static void mdfld_dsi_dbi_prepare(struct drm_encoder *encoder)
334 struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
335 struct mdfld_dsi_dbi_output *dbi_output
336 = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
338 dbi_output->mode_flags |= MODE_SETTING_IN_ENCODER;
339 dbi_output->mode_flags &= ~MODE_SETTING_ENCODER_DONE;
341 mdfld_dsi_dbi_set_power(encoder, false);
344 static void mdfld_dsi_dbi_commit(struct drm_encoder *encoder)
346 struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
347 struct mdfld_dsi_dbi_output *dbi_output =
348 MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
349 struct drm_device *dev = dbi_output->dev;
350 struct drm_psb_private *dev_priv = dev->dev_private;
351 struct psb_drm_dpu_rect rect;
353 mdfld_dsi_dbi_set_power(encoder, true);
354 dbi_output->mode_flags &= ~MODE_SETTING_IN_ENCODER;
356 rect.x = rect.y = 0;
357 rect.width = 864;
358 rect.height = 480;
360 if (dbi_output->channel_num == 1) {
361 dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_2;
362 /*if dpu enabled report a fullscreen damage*/
363 mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEC, &rect);
364 } else {
365 dev_priv->dsr_fb_update |= MDFLD_DSR_2D_3D_0;
366 mdfld_dbi_dpu_report_damage(dev, MDFLD_PLANEA, &rect);
368 dbi_output->mode_flags |= MODE_SETTING_ENCODER_DONE;
371 static void mdfld_dsi_dbi_dpms(struct drm_encoder *encoder, int mode)
373 struct mdfld_dsi_encoder *dsi_encoder = MDFLD_DSI_ENCODER(encoder);
374 struct mdfld_dsi_dbi_output *dbi_output
375 = MDFLD_DSI_DBI_OUTPUT(dsi_encoder);
376 struct drm_device *dev = dbi_output->dev;
377 struct drm_psb_private *dev_priv = dev->dev_private;
378 static bool bdispoff;
380 dev_dbg(dev->dev, "%s\n", (mode == DRM_MODE_DPMS_ON ? "on" : "off"));
382 if (mode == DRM_MODE_DPMS_ON) {
384 * FIXME: in case I am wrong!
385 * we don't need to exit dsr here to wake up plane/pipe/pll
386 * if everything goes right, hw_begin will resume them all
387 * during set_power.
389 if (bdispoff /* FIXME && gbgfxsuspended */) {
390 mdfld_dsi_dbi_exit_dsr(dev, MDFLD_DSR_2D_3D);
391 bdispoff = false;
392 dev_priv->dispstatus = true;
395 mdfld_dsi_dbi_set_power(encoder, true);
396 /* FIXME if (gbgfxsuspended)
397 gbgfxsuspended = false; */
398 } else {
400 * I am not sure whether this is the perfect place to
401 * turn rpm on since we still have a lot of CRTC turnning
402 * on work to do.
404 bdispoff = true;
405 dev_priv->dispstatus = false;
406 mdfld_dsi_dbi_set_power(encoder, false);
412 * Update the DBI MIPI Panel Frame Buffer.
414 static void mdfld_dsi_dbi_update_fb(struct mdfld_dsi_dbi_output *dbi_output,
415 int pipe)
417 struct mdfld_dsi_pkg_sender *sender =
418 mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
419 struct drm_device *dev = dbi_output->dev;
420 struct drm_crtc *crtc = dbi_output->base.base.crtc;
421 struct psb_intel_crtc *psb_crtc = (crtc) ?
422 to_psb_intel_crtc(crtc) : NULL;
423 u32 dpll_reg = MRST_DPLL_A;
424 u32 dspcntr_reg = DSPACNTR;
425 u32 pipeconf_reg = PIPEACONF;
426 u32 dsplinoff_reg = DSPALINOFF;
427 u32 dspsurf_reg = DSPASURF;
428 u32 reg_offset = 0;
430 /* If mode setting on-going, back off */
431 if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
432 (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING) ||
433 !(dbi_output->mode_flags & MODE_SETTING_ENCODER_DONE))
434 return;
436 if (pipe == 2) {
437 dspcntr_reg = DSPCCNTR;
438 pipeconf_reg = PIPECCONF;
439 dsplinoff_reg = DSPCLINOFF;
440 dspsurf_reg = DSPCSURF;
441 reg_offset = MIPIC_REG_OFFSET;
444 if (!gma_power_begin(dev, true)) {
445 dev_err(dev->dev, "hw begin failed\n");
446 return;
449 /* Check DBI FIFO status */
450 if (!(REG_READ(dpll_reg) & DPLL_VCO_ENABLE) ||
451 !(REG_READ(dspcntr_reg) & DISPLAY_PLANE_ENABLE) ||
452 !(REG_READ(pipeconf_reg) & DISPLAY_PLANE_ENABLE))
453 goto update_fb_out0;
455 /* Refresh plane changes */
456 REG_WRITE(dsplinoff_reg, REG_READ(dsplinoff_reg));
457 REG_WRITE(dspsurf_reg, REG_READ(dspsurf_reg));
458 REG_READ(dspsurf_reg);
460 mdfld_dsi_send_dcs(sender,
461 DCS_WRITE_MEM_START,
462 NULL,
464 CMD_DATA_SRC_PIPE,
465 MDFLD_DSI_SEND_PACKAGE);
467 dbi_output->dsr_fb_update_done = true;
468 update_fb_out0:
469 gma_power_end(dev);
472 static int tpo_cmd_get_panel_info(struct drm_device *dev,
473 int pipe,
474 struct panel_info *pi)
476 if (!dev || !pi)
477 return -EINVAL;
479 pi->width_mm = TPO_PANEL_WIDTH;
480 pi->height_mm = TPO_PANEL_HEIGHT;
482 return 0;
486 /* TPO DBI encoder helper funcs */
487 static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
488 .dpms = mdfld_dsi_dbi_dpms,
489 .mode_fixup = mdfld_dsi_dbi_mode_fixup,
490 .prepare = mdfld_dsi_dbi_prepare,
491 .mode_set = mdfld_dsi_dbi_mode_set,
492 .commit = mdfld_dsi_dbi_commit,
495 /* TPO DBI encoder funcs */
496 static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
497 .destroy = drm_encoder_cleanup,
500 void tpo_cmd_init(struct drm_device *dev, struct panel_funcs *p_funcs)
502 p_funcs->encoder_funcs = &mdfld_dsi_dbi_encoder_funcs;
503 p_funcs->encoder_helper_funcs = &mdfld_dsi_dbi_helper_funcs;
504 p_funcs->get_config_mode = &tpo_cmd_get_config_mode;
505 p_funcs->update_fb = mdfld_dsi_dbi_update_fb;
506 p_funcs->get_panel_info = tpo_cmd_get_panel_info;
507 p_funcs->reset = mdfld_dsi_panel_reset;
508 p_funcs->drv_ic_init = mdfld_dsi_brightness_init;