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