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>
34 #include <linux/platform_device.h>
37 #include "mddihosti.h"
39 #include <mach/gpio.h>
42 static int mddi_probe(struct platform_device
*pdev
);
43 static int mddi_remove(struct platform_device
*pdev
);
45 static int mddi_off(struct platform_device
*pdev
);
46 static int mddi_on(struct platform_device
*pdev
);
48 static int mddi_suspend(struct platform_device
*pdev
, pm_message_t state
);
49 static int mddi_resume(struct platform_device
*pdev
);
51 #ifdef CONFIG_HAS_EARLYSUSPEND
52 static void mddi_early_suspend(struct early_suspend
*h
);
53 static void mddi_early_resume(struct early_suspend
*h
);
56 static struct platform_device
*pdev_list
[MSM_FB_MAX_DEV_LIST
];
57 static int pdev_list_cnt
;
58 static struct clk
*mddi_clk
;
59 static struct clk
*mddi_pclk
;
60 static struct mddi_platform_data
*mddi_pdata
;
62 static struct platform_driver mddi_driver
= {
64 .remove
= mddi_remove
,
65 #ifndef CONFIG_HAS_EARLYSUSPEND
67 .suspend
= mddi_suspend
,
68 .resume
= mddi_resume
,
79 extern int int_mddi_pri_flag
;
81 static int mddi_off(struct platform_device
*pdev
)
85 ret
= panel_next_off(pdev
);
87 if (mddi_pdata
&& mddi_pdata
->mddi_power_save
)
88 mddi_pdata
->mddi_power_save(0);
93 static int mddi_on(struct platform_device
*pdev
)
97 struct msm_fb_data_type
*mfd
;
99 mfd
= platform_get_drvdata(pdev
);
101 if (mddi_pdata
&& mddi_pdata
->mddi_power_save
)
102 mddi_pdata
->mddi_power_save(1);
104 clk_rate
= mfd
->fbi
->var
.pixclock
;
105 clk_rate
= min(clk_rate
, mfd
->panel_info
.clk_max
);
108 mddi_pdata
->mddi_sel_clk
&&
109 mddi_pdata
->mddi_sel_clk(&clk_rate
))
111 "%s: can't select mddi io clk targate rate = %d\n",
114 if (clk_set_min_rate(mddi_clk
, clk_rate
) < 0)
115 printk(KERN_ERR
"%s: clk_set_min_rate failed\n",
118 ret
= panel_next_on(pdev
);
123 static int mddi_resource_initialized
;
125 static int mddi_probe(struct platform_device
*pdev
)
127 struct msm_fb_data_type
*mfd
;
128 struct platform_device
*mdp_dev
= NULL
;
129 struct msm_fb_panel_data
*pdata
= NULL
;
131 resource_size_t size
;
134 if ((pdev
->id
== 0) && (pdev
->num_resources
>= 0)) {
135 mddi_pdata
= pdev
->dev
.platform_data
;
137 size
= resource_size(&pdev
->resource
[0]);
138 msm_pmdh_base
= ioremap(pdev
->resource
[0].start
, size
);
140 MSM_FB_INFO("primary mddi base phy_addr = 0x%x virt = 0x%x\n",
141 pdev
->resource
[0].start
, (int) msm_pmdh_base
);
143 if (unlikely(!msm_pmdh_base
))
146 if (mddi_pdata
&& mddi_pdata
->mddi_power_save
)
147 mddi_pdata
->mddi_power_save(1);
149 mddi_resource_initialized
= 1;
153 if (!mddi_resource_initialized
)
156 mfd
= platform_get_drvdata(pdev
);
161 if (mfd
->key
!= MFD_KEY
)
164 if (pdev_list_cnt
>= MSM_FB_MAX_DEV_LIST
)
167 mdp_dev
= platform_device_alloc("mdp", pdev
->id
);
172 * link to the latest pdev
175 mfd
->dest
= DISPLAY_LCD
;
178 * alloc panel device data
180 if (platform_device_add_data
181 (mdp_dev
, pdev
->dev
.platform_data
,
182 sizeof(struct msm_fb_panel_data
))) {
183 printk(KERN_ERR
"mddi_probe: platform_device_add_data failed!\n");
184 platform_device_put(mdp_dev
);
190 pdata
= mdp_dev
->dev
.platform_data
;
192 pdata
->off
= mddi_off
;
196 * get/set panel specific fb info
198 mfd
->panel_info
= pdata
->panel_info
;
199 mfd
->fb_imgType
= MDP_RGB_565
;
201 clk_rate
= mfd
->panel_info
.clk_max
;
203 mddi_pdata
->mddi_sel_clk
&&
204 mddi_pdata
->mddi_sel_clk(&clk_rate
))
206 "%s: can't select mddi io clk targate rate = %d\n",
209 if (clk_set_max_rate(mddi_clk
, clk_rate
) < 0)
210 printk(KERN_ERR
"%s: clk_set_max_rate failed\n", __func__
);
211 mfd
->panel_info
.clk_rate
= mfd
->panel_info
.clk_min
;
216 platform_set_drvdata(mdp_dev
, mfd
);
219 * register in mdp driver
221 rc
= platform_device_add(mdp_dev
);
225 pdev_list
[pdev_list_cnt
++] = pdev
;
227 #ifdef CONFIG_HAS_EARLYSUSPEND
228 mfd
->mddi_early_suspend
.level
= EARLY_SUSPEND_LEVEL_DISABLE_FB
;
229 mfd
->mddi_early_suspend
.suspend
= mddi_early_suspend
;
230 mfd
->mddi_early_suspend
.resume
= mddi_early_resume
;
231 register_early_suspend(&mfd
->mddi_early_suspend
);
237 platform_device_put(mdp_dev
);
241 static int mddi_pad_ctrl
;
242 static int mddi_power_locked
;
243 static int mddi_is_in_suspend
;
245 void mddi_disable(int lock
)
247 mddi_host_type host_idx
= MDDI_HOST_PRIM
;
249 if (mddi_power_locked
)
253 mddi_power_locked
= 1;
255 if (mddi_host_timer
.function
)
256 del_timer_sync(&mddi_host_timer
);
258 mddi_pad_ctrl
= mddi_host_reg_in(PAD_CTL
);
259 mddi_host_reg_out(PAD_CTL
, 0x0);
261 if (clk_set_min_rate(mddi_clk
, 0) < 0)
262 printk(KERN_ERR
"%s: clk_set_min_rate failed\n", __func__
);
264 clk_disable(mddi_clk
);
266 clk_disable(mddi_pclk
);
267 disable_irq(INT_MDDI_PRI
);
269 if (mddi_pdata
&& mddi_pdata
->mddi_power_save
)
270 mddi_pdata
->mddi_power_save(0);
273 static int mddi_suspend(struct platform_device
*pdev
, pm_message_t state
)
275 if (mddi_is_in_suspend
)
278 mddi_is_in_suspend
= 1;
283 static int mddi_resume(struct platform_device
*pdev
)
285 mddi_host_type host_idx
= MDDI_HOST_PRIM
;
287 if (!mddi_is_in_suspend
)
290 mddi_is_in_suspend
= 0;
292 if (mddi_power_locked
)
295 enable_irq(INT_MDDI_PRI
);
296 clk_enable(mddi_clk
);
298 clk_enable(mddi_pclk
);
299 mddi_host_reg_out(PAD_CTL
, mddi_pad_ctrl
);
301 if (mddi_host_timer
.function
)
302 mddi_host_timer_service(0);
307 #ifdef CONFIG_HAS_EARLYSUSPEND
308 static void mddi_early_suspend(struct early_suspend
*h
)
311 struct msm_fb_data_type
*mfd
= container_of(h
, struct msm_fb_data_type
,
314 state
.event
= PM_EVENT_SUSPEND
;
315 mddi_suspend(mfd
->pdev
, state
);
318 static void mddi_early_resume(struct early_suspend
*h
)
320 struct msm_fb_data_type
*mfd
= container_of(h
, struct msm_fb_data_type
,
322 mddi_resume(mfd
->pdev
);
326 static int mddi_remove(struct platform_device
*pdev
)
328 if (mddi_host_timer
.function
)
329 del_timer_sync(&mddi_host_timer
);
331 iounmap(msm_pmdh_base
);
336 static int mddi_register_driver(void)
338 return platform_driver_register(&mddi_driver
);
341 static int __init
mddi_driver_init(void)
345 mddi_clk
= clk_get(NULL
, "mddi_clk");
346 if (IS_ERR(mddi_clk
)) {
347 printk(KERN_ERR
"can't find mddi_clk \n");
348 return PTR_ERR(mddi_clk
);
350 clk_enable(mddi_clk
);
352 mddi_pclk
= clk_get(NULL
, "mddi_pclk");
353 if (IS_ERR(mddi_pclk
))
356 clk_enable(mddi_pclk
);
358 ret
= mddi_register_driver();
360 clk_disable(mddi_clk
);
363 clk_disable(mddi_pclk
);
366 printk(KERN_ERR
"mddi_register_driver() failed!\n");
375 module_init(mddi_driver_init
);