gma500: resync with Medfield progress
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / drivers / staging / gma500 / mdfld_dsi_dbi.c
blob06424f945bc8973841d8829e4ddcaa71556385e9
1 /*
2 * Copyright © 2010 Intel Corporation
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, 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:
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
23 * Authors:
24 * jim liu <jim.liu@intel.com>
25 * Jackie Li<yaodong.li@intel.com>
28 #include "mdfld_dsi_dbi.h"
29 #include "mdfld_dsi_dbi_dpu.h"
30 #include "mdfld_dsi_pkg_sender.h"
32 #include "power.h"
33 #include <linux/pm_runtime.h>
35 int enable_gfx_rtpm;
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;
45 #define MDFLD_DSR_MAX_IDLE_COUNT 2
48 * set refreshing area
50 int mdfld_dsi_dbi_update_area(struct mdfld_dsi_dbi_output *dbi_output,
51 u16 x1, u16 y1, u16 x2, u16 y2)
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;
59 if (!sender) {
60 WARN_ON(1);
61 return -EINVAL;
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;
71 err = mdfld_dsi_send_dcs(sender,
72 cmd,
73 param,
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;
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;
89 err = mdfld_dsi_send_dcs(sender,
90 cmd,
91 param,
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;
100 /*update screen*/
101 err = mdfld_dsi_send_dcs(sender,
102 write_mem_start,
103 NULL,
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;
111 mdfld_dsi_cmds_kick_out(sender);
112 err_out:
113 return err;
117 * set panel's power state
119 int mdfld_dsi_dbi_update_power(struct mdfld_dsi_dbi_output *dbi_output,
120 int mode)
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;
128 if (!sender) {
129 WARN_ON(1);
130 return -EINVAL;
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,
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;
147 /* Set display on */
148 err = mdfld_dsi_send_dcs(sender,
149 DCS_SET_DISPLAY_ON,
150 NULL,
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;
160 /* set tear effect on */
161 err = mdfld_dsi_send_dcs(sender,
162 DCS_SET_TEAR_ON,
163 &param,
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;
174 * FIXME: remove this later
176 err = mdfld_dsi_send_dcs(sender,
177 DCS_WRITE_MEM_START,
178 NULL,
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;
187 } else {
188 /* Set tear effect off */
189 err = mdfld_dsi_send_dcs(sender,
190 DCS_SET_TEAR_OFF,
191 NULL,
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;
201 /* Turn display off */
202 err = mdfld_dsi_send_dcs(sender,
203 DCS_SET_DISPLAY_OFF,
204 NULL,
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;
214 /* Now enter sleep mode */
215 err = mdfld_dsi_send_dcs(sender,
216 DCS_ENTER_SLEEP_MODE,
217 NULL,
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;
227 mdfld_dsi_cmds_kick_out(sender);
228 power_err:
229 return err;
233 * send a generic DCS command with a parameter list
235 int mdfld_dsi_dbi_send_dcs(struct mdfld_dsi_dbi_output *dbi_output,
236 u8 dcs, u8 *param, u32 num, u8 data_src)
238 struct mdfld_dsi_pkg_sender *sender =
239 mdfld_dsi_encoder_get_pkg_sender(&dbi_output->base);
240 int ret;
242 if (!sender) {
243 WARN_ON(1);
244 return -EINVAL;
247 ret = mdfld_dsi_send_dcs(sender,
248 dcs,
249 param,
250 num,
251 data_src,
252 MDFLD_DSI_SEND_PACKAGE);
254 return ret;
258 * Enter DSR
260 void mdfld_dsi_dbi_enter_dsr(struct mdfld_dsi_dbi_output *dbi_output, int pipe)
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;
272 if (!dbi_output)
273 return;
275 /* FIXME check if can go */
276 dev_priv->is_in_idle = true;
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;
283 if (pipe == 2) {
284 dpll_reg = MRST_DPLL_A;
285 pipeconf_reg = PIPECCONF;
286 dspcntr_reg = DSPCCNTR;
289 if (!gma_power_begin(dev, true)) {
290 dev_err(dev->dev, "hw begin failed\n");
291 return;
293 /* Disable te interrupts */
294 mdfld_disable_te(dev, pipe);
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);
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);
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);
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); */
330 #ifndef CONFIG_MDFLD_DSI_DPU
331 static void mdfld_dbi_output_exit_dsr(struct mdfld_dsi_dbi_output *dbi_output,
332 int pipe)
334 struct drm_device *dev = dbi_output->dev;
335 struct drm_crtc *crtc = dbi_output->base.base.crtc;
336 struct psb_intel_crtc *psb_crtc = (crtc) ?
337 to_psb_intel_crtc(crtc) : NULL;
338 u32 reg_val;
339 u32 dpll_reg = MRST_DPLL_A;
340 u32 pipeconf_reg = PIPEACONF;
341 u32 dspcntr_reg = DSPACNTR;
342 u32 reg_offset = 0;
344 /*if mode setting on-going, back off*/
345 if ((dbi_output->mode_flags & MODE_SETTING_ON_GOING) ||
346 (psb_crtc && psb_crtc->mode_flags & MODE_SETTING_ON_GOING))
347 return;
349 if (pipe == 2) {
350 dpll_reg = MRST_DPLL_A;
351 pipeconf_reg = PIPECCONF;
352 dspcntr_reg = DSPCCNTR;
353 reg_offset = MIPIC_REG_OFFSET;
356 if (!gma_power_begin(dev, true)) {
357 dev_err(dev->dev, "hw begin failed\n");
358 return;
361 /* Enable DPLL */
362 reg_val = REG_READ(dpll_reg);
363 if (!(reg_val & DPLL_VCO_ENABLE)) {
364 if (reg_val & MDFLD_PWR_GATE_EN) {
365 reg_val &= ~MDFLD_PWR_GATE_EN;
366 REG_WRITE(dpll_reg, reg_val);
367 REG_READ(dpll_reg);
368 udelay(500);
371 reg_val |= DPLL_VCO_ENABLE;
372 REG_WRITE(dpll_reg, reg_val);
373 REG_READ(dpll_reg);
374 udelay(500);
376 /* Add timeout */
377 while (!(REG_READ(pipeconf_reg) & PIPECONF_DSIPLL_LOCK))
378 cpu_relax();
381 /* Enable pipe */
382 reg_val = REG_READ(pipeconf_reg);
383 if (!(reg_val & PIPEACONF_ENABLE)) {
384 reg_val |= PIPEACONF_ENABLE;
385 REG_WRITE(pipeconf_reg, reg_val);
386 REG_READ(pipeconf_reg);
387 udelay(500);
388 mdfldWaitForPipeEnable(dev, pipe);
391 /* Enable plane */
392 reg_val = REG_READ(dspcntr_reg);
393 if (!(reg_val & DISPLAY_PLANE_ENABLE)) {
394 reg_val |= DISPLAY_PLANE_ENABLE;
395 REG_WRITE(dspcntr_reg, reg_val);
396 REG_READ(dspcntr_reg);
397 udelay(500);
400 /* Enable TE interrupt on this pipe */
401 mdfld_enable_te(dev, pipe);
402 gma_power_end(dev);
404 /*clean IN_DSR flag*/
405 dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
409 * Exit from DSR
411 void mdfld_dsi_dbi_exit_dsr(struct drm_device *dev, u32 update_src)
413 struct drm_psb_private *dev_priv = dev->dev_private;
414 struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
415 struct mdfld_dsi_dbi_output **dbi_output;
416 int i;
417 int pipe;
419 /* FIXME can go ? */
420 dev_priv->is_in_idle = false;
421 dbi_output = dsr_info->dbi_outputs;
423 #ifdef CONFIG_PM_RUNTIME
424 if (!enable_gfx_rtpm) {
425 /* pm_runtime_allow(&gpDrmDevice->pdev->dev); */
426 /* schedule_delayed_work(&rtpm_work, 30 * 1000);*/ /* FIXME: HZ ? */
428 #endif
430 /* For each output, exit dsr */
431 for (i = 0; i < dsr_info->dbi_output_num; i++) {
432 /* If panel has been turned off, skip */
433 if (!dbi_output[i] || !dbi_output[i]->dbi_panel_on)
434 continue;
435 pipe = dbi_output[i]->channel_num ? 2 : 0;
436 enter_dsr = 0;
437 mdfld_dbi_output_exit_dsr(dbi_output[i], pipe);
439 dev_priv->dsr_fb_update |= update_src;
442 static bool mdfld_dbi_is_in_dsr(struct drm_device *dev)
444 if (REG_READ(MRST_DPLL_A) & DPLL_VCO_ENABLE)
445 return false;
446 if ((REG_READ(PIPEACONF) & PIPEACONF_ENABLE) ||
447 (REG_READ(PIPECCONF) & PIPEACONF_ENABLE))
448 return false;
449 if ((REG_READ(DSPACNTR) & DISPLAY_PLANE_ENABLE) ||
450 (REG_READ(DSPCCNTR) & DISPLAY_PLANE_ENABLE))
451 return false;
453 return true;
456 /* Periodically update dbi panel */
457 void mdfld_dbi_update_panel(struct drm_device *dev, int pipe)
459 struct drm_psb_private *dev_priv = dev->dev_private;
460 struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
461 struct mdfld_dsi_dbi_output **dbi_outputs;
462 struct mdfld_dsi_dbi_output *dbi_output;
463 int i;
464 int can_enter_dsr = 0;
465 u32 damage_mask;
467 dbi_outputs = dsr_info->dbi_outputs;
468 dbi_output = pipe ? dbi_outputs[1] : dbi_outputs[0];
470 if (!dbi_output)
471 return;
473 if (pipe == 0)
474 damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_0;
475 else if (pipe == 2)
476 damage_mask = dev_priv->dsr_fb_update & MDFLD_DSR_DAMAGE_MASK_2;
477 else
478 return;
480 /* If FB is damaged and panel is on update on-panel FB */
481 if (damage_mask && dbi_output->dbi_panel_on) {
482 dbi_output->dsr_fb_update_done = false;
484 if (dbi_output->p_funcs->update_fb)
485 dbi_output->p_funcs->update_fb(dbi_output, pipe);
487 if (dev_priv->dsr_enable && dbi_output->dsr_fb_update_done)
488 dev_priv->dsr_fb_update &= ~damage_mask;
490 /*clean IN_DSR flag*/
491 dbi_output->mode_flags &= ~MODE_SETTING_IN_DSR;
493 dbi_output->dsr_idle_count = 0;
494 } else {
495 dbi_output->dsr_idle_count++;
498 switch (dsr_info->dbi_output_num) {
499 case 1:
500 if (dbi_output->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
501 can_enter_dsr = 1;
502 break;
503 case 2:
504 if (dbi_outputs[0]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT
505 && dbi_outputs[1]->dsr_idle_count > MDFLD_DSR_MAX_IDLE_COUNT)
506 can_enter_dsr = 1;
507 break;
508 default:
509 DRM_ERROR("Wrong DBI output number\n");
512 /* Try to enter DSR */
513 if (can_enter_dsr) {
514 for (i = 0; i < dsr_info->dbi_output_num; i++) {
515 if (!mdfld_dbi_is_in_dsr(dev) && dbi_outputs[i] &&
516 !(dbi_outputs[i]->mode_flags & MODE_SETTING_ON_GOING)) {
517 mdfld_dsi_dbi_enter_dsr(dbi_outputs[i],
518 dbi_outputs[i]->channel_num ? 2 : 0);
519 #if 0
520 enter_dsr = 1;
521 pr_err("%s: enter_dsr = 1\n", __func__);
522 #endif
525 /*schedule rpm suspend after gfxrtdelay*/
526 #ifdef CONFIG_GFX_RTPM
527 if (!dev_priv->rpm_enabled
528 || !enter_dsr
529 /* || (REG_READ(HDMIB_CONTROL) & HDMIB_PORT_EN) */
530 || pm_schedule_suspend(&dev->pdev->dev, gfxrtdelay))
531 dev_warn(dev->dev,
532 "Runtime PM schedule suspend failed, rpm %d\n",
533 dev_priv->rpm_enabled);
534 #endif
538 int mdfld_dbi_dsr_init(struct drm_device *dev)
540 struct drm_psb_private *dev_priv = dev->dev_private;
541 struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
543 if (!dsr_info || IS_ERR(dsr_info)) {
544 dsr_info = kzalloc(sizeof(struct mdfld_dbi_dsr_info),
545 GFP_KERNEL);
546 if (!dsr_info) {
547 dev_err(dev->dev, "No memory\n");
548 return -ENOMEM;
550 dev_priv->dbi_dsr_info = dsr_info;
552 return 0;
555 void mdfld_dbi_dsr_exit(struct drm_device *dev)
557 struct drm_psb_private *dev_priv = dev->dev_private;
558 struct mdfld_dbi_dsr_info *dsr_info = dev_priv->dbi_dsr_info;
560 if (dsr_info) {
561 kfree(dsr_info);
562 dev_priv->dbi_dsr_info = NULL;
565 #endif
567 void mdfld_dsi_controller_dbi_init(struct mdfld_dsi_config *dsi_config,
568 int pipe)
570 struct drm_device *dev = dsi_config->dev;
571 u32 reg_offset = pipe ? MIPIC_REG_OFFSET : 0;
572 int lane_count = dsi_config->lane_count;
573 u32 val = 0;
575 dev_dbg(dev->dev, "Init DBI interface on pipe %d...\n", pipe);
577 /* Un-ready device */
578 REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000000);
580 /* Init dsi adapter before kicking off */
581 REG_WRITE((MIPIA_CONTROL_REG + reg_offset), 0x00000018);
583 /* TODO: figure out how to setup these registers */
584 REG_WRITE((MIPIA_DPHY_PARAM_REG + reg_offset), 0x150c3408);
585 REG_WRITE((MIPIA_CLK_LANE_SWITCH_TIME_CNT_REG + reg_offset),
586 0x000a0014);
587 REG_WRITE((MIPIA_DBI_BW_CTRL_REG + reg_offset), 0x00000400);
588 REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000001);
589 REG_WRITE((MIPIA_HS_LS_DBI_ENABLE_REG + reg_offset), 0x00000000);
591 /* Enable all interrupts */
592 REG_WRITE((MIPIA_INTR_EN_REG + reg_offset), 0xffffffff);
593 /* Max value: 20 clock cycles of txclkesc */
594 REG_WRITE((MIPIA_TURN_AROUND_TIMEOUT_REG + reg_offset), 0x0000001f);
595 /* Min 21 txclkesc, max: ffffh */
596 REG_WRITE((MIPIA_DEVICE_RESET_TIMER_REG + reg_offset), 0x0000ffff);
597 /* Min: 7d0 max: 4e20 */
598 REG_WRITE((MIPIA_INIT_COUNT_REG + reg_offset), 0x00000fa0);
600 /* Set up func_prg */
601 val |= lane_count;
602 val |= (dsi_config->channel_num << DSI_DBI_VIRT_CHANNEL_OFFSET);
603 val |= DSI_DBI_COLOR_FORMAT_OPTION2;
604 REG_WRITE((MIPIA_DSI_FUNC_PRG_REG + reg_offset), val);
606 REG_WRITE((MIPIA_HS_TX_TIMEOUT_REG + reg_offset), 0x3fffff);
607 REG_WRITE((MIPIA_LP_RX_TIMEOUT_REG + reg_offset), 0xffff);
609 /* De-assert dbi_stall when half of DBI FIFO is empty */
610 /* REG_WRITE((MIPIA_DBI_FIFO_THROTTLE_REG + reg_offset), 0x00000000); */
612 REG_WRITE((MIPIA_HIGH_LOW_SWITCH_COUNT_REG + reg_offset), 0x46);
613 REG_WRITE((MIPIA_EOT_DISABLE_REG + reg_offset), 0x00000000);
614 REG_WRITE((MIPIA_LP_BYTECLK_REG + reg_offset), 0x00000004);
615 REG_WRITE((MIPIA_DEVICE_READY_REG + reg_offset), 0x00000001);
618 #if 0
619 /*DBI encoder helper funcs*/
620 static const struct drm_encoder_helper_funcs mdfld_dsi_dbi_helper_funcs = {
621 .dpms = mdfld_dsi_dbi_dpms,
622 .mode_fixup = mdfld_dsi_dbi_mode_fixup,
623 .prepare = mdfld_dsi_dbi_prepare,
624 .mode_set = mdfld_dsi_dbi_mode_set,
625 .commit = mdfld_dsi_dbi_commit,
628 /*DBI encoder funcs*/
629 static const struct drm_encoder_funcs mdfld_dsi_dbi_encoder_funcs = {
630 .destroy = drm_encoder_cleanup,
633 #endif
636 * Init DSI DBI encoder.
637 * Allocate an mdfld_dsi_encoder and attach it to given @dsi_connector
638 * return pointer of newly allocated DBI encoder, NULL on error
640 struct mdfld_dsi_encoder *mdfld_dsi_dbi_init(struct drm_device *dev,
641 struct mdfld_dsi_connector *dsi_connector,
642 struct panel_funcs *p_funcs)
644 struct drm_psb_private *dev_priv = dev->dev_private;
645 struct mdfld_dsi_dbi_output *dbi_output = NULL;
646 struct mdfld_dsi_config *dsi_config;
647 struct drm_connector *connector = NULL;
648 struct drm_encoder *encoder = NULL;
649 struct drm_display_mode *fixed_mode = NULL;
650 struct psb_gtt *pg = dev_priv ? (&dev_priv->gtt) : NULL;
652 #ifdef CONFIG_MDFLD_DSI_DPU
653 struct mdfld_dbi_dpu_info *dpu_info = dev_priv ? (dev_priv->dbi_dpu_info) : NULL;
654 #else
655 struct mdfld_dbi_dsr_info *dsr_info = dev_priv ? (dev_priv->dbi_dsr_info) : NULL;
656 #endif
657 u32 data = 0;
658 int pipe;
659 int ret;
661 if (!pg || !dsi_connector || !p_funcs) {
662 WARN_ON(1);
663 return NULL;
666 dsi_config = mdfld_dsi_get_config(dsi_connector);
667 pipe = dsi_connector->pipe;
669 /*panel hard-reset*/
670 if (p_funcs->reset) {
671 ret = p_funcs->reset(pipe);
672 if (ret) {
673 DRM_ERROR("Panel %d hard-reset failed\n", pipe);
674 return NULL;
677 /* Panel drvIC init */
678 if (p_funcs->drv_ic_init)
679 p_funcs->drv_ic_init(dsi_config, pipe);
681 /* Panel power mode detect */
682 ret = mdfld_dsi_get_power_mode(dsi_config,
683 &data,
684 MDFLD_DSI_HS_TRANSMISSION);
685 if (ret) {
686 DRM_ERROR("Panel %d get power mode failed\n", pipe);
687 dsi_connector->status = connector_status_disconnected;
688 } else {
689 DRM_INFO("pipe %d power mode 0x%x\n", pipe, data);
690 dsi_connector->status = connector_status_connected;
693 /*TODO: get panel info from DDB*/
695 dbi_output = kzalloc(sizeof(struct mdfld_dsi_dbi_output), GFP_KERNEL);
696 if (!dbi_output) {
697 dev_err(dev->dev, "No memory\n");
698 return NULL;
701 if (dsi_connector->pipe == 0) {
702 dbi_output->channel_num = 0;
703 dev_priv->dbi_output = dbi_output;
704 } else if (dsi_connector->pipe == 2) {
705 dbi_output->channel_num = 1;
706 dev_priv->dbi_output2 = dbi_output;
707 } else {
708 dev_err(dev->dev, "only support 2 DSI outputs\n");
709 goto out_err1;
712 dbi_output->dev = dev;
713 dbi_output->p_funcs = p_funcs;
714 fixed_mode = dsi_config->fixed_mode;
715 dbi_output->panel_fixed_mode = fixed_mode;
717 /* Create drm encoder object */
718 connector = &dsi_connector->base.base;
719 encoder = &dbi_output->base.base;
720 drm_encoder_init(dev,
721 encoder,
722 p_funcs->encoder_funcs,
723 DRM_MODE_ENCODER_MIPI);
724 drm_encoder_helper_add(encoder, p_funcs->encoder_helper_funcs);
726 /* Attach to given connector */
727 drm_mode_connector_attach_encoder(connector, encoder);
729 /* Set possible CRTCs and clones */
730 if (dsi_connector->pipe) {
731 encoder->possible_crtcs = (1 << 2);
732 encoder->possible_clones = (1 << 1);
733 } else {
734 encoder->possible_crtcs = (1 << 0);
735 encoder->possible_clones = (1 << 0);
738 dev_priv->dsr_fb_update = 0;
739 dev_priv->dsr_enable = false;
740 dev_priv->exit_idle = mdfld_dsi_dbi_exit_dsr;
742 dbi_output->first_boot = true;
743 dbi_output->mode_flags = MODE_SETTING_IN_ENCODER;
745 #ifdef CONFIG_MDFLD_DSI_DPU
746 /* Add this output to dpu_info */
747 if (dsi_connector->status == connector_status_connected) {
748 if (dsi_connector->pipe == 0)
749 dpu_info->dbi_outputs[0] = dbi_output;
750 else
751 dpu_info->dbi_outputs[1] = dbi_output;
753 dpu_info->dbi_output_num++;
756 #else /*CONFIG_MDFLD_DSI_DPU*/
757 if (dsi_connector->status == connector_status_connected) {
758 /* Add this output to dsr_info */
759 if (dsi_connector->pipe == 0)
760 dsr_info->dbi_outputs[0] = dbi_output;
761 else
762 dsr_info->dbi_outputs[1] = dbi_output;
764 dsr_info->dbi_output_num++;
766 #endif
767 return &dbi_output->base;
768 out_err1:
769 kfree(dbi_output);
770 return NULL;