Merge branches 'imx/pata' and 'imx/sata' into next/driver
[pandora-kernel.git] / drivers / staging / gma500 / mdfld_dsi_dbi.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_dbi.h"
29 #include "mdfld_dsi_dbi_dpu.h"
30 #include "mdfld_dsi_pkg_sender.h"
31
32 #include "power.h"
33 #include <linux/pm_runtime.h>
34
35 int enable_gfx_rtpm;
36
37 extern struct drm_device *gpDrmDevice;
38 extern int gfxrtdelay;
39 int enter_dsr;
40 struct mdfld_dsi_dbi_output *gdbi_output;
41 extern bool gbgfxsuspended;
42 extern int enable_gfx_rtpm;
43 extern int gfxrtdelay;
44
45 #define MDFLD_DSR_MAX_IDLE_COUNT        2
46
47 /*
48  * set refreshing area
49  */
50 int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
51                                 u16 x1, u16 y1, u16 x2, u16 y2)
52 {
53         struct mdfld_dsi_pkg_sender *sender =
54                 mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
55         u8 param[4];
56         u8 cmd;
57         int err;
58
59         if (!sender) {
60                 WARN_ON(1);
61                 return -EINVAL;
62         }
63
64         /* Set column */
65         cmd = DCS_SET_COLUMN_ADDRESS;
66         param[0] = x1 >> 8;
67         param[1] = x1;
68         param[2] = x2 >> 8;
69         param[3] = x2;
70
71         err = mdfld_dsi_send_dcs(sender,
72                                  cmd,
73                                  param,
74                                  4,
75                                  CMD_DATA_SRC_SYSTEM_MEM,
76                                  MDFLD_DSI_QUEUE_PACKAGE);
77         if (err) {
78                 dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
79                 goto err_out;
80         }
81
82         /* Set page */
83         cmd = DCS_SET_PAGE_ADDRESS;
84         param[0] = y1 >> 8;
85         param[1] = y1;
86         param[2] = y2 >> 8;
87         param[3] = y2;
88
89         err = mdfld_dsi_send_dcs(sender,
90                                  cmd,
91                                  param,
92                                  4,
93                                  CMD_DATA_SRC_SYSTEM_MEM,
94                                  MDFLD_DSI_QUEUE_PACKAGE);
95         if (err) {
96                 dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
97                 goto err_out;
98         }
99
100         /*update screen*/
101         err = mdfld_dsi_send_dcs(sender,
102                                  write_mem_start,
103                                  NULL,
104                                  0,
105                                  CMD_DATA_SRC_PIPE,
106                                  MDFLD_DSI_QUEUE_PACKAGE);
107         if (err) {
108                 dev_err(sender->dev->dev, "DCS 0x%x sent failed\n", cmd);
109                 goto err_out;
110         }
111         mdfld_dsi_cmds_kick_out(sender);
112 err_out:
113         return err;
114 }
115
116 /*
117  * set panel's power state
118  */
119 int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
120                                                                 int mode)
121 {
122         struct drm_device *dev = dbi_output->dev;
123         struct mdfld_dsi_pkg_sender *sender =
124                 mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
125         u8 param = 0;
126         u32 err = 0;
127
128         if (!sender) {
129                 WARN_ON(1);
130                 return -EINVAL;
131         }
132
133         if (mode == DRM_MODE_DPMS_ON) {
134                 /* Exit sleep mode */
135                 err = mdfld_dsi_send_dcs(sender,
136                                          DCS_EXIT_SLEEP_MODE,
137                                          NULL,
138                                          0,
139                                          CMD_DATA_SRC_SYSTEM_MEM,
140                                          MDFLD_DSI_QUEUE_PACKAGE);
141                 if (err) {
142                         dev_err(dev->dev, "DCS 0x%x sent failed\n",
143                                                 DCS_EXIT_SLEEP_MODE);
144                         goto power_err;
145                 }
146
147                 /* Set display on */
148                 err = mdfld_dsi_send_dcs(sender,
149                                          DCS_SET_DISPLAY_ON,
150                                          NULL,
151                                          0,
152                                          CMD_DATA_SRC_SYSTEM_MEM,
153                                          MDFLD_DSI_QUEUE_PACKAGE);
154                 if (err) {
155                         dev_err(dev->dev, "DCS 0x%x sent failed\n",
156                                                         DCS_SET_DISPLAY_ON);
157                         goto power_err;
158                 }
159
160                 /* set tear effect on */
161                 err = mdfld_dsi_send_dcs(sender,
162                                          DCS_SET_TEAR_ON,
163                                          &param,
164                                          1,
165                                          CMD_DATA_SRC_SYSTEM_MEM,
166                                          MDFLD_DSI_QUEUE_PACKAGE);
167                 if (err) {
168                         dev_err(dev->dev, "DCS 0x%x sent failed\n",
169                                                         set_tear_on);
170                         goto power_err;
171                 }
172
173                 /**
174                  * FIXME: remove this later
175                  */
176                 err = mdfld_dsi_send_dcs(sender,
177                                          DCS_WRITE_MEM_START,
178                                          NULL,
179                                          0,
180                                          CMD_DATA_SRC_PIPE,
181                                          MDFLD_DSI_QUEUE_PACKAGE);
182                 if (err) {
183                         dev_err(dev->dev, "DCS 0x%x sent failed\n",
184                                                 DCS_WRITE_MEM_START);
185                         goto power_err;
186                 }
187         } else {
188                 /* Set tear effect off */
189                 err = mdfld_dsi_send_dcs(sender,
190                                          DCS_SET_TEAR_OFF,
191                                          NULL,
192                                          0,
193                                          CMD_DATA_SRC_SYSTEM_MEM,
194                                          MDFLD_DSI_QUEUE_PACKAGE);
195                 if (err) {
196                         dev_err(dev->dev, "DCS 0x%x sent failed\n",
197                                                         DCS_SET_TEAR_OFF);
198                         goto power_err;
199                 }
200
201                 /* Turn display off */
202                 err = mdfld_dsi_send_dcs(sender,
203                                          DCS_SET_DISPLAY_OFF,
204                                          NULL,
205                                          0,
206                                          CMD_DATA_SRC_SYSTEM_MEM,
207                                          MDFLD_DSI_QUEUE_PACKAGE);
208                 if (err) {
209                         dev_err(dev->dev, "DCS 0x%x sent failed\n",
210                                                 DCS_SET_DISPLAY_OFF);
211                         goto power_err;
212                 }
213
214                 /* Now enter sleep mode */
215                 err = mdfld_dsi_send_dcs(sender,
216                                          DCS_ENTER_SLEEP_MODE,
217                                          NULL,
218                                          0,
219                                          CMD_DATA_SRC_SYSTEM_MEM,
220                                          MDFLD_DSI_QUEUE_PACKAGE);
221                 if (err) {
222                         dev_err(dev->dev, "DCS 0x%x sent failed\n",
223                                                         DCS_ENTER_SLEEP_MODE);
224                         goto power_err;
225                 }
226         }
227         mdfld_dsi_cmds_kick_out(sender);
228 power_err:
229         return err;
230 }
231
232 /*
233  * send a generic DCS command with a parameter list
234  */
235 int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
236                         u8 dcs,  u8 *param, u32 num, u8 data_src)
237 {
238         struct mdfld_dsi_pkg_sender *sender =
239                 mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
240         int ret;
241
242         if (!sender) {
243                 WARN_ON(1);
244                 return -EINVAL;
245         }
246
247         ret = mdfld_dsi_send_dcs(sender,
248                                  dcs,
249                                  param,
250                                  num,
251                                  data_src,
252                                  MDFLD_DSI_SEND_PACKAGE);
253
254         return ret;
255 }
256
257 /*
258  * Enter DSR
259  */
260 void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
261 {
262         u32 reg_val;
263         struct drm_device *dev = dbi_output->dev;
264         struct drm_psb_private *dev_priv = dev->dev_private;
265         struct drm_crtc *crtc = dbi_output->base.base.crtc;
266         struct psb_intel_crtc *psb_crtc = (crtc) ?
267                                         to_psb_intel_crtc(crtc) : NULL;
268         u32 dpll_reg = MRST_DPLL_A;
269         u32 pipeconf_reg = PIPEACONF;
270         u32 dspcntr_reg = DSPACNTR;
271
272         if (!dbi_output)
273                 return;
274
275         /* FIXME check if can go */
276         dev_priv->is_in_idle = true;
277
278         gdbi_output = dbi_output;
279         if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
280                 (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
281                 return;
282
283         if (pipe == 2) {
284                 dpll_reg = MRST_DPLL_A;
285                 pipeconf_reg = PIPECCONF;
286                 dspcntr_reg = DSPCCNTR;
287         }
288
289         if (!gma_power_begin(dev, true)) {
290                 dev_err(dev->dev, "hw begin failed\n");
291                 return;
292         }
293         /* Disable te interrupts */
294         mdfld_disable_te(dev, pipe);
295
296         /* Disable plane */
297         reg_val = REG_READ(dspcntr_reg);
298         if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
299                 REG_WRITE(dspcntr_reg, reg_val & ~DISPLAY_PLANE_ENABLE);
300                 REG_READ(dspcntr_reg);
301         }
302
303         /* Disable pipe */
304         reg_val = REG_READ(pipeconf_reg);
305         if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
306                 reg_val &= ~DISPLAY_PLANE_ENABLE;
307                 reg_val |= (PIPECONF_PLANE_OFF | PIPECONF_CURSOR_OFF);
308                 REG_WRITE(pipeconf_reg, reg_val);
309                 REG_READ(pipeconf_reg);
310                 mdfldWaitForPipeDisable(dev, pipe);
311         }
312
313         /* Disable DPLL */
314         reg_val = REG_READ(dpll_reg);
315         if (!(reg_val & DPLL_VCO_ENABLE)) {
316                 reg_val &= ~DPLL_VCO_ENABLE;
317                 REG_WRITE(dpll_reg, reg_val);
318                 REG_READ(dpll_reg);
319                 udelay(500);
320         }
321
322         gma_power_end(dev);
323         dbi_output->mode_flags |= MODE_SETTING_IN_DSR;
324         if (pipe == 2) {
325                 enter_dsr = 1;
326                 /* pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay); */
327         }
328 }
329
330 static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
331                         int pipe)
332 {
333         struct drm_device *dev = dbi_output->dev;
334         struct drm_crtc *crtc = dbi_output->base.base.crtc;
335         struct psb_intel_crtc *psb_crtc = (crtc) ?
336                                         to_psb_intel_crtc(crtc) : NULL;
337         u32 reg_val;
338         u32 dpll_reg = MRST_DPLL_A;
339         u32 pipeconf_reg = PIPEACONF;
340         u32 dspcntr_reg = DSPACNTR;
341         u32 reg_offset = 0;
342
343         /*if mode setting on-going, back off*/
344         if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
345                 (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
346                 return;
347
348         if (pipe == 2) {
349                 dpll_reg = MRST_DPLL_A;
350                 pipeconf_reg = PIPECCONF;
351                 dspcntr_reg = DSPCCNTR;
352                 reg_offset = MIPIC_REG_OFFSET;
353         }
354
355         if (!gma_power_begin(dev, true)) {
356                 dev_err(dev->dev, "hw begin failed\n");
357                 return;
358         }
359
360         /* Enable DPLL */
361         reg_val = REG_READ(dpll_reg);
362         if (!(reg_val & DPLL_VCO_ENABLE)) {
363                 if (reg_val & MDFLD_PWR_GATE_EN) {
364                         reg_val &= ~MDFLD_PWR_GATE_EN;
365                         REG_WRITE(dpll_reg, reg_val);
366                         REG_READ(dpll_reg);
367                         udelay(500);
368                 }
369
370                 reg_val |= DPLL_VCO_ENABLE;
371                 REG_WRITE(dpll_reg, reg_val);
372                 REG_READ(dpll_reg);
373                 udelay(500);
374
375                 /* Add timeout */
376                 while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK))
377                         cpu_relax();
378         }
379
380         /* Enable pipe */
381         reg_val = REG_READ(pipeconf_reg);
382         if (!(reg_val & PIPEACONF_ENABLE)) {
383                 reg_val |= PIPEACONF_ENABLE;
384                 REG_WRITE(pipeconf_reg, reg_val);
385                 REG_READ(pipeconf_reg);
386                 udelay(500);
387                 mdfldWaitForPipeEnable(dev, pipe);
388         }
389
390         /* Enable plane */
391         reg_val = REG_READ(dspcntr_reg);
392         if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
393                 reg_val |= DISPLAY_PLANE_ENABLE;
394                 REG_WRITE(dspcntr_reg, reg_val);
395                 REG_READ(dspcntr_reg);
396                 udelay(500);
397         }
398
399         /* Enable TE interrupt on this pipe */
400         mdfld_enable_te(dev, pipe);
401         gma_power_end(dev);
402
403         /*clean IN_DSR flag*/
404         dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
405 }
406
407 /*
408  * Exit from DSR
409  */
410 void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src)
411 {
412         struct drm_psb_private *dev_priv = dev->dev_private;
413         struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
414         struct mdfld_dsi_dbi_output **dbi_output;
415         int i;
416         int pipe;
417
418         /* FIXME can go ? */
419         dev_priv->is_in_idle = false;
420         dbi_output = dsr_info->dbi_outputs;
421
422 #ifdef CONFIG_PM_RUNTIME
423          if (!enable_gfx_rtpm) {
424 /*                pm_runtime_allow(&gpDrmDevice->pdev->dev); */
425 /*              schedule_delayed_work(&rtpm_work, 30 * 1000);*/ /* FIXME: HZ ? */
426         }
427 #endif
428
429         /* For each output, exit dsr */
430         for (i = 0; i < dsr_info->dbi_output_num; i++) {
431                 /* If panel has been turned off, skip */
432                 if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on)
433                         continue;
434                 pipe = dbi_output[i]->channel_num ? 2 : 0;
435                 enter_dsr = 0;
436                 mdfld_dbi_output_exit_dsr(dbi_output[i], pipe);
437         }
438         dev_priv->dsr_fb_update |= update_src;
439 }
440
441 static bool mdfld_dbi_is_in_dsr(struct drm_device *dev)
442 {
443         if (REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE)
444                 return false;
445         if ((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) ||
446            (REG_READ(PIPECCONF) & PIPEACONF_ENABLE))
447                 return false;
448         if ((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) ||
449            (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE))
450                 return false;
451
452         return true;
453 }
454
455 /* Periodically update dbi panel */
456 void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
457 {
458         struct drm_psb_private *dev_priv = dev->dev_private;
459         struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
460         struct mdfld_dsi_dbi_output **dbi_outputs;
461         struct mdfld_dsi_dbi_output *dbi_output;
462         int i;
463         int can_enter_dsr = 0;
464         u32 damage_mask;
465
466         dbi_outputs = dsr_info->dbi_outputs;
467         dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0];
468
469         if (!dbi_output)
470                 return;
471
472         if (pipe == 0)
473                 damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0;
474         else if (pipe == 2)
475                 damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2;
476         else
477                 return;
478
479         /* If FB is damaged and panel is on update on-panel FB */
480         if (damage_mask && dbi_output->dbi_panel_on) {
481                 dbi_output->dsr_fb_update_done = false;
482
483                 if (dbi_output->p_funcs->update_fb)
484                         dbi_output->p_funcs->update_fb(dbi_output, pipe);
485
486                 if (dev_priv->dsr_enable && dbi_output->dsr_fb_update_done)
487                         dev_priv->dsr_fb_update &= ~damage_mask;
488
489                 /*clean IN_DSR flag*/
490                 dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
491
492                 dbi_output->dsr_idle_count = 0;
493         } else {
494                 dbi_output->dsr_idle_count++;
495         }
496
497         switch (dsr_info->dbi_output_num) {
498         case 1:
499                 if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
500                         can_enter_dsr = 1;
501                 break;
502         case 2:
503                 if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT
504                    && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
505                         can_enter_dsr = 1;
506                 break;
507         default:
508                 DRM_ERROR("Wrong DBI output number\n");
509         }
510
511         /* Try to enter DSR */
512         if (can_enter_dsr) {
513                 for (i = 0; i < dsr_info->dbi_output_num; i++) {
514                         if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] &&
515                            !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) {
516                                 mdfld_dsi_dbi_enter_dsr(dbi_outputs[i],
517                                         dbi_outputs[i]->channel_num ? 2 : 0);
518 #if 0
519                                 enter_dsr = 1;
520                                 pr_err("%s: enter_dsr = 1\n", __func__);
521 #endif
522                         }
523                 }
524         /*schedule rpm suspend after gfxrtdelay*/
525 #ifdef CONFIG_GFX_RTPM
526                 if (!dev_priv->rpm_enabled
527                         || !enter_dsr
528         /*              || (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN) */
529                         || pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay))
530                         dev_warn(dev->dev,
531                                 "Runtime PM schedule suspend failed, rpm %d\n",
532                                         dev_priv->rpm_enabled);
533 #endif
534         }
535 }
536
537 int mdfld_dbi_dsr_init(struct drm_device *dev)
538 {
539         struct drm_psb_private *dev_priv = dev->dev_private;
540         struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
541
542         if (!dsr_info || IS_ERR(dsr_info)) {
543                 dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info),
544                                                                 GFP_KERNEL);
545                 if (!dsr_info) {
546                         dev_err(dev->dev, "No memory\n");
547                         return -ENOMEM;
548                 }
549                 dev_priv->dbi_dsr_info = dsr_info;
550         }
551         return 0;
552 }
553
554 void mdfld_dbi_dsr_exit(struct drm_device *dev)
555 {
556         struct drm_psb_private *dev_priv = dev->dev_private;
557         struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
558
559         if (dsr_info) {
560                 kfree(dsr_info);
561                 dev_priv->dbi_dsr_info = NULL;
562         }
563 }
564
565 void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
566                                                                 int pipe)
567 {
568         struct drm_device *dev = dsi_config->dev;
569         u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
570         int lane_count = dsi_config->lane_count;
571         u32 val = 0;
572
573         dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
574
575         /* Un-ready device */
576         REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
577
578         /* Init dsi adapter before kicking off */
579         REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
580
581         /* TODO: figure out how to setup these registers */
582         REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
583         REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
584                                                         0x000a0014);
585         REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
586         REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
587         REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
588
589         /* Enable all interrupts */
590         REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
591         /* Max value: 20 clock cycles of txclkesc */
592         REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
593         /* Min 21 txclkesc, max: ffffh */
594         REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
595         /* Min: 7d0 max: 4e20 */
596         REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
597
598         /* Set up func_prg */
599         val |= lane_count;
600         val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
601         val |= DSI_DBI_COLOR_FORMAT_OPTION2;
602         REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
603
604         REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
605         REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
606
607         /* De-assert dbi_stall when half of DBI FIFO is empty */
608         /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
609
610         REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
611         REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
612         REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
613         REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
614 }
615
616 #if 0
617 /*DBI encoder helper funcs*/
618 static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
619         .dpms = mdfld_dsi_dbi_dpms,
620         .mode_fixup = mdfld_dsi_dbi_mode_fixup,
621         .prepare = mdfld_dsi_dbi_prepare,
622         .mode_set = mdfld_dsi_dbi_mode_set,
623         .commit = mdfld_dsi_dbi_commit,
624 };
625
626 /*DBI encoder funcs*/
627 static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
628         .destroy = drm_encoder_cleanup,
629 };
630
631 #endif
632
633 /*
634  * Init DSI DBI encoder.
635  * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
636  * return pointer of newly allocated DBI encoder, NULL on error
637  */
638 struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
639                                 struct mdfld_dsi_connector *dsi_connector,
640                                 struct panel_funcs *p_funcs)
641 {
642         struct drm_psb_private *dev_priv = dev->dev_private;
643         struct mdfld_dsi_dbi_output *dbi_output = NULL;
644         struct mdfld_dsi_config *dsi_config;
645         struct drm_connector *connector = NULL;
646         struct drm_encoder *encoder = NULL;
647         struct drm_display_mode *fixed_mode = NULL;
648         struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL;
649         struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
650         struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
651         u32 data = 0;
652         int pipe;
653         int ret;
654
655         if (!pg || !dsi_connector || !p_funcs) {
656                 WARN_ON(1);
657                 return NULL;
658         }
659
660         dsi_config = mdfld_dsi_get_config(dsi_connector);
661         pipe = dsi_connector->pipe;
662
663         /*panel hard-reset*/
664         if (p_funcs->reset) {
665                 ret = p_funcs->reset(pipe);
666                 if (ret) {
667                         DRM_ERROR("Panel %d hard-reset failed\n", pipe);
668                         return NULL;
669                 }
670         }
671         /* Panel drvIC init */
672         if (p_funcs->drv_ic_init)
673                 p_funcs->drv_ic_init(dsi_config, pipe);
674
675         /* Panel power mode detect */
676         ret = mdfld_dsi_get_power_mode(dsi_config,
677                                        &data,
678                                        MDFLD_DSI_HS_TRANSMISSION);
679         if (ret) {
680                 DRM_ERROR("Panel %d get power mode failed\n", pipe);
681                 dsi_connector->status = connector_status_disconnected;
682         } else {
683                 DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
684                 dsi_connector->status = connector_status_connected;
685         }
686
687         /*TODO: get panel info from DDB*/
688
689         dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
690         if (!dbi_output) {
691                 dev_err(dev->dev, "No memory\n");
692                 return NULL;
693         }
694
695         if (dsi_connector->pipe == 0) {
696                 dbi_output->channel_num = 0;
697                 dev_priv->dbi_output = dbi_output;
698         } else if (dsi_connector->pipe == 2) {
699                 dbi_output->channel_num = 1;
700                 dev_priv->dbi_output2 = dbi_output;
701         } else {
702                 dev_err(dev->dev, "only support 2 DSI outputs\n");
703                 goto out_err1;
704         }
705
706         dbi_output->dev = dev;
707         dbi_output->p_funcs = p_funcs;
708         fixed_mode = dsi_config->fixed_mode;
709         dbi_output->panel_fixed_mode = fixed_mode;
710
711         /* Create drm encoder object */
712         connector = &dsi_connector->base.base;
713         encoder = &dbi_output->base.base;
714         /* Review this if we ever get MIPI-HDMI bridges or similar */
715         drm_encoder_init(dev,
716                         encoder,
717                         p_funcs->encoder_funcs,
718                         DRM_MODE_ENCODER_LVDS);
719         drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs);
720
721         /* Attach to given connector */
722         drm_mode_connector_attach_encoder(connector, encoder);
723
724         /* Set possible CRTCs and clones */
725         if (dsi_connector->pipe) {
726                 encoder->possible_crtcs = (1 << 2);
727                 encoder->possible_clones = (1 << 1);
728         } else {
729                 encoder->possible_crtcs = (1 << 0);
730                 encoder->possible_clones = (1 << 0);
731         }
732
733         dev_priv->dsr_fb_update = 0;
734         dev_priv->dsr_enable = false;
735         dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr;
736
737         dbi_output->first_boot = true;
738         dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;
739
740         /* Add this output to dpu_info if in DPU mode */
741         if (dpu_info && dsi_connector->status == connector_status_connected) {
742                 if (dsi_connector->pipe == 0)
743                         dpu_info->dbi_outputs[0] = dbi_output;
744                 else
745                         dpu_info->dbi_outputs[1] = dbi_output;
746
747                 dpu_info->dbi_output_num++;
748         } else if (dsi_connector->status == connector_status_connected) {
749                 /* Add this output to dsr_info if not */
750                 if (dsi_connector->pipe == 0)
751                         dsr_info->dbi_outputs[0] = dbi_output;
752                 else
753                         dsr_info->dbi_outputs[1] = dbi_output;
754
755                 dsr_info->dbi_output_num++;
756         }
757         return &dbi_output->base;
758 out_err1:
759         kfree(dbi_output);
760         return NULL;
761 }