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);