aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/devfreq
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/devfreq')
-rw-r--r--drivers/devfreq/exynos4_bus.c186
-rw-r--r--drivers/devfreq/exynos4_display.c388
2 files changed, 114 insertions, 460 deletions
diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c
index 2d35f22..b634111 100644
--- a/drivers/devfreq/exynos4_bus.c
+++ b/drivers/devfreq/exynos4_bus.c
@@ -71,12 +71,14 @@ enum busclk_level_idx {
LV_2,
LV_3,
LV_4,
+ LV_5,
+ LV_6,
_LV_END
};
#define EX4210_LV_MAX LV_2
-#define EX4x12_LV_MAX LV_4
+#define EX4x12_LV_MAX LV_6
#define EX4210_LV_NUM (LV_2 + 1)
-#define EX4x12_LV_NUM (LV_4 + 1)
+#define EX4x12_LV_NUM (LV_6 + 1)
struct busfreq_data {
enum exynos4_busf_type type;
@@ -124,11 +126,13 @@ static struct bus_opp_table exynos4210_busclk_table[] = {
* clock and voltage of both mif/int are controlled.
*/
static struct bus_opp_table exynos4x12_mifclk_table[] = {
- {LV_0, 400000, 1100000},
- {LV_1, 267000, 1000000},
- {LV_2, 160000, 950000},
- {LV_3, 133000, 950000},
- {LV_4, 100000, 950000},
+ {LV_0, 400266, 1100000}, /* MIF : 400MHz INT : 266MHz */
+ {LV_1, 400200, 1100000}, /* MIF : 400MHz INT : 200MHz */
+ {LV_2, 267200, 1000000}, /* MIF : 267MHz INT : 200MHz */
+ {LV_3, 267160, 1000000}, /* MIF : 267MHz INT : 160MHz */
+ {LV_4, 160160, 950000}, /* MIF : 160MHz INT : 160MHz */
+ {LV_5, 133133, 950000}, /* MIF : 133MHz INT : 133MHz */
+ {LV_6, 100100, 950000}, /* MIF : 100MHz INT : 100MHz */
{0, 0, 0},
};
@@ -139,9 +143,11 @@ static struct bus_opp_table exynos4x12_mifclk_table[] = {
static struct bus_opp_table exynos4x12_intclk_table[] = {
{LV_0, 266000, 1100000},
{LV_1, 200000, 1000000},
- {LV_2, 160000, 950000},
- {LV_3, 133000, 925000},
- {LV_4, 100000, 900000},
+ {LV_2, 200000, 1000000},
+ {LV_3, 160000, 950000},
+ {LV_4, 160000, 950000},
+ {LV_5, 133000, 925000},
+ {LV_6, 100000, 900000},
{0, 0, 0},
};
@@ -189,43 +195,45 @@ static unsigned int exynos4212_int_volt[][_LV_END] = {
};
static unsigned int exynos4412_mif_volt[][_LV_END] = {
- /* 400 267 160 133 100 */
- {1100000, 1000000, 950000, 950000, 950000}, /* RESERVED */
- {1050000, 950000, 900000, 900000, 900000}, /* RESERVED */
- {1050000, 950000, 900000, 900000, 900000}, /* ASV2 */
- {1050000, 950000, 900000, 900000, 900000}, /* ASV3 */
- {1050000, 950000, 900000, 900000, 900000}, /* ASV4 */
- {1000000, 950000, 900000, 900000, 900000}, /* ASV5 */
- {1000000, 950000, 900000, 900000, 900000}, /* ASV6 */
- {1000000, 950000, 900000, 900000, 900000}, /* ASV7 */
- {1000000, 950000, 900000, 900000, 900000}, /* ASV8 */
- {1000000, 950000, 900000, 900000, 850000}, /* ASV9 */
- {1000000, 900000, 900000, 900000, 850000}, /* ASV10 */
- {1000000, 900000, 900000, 900000, 850000}, /* RESERVED */
+ /* 400 400 267 267 160 133 100 */
+ {1100000, 1100000, 1000000, 1000000, 950000, 950000, 950000}, /* RESERVED */
+ {1050000, 1050000, 950000, 950000, 900000, 900000, 900000}, /* RESERVED */
+ {1050000, 1050000, 950000, 950000, 900000, 900000, 900000}, /* ASV2 */
+ {1050000, 1050000, 950000, 950000, 900000, 900000, 900000}, /* ASV3 */
+ {1050000, 1050000, 950000, 950000, 900000, 900000, 900000}, /* ASV4 */
+ {1000000, 1000000, 950000, 950000, 900000, 900000, 900000}, /* ASV5 */
+ {1000000, 1000000, 950000, 950000, 900000, 900000, 900000}, /* ASV6 */
+ {1000000, 1000000, 950000, 950000, 900000, 900000, 900000}, /* ASV7 */
+ {1000000, 1000000, 950000, 950000, 900000, 900000, 900000}, /* ASV8 */
+ {1000000, 1000000, 950000, 950000, 900000, 900000, 850000}, /* ASV9 */
+ {1000000, 1000000, 900000, 900000, 900000, 900000, 850000}, /* ASV10 */
+ {1000000, 1000000, 900000, 900000, 900000, 900000, 850000}, /* RESERVED */
};
static unsigned int exynos4412_int_volt[][_LV_END] = {
- /* GDR : 266 200 160 133 100 */
- {1112500, 1062500, 975000, 937500, 900000}, /* RESERVED */
- {1100000, 1050000, 962500, 925000, 887500}, /* RESERVED */
- {1075000, 1025000, 937500, 912500, 875000}, /* ASV2 */
- {1062500, 1012500, 937500, 900000, 862500}, /* ASV3 */
- {1062500, 1012500, 925000, 900000, 862500}, /* ASV4 */
- {1050000, 1000000, 925000, 887500, 850000}, /* ASV5 */
- {1050000, 1000000, 912500, 875000, 850000}, /* ASV6 */
- {1037500, 987500, 912500, 862500, 850000}, /* ASV7 */
- {1037500, 987500, 900000, 862500, 850000}, /* ASV8 */
- {1037500, 987500, 900000, 862500, 850000}, /* ASV9 */
- {1037500, 987500, 900000, 862500, 850000}, /* ASV10 */
- {1025000, 975000, 887500, 850000, 850000}, /* RESERVED */
+ /* GDR : 266 200 200 160 160 133 100 */
+ {1112500, 1062500, 1062500, 975000, 975000, 937500, 900000}, /* RESERVED */
+ {1100000, 1050000, 1050000, 962500, 962500, 925000, 887500}, /* RESERVED */
+ {1075000, 1025000, 1025000, 937500, 937500, 912500, 875000}, /* ASV2 */
+ {1062500, 1012500, 1012500, 937500, 937500, 900000, 862500}, /* ASV3 */
+ {1062500, 1012500, 1012500, 925000, 925000, 900000, 862500}, /* ASV4 */
+ {1050000, 1000000, 1000000, 925000, 925000, 887500, 850000}, /* ASV5 */
+ {1050000, 1000000, 1000000, 912500, 912500, 875000, 850000}, /* ASV6 */
+ {1037500, 987500, 987500, 912500, 912500, 862500, 850000}, /* ASV7 */
+ {1037500, 987500, 987500, 900000, 900000, 862500, 850000}, /* ASV8 */
+ {1037500, 987500, 987500, 900000, 900000, 862500, 850000}, /* ASV9 */
+ {1037500, 987500, 987500, 900000, 900000, 862500, 850000}, /* ASV10 */
+ {1025000, 975000, 975000, 887500, 887500, 850000, 850000}, /* RESERVED */
};
static unsigned int exynos4x12_qos_value[][4] = {
- {0x00, 0x00, 0x00, 0x00}, /* 400 */
- {0x00, 0x00, 0x00, 0x00}, /* 267 */
- {0x06, 0x03, 0x06, 0x0e}, /* 160 */
- {0x06, 0x03, 0x06, 0x0e}, /* 133 */
- {0x03, 0x0B, 0x00, 0x00}, /* 100 */
+ {0x06, 0x0b, 0x06, 0x0f},
+ {0x06, 0x0b, 0x06, 0x0f},
+ {0x06, 0x0b, 0x06, 0x0f},
+ {0x06, 0x0b, 0x06, 0x0f},
+ {0x06, 0x03, 0x06, 0x0e},
+ {0x04, 0x03, 0x04, 0x0e},
+ {0x03, 0x0b, 0x00, 0x00},
};
static unsigned int exynos4x12_timingrow[] = {
@@ -282,13 +290,17 @@ static unsigned int exynos4x12_clkdiv_dmc0[][6] = {
/* DMC L0: 400MHz */
{3, 1, 1, 1, 1, 1},
- /* DMC L1: 266.7MHz */
+ /* DMC L1: 400MHz */
+ {3, 1, 1, 1, 1, 1},
+ /* DMC L2: 266.7MHz */
+ {4, 1, 1, 2, 1, 1},
+ /* DMC L3: 266.7MHz */
{4, 1, 1, 2, 1, 1},
- /* DMC L2: 160MHz */
+ /* DMC L4: 160MHz */
{5, 1, 1, 4, 1, 1},
- /* DMC L3: 133MHz */
+ /* DMC L5: 133MHz */
{5, 1, 1, 5, 1, 1},
- /* DMC L4: 100MHz */
+ /* DMC L6: 100MHz */
{7, 1, 1, 7, 1, 1},
};
static unsigned int exynos4x12_clkdiv_dmc1[][3] = {
@@ -299,13 +311,17 @@ static unsigned int exynos4x12_clkdiv_dmc1[][3] = {
/* DMC L0: 400MHz */
{3, 1, 1},
- /* DMC L1: 266.7MHz */
+ /* DMC L1: 400MHz */
+ {3, 1, 1},
+ /* DMC L2: 266.7MHz */
+ {4, 2, 1},
+ /* DMC L3: 266.7MHz */
{4, 2, 1},
- /* DMC L2: 160MHz */
+ /* DMC L4: 160MHz */
{5, 4, 1},
- /* DMC L3: 133MHz */
+ /* DMC L5: 133MHz */
{5, 5, 1},
- /* DMC L4: 100MHz */
+ /* DMC L6: 100MHz */
{7, 7, 1},
};
static unsigned int exynos4x12_clkdiv_top[][5] = {
@@ -319,11 +335,15 @@ static unsigned int exynos4x12_clkdiv_top[][5] = {
{2, 7, 4, 5, 1},
/* ACLK_GDL/R L1: 200MHz */
{2, 7, 4, 5, 1},
- /* ACLK_GDL/R L2: 160MHz */
+ /* ACLK_GDL/R L2: 200MHz */
+ {2, 7, 4, 5, 1},
+ /* ACLK_GDL/R L3: 160MHz */
{4, 7, 5, 7, 1},
- /* ACLK_GDL/R L3: 133MHz */
+ /* ACLK_GDL/R L4: 160MHz */
+ {4, 7, 5, 7, 1},
+ /* ACLK_GDL/R L5: 133MHz */
{5, 7, 5, 7, 1},
- /* ACLK_GDL/R L4: 100MHz */
+ /* ACLK_GDL/R L6: 100MHz */
{7, 7, 7, 7, 1},
};
static unsigned int exynos4x12_clkdiv_l_bus[][2] = {
@@ -332,15 +352,19 @@ static unsigned int exynos4x12_clkdiv_l_bus[][2] = {
* { DIVGDL, DIVGPL }
*/
- /* ACLK_GDL L0: 266MHz */
+ /* ACLK_GDL L0: 200MHz */
{3, 1},
/* ACLK_GDL L1: 200MHz */
{3, 1},
- /* ACLK_GDL L2: 160MHz */
+ /* ACLK_GDL L2: 200MHz */
+ {3, 1},
+ /* ACLK_GDL L3: 160MHz */
+ {4, 1},
+ /* ACLK_GDL L4: 160MHz */
{4, 1},
- /* ACLK_GDL L3: 133MHz */
+ /* ACLK_GDL L5: 133MHz */
{5, 1},
- /* ACLK_GDL L4: 100MHz */
+ /* ACLK_GDL L6: 100MHz */
{7, 1},
};
static unsigned int exynos4x12_clkdiv_r_bus[][2] = {
@@ -353,11 +377,15 @@ static unsigned int exynos4x12_clkdiv_r_bus[][2] = {
{2, 1},
/* ACLK_GDR L1: 200MHz */
{3, 1},
- /* ACLK_GDR L2: 160MHz */
+ /* ACLK_GDR L2: 200MHz */
+ {3, 1},
+ /* ACLK_GDR L3: 160MHz */
+ {4, 1},
+ /* ACLK_GDR L4: 160MHz */
{4, 1},
- /* ACLK_GDR L3: 133MHz */
+ /* ACLK_GDR L5: 133MHz */
{5, 1},
- /* ACLK_GDR L4: 100MHz */
+ /* ACLK_GDR L6: 100MHz */
{7, 1},
};
static unsigned int exynos4x12_clkdiv_sclkip[][3] = {
@@ -370,6 +398,10 @@ static unsigned int exynos4x12_clkdiv_sclkip[][3] = {
{3, 3, 4},
/* SCLK_MFC: 200MHz */
{3, 3, 4},
+ /* SCLK_MFC: 200MHz */
+ {3, 3, 4},
+ /* SCLK_MFC: 160MHz */
+ {4, 4, 5},
/* SCLK_MFC: 160MHz */
{4, 4, 5},
/* SCLK_MFC: 133MHz */
@@ -689,16 +721,20 @@ static int exynos4x12_get_dev_status(struct busfreq_data *data,
static int exynos4x12_get_intspec(unsigned long mifclk)
{
switch (mifclk) {
- case 400000:
+ case 400266:
return LV_0; /* 266000 */
- case 267000:
+ case 400200:
return LV_1; /* 200000 */
- case 160000:
- return LV_2; /* 160000 */
- case 133000:
- return LV_3; /* 133000 */
- case 100000:
- return LV_4; /* 100000 */
+ case 267200:
+ return LV_2; /* 200000 */
+ case 267160:
+ return LV_3; /* 160000 */
+ case 160160:
+ return LV_4; /* 160000 */
+ case 133133:
+ return LV_5; /* 133000 */
+ case 100100:
+ return LV_6; /* 100000 */
}
return -EINVAL;
@@ -759,21 +795,27 @@ static void exynos4x12_set_qos(struct busfreq_data *data, struct opp *opp)
int index;
switch (opp_get_freq(opp)) {
- case 400000:
+ case 400266:
index = 0;
break;
- case 267000:
+ case 400200:
index = 1;
break;
- case 160000:
+ case 267200:
index = 2;
break;
- case 133000:
+ case 267160:
index = 3;
break;
- case 100000:
+ case 160160:
index = 4;
break;
+ case 133133:
+ index = 5;
+ break;
+ case 100100:
+ index = 6;
+ break;
default:
dev_err(data->dev, "Incorrect OPP configuration.\n");
return;
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");