1 /* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
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.
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.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 #include <linux/module.h>
19 #include <linux/kernel.h>
20 #include <linux/sched.h>
21 #include <linux/time.h>
22 #include <linux/init.h>
23 #include <linux/interrupt.h>
24 #include <linux/spinlock.h>
25 #include <linux/delay.h>
26 #include <mach/hardware.h>
29 #include <asm/system.h>
30 #include <asm/mach-types.h>
31 #include <linux/semaphore.h>
32 #include <linux/uaccess.h>
33 #include <linux/clk.h>
35 #include <linux/platform_device.h>
38 #include "mddihosti.h"
40 static int mddi_ext_probe(struct platform_device
*pdev
);
41 static int mddi_ext_remove(struct platform_device
*pdev
);
43 static int mddi_ext_off(struct platform_device
*pdev
);
44 static int mddi_ext_on(struct platform_device
*pdev
);
46 static struct platform_device
*pdev_list
[MSM_FB_MAX_DEV_LIST
];
47 static int pdev_list_cnt
;
49 static int mddi_ext_suspend(struct platform_device
*pdev
, pm_message_t state
);
50 static int mddi_ext_resume(struct platform_device
*pdev
);
52 #ifdef CONFIG_HAS_EARLYSUSPEND
53 static void mddi_ext_early_suspend(struct early_suspend
*h
);
54 static void mddi_ext_early_resume(struct early_suspend
*h
);
57 static struct platform_driver mddi_ext_driver
= {
58 .probe
= mddi_ext_probe
,
59 .remove
= mddi_ext_remove
,
60 #ifndef CONFIG_HAS_EARLYSUSPEND
62 .suspend
= mddi_ext_suspend
,
63 .resume
= mddi_ext_resume
,
74 static struct clk
*mddi_ext_clk
;
75 static struct mddi_platform_data
*mddi_ext_pdata
;
77 extern int int_mddi_ext_flag
;
79 static int mddi_ext_off(struct platform_device
*pdev
)
83 ret
= panel_next_off(pdev
);
84 mddi_host_stop_ext_display();
89 static int mddi_ext_on(struct platform_device
*pdev
)
93 struct msm_fb_data_type
*mfd
;
95 mfd
= platform_get_drvdata(pdev
);
97 clk_rate
= mfd
->fbi
->var
.pixclock
;
98 clk_rate
= min(clk_rate
, mfd
->panel_info
.clk_max
);
100 if (mddi_ext_pdata
&&
101 mddi_ext_pdata
->mddi_sel_clk
&&
102 mddi_ext_pdata
->mddi_sel_clk(&clk_rate
))
104 "%s: can't select mddi io clk targate rate = %d\n",
107 if (clk_set_min_rate(mddi_ext_clk
, clk_rate
) < 0)
108 printk(KERN_ERR
"%s: clk_set_min_rate failed\n",
111 mddi_host_start_ext_display();
112 ret
= panel_next_on(pdev
);
117 static int mddi_ext_resource_initialized
;
119 static int mddi_ext_probe(struct platform_device
*pdev
)
121 struct msm_fb_data_type
*mfd
;
122 struct platform_device
*mdp_dev
= NULL
;
123 struct msm_fb_panel_data
*pdata
= NULL
;
125 resource_size_t size
;
128 if ((pdev
->id
== 0) && (pdev
->num_resources
>= 0)) {
129 mddi_ext_pdata
= pdev
->dev
.platform_data
;
131 size
= resource_size(&pdev
->resource
[0]);
132 msm_emdh_base
= ioremap(pdev
->resource
[0].start
, size
);
134 MSM_FB_INFO("external mddi base address = 0x%x\n",
135 pdev
->resource
[0].start
);
137 if (unlikely(!msm_emdh_base
))
140 mddi_ext_resource_initialized
= 1;
144 if (!mddi_ext_resource_initialized
)
147 mfd
= platform_get_drvdata(pdev
);
152 if (mfd
->key
!= MFD_KEY
)
155 if (pdev_list_cnt
>= MSM_FB_MAX_DEV_LIST
)
158 mdp_dev
= platform_device_alloc("mdp", pdev
->id
);
163 * link to the latest pdev
166 mfd
->dest
= DISPLAY_EXT_MDDI
;
169 * alloc panel device data
171 if (platform_device_add_data
172 (mdp_dev
, pdev
->dev
.platform_data
,
173 sizeof(struct msm_fb_panel_data
))) {
174 printk(KERN_ERR
"mddi_ext_probe: platform_device_add_data failed!\n");
175 platform_device_put(mdp_dev
);
181 pdata
= mdp_dev
->dev
.platform_data
;
182 pdata
->on
= mddi_ext_on
;
183 pdata
->off
= mddi_ext_off
;
187 * get/set panel specific fb info
189 mfd
->panel_info
= pdata
->panel_info
;
190 mfd
->fb_imgType
= MDP_RGB_565
;
192 clk_rate
= mfd
->panel_info
.clk_max
;
193 if (mddi_ext_pdata
&&
194 mddi_ext_pdata
->mddi_sel_clk
&&
195 mddi_ext_pdata
->mddi_sel_clk(&clk_rate
))
197 "%s: can't select mddi io clk targate rate = %d\n",
200 if (clk_set_max_rate(mddi_ext_clk
, clk_rate
) < 0)
201 printk(KERN_ERR
"%s: clk_set_max_rate failed\n", __func__
);
202 mfd
->panel_info
.clk_rate
= mfd
->panel_info
.clk_min
;
207 platform_set_drvdata(mdp_dev
, mfd
);
210 * register in mdp driver
212 rc
= platform_device_add(mdp_dev
);
214 goto mddi_ext_probe_err
;
216 pdev_list
[pdev_list_cnt
++] = pdev
;
218 #ifdef CONFIG_HAS_EARLYSUSPEND
219 mfd
->mddi_ext_early_suspend
.level
= EARLY_SUSPEND_LEVEL_DISABLE_FB
;
220 mfd
->mddi_ext_early_suspend
.suspend
= mddi_ext_early_suspend
;
221 mfd
->mddi_ext_early_suspend
.resume
= mddi_ext_early_resume
;
222 register_early_suspend(&mfd
->mddi_ext_early_suspend
);
228 platform_device_put(mdp_dev
);
232 static int mddi_ext_is_in_suspend
;
234 static int mddi_ext_suspend(struct platform_device
*pdev
, pm_message_t state
)
236 if (mddi_ext_is_in_suspend
)
239 mddi_ext_is_in_suspend
= 1;
241 if (clk_set_min_rate(mddi_ext_clk
, 0) < 0)
242 printk(KERN_ERR
"%s: clk_set_min_rate failed\n", __func__
);
244 clk_disable(mddi_ext_clk
);
245 disable_irq(INT_MDDI_EXT
);
250 static int mddi_ext_resume(struct platform_device
*pdev
)
252 struct msm_fb_data_type
*mfd
;
254 mfd
= platform_get_drvdata(pdev
);
256 if (!mddi_ext_is_in_suspend
)
259 mddi_ext_is_in_suspend
= 0;
260 enable_irq(INT_MDDI_EXT
);
262 clk_enable(mddi_ext_clk
);
267 #ifdef CONFIG_HAS_EARLYSUSPEND
268 static void mddi_ext_early_suspend(struct early_suspend
*h
)
271 struct msm_fb_data_type
*mfd
= container_of(h
, struct msm_fb_data_type
,
272 mddi_ext_early_suspend
);
274 state
.event
= PM_EVENT_SUSPEND
;
275 mddi_ext_suspend(mfd
->pdev
, state
);
278 static void mddi_ext_early_resume(struct early_suspend
*h
)
280 struct msm_fb_data_type
*mfd
= container_of(h
, struct msm_fb_data_type
,
281 mddi_ext_early_suspend
);
282 mddi_ext_resume(mfd
->pdev
);
286 static int mddi_ext_remove(struct platform_device
*pdev
)
288 iounmap(msm_emdh_base
);
292 static int mddi_ext_register_driver(void)
294 return platform_driver_register(&mddi_ext_driver
);
297 static int __init
mddi_ext_driver_init(void)
301 mddi_ext_clk
= clk_get(NULL
, "emdh_clk");
302 if (IS_ERR(mddi_ext_clk
)) {
303 printk(KERN_ERR
"can't find emdh_clk\n");
304 return PTR_ERR(mddi_ext_clk
);
306 clk_enable(mddi_ext_clk
);
308 ret
= mddi_ext_register_driver();
310 clk_disable(mddi_ext_clk
);
311 clk_put(mddi_ext_clk
);
312 printk(KERN_ERR
"mddi_ext_register_driver() failed!\n");
320 module_init(mddi_ext_driver_init
);