diff options
author | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 09:48:20 +0200 |
---|---|---|
committer | codeworkx <codeworkx@cyanogenmod.com> | 2012-09-22 14:02:16 +0200 |
commit | 2489007e7d740ccbc3e0a202914e243ad5178787 (patch) | |
tree | b8e6380ea7b1da63474ad68a5dba997e01146043 /drivers/devfreq/exynos4_display.c | |
parent | 5f67568eb31e3a813c7c52461dcf66ade15fc2e7 (diff) | |
download | kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.zip kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.gz kernel_samsung_smdk4412-2489007e7d740ccbc3e0a202914e243ad5178787.tar.bz2 |
merge opensource jb u5
Change-Id: I1aaec157aa196f3448eff8636134fce89a814cf2
Diffstat (limited to 'drivers/devfreq/exynos4_display.c')
-rw-r--r-- | drivers/devfreq/exynos4_display.c | 388 |
1 files changed, 0 insertions, 388 deletions
diff --git a/drivers/devfreq/exynos4_display.c b/drivers/devfreq/exynos4_display.c deleted file mode 100644 index c26124de..0000000 --- a/drivers/devfreq/exynos4_display.c +++ /dev/null @@ -1,388 +0,0 @@ -/* drivers/devfreq/exynos4_display.c - * - * Copyright (c) 2012 Samsung Electronics Co., Ltd. - * http://www.samsung.com/ - * - * Chanwoo Choi <cw00.choi@samsung.com> - * Myungjoo Ham <myungjoo.ham@samsung.com> - * Kyungmin Park <kyungmin.park@samsung.com> - * - * EXYNOS4 - Dynamic LCD refresh rate support - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as - * published by the Free Software Foundation. - * - */ - -#include <linux/kernel.h> -#include <linux/err.h> -#include <linux/opp.h> -#include <linux/mutex.h> -#include <linux/suspend.h> -#include <linux/notifier.h> -#include <linux/slab.h> -#include <linux/platform_device.h> -#include <linux/devfreq.h> -#include <linux/devfreq/exynos4_display.h> -#include <linux/pm_qos_params.h> - -#define EXYNOS4_DISPLAY_ON 1 -#define EXYNOS4_DISPLAY_OFF 0 - -#define DEFAULT_DELAY_TIME 1000 /* us (millisecond) */ - -enum exynos4_display_type { - TYPE_DISPLAY_EXYNOS4210, - TYPE_DISPLAY_EXYNOS4x12, -}; - -struct exynos4_display_data { - enum exynos4_display_type type; - struct devfreq *devfreq; - struct opp *curr_opp; - struct device *dev; - - struct delayed_work wq_lowfreq; - - struct notifier_block nb_pm; - - unsigned int state; - struct mutex lock; -}; - -/* Define frequency level */ -enum display_clk_level_idx { - LV_0 = 0, - LV_1, - _LV_END -}; - -/* Define opp table which include various frequency level */ -struct display_opp_table { - unsigned int idx; - unsigned long clk; - unsigned long volt; -}; - -static struct display_opp_table exynos4_display_clk_table[] = { - {LV_0, 40, 0 }, - {LV_1, 60, 0 }, - {0, 0, 0 }, -}; - -/* - * The exynos-display driver send newly frequency to display client - * if it receive event from sender device. - * List of display client device - * - FIMD and so on - */ -static BLOCKING_NOTIFIER_HEAD(exynos4_display_notifier_client_list); - -int exynos4_display_register_client(struct notifier_block *nb) -{ - return blocking_notifier_chain_register( - &exynos4_display_notifier_client_list, nb); -} -EXPORT_SYMBOL(exynos4_display_register_client); - -int exynos4_display_unregister_client(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister( - &exynos4_display_notifier_client_list, nb); -} -EXPORT_SYMBOL(exynos4_display_unregister_client); - -static int exynos4_display_send_event_to_display(unsigned long val, void *v) -{ - return blocking_notifier_call_chain( - &exynos4_display_notifier_client_list, val, v); -} - -/* - * Register exynos-display as client to pm notifer - * - This callback gets called when something important happens in pm state. - */ -static int exynos4_display_pm_notifier_callback(struct notifier_block *this, - unsigned long event, void *_data) -{ - struct exynos4_display_data *data = container_of(this, - struct exynos4_display_data, nb_pm); - - if (data->state == EXYNOS4_DISPLAY_OFF) - return NOTIFY_OK; - - switch (event) { - case PM_SUSPEND_PREPARE: - mutex_lock(&data->lock); - data->state = EXYNOS4_DISPLAY_OFF; - mutex_unlock(&data->lock); - - if (delayed_work_pending(&data->wq_lowfreq)) - cancel_delayed_work(&data->wq_lowfreq); - - return NOTIFY_OK; - case PM_POST_RESTORE: - case PM_POST_SUSPEND: - mutex_lock(&data->lock); - data->state = EXYNOS4_DISPLAY_ON; - mutex_unlock(&data->lock); - - return NOTIFY_OK; - } - - return NOTIFY_DONE; -} - -/* - * Enable/disable exynos-display operation - */ -static void exynos4_display_disable(struct exynos4_display_data *data) -{ - struct opp *opp; - unsigned long freq = EXYNOS4_DISPLAY_LV_DEFAULT; - - /* Cancel workqueue which set low frequency of display client - * if it is pending state before executing workqueue. */ - if (delayed_work_pending(&data->wq_lowfreq)) - cancel_delayed_work(&data->wq_lowfreq); - - /* Set high frequency(default) of display client */ - exynos4_display_send_event_to_display(freq, NULL); - - mutex_lock(&data->lock); - data->state = EXYNOS4_DISPLAY_OFF; - mutex_unlock(&data->lock); - - /* Find opp object with high frequency */ - opp = opp_find_freq_floor(data->dev, &freq); - if (IS_ERR(opp)) { - dev_err(data->dev, - "invalid initial frequency %lu kHz.\n", freq); - } else - data->curr_opp = opp; -} - -static void exynos4_display_enable(struct exynos4_display_data *data) -{ - data->state = EXYNOS4_DISPLAY_ON; -} - -/* - * Timer to set display with low frequency state after 1 second - */ -static void exynos4_display_set_lowfreq(struct work_struct *work) -{ - exynos4_display_send_event_to_display(EXYNOS4_DISPLAY_LV_LF, NULL); -} - -/* - * Send event to display client for changing frequency when DVFREQ framework - * update state of device - */ -static int exynos4_display_profile_target(struct device *dev, - unsigned long *_freq, u32 options) -{ - /* Inform display client of new frequency */ - struct exynos4_display_data *data = dev_get_drvdata(dev); - struct opp *opp = devfreq_recommended_opp(dev, _freq, options & - DEVFREQ_OPTION_FREQ_GLB); - unsigned long old_freq = opp_get_freq(data->curr_opp); - unsigned long new_freq = opp_get_freq(opp); - - /* TODO: No longer use fb notifier to identify LCD on/off state and - have yet alternative feature of it. So, exynos4-display change - refresh rate of display clinet irrespective of LCD state until - proper feature will be implemented. */ - if (old_freq == new_freq) - return 0; - - opp = opp_find_freq_floor(dev, &new_freq); - data->curr_opp = opp; - - switch (new_freq) { - case EXYNOS4_DISPLAY_LV_HF: - if (delayed_work_pending(&data->wq_lowfreq)) - cancel_delayed_work(&data->wq_lowfreq); - - exynos4_display_send_event_to_display( - EXYNOS4_DISPLAY_LV_HF, NULL); - break; - case EXYNOS4_DISPLAY_LV_LF: - schedule_delayed_work(&data->wq_lowfreq, - msecs_to_jiffies(DEFAULT_DELAY_TIME)); - break; - } - - printk(KERN_DEBUG "exynos4-display: request %ldHz from \'%s\'\n", - new_freq, dev_name(dev)); - - return 0; -} - -static void exynos4_display_profile_exit(struct device *dev) -{ - /* TODO */ -} - -static struct devfreq_dev_profile exynos4_display_profile = { - .initial_freq = EXYNOS4_DISPLAY_LV_DEFAULT, - .target = exynos4_display_profile_target, - .exit = exynos4_display_profile_exit, -}; - -static int exynos4_display_probe(struct platform_device *pdev) -{ - struct exynos4_display_data *data; - struct device *dev = &pdev->dev; - struct opp *opp; - int ret = 0; - int i; - struct devfreq_pm_qos_table *qos_list; - - data = kzalloc(sizeof(struct exynos4_display_data), GFP_KERNEL); - if (!data) { - dev_err(dev, "cannot allocate memory.\n"); - return -ENOMEM; - } - data->dev = dev; - data->state = EXYNOS4_DISPLAY_ON; - mutex_init(&data->lock); - - /* Register OPP entries */ - for (i = 0 ; i < _LV_END ; i++) { - ret = opp_add(dev, exynos4_display_clk_table[i].clk, - exynos4_display_clk_table[i].volt); - if (ret) { - dev_err(dev, "cannot add opp entries.\n"); - goto err_alloc_mem; - } - } - - /* Find opp object with init frequency */ - opp = opp_find_freq_floor(dev, &exynos4_display_profile.initial_freq); - if (IS_ERR(opp)) { - dev_err(dev, "invalid initial frequency %lu kHz.\n", - exynos4_display_profile.initial_freq); - ret = PTR_ERR(opp); - goto err_alloc_mem; - } - data->curr_opp = opp; - - /* Initialize QoS */ - qos_list = kzalloc(sizeof(struct devfreq_pm_qos_table) * _LV_END, - GFP_KERNEL); - for (i = 0 ; i < _LV_END ; i++) { - qos_list[i].freq = exynos4_display_clk_table[i].clk; - qos_list[i].qos_value = exynos4_display_clk_table[i].clk; - } - exynos4_display_profile.qos_type = PM_QOS_DISPLAY_FREQUENCY; - exynos4_display_profile.qos_use_max = true; - exynos4_display_profile.qos_list = qos_list; - - /* Register exynos4_display to DEVFREQ framework */ - data->devfreq = devfreq_add_device(dev, &exynos4_display_profile, - &devfreq_powersave, NULL); - if (IS_ERR(data->devfreq)) { - ret = PTR_ERR(data->devfreq); - dev_err(dev, - "failed to add exynos4 lcd to DEVFREQ : %d\n", ret); - goto err_alloc_mem; - } - devfreq_register_opp_notifier(dev, data->devfreq); - - /* Register exynos4_display as client to pm notifier */ - memset(&data->nb_pm, 0, sizeof(data->nb_pm)); - data->nb_pm.notifier_call = exynos4_display_pm_notifier_callback; - ret = register_pm_notifier(&data->nb_pm); - if (ret < 0) { - dev_err(dev, "failed to get pm notifier: %d\n", ret); - goto err_add_devfreq; - } - - INIT_DELAYED_WORK(&data->wq_lowfreq, exynos4_display_set_lowfreq); - - platform_set_drvdata(pdev, data); - - return 0; - -err_add_devfreq: - devfreq_remove_device(data->devfreq); -err_alloc_mem: - kfree(data); - - return ret; -} - -static int __devexit exynos4_display_remove(struct platform_device *pdev) -{ - struct exynos4_display_data *data = pdev->dev.platform_data; - - unregister_pm_notifier(&data->nb_pm); - exynos4_display_disable(data); - - devfreq_remove_device(data->devfreq); - - kfree(data); - - return 0; -} - -#ifdef CONFIG_PM -static int exynos4_display_suspend(struct device *dev) -{ - /* TODO */ - return 0; -} - -static int exynos4_display_resume(struct device *dev) -{ - /* TODO */ - return 0; -} - -static const struct dev_pm_ops exynos4_display_dev_pm_ops = { - .suspend = exynos4_display_suspend, - .resume = exynos4_display_resume, -}; - -#define exynos4_display_DEV_PM_OPS (&exynos4_display_dev_pm_ops) -#else -#define exynos4_display_DEV_PM_OPS NULL -#endif /* CONFIG_PM */ - -static struct platform_device_id exynos4_display_ids[] = { - { "exynos4210-display", TYPE_DISPLAY_EXYNOS4210 }, - { "exynos4212-display", TYPE_DISPLAY_EXYNOS4x12 }, - { "exynos4412-display", TYPE_DISPLAY_EXYNOS4x12 }, - { }, -}; - -static struct platform_driver exynos4_display_driver = { - .probe = exynos4_display_probe, - .remove = __devexit_p(exynos4_display_remove), - .id_table = exynos4_display_ids, - .driver = { - .name = "exynos4-display", - .owner = THIS_MODULE, - .pm = exynos4_display_DEV_PM_OPS, - }, -}; - -static int __init exynos4_display_init(void) -{ - return platform_driver_register(&exynos4_display_driver); -} -late_initcall(exynos4_display_init); - -static void __exit exynos4_display_exit(void) -{ - platform_driver_unregister(&exynos4_display_driver); -} -module_exit(exynos4_display_exit); -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("EXYNOS4 display driver with devfreq framework"); -MODULE_AUTHOR("Chanwoo Choi <cw00.choi@samsung.com>"); -MODULE_AUTHOR("Myungjoo Ham <myungjoo.ham@samsung.com>"); -MODULE_AUTHOR("Kyungmin Park <kyungmin.park@samsung.com>"); -MODULE_ALIAS("exynos-display"); |