Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/roland...
[pandora-kernel.git] / drivers / staging / gma500 / mdfld_dsi_output.c
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  * jim liu <jim.liu@intel.com>
25  * Jackie Li<yaodong.li@intel.com>
26  */
27
28 #include "mdfld_dsi_output.h"
29 #include "mdfld_dsi_dbi.h"
30 #include "mdfld_dsi_dpi.h"
31 #include "mdfld_output.h"
32 #include <asm/intel_scu_ipc.h>
33 #include "mdfld_dsi_pkg_sender.h"
34 #include <linux/pm_runtime.h>
35
36 #define MDFLD_DSI_BRIGHTNESS_MAX_LEVEL 100
37
38 static int CABC_control = 1;
39 static int LABC_control = 1;
40
41 module_param (CABC_control, int, 0644);
42 module_param (LABC_control, int, 0644);
43
44 /**
45  * make these MCS command global 
46  * we don't need 'movl' everytime we send them.
47  * FIXME: these datas were provided by OEM, we should get them from GCT.
48  **/
49 static u32 mdfld_dbi_mcs_hysteresis[] = {
50         0x42000f57, 0x8c006400, 0xff00bf00, 0xffffffff,
51         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
52         0x38000aff, 0x82005000, 0xff00ab00, 0xffffffff,
53         0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff,
54         0x000000ff,
55 };
56
57 static u32 mdfld_dbi_mcs_display_profile[] = {
58         0x50281450, 0x0000c882, 0x00000000, 0x00000000,
59         0x00000000,
60 };
61
62 static u32 mdfld_dbi_mcs_kbbc_profile[] = {
63         0x00ffcc60, 0x00000000, 0x00000000, 0x00000000,
64 }; 
65         
66 static u32 mdfld_dbi_mcs_gamma_profile[] = {
67         0x81111158, 0x88888888, 0x88888888,
68 }; 
69
70 /*
71  * write hysteresis values.
72  */
73 static void mdfld_dsi_write_hysteresis (struct mdfld_dsi_config *dsi_config,
74                                                                 int pipe)
75 {
76         struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
77
78         if(!sender) {
79                 WARN_ON(1);
80                 return;
81         }
82         mdfld_dsi_send_mcs_long_hs(sender,
83                                    mdfld_dbi_mcs_hysteresis,
84                                    17,
85                                    MDFLD_DSI_SEND_PACKAGE);
86 }
87
88 /*
89  * write display profile values.
90  */
91 static void mdfld_dsi_write_display_profile(struct mdfld_dsi_config *dsi_config, int pipe)
92 {
93         struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
94
95         if(!sender) {
96                 WARN_ON(1);
97                 return;
98         }
99         mdfld_dsi_send_mcs_long_hs(sender,
100                                    mdfld_dbi_mcs_display_profile,
101                                    5,
102                                    MDFLD_DSI_SEND_PACKAGE);
103 }
104
105 /*
106  * write KBBC profile values.
107  */
108 static void mdfld_dsi_write_kbbc_profile (struct mdfld_dsi_config * dsi_config, int pipe)
109 {
110         struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
111
112         if(!sender) {
113                 WARN_ON(1);
114                 return;
115         }
116         mdfld_dsi_send_mcs_long_hs(sender,
117                                    mdfld_dbi_mcs_kbbc_profile,
118                                    4,
119                                    MDFLD_DSI_SEND_PACKAGE);
120 }
121
122 /*
123  * write gamma setting.
124  */
125 static void mdfld_dsi_write_gamma_setting (struct mdfld_dsi_config *dsi_config, int pipe)
126 {
127         struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
128
129         if(!sender) {
130                 WARN_ON(1);
131                 return;
132         }
133         mdfld_dsi_send_mcs_long_hs(sender,
134                                    mdfld_dbi_mcs_gamma_profile,
135                                    3,
136                                    MDFLD_DSI_SEND_PACKAGE);
137 }
138
139 /*
140  * Check and see if the generic control or data buffer is empty and ready.
141  */
142 void mdfld_dsi_gen_fifo_ready (struct drm_device *dev, u32 gen_fifo_stat_reg, u32 fifo_stat)
143 {
144         u32 GEN_BF_time_out_count = 0;
145         
146         /* Check MIPI Adatper command registers */
147         for (GEN_BF_time_out_count = 0; GEN_BF_time_out_count < GEN_FB_TIME_OUT; GEN_BF_time_out_count++)
148         {
149                 if ((REG_READ(gen_fifo_stat_reg) & fifo_stat) == fifo_stat)
150                         break;
151                 udelay (100);
152         }
153
154         if (GEN_BF_time_out_count == GEN_FB_TIME_OUT)
155                 dev_err(dev->dev,
156         "mdfld_dsi_gen_fifo_ready, Timeout. gen_fifo_stat_reg = 0x%x. \n",
157                                                 gen_fifo_stat_reg);
158 }
159
160 /*
161  * Manage the DSI MIPI keyboard and display brightness.
162  * FIXME: this is exported to OSPM code. should work out an specific 
163  * display interface to OSPM. 
164  */
165 void mdfld_dsi_brightness_init(struct mdfld_dsi_config *dsi_config, int pipe)
166 {
167         struct mdfld_dsi_pkg_sender *sender = mdfld_dsi_get_pkg_sender(dsi_config);
168         struct drm_device *dev = sender->dev;
169         struct drm_psb_private *dev_priv = dev->dev_private;
170         u32 gen_ctrl_val;
171         
172         if(!sender) {
173                 WARN_ON(1);
174                 return;
175         }
176         /* Set default display backlight value to 85% (0xd8)*/
177         mdfld_dsi_send_mcs_short_hs(sender,
178                                     write_display_brightness,
179                                     0xd8,
180                                     1,
181                                     MDFLD_DSI_SEND_PACKAGE);
182
183         /* Set minimum brightness setting of CABC function to 20% (0x33)*/
184         mdfld_dsi_send_mcs_short_hs(sender,
185                                     write_cabc_min_bright,
186                                     0x33,
187                                     1,
188                                     MDFLD_DSI_SEND_PACKAGE);
189
190         mdfld_dsi_write_hysteresis(dsi_config, pipe);
191         mdfld_dsi_write_display_profile (dsi_config, pipe);
192         mdfld_dsi_write_kbbc_profile (dsi_config, pipe);
193         mdfld_dsi_write_gamma_setting (dsi_config, pipe);
194
195         /* Enable backlight or/and LABC */
196         gen_ctrl_val = BRIGHT_CNTL_BLOCK_ON | DISPLAY_DIMMING_ON| BACKLIGHT_ON;
197         if (LABC_control == 1 || CABC_control == 1)
198                 gen_ctrl_val |= DISPLAY_DIMMING_ON| DISPLAY_BRIGHTNESS_AUTO | GAMMA_AUTO;
199
200         if (LABC_control == 1)
201                 gen_ctrl_val |= AMBIENT_LIGHT_SENSE_ON;
202
203         dev_priv->mipi_ctrl_display = gen_ctrl_val;
204
205         mdfld_dsi_send_mcs_short_hs(sender,
206                                     write_ctrl_display,
207                                     (u8)gen_ctrl_val,
208                                     1,
209                                     MDFLD_DSI_SEND_PACKAGE);
210
211         if (CABC_control == 0)
212                 return;
213         mdfld_dsi_send_mcs_short_hs(sender,
214                                     write_ctrl_cabc,
215                                     UI_IMAGE,
216                                     1,
217                                     MDFLD_DSI_SEND_PACKAGE);
218 }
219
220 /*
221  * Manage the mipi display brightness.
222  * TODO: refine this interface later
223  */
224 void mdfld_dsi_brightness_control(struct drm_device *dev, int pipe, int level)
225 {
226         struct mdfld_dsi_pkg_sender *sender;
227         struct drm_psb_private *dev_priv;
228         struct mdfld_dsi_config *dsi_config;
229         u32 gen_ctrl_val;
230         int p_type;     
231         
232         if (!dev || (pipe != 0 && pipe != 2)) {
233                 dev_err(dev->dev, "Invalid parameter\n");
234                 return;
235         }
236
237         p_type = mdfld_get_panel_type(dev, 0);
238
239         dev_priv = dev->dev_private;
240
241         if(pipe)
242                 dsi_config = dev_priv->dsi_configs[1];
243         else
244                 dsi_config = dev_priv->dsi_configs[0];
245
246         sender = mdfld_dsi_get_pkg_sender(dsi_config);
247
248         if(!sender) {
249                 WARN_ON(1);
250                 return;
251         }
252
253         gen_ctrl_val = ((level * 0xff) / MDFLD_DSI_BRIGHTNESS_MAX_LEVEL) & 0xff;
254
255         dev_dbg(dev->dev,
256                 "pipe = %d, gen_ctrl_val = %d.  \n", pipe, gen_ctrl_val);
257         
258         if(p_type == TMD_VID || p_type == TMD_CMD){
259                 /* Set display backlight value */
260                 mdfld_dsi_send_mcs_short_hs(sender, 
261                                         tmd_write_display_brightness, 
262                                         (u8)gen_ctrl_val, 
263                                          1, 
264                                         MDFLD_DSI_SEND_PACKAGE);                
265         } else {                        
266                 /* Set display backlight value */
267                 mdfld_dsi_send_mcs_short_hs(sender,
268                                     write_display_brightness,
269                                     (u8)gen_ctrl_val,
270                                     1,
271                                     MDFLD_DSI_SEND_PACKAGE);
272
273
274                 /* Enable backlight control */
275                 if (level == 0)
276                         gen_ctrl_val = 0;
277                 else 
278                         gen_ctrl_val = dev_priv->mipi_ctrl_display;
279
280                 mdfld_dsi_send_mcs_short_hs(sender,
281                                     write_ctrl_display,
282                                    (u8)gen_ctrl_val,
283                                    1,
284                                    MDFLD_DSI_SEND_PACKAGE);
285         }
286 }
287
288 /*
289  * shut down DSI controller
290  */ 
291 void mdfld_dsi_controller_shutdown(struct mdfld_dsi_config * dsi_config, int pipe)
292 {
293         struct drm_device * dev;
294         u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
295         int retry = 100;
296         
297         if (!dsi_config) {
298                 WARN_ON(1);
299                 return;
300         }
301         
302         dev = dsi_config->dev;
303         
304         if (!gma_power_begin(dev, true)) {
305                 dev_err(dev->dev, "hw begin failed\n");
306                 return;
307         }
308                 
309         if(!(REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) &  DSI_DEVICE_READY)) 
310                 goto shutdown_out;
311         
312         /* Send shut down package, clean packet send bit first */
313         if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
314                 REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), 
315                                 (REG_READ(MIPIA_INTR_STAT_REG + reg_offset) | DSI_INTR_STATE_SPL_PKG_SENT));
316         }
317         
318         /*send shut down package in HS*/
319         REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_SHUTDOWN);
320         
321         
322         /*
323          * make sure shut down is sent.
324          * FIXME: add max retry counter
325          */
326         while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
327                 retry--;
328                 
329                 if(!retry) {
330                         dev_err(dev->dev, "timeout\n");
331                         break;
332                 }
333         }
334         
335         /*sleep 1 ms to ensure shutdown finished*/
336         msleep(100);
337         
338         /*un-ready device*/
339         REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
340                            (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & ~DSI_DEVICE_READY));
341
342 shutdown_out:                      
343         gma_power_end(dev);
344 }
345
346 void mdfld_dsi_controller_startup(struct mdfld_dsi_config * dsi_config, int pipe)
347 {
348         struct drm_device * dev;
349         u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
350         int retry = 100;
351         
352         
353         if (!dsi_config) {
354                 WARN_ON(1);
355                 return;
356         }
357         
358         dev = dsi_config->dev;
359         dev_dbg(dev->dev, "starting up DSI controller on pipe %d...\n", pipe);
360         
361         if (!gma_power_begin(dev, true)) {
362                 dev_err(dev->dev, "hw begin failed\n");
363                 return;
364         }
365         
366         if((REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) & DSI_DEVICE_READY)) 
367                 goto startup_out;
368         
369         /*if config DPI, turn on DPI interface*/
370         if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
371                 if(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT) {
372                         REG_WRITE((MIPIA_INTR_STAT_REG + reg_offset), DSI_INTR_STATE_SPL_PKG_SENT);
373                 }
374                 
375                 REG_WRITE((MIPIA_DPI_CONTROL_REG + reg_offset), DSI_DPI_CTRL_HS_TURN_ON);
376                 
377                 /*
378                  * make sure shut down is sent.
379                  * FIXME: add max retry counter
380                  */
381                 while(!(REG_READ(MIPIA_INTR_STAT_REG + reg_offset) & DSI_INTR_STATE_SPL_PKG_SENT)) {
382                         retry--;
383                         if(!retry) {
384                                 dev_err(dev->dev, "timeout\n");
385                                 break;
386                         }
387                 }
388                 
389                 msleep(100);
390         }
391         
392         /*set device ready*/
393         REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset),
394                            (REG_READ(MIPIA_DEVICE_READY_REG + reg_offset) | DSI_DEVICE_READY));
395
396 startup_out:    
397         gma_power_end(dev);
398 }
399
400
401 static int mdfld_dsi_get_panel_status(struct mdfld_dsi_config *dsi_config,
402                                         u8 dcs,
403                                         u32 *data,
404                                         u8 transmission)
405 {
406         struct mdfld_dsi_pkg_sender *sender
407                 = mdfld_dsi_get_pkg_sender(dsi_config);
408
409         if (!sender || !data) {
410                 DRM_ERROR("Invalid parameter\n");
411                 return -EINVAL;
412         }
413
414         if (transmission == MDFLD_DSI_HS_TRANSMISSION)
415                 return mdfld_dsi_read_mcs_hs(sender, dcs, data, 1);
416         else if (transmission == MDFLD_DSI_LP_TRANSMISSION)
417                 return mdfld_dsi_read_mcs_lp(sender, dcs, data, 1);
418         else
419                 return -EINVAL;
420 }
421
422 int mdfld_dsi_get_power_mode(struct mdfld_dsi_config *dsi_config,
423                                 u32 *mode,
424                                 u8 transmission)
425 {
426         if (!dsi_config || !mode) {
427                 DRM_ERROR("Invalid parameter\n");
428                 return -EINVAL;
429         }
430
431         return mdfld_dsi_get_panel_status(dsi_config, 0x0a, mode, transmission);
432 }
433
434 int mdfld_dsi_get_diagnostic_result(struct mdfld_dsi_config *dsi_config,
435                                         u32 *result,
436                                         u8 transmission)
437 {
438         if (!dsi_config || !result) {
439                 DRM_ERROR("Invalid parameter\n");
440                 return -EINVAL;
441         }
442
443         return mdfld_dsi_get_panel_status(dsi_config, 0x0f, result,
444                                           transmission);
445 }
446
447 /*
448  * NOTE: this function was used by OSPM.
449  * TODO: will be removed later, should work out display interfaces for OSPM
450  */
451 void mdfld_dsi_controller_init(struct mdfld_dsi_config * dsi_config, int pipe)
452 {
453         if(!dsi_config || ((pipe != 0) && (pipe != 2))) {
454                 WARN_ON(1);
455                 return;
456         }
457
458         if(dsi_config->type)
459                 mdfld_dsi_dpi_controller_init(dsi_config, pipe);
460         else
461                 mdfld_dsi_controller_dbi_init(dsi_config, pipe);
462 }
463
464 static void mdfld_dsi_connector_save(struct drm_connector * connector)
465 {
466 }
467
468 static void mdfld_dsi_connector_restore(struct drm_connector * connector)
469 {
470 }
471
472 static enum drm_connector_status mdfld_dsi_connector_detect(struct drm_connector * connector, bool force)
473 {
474         struct psb_intel_output *psb_output
475                                         = to_psb_intel_output(connector);
476         struct mdfld_dsi_connector *dsi_connector
477                                         = MDFLD_DSI_CONNECTOR(psb_output);
478         return dsi_connector->status;
479 }
480
481 static int mdfld_dsi_connector_set_property(struct drm_connector *connector,
482                                         struct drm_property *property,
483                                         uint64_t value)
484 {
485         struct drm_encoder *encoder = connector->encoder;
486
487         if (!strcmp(property->name, "scaling mode") && encoder) {
488                 struct psb_intel_crtc * psb_crtc = to_psb_intel_crtc(encoder->crtc);
489                 bool bTransitionFromToCentered;
490                 uint64_t curValue;
491
492                 if (!psb_crtc)
493                         goto set_prop_error;
494
495                 switch (value) {
496                 case DRM_MODE_SCALE_FULLSCREEN:
497                         break;
498                 case DRM_MODE_SCALE_NO_SCALE:
499                         break;
500                 case DRM_MODE_SCALE_ASPECT:
501                         break;
502                 default:
503                         goto set_prop_error;
504                 }
505
506                 if (drm_connector_property_get_value(connector, property, &curValue))
507                         goto set_prop_error;
508
509                 if (curValue == value)
510                         goto set_prop_done;
511
512                 if (drm_connector_property_set_value(connector, property, value))
513                         goto set_prop_error;
514
515                 bTransitionFromToCentered = (curValue == DRM_MODE_SCALE_NO_SCALE) ||
516                         (value == DRM_MODE_SCALE_NO_SCALE);
517
518                 if (psb_crtc->saved_mode.hdisplay != 0 &&
519                     psb_crtc->saved_mode.vdisplay != 0) {
520                         if (bTransitionFromToCentered) {
521                                 if (!drm_crtc_helper_set_mode(encoder->crtc, &psb_crtc->saved_mode,
522                                             encoder->crtc->x, encoder->crtc->y, encoder->crtc->fb))
523                                         goto set_prop_error;
524                         } else {
525                                 struct drm_encoder_helper_funcs *pEncHFuncs  = encoder->helper_private;
526                                 pEncHFuncs->mode_set(encoder, &psb_crtc->saved_mode,
527                                                      &psb_crtc->saved_adjusted_mode);
528                         }
529                 }
530 #ifdef CONFIG_BACKLIGHT_CLASS_DEVICE
531         } else if (!strcmp(property->name, "backlight") && encoder) {
532                 struct drm_psb_private *dev_priv = encoder->dev->dev_private;
533                 struct backlight_device *psb_bd = dev_priv->backlight_device;
534                 dev_dbg(encoder->dev->dev, "backlight level = %d\n", (int)value);
535                 if (drm_connector_property_set_value(connector, property, value))
536                         goto set_prop_error;
537                 else {
538                         dev_dbg(encoder->dev->dev,
539                                         "set brightness to %d", (int)value);
540                         if (psb_bd) {
541                                 psb_bd->props.brightness = value;
542                                 backlight_update_status(psb_bd);
543                         }
544                 }
545 #endif
546         }
547 set_prop_done:
548     return 0;
549 set_prop_error:
550     return -1;
551 }
552
553 static void mdfld_dsi_connector_destroy(struct drm_connector *connector)
554 {
555         struct psb_intel_output * psb_output = to_psb_intel_output(connector);
556         struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
557         struct mdfld_dsi_pkg_sender * sender;
558         
559         if(!dsi_connector)
560                 return;
561         
562         drm_sysfs_connector_remove(connector);
563         drm_connector_cleanup(connector);
564         
565         sender = dsi_connector->pkg_sender;
566
567         mdfld_dsi_pkg_sender_destroy(sender);
568
569         kfree(dsi_connector);
570 }
571
572 static int mdfld_dsi_connector_get_modes(struct drm_connector * connector)
573 {
574         struct psb_intel_output * psb_output = to_psb_intel_output(connector);
575         struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
576         struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
577         struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
578         struct drm_display_mode * dup_mode = NULL;
579         struct drm_device * dev = connector->dev;
580         
581         connector->display_info.min_vfreq = 0;
582         connector->display_info.max_vfreq = 200;
583         connector->display_info.min_hfreq = 0;
584         connector->display_info.max_hfreq = 200;
585
586         if(fixed_mode) {
587                 dev_dbg(dev->dev, "fixed_mode %dx%d\n",
588                         fixed_mode->hdisplay, fixed_mode->vdisplay);
589                 
590                 dup_mode = drm_mode_duplicate(dev, fixed_mode);
591                 drm_mode_probed_add(connector, dup_mode);
592                 return 1;
593         }
594         dev_err(dev->dev, "Didn't get any modes!\n");
595         return 0;
596 }
597
598 static int mdfld_dsi_connector_mode_valid(struct drm_connector * connector, struct drm_display_mode * mode)
599 {
600         struct psb_intel_output * psb_output = to_psb_intel_output(connector);
601         struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
602         struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
603         struct drm_display_mode * fixed_mode = dsi_config->fixed_mode;
604
605         dev_dbg(connector->dev->dev, "mode %p, fixed mode %p\n",
606                                                         mode, fixed_mode);
607
608         if(mode->flags & DRM_MODE_FLAG_DBLSCAN) 
609                 return MODE_NO_DBLESCAN;
610
611         if(mode->flags & DRM_MODE_FLAG_INTERLACE)
612                 return MODE_NO_INTERLACE;
613
614         /**
615          * FIXME: current DC has no fitting unit, reject any mode setting request
616          * will figure out a way to do up-scaling(pannel fitting) later.  
617          **/
618         if(fixed_mode) {
619                 if(mode->hdisplay != fixed_mode->hdisplay)
620                         return MODE_PANEL;
621
622                 if(mode->vdisplay != fixed_mode->vdisplay)
623                         return MODE_PANEL;
624         }
625         dev_dbg(connector->dev->dev, "mode ok\n");
626
627         return MODE_OK;
628 }
629
630 static void mdfld_dsi_connector_dpms(struct drm_connector *connector, int mode)
631 {
632 #ifdef CONFIG_PM_RUNTIME
633         struct drm_device * dev = connector->dev;
634         struct drm_psb_private * dev_priv = dev->dev_private;
635         bool panel_on, panel_on2;
636 #endif
637         /* First, execute DPMS */
638         drm_helper_connector_dpms(connector, mode);
639
640 #ifdef CONFIG_PM_RUNTIME
641         if(mdfld_panel_dpi(dev)) {
642                 /* DPI panel */
643                 panel_on = dev_priv->dpi_panel_on;
644                 panel_on2 = dev_priv->dpi_panel_on2;
645         } else {
646                 /* DBI panel */
647                 panel_on = dev_priv->dbi_panel_on;
648                 panel_on2 = dev_priv->dbi_panel_on2;
649         }
650
651         /* Then check all display panels + monitors status */
652         /* Make sure that the Display (B) sub-system status isn't i3 when
653          * R/W the DC register, otherwise "Fabric error" issue would occur
654          * during S0i3 state. */
655         if(!panel_on && !panel_on2 && !(REG_READ(HDMIB_CONTROL)
656                                                 & HDMIB_PORT_EN)) {
657                 /* Request rpm idle */
658                 if(dev_priv->rpm_enabled)
659                         pm_request_idle(&dev->pdev->dev);
660         }
661         /*
662          * if rpm wasn't enabled yet, try to allow it
663          * FIXME: won't enable rpm for DPI since DPI
664          * CRTC setting is a little messy now.
665          * Enable it later!
666          */
667 #if 0
668         if(!dev_priv->rpm_enabled && !mdfld_panel_dpi(dev))
669                 ospm_runtime_pm_allow(dev);
670 #endif
671 #endif
672 }
673
674 static struct drm_encoder *mdfld_dsi_connector_best_encoder(
675                                         struct drm_connector *connector) 
676 {
677         struct psb_intel_output * psb_output = to_psb_intel_output(connector);
678         struct mdfld_dsi_connector * dsi_connector = MDFLD_DSI_CONNECTOR(psb_output);
679         struct mdfld_dsi_config * dsi_config = mdfld_dsi_get_config(dsi_connector);
680         struct mdfld_dsi_encoder * encoder = NULL;
681         
682         if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) 
683                 encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DBI];
684         else if (dsi_config->type == MDFLD_DSI_ENCODER_DPI) 
685                 encoder = dsi_config->encoders[MDFLD_DSI_ENCODER_DPI];
686         
687         dev_dbg(connector->dev->dev, "get encoder %p\n", encoder);
688         
689         if(!encoder) {
690                 dev_err(connector->dev->dev,
691                         "Invalid encoder for type %d\n", dsi_config->type);
692                 return NULL;
693         }
694         dsi_config->encoder = encoder;  
695         return &encoder->base;  
696 }
697
698 /* DSI connector funcs */
699 static const struct drm_connector_funcs mdfld_dsi_connector_funcs = {
700         .dpms = /*drm_helper_connector_dpms*/mdfld_dsi_connector_dpms,
701         .save = mdfld_dsi_connector_save,
702         .restore = mdfld_dsi_connector_restore,
703         .detect = mdfld_dsi_connector_detect,
704         .fill_modes = drm_helper_probe_single_connector_modes,
705         .set_property = mdfld_dsi_connector_set_property,
706         .destroy = mdfld_dsi_connector_destroy,
707 };
708
709 /* DSI connector helper funcs */
710 static const struct drm_connector_helper_funcs mdfld_dsi_connector_helper_funcs = {
711         .get_modes = mdfld_dsi_connector_get_modes,
712         .mode_valid = mdfld_dsi_connector_mode_valid,
713         .best_encoder = mdfld_dsi_connector_best_encoder,
714 };
715
716 static int mdfld_dsi_get_default_config(struct drm_device * dev, 
717                                                                                 struct mdfld_dsi_config * config, int pipe)
718 {
719         if(!dev || !config) {
720                 WARN_ON(1);
721                 return -EINVAL;
722         }
723         
724         config->bpp = 24;
725         config->type = mdfld_panel_dpi(dev);
726         config->lane_count = 2;
727         config->channel_num = 0;
728         /*NOTE: video mode is ignored when type is MDFLD_DSI_ENCODER_DBI*/
729         if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
730                 config->video_mode = MDFLD_DSI_VIDEO_NON_BURST_MODE_SYNC_PULSE;
731         } else {
732                 config->video_mode = MDFLD_DSI_VIDEO_BURST_MODE;
733         }
734         
735         return 0;
736 }
737
738 /*
739  * Returns the panel fixed mode from configuration. 
740  */
741 struct drm_display_mode *
742 mdfld_dsi_get_configuration_mode(struct mdfld_dsi_config * dsi_config, int pipe)
743 {
744         struct drm_device *dev = dsi_config->dev;
745         struct drm_display_mode *mode;
746         struct drm_psb_private *dev_priv = dev->dev_private;
747         struct mrst_timing_info *ti = &dev_priv->gct_data.DTD;
748         bool use_gct = false;
749
750         mode = kzalloc(sizeof(*mode), GFP_KERNEL);
751         if (!mode) {
752                 dev_err(dev->dev, "Out of memory for mode\n");
753                 return NULL;
754         }
755         if (use_gct) {
756                 dev_dbg(dev->dev, "gct find MIPI panel.\n");
757
758                 mode->hdisplay = (ti->hactive_hi << 8) | ti->hactive_lo;
759                 mode->vdisplay = (ti->vactive_hi << 8) | ti->vactive_lo;
760                 mode->hsync_start = mode->hdisplay + \
761                                 ((ti->hsync_offset_hi << 8) | \
762                                 ti->hsync_offset_lo);
763                 mode->hsync_end = mode->hsync_start + \
764                                 ((ti->hsync_pulse_width_hi << 8) | \
765                                 ti->hsync_pulse_width_lo);
766                 mode->htotal = mode->hdisplay + ((ti->hblank_hi << 8) | \
767                                                                 ti->hblank_lo);
768                 mode->vsync_start = \
769                         mode->vdisplay + ((ti->vsync_offset_hi << 8) | \
770                                                 ti->vsync_offset_lo);
771                 mode->vsync_end = \
772                         mode->vsync_start + ((ti->vsync_pulse_width_hi << 8) | \
773                                                 ti->vsync_pulse_width_lo);
774                 mode->vtotal = mode->vdisplay + \
775                                 ((ti->vblank_hi << 8) | ti->vblank_lo);
776                 mode->clock = ti->pixel_clock * 10;
777         } else {
778                 if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) { 
779                         if (mdfld_get_panel_type(dev, pipe) == TMD_VID) {
780                                 mode->hdisplay = 480;
781                                 mode->vdisplay = 854;
782                                 mode->hsync_start = 487;
783                                 mode->hsync_end = 490;
784                                 mode->htotal = 499;
785                                 mode->vsync_start = 861;
786                                 mode->vsync_end = 865;
787                                 mode->vtotal = 873;
788                                 mode->clock = 33264;
789                         } else {
790                                 mode->hdisplay = 864;
791                                 mode->vdisplay = 480;
792                                 mode->hsync_start = 873;
793                                 mode->hsync_end = 876;
794                                 mode->htotal = 887;
795                                 mode->vsync_start = 487;
796                                 mode->vsync_end = 490;
797                                 mode->vtotal = 499;
798                                 mode->clock = 33264;
799                         }
800                 } else if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
801                         mode->hdisplay = 864;
802                         mode->vdisplay = 480;
803                         mode->hsync_start = 872;
804                         mode->hsync_end = 876;
805                         mode->htotal = 884;
806                         mode->vsync_start = 482;
807                         mode->vsync_end = 494;
808                         mode->vtotal = 486;
809                         mode->clock = 25777;
810                         
811                 }
812         }
813
814         drm_mode_set_name(mode);
815         drm_mode_set_crtcinfo(mode, 0);
816         
817         mode->type |= DRM_MODE_TYPE_PREFERRED;
818
819         return mode;
820 }
821
822 int mdfld_dsi_panel_reset(int pipe)
823 {
824         unsigned gpio;
825         int ret = 0;
826
827         switch (pipe) {
828         case 0:
829                 gpio = 128;
830                 break;
831         case 2:
832                 gpio = 34;
833                 break;
834         default:
835                 DRM_ERROR("Invalid output\n");
836                 return -EINVAL;
837         }
838
839         ret = gpio_request(gpio, "gfx");
840         if (ret) {
841                 DRM_ERROR("gpio_rqueset failed\n");
842                 return ret;
843         }
844
845         ret = gpio_direction_output(gpio, 1);
846         if (ret) {
847                 DRM_ERROR("gpio_direction_output failed\n");
848                 goto gpio_error;
849         }
850
851         gpio_get_value(128);
852
853 gpio_error:
854         if (gpio_is_valid(gpio))
855                 gpio_free(gpio);
856
857         return ret;
858 }
859
860 /*
861  * MIPI output init
862  * @dev drm device
863  * @pipe pipe number. 0 or 2
864  * @config 
865  * 
866  * Do the initialization of a MIPI output, including create DRM mode objects
867  * initialization of DSI output on @pipe 
868  */
869 void mdfld_dsi_output_init(struct drm_device *dev,
870                            int pipe, 
871                            struct mdfld_dsi_config *config,
872                            struct panel_funcs* p_cmd_funcs,
873                            struct panel_funcs* p_vid_funcs)
874 {
875         struct mdfld_dsi_config * dsi_config;
876         struct mdfld_dsi_connector * dsi_connector;
877         struct psb_intel_output * psb_output;
878         struct drm_connector * connector;
879         struct mdfld_dsi_encoder * encoder;
880         struct drm_psb_private * dev_priv = dev->dev_private;
881         struct panel_info dsi_panel_info;
882         u32 width_mm, height_mm;
883
884         dev_dbg(dev->dev, "init DSI output on pipe %d\n", pipe);
885         
886         if(!dev || ((pipe != 0) && (pipe != 2))) {
887                 WARN_ON(1);
888                 return;
889         }
890         
891         /*create a new connetor*/
892         dsi_connector = kzalloc(sizeof(struct mdfld_dsi_connector), GFP_KERNEL);
893         if(!dsi_connector) {
894                 DRM_ERROR("No memory");
895                 return;
896         }
897         
898         dsi_connector->pipe =  pipe;
899         
900         /*set DSI config*/
901         if(config) { 
902                 dsi_config = config;
903         } else {
904                 dsi_config = kzalloc(sizeof(struct mdfld_dsi_config), GFP_KERNEL);
905                 if(!dsi_config) {
906                         dev_err(dev->dev,
907                                 "cannot allocate memory for DSI config\n");
908                         goto dsi_init_err0;
909                 }
910                 
911                 mdfld_dsi_get_default_config(dev, dsi_config, pipe);
912         }
913         
914         dsi_connector->private = dsi_config;
915         
916         dsi_config->changed = 1;
917         dsi_config->dev = dev;
918         
919         /* Init fixed mode basing on DSI config type */
920         if(dsi_config->type == MDFLD_DSI_ENCODER_DBI) {
921                 dsi_config->fixed_mode = p_cmd_funcs->get_config_mode(dev);
922                 if(p_cmd_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
923                         goto dsi_init_err0;
924         } else if(dsi_config->type == MDFLD_DSI_ENCODER_DPI) {
925                 dsi_config->fixed_mode = p_vid_funcs->get_config_mode(dev);
926                 if(p_vid_funcs->get_panel_info(dev, pipe, &dsi_panel_info))
927                         goto dsi_init_err0;
928         }
929
930         width_mm = dsi_panel_info.width_mm;
931         height_mm = dsi_panel_info.height_mm;
932
933         dsi_config->mode = dsi_config->fixed_mode;
934         dsi_config->connector = dsi_connector;
935         
936         if(!dsi_config->fixed_mode) {
937                 dev_err(dev->dev, "No pannel fixed mode was found\n");
938                 goto dsi_init_err0;
939         }
940         
941         if(pipe && dev_priv->dsi_configs[0]) {
942                 dsi_config->dvr_ic_inited = 0;
943                 dev_priv->dsi_configs[1] = dsi_config;
944         } else if(pipe == 0) {
945                 dsi_config->dvr_ic_inited = 1;
946                 dev_priv->dsi_configs[0] = dsi_config;
947         } else {
948                 dev_err(dev->dev, "Trying to init MIPI1 before MIPI0\n");
949                 goto dsi_init_err0;
950         }
951
952         /*init drm connector object*/
953         psb_output = &dsi_connector->base;
954         
955         psb_output->type = (pipe == 0) ? INTEL_OUTPUT_MIPI : INTEL_OUTPUT_MIPI2;
956
957         connector = &psb_output->base;
958         /* Revisit type if MIPI/HDMI bridges ever appear on Medfield */
959         drm_connector_init(dev, connector, &mdfld_dsi_connector_funcs,
960                                                 DRM_MODE_CONNECTOR_LVDS);
961         drm_connector_helper_add(connector, &mdfld_dsi_connector_helper_funcs);
962         
963         connector->display_info.subpixel_order = SubPixelHorizontalRGB;
964         connector->display_info.width_mm = width_mm;
965         connector->display_info.height_mm = height_mm;
966         connector->interlace_allowed = false;
967         connector->doublescan_allowed = false;
968         
969         /* Attach properties */
970         drm_connector_attach_property(connector, dev->mode_config.scaling_mode_property, DRM_MODE_SCALE_FULLSCREEN);
971         drm_connector_attach_property(connector, dev_priv->backlight_property, MDFLD_DSI_BRIGHTNESS_MAX_LEVEL);
972
973         /* Init DSI package sender on this output */
974         if (mdfld_dsi_pkg_sender_init(dsi_connector, pipe)) {
975                 DRM_ERROR("Package Sender initialization failed on pipe %d\n", pipe);
976                 goto dsi_init_err0;
977         }
978
979         /* Init DBI & DPI encoders */
980         if (p_cmd_funcs) {
981                 encoder = mdfld_dsi_dbi_init(dev, dsi_connector, p_cmd_funcs);
982                 if(!encoder) {
983                         dev_err(dev->dev, "Create DBI encoder failed\n");
984                         goto dsi_init_err1;
985                 }
986                 encoder->private = dsi_config;
987                 dsi_config->encoders[MDFLD_DSI_ENCODER_DBI] = encoder;
988         }
989         
990         if(p_vid_funcs) {
991                 encoder = mdfld_dsi_dpi_init(dev, dsi_connector, p_vid_funcs);
992                 if(!encoder) {
993                         dev_err(dev->dev, "Create DPI encoder failed\n");
994                         goto dsi_init_err1;
995                 }
996                 encoder->private = dsi_config;
997                 dsi_config->encoders[MDFLD_DSI_ENCODER_DPI] = encoder;
998         }
999         
1000         drm_sysfs_connector_add(connector);
1001         return;
1002         
1003         /*TODO: add code to destroy outputs on error*/
1004 dsi_init_err1:
1005         /*destroy sender*/
1006         mdfld_dsi_pkg_sender_destroy(dsi_connector->pkg_sender);
1007
1008         drm_connector_cleanup(connector);
1009         kfree(dsi_config->fixed_mode);
1010         kfree(dsi_config);
1011 dsi_init_err0:
1012         kfree(dsi_connector);
1013 }