]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blob - drivers/staging/gma500/mdfld_dsi_dbi.c
Linux 3.3-rc2
[mirror_ubuntu-artful-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 }