blob: 61bb3458b7700856abf20e935de711c8615bd971 [file] [log] [blame]
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07001/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 */
13
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/sched.h>
17#include <linux/time.h>
18#include <linux/init.h>
19#include <linux/interrupt.h>
20#include <linux/spinlock.h>
21#include <linux/delay.h>
22#include <linux/io.h>
23#include <linux/semaphore.h>
24#include <linux/uaccess.h>
25#include <linux/clk.h>
26#include <linux/platform_device.h>
27#include <asm/system.h>
28#include <asm/mach-types.h>
29#include <mach/hardware.h>
30#include <mach/gpio.h>
31#include <mach/clk.h>
32
33#include "msm_fb.h"
34#include "mipi_dsi.h"
35#include "mdp.h"
36#include "mdp4.h"
37
38u32 dsi_irq;
39
40static int mipi_dsi_probe(struct platform_device *pdev);
41static int mipi_dsi_remove(struct platform_device *pdev);
42
43static int mipi_dsi_off(struct platform_device *pdev);
44static int mipi_dsi_on(struct platform_device *pdev);
45
46static struct platform_device *pdev_list[MSM_FB_MAX_DEV_LIST];
47static int pdev_list_cnt;
48static struct mipi_dsi_platform_data *mipi_dsi_pdata;
49
50static int vsync_gpio = -1;
51
52static struct platform_driver mipi_dsi_driver = {
53 .probe = mipi_dsi_probe,
54 .remove = mipi_dsi_remove,
55 .shutdown = NULL,
56 .driver = {
57 .name = "mipi_dsi",
58 },
59};
60
61struct device dsi_dev;
62
63static int mipi_dsi_off(struct platform_device *pdev)
64{
65 int ret = 0;
66 struct msm_fb_data_type *mfd;
67 struct msm_panel_info *pinfo;
68
69 mfd = platform_get_drvdata(pdev);
70 pinfo = &mfd->panel_info;
71
72 if (mdp_rev >= MDP_REV_41)
73 mutex_lock(&mfd->dma->ov_mutex);
74 else
75 down(&mfd->dma->mutex);
76
77 mdp4_overlay_dsi_state_set(ST_DSI_SUSPEND);
78
79 /*
80 * Description: dsi clock is need to perform shutdown.
81 * mdp4_dsi_cmd_dma_busy_wait() will enable dsi clock if disabled.
82 * also, wait until dma (overlay and dmap) finish.
83 */
84 if (mfd->panel_info.type == MIPI_CMD_PANEL) {
85 if (mdp_rev >= MDP_REV_41) {
86 mdp4_dsi_cmd_dma_busy_wait(mfd);
87 mdp4_dsi_blt_dmap_busy_wait(mfd);
88 } else {
89 mdp3_dsi_cmd_dma_busy_wait(mfd);
90 }
91 }
92
93 /*
94 * Desctiption: change to DSI_CMD_MODE since it needed to
95 * tx DCS dsiplay off comamnd to panel
96 */
97 mipi_dsi_op_mode_config(DSI_CMD_MODE);
98
99 if (mfd->panel_info.type == MIPI_CMD_PANEL) {
100 if (pinfo->lcd.vsync_enable) {
101 if (pinfo->lcd.hw_vsync_mode && vsync_gpio > 0)
102 gpio_free(vsync_gpio);
103
104 mipi_dsi_set_tear_off(mfd);
105 }
106 }
107
108 ret = panel_next_off(pdev);
109
110#ifdef CONFIG_MSM_BUS_SCALING
111 mdp_bus_scale_update_request(0);
112#endif
113 /* disbale dsi engine */
114 MIPI_OUTP(MIPI_DSI_BASE + 0x0000, 0);
115
116 mipi_dsi_phy_ctrl(0);
117
118 local_bh_disable();
119 mipi_dsi_clk_disable();
120 local_bh_enable();
121
122 if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
123 mipi_dsi_pdata->dsi_power_save(0);
124
125 if (mdp_rev >= MDP_REV_41)
126 mutex_unlock(&mfd->dma->ov_mutex);
127 else
128 up(&mfd->dma->mutex);
129
130 pr_debug("%s:\n", __func__);
131
132 return ret;
133}
134
135static int mipi_dsi_on(struct platform_device *pdev)
136{
137 int ret = 0;
138 u32 clk_rate;
139 struct msm_fb_data_type *mfd;
140 struct fb_info *fbi;
141 struct fb_var_screeninfo *var;
142 struct msm_panel_info *pinfo;
143 struct mipi_panel_info *mipi;
144 u32 hbp, hfp, vbp, vfp, hspw, vspw, width, height;
145 u32 ystride, bpp, data;
146 u32 dummy_xres, dummy_yres;
147 int target_type = 0;
148
149 mfd = platform_get_drvdata(pdev);
150 fbi = mfd->fbi;
151 var = &fbi->var;
152 pinfo = &mfd->panel_info;
153
154 if (mipi_dsi_pdata && mipi_dsi_pdata->dsi_power_save)
155 mipi_dsi_pdata->dsi_power_save(1);
156
157 clk_rate = mfd->fbi->var.pixclock;
158 clk_rate = min(clk_rate, mfd->panel_info.clk_max);
159
160 local_bh_disable();
161 mipi_dsi_clk_enable();
162 local_bh_enable();
163
164#ifndef CONFIG_FB_MSM_MDP303
165 mdp4_overlay_dsi_state_set(ST_DSI_RESUME);
166#endif
167
168 MIPI_OUTP(MIPI_DSI_BASE + 0x114, 1);
169 MIPI_OUTP(MIPI_DSI_BASE + 0x114, 0);
170
171 hbp = var->left_margin;
172 hfp = var->right_margin;
173 vbp = var->upper_margin;
174 vfp = var->lower_margin;
175 hspw = var->hsync_len;
176 vspw = var->vsync_len;
177 width = mfd->panel_info.xres;
178 height = mfd->panel_info.yres;
179
180 mipi_dsi_phy_ctrl(1);
181
182 if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata)
183 target_type = mipi_dsi_pdata->target_type;
184
185 mipi_dsi_phy_init(0, &(mfd->panel_info), target_type);
186
187 mipi = &mfd->panel_info.mipi;
188 if (mfd->panel_info.type == MIPI_VIDEO_PANEL) {
189 dummy_xres = mfd->panel_info.mipi.xres_pad;
190 dummy_yres = mfd->panel_info.mipi.yres_pad;
191
192 if (mdp_rev >= MDP_REV_41) {
193 MIPI_OUTP(MIPI_DSI_BASE + 0x20,
194 ((hspw + hbp + width + dummy_xres) << 16 |
195 (hspw + hbp)));
196 MIPI_OUTP(MIPI_DSI_BASE + 0x24,
197 ((vspw + vbp + height + dummy_yres) << 16 |
198 (vspw + vbp)));
199 MIPI_OUTP(MIPI_DSI_BASE + 0x28,
200 (vspw + vbp + height + dummy_yres +
201 vfp - 1) << 16 | (hspw + hbp +
202 width + dummy_xres + hfp - 1));
203 } else {
204 /* DSI_LAN_SWAP_CTRL */
205 MIPI_OUTP(MIPI_DSI_BASE + 0x00ac, mipi->dlane_swap);
206
207 MIPI_OUTP(MIPI_DSI_BASE + 0x20,
208 ((hbp + width + dummy_xres) << 16 | (hbp)));
209 MIPI_OUTP(MIPI_DSI_BASE + 0x24,
210 ((vbp + height + dummy_yres) << 16 | (vbp)));
211 MIPI_OUTP(MIPI_DSI_BASE + 0x28,
212 (vbp + height + dummy_yres + vfp) << 16 |
213 (hbp + width + dummy_xres + hfp));
214 }
215
216 MIPI_OUTP(MIPI_DSI_BASE + 0x2c, (hspw << 16));
217 MIPI_OUTP(MIPI_DSI_BASE + 0x30, 0);
218 MIPI_OUTP(MIPI_DSI_BASE + 0x34, (vspw << 16));
219
220 } else { /* command mode */
221 if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
222 bpp = 3;
223 else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB666)
224 bpp = 3;
225 else if (mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
226 bpp = 2;
227 else
228 bpp = 3; /* Default format set to RGB888 */
229
230 ystride = width * bpp + 1;
231
232 /* DSI_COMMAND_MODE_MDP_STREAM_CTRL */
233 data = (ystride << 16) | (mipi->vc << 8) | DTYPE_DCS_LWRITE;
234 MIPI_OUTP(MIPI_DSI_BASE + 0x5c, data);
235 MIPI_OUTP(MIPI_DSI_BASE + 0x54, data);
236
237 /* DSI_COMMAND_MODE_MDP_STREAM_TOTAL */
238 data = height << 16 | width;
239 MIPI_OUTP(MIPI_DSI_BASE + 0x60, data);
240 MIPI_OUTP(MIPI_DSI_BASE + 0x58, data);
241 }
242
243 mipi_dsi_host_init(mipi);
244 mipi_dsi_cmd_bta_sw_trigger(); /* clean up ack_err_status */
245
246 ret = panel_next_on(pdev);
247
248 mipi_dsi_op_mode_config(mipi->mode);
249
250 if (mfd->panel_info.type == MIPI_CMD_PANEL) {
251 if (pinfo->lcd.vsync_enable) {
252 if (pinfo->lcd.hw_vsync_mode && vsync_gpio > 0) {
253 if (gpio_request(vsync_gpio, "MDP_VSYNC") == 0)
254 gpio_direction_input(vsync_gpio);
255 else
256 pr_err("%s: unable to request gpio=%d\n",
257 __func__, vsync_gpio);
258 }
259 mipi_dsi_set_tear_on(mfd);
260 }
261 }
262
263#ifdef CONFIG_MSM_BUS_SCALING
264 mdp_bus_scale_update_request(2);
265#endif
266 return ret;
267}
268
269
270static int mipi_dsi_resource_initialized;
271
272static int mipi_dsi_probe(struct platform_device *pdev)
273{
274 struct msm_fb_data_type *mfd;
275 struct fb_info *fbi;
276 struct msm_panel_info *pinfo;
277 struct mipi_panel_info *mipi;
278 struct platform_device *mdp_dev = NULL;
279 struct msm_fb_panel_data *pdata = NULL;
280 int rc;
281 uint8 lanes = 0, bpp;
282 uint32 h_period, v_period, dsi_pclk_rate;
283
284 resource_size_t size ;
285
286 if ((pdev->id == 1) && (pdev->num_resources >= 0)) {
287 mipi_dsi_pdata = pdev->dev.platform_data;
288
289 size = resource_size(&pdev->resource[0]);
290 mipi_dsi_base = ioremap(pdev->resource[0].start, size);
291
292 MSM_FB_INFO("mipi_dsi base phy_addr = 0x%x virt = 0x%x\n",
293 pdev->resource[0].start, (int) mipi_dsi_base);
294
295 if (!mipi_dsi_base)
296 return -ENOMEM;
297
298 if (mdp_rev >= MDP_REV_41) {
299 mmss_sfpb_base = ioremap(MMSS_SFPB_BASE_PHY, 0x100);
300 MSM_FB_INFO("mmss_sfpb base phy_addr = 0x%x,"
301 "virt = 0x%x\n", MMSS_SFPB_BASE_PHY,
302 (int) mmss_sfpb_base);
303
304 if (!mmss_sfpb_base)
305 return -ENOMEM;
306 }
307
308 dsi_irq = platform_get_irq(pdev, 0);
309 if (dsi_irq < 0) {
310 pr_err("mipi_dsi: can not get mdp irq\n");
311 return -ENOMEM;
312 }
313
314 rc = request_irq(dsi_irq, mipi_dsi_isr, IRQF_DISABLED,
315 "MIPI_DSI", 0);
316 if (rc) {
317 pr_err("mipi_dsi_host request_irq() failed!\n");
318 return rc;
319 }
320
321 disable_irq(dsi_irq);
322
323 if (mdp_rev == MDP_REV_42 && mipi_dsi_pdata &&
324 mipi_dsi_pdata->target_type == 1) {
325 /* Target type is 1 for device with (De)serializer
326 * 0x4f00000 is the base for TV Encoder.
327 * Unused Offset 0x1000 is used for
328 * (de)serializer on emulation platform
329 */
330 periph_base = ioremap(MMSS_SERDES_BASE_PHY, 0x100);
331
332 if (periph_base) {
333 pr_debug("periph_base %p\n", periph_base);
334 writel(0x4, periph_base + 0x28);
335 writel(0xc, periph_base + 0x28);
336 } else {
337 pr_err("periph_base is NULL\n");
338 free_irq(dsi_irq, 0);
339 return -ENOMEM;
340 }
341 }
342
343 if (mipi_dsi_pdata) {
344 vsync_gpio = mipi_dsi_pdata->vsync_gpio;
345 pr_debug("%s: vsync_gpio=%d\n", __func__, vsync_gpio);
346
347 if (mdp_rev == MDP_REV_303 &&
348 mipi_dsi_pdata->dsi_client_reset) {
349 if (mipi_dsi_pdata->dsi_client_reset())
350 pr_err("%s: DSI Client Reset failed!\n",
351 __func__);
352 else
353 pr_debug("%s: DSI Client Reset success\n",
354 __func__);
355 }
356 }
357
358 mipi_dsi_resource_initialized = 1;
359
360 return 0;
361 }
362
363 mipi_dsi_clk_init(&pdev->dev);
364
365 if (!mipi_dsi_resource_initialized)
366 return -EPERM;
367
368 mfd = platform_get_drvdata(pdev);
369
370 if (!mfd)
371 return -ENODEV;
372
373 if (mfd->key != MFD_KEY)
374 return -EINVAL;
375
376 if (pdev_list_cnt >= MSM_FB_MAX_DEV_LIST)
377 return -ENOMEM;
378
379
380 mdp_dev = platform_device_alloc("mdp", pdev->id);
381 if (!mdp_dev)
382 return -ENOMEM;
383
384 /*
385 * link to the latest pdev
386 */
387 mfd->pdev = mdp_dev;
388 mfd->dest = DISPLAY_LCD;
389
390 /*
391 * alloc panel device data
392 */
393 if (platform_device_add_data
394 (mdp_dev, pdev->dev.platform_data,
395 sizeof(struct msm_fb_panel_data))) {
396 pr_err("mipi_dsi_probe: platform_device_add_data failed!\n");
397 platform_device_put(mdp_dev);
398 return -ENOMEM;
399 }
400 /*
401 * data chain
402 */
403 pdata = mdp_dev->dev.platform_data;
404 pdata->on = mipi_dsi_on;
405 pdata->off = mipi_dsi_off;
406 pdata->next = pdev;
407
408 /*
409 * get/set panel specific fb info
410 */
411 mfd->panel_info = pdata->panel_info;
412 pinfo = &mfd->panel_info;
413
414 if (mdp_rev == MDP_REV_303 &&
415 mipi_dsi_pdata->get_lane_config) {
416 if (mipi_dsi_pdata->get_lane_config() != 2) {
417 pr_info("Changing to DSI Single Mode Configuration\n");
418#ifdef CONFIG_FB_MSM_MDP303
419 update_lane_config(pinfo);
420#endif
421 }
422 }
423
424 if (mfd->index == 0)
425 mfd->fb_imgType = MSMFB_DEFAULT_TYPE;
426 else
427 mfd->fb_imgType = MDP_RGB_565;
428
429 fbi = mfd->fbi;
430 fbi->var.pixclock = mfd->panel_info.clk_rate;
431 fbi->var.left_margin = mfd->panel_info.lcdc.h_back_porch;
432 fbi->var.right_margin = mfd->panel_info.lcdc.h_front_porch;
433 fbi->var.upper_margin = mfd->panel_info.lcdc.v_back_porch;
434 fbi->var.lower_margin = mfd->panel_info.lcdc.v_front_porch;
435 fbi->var.hsync_len = mfd->panel_info.lcdc.h_pulse_width;
436 fbi->var.vsync_len = mfd->panel_info.lcdc.v_pulse_width;
437
438 h_period = ((mfd->panel_info.lcdc.h_pulse_width)
439 + (mfd->panel_info.lcdc.h_back_porch)
440 + (mfd->panel_info.xres)
441 + (mfd->panel_info.lcdc.h_front_porch));
442
443 v_period = ((mfd->panel_info.lcdc.v_pulse_width)
444 + (mfd->panel_info.lcdc.v_back_porch)
445 + (mfd->panel_info.yres)
446 + (mfd->panel_info.lcdc.v_front_porch));
447
448 mipi = &mfd->panel_info.mipi;
449
450 if (mipi->data_lane3)
451 lanes += 1;
452 if (mipi->data_lane2)
453 lanes += 1;
454 if (mipi->data_lane1)
455 lanes += 1;
456 if (mipi->data_lane0)
457 lanes += 1;
458
459 if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB888)
460 || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB888)
461 || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB666_LOOSE))
462 bpp = 3;
463 else if ((mipi->dst_format == DSI_CMD_DST_FORMAT_RGB565)
464 || (mipi->dst_format == DSI_VIDEO_DST_FORMAT_RGB565))
465 bpp = 2;
466 else
467 bpp = 3; /* Default format set to RGB888 */
468
469 if (mfd->panel_info.type == MIPI_VIDEO_PANEL &&
470 !mfd->panel_info.clk_rate) {
471 h_period += mfd->panel_info.mipi.xres_pad;
472 v_period += mfd->panel_info.mipi.yres_pad;
473
474 if (lanes > 0) {
475 mfd->panel_info.clk_rate =
476 ((h_period * v_period * (mipi->frame_rate) * bpp * 8)
477 / lanes);
478 } else {
479 pr_err("%s: forcing mipi_dsi lanes to 1\n", __func__);
480 mfd->panel_info.clk_rate =
481 (h_period * v_period
482 * (mipi->frame_rate) * bpp * 8);
483 }
484 }
485 pll_divider_config.clk_rate = mfd->panel_info.clk_rate;
486
487 rc = mipi_dsi_clk_div_config(bpp, lanes, &dsi_pclk_rate);
488 if (rc)
489 goto mipi_dsi_probe_err;
490
491 if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 103300000))
492 dsi_pclk_rate = 35000000;
493 mipi->dsi_pclk_rate = dsi_pclk_rate;
494
495 /*
496 * set driver data
497 */
498 platform_set_drvdata(mdp_dev, mfd);
499
500 /*
501 * register in mdp driver
502 */
503 rc = platform_device_add(mdp_dev);
504 if (rc)
505 goto mipi_dsi_probe_err;
506
507 pdev_list[pdev_list_cnt++] = pdev;
508
509return 0;
510
511mipi_dsi_probe_err:
512 platform_device_put(mdp_dev);
513 return rc;
514}
515
516static int mipi_dsi_remove(struct platform_device *pdev)
517{
518 struct msm_fb_data_type *mfd;
519
520 mfd = platform_get_drvdata(pdev);
521 iounmap(mipi_dsi_base);
522 return 0;
523}
524
525static int mipi_dsi_register_driver(void)
526{
527 return platform_driver_register(&mipi_dsi_driver);
528}
529
530static int __init mipi_dsi_driver_init(void)
531{
532 int ret;
533
534 mipi_dsi_init();
535
536 ret = mipi_dsi_register_driver();
537
538 device_initialize(&dsi_dev);
539
540 if (ret) {
541 pr_err("mipi_dsi_register_driver() failed!\n");
542 return ret;
543 }
544
545 return ret;
546}
547
548module_init(mipi_dsi_driver_init);