aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoonyoung Shim <jy0922.shim@samsung.com>2012-04-23 06:35:50 -0400
committerInki Dae <inki.dae@samsung.com>2012-05-08 05:46:33 -0400
commitcf8fc4f10e2c5c5b6b60d6e79d61cc58afa5967d (patch)
tree74cdc233ce54eb37ef67e7fec7af5ee2bf75911f
parent66265a2e8e867a9c5ce63e5f883cf751b35b66d5 (diff)
drm/exynos: add dpms for hdmi
The power and clocks turns on always in exynos hdmi and mixer driver, but we should turn off the power and clocks of exynos hdmi and mixer when the hdmi cable unplugged or when hdmi unused. There are two interrupt to detect hotplug of hdmi cable - internal interrupt and external interrupt. The internal interrupt can use only when hdmi is dpms on so if hdmi is dpms off, we should use external interrupt to detect hotplug of hdmi cable. If hdmi is dpms on, we cannot external interrupt because the gpio pin for external interrupt is used to hdmi HPD pin for internal interrupt. Signed-off-by: Joonyoung Shim <jy0922.shim@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Inki Dae <inki.dae@samsung.com>
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.c77
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_hdmi.h6
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c276
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c288
4 files changed, 341 insertions, 306 deletions
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index 3424463676e0..5d9d2c2f8f3f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -37,6 +37,8 @@ struct drm_hdmi_context {
37 struct exynos_drm_subdrv subdrv; 37 struct exynos_drm_subdrv subdrv;
38 struct exynos_drm_hdmi_context *hdmi_ctx; 38 struct exynos_drm_hdmi_context *hdmi_ctx;
39 struct exynos_drm_hdmi_context *mixer_ctx; 39 struct exynos_drm_hdmi_context *mixer_ctx;
40
41 bool enabled[MIXER_WIN_NR];
40}; 42};
41 43
42void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops) 44void exynos_hdmi_ops_register(struct exynos_hdmi_ops *ops)
@@ -189,23 +191,34 @@ static void drm_hdmi_dpms(struct device *subdrv_dev, int mode)
189 191
190 DRM_DEBUG_KMS("%s\n", __FILE__); 192 DRM_DEBUG_KMS("%s\n", __FILE__);
191 193
192 switch (mode) { 194 if (mixer_ops && mixer_ops->dpms)
193 case DRM_MODE_DPMS_ON: 195 mixer_ops->dpms(ctx->mixer_ctx->ctx, mode);
194 break; 196
195 case DRM_MODE_DPMS_STANDBY: 197 if (hdmi_ops && hdmi_ops->dpms)
196 case DRM_MODE_DPMS_SUSPEND: 198 hdmi_ops->dpms(ctx->hdmi_ctx->ctx, mode);
197 case DRM_MODE_DPMS_OFF: 199}
198 if (hdmi_ops && hdmi_ops->disable) 200
199 hdmi_ops->disable(ctx->hdmi_ctx->ctx); 201static void drm_hdmi_apply(struct device *subdrv_dev)
200 break; 202{
201 default: 203 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
202 DRM_DEBUG_KMS("unkown dps mode: %d\n", mode); 204 int i;
203 break; 205
206 DRM_DEBUG_KMS("%s\n", __FILE__);
207
208 for (i = 0; i < MIXER_WIN_NR; i++) {
209 if (!ctx->enabled[i])
210 continue;
211 if (mixer_ops && mixer_ops->win_commit)
212 mixer_ops->win_commit(ctx->mixer_ctx->ctx, i);
204 } 213 }
214
215 if (hdmi_ops && hdmi_ops->commit)
216 hdmi_ops->commit(ctx->hdmi_ctx->ctx);
205} 217}
206 218
207static struct exynos_drm_manager_ops drm_hdmi_manager_ops = { 219static struct exynos_drm_manager_ops drm_hdmi_manager_ops = {
208 .dpms = drm_hdmi_dpms, 220 .dpms = drm_hdmi_dpms,
221 .apply = drm_hdmi_apply,
209 .enable_vblank = drm_hdmi_enable_vblank, 222 .enable_vblank = drm_hdmi_enable_vblank,
210 .disable_vblank = drm_hdmi_disable_vblank, 223 .disable_vblank = drm_hdmi_disable_vblank,
211 .mode_fixup = drm_hdmi_mode_fixup, 224 .mode_fixup = drm_hdmi_mode_fixup,
@@ -228,21 +241,37 @@ static void drm_mixer_mode_set(struct device *subdrv_dev,
228static void drm_mixer_commit(struct device *subdrv_dev, int zpos) 241static void drm_mixer_commit(struct device *subdrv_dev, int zpos)
229{ 242{
230 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 243 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
244 int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
231 245
232 DRM_DEBUG_KMS("%s\n", __FILE__); 246 DRM_DEBUG_KMS("%s\n", __FILE__);
233 247
248 if (win < 0 || win > MIXER_WIN_NR) {
249 DRM_ERROR("mixer window[%d] is wrong\n", win);
250 return;
251 }
252
234 if (mixer_ops && mixer_ops->win_commit) 253 if (mixer_ops && mixer_ops->win_commit)
235 mixer_ops->win_commit(ctx->mixer_ctx->ctx, zpos); 254 mixer_ops->win_commit(ctx->mixer_ctx->ctx, win);
255
256 ctx->enabled[win] = true;
236} 257}
237 258
238static void drm_mixer_disable(struct device *subdrv_dev, int zpos) 259static void drm_mixer_disable(struct device *subdrv_dev, int zpos)
239{ 260{
240 struct drm_hdmi_context *ctx = to_context(subdrv_dev); 261 struct drm_hdmi_context *ctx = to_context(subdrv_dev);
262 int win = (zpos == DEFAULT_ZPOS) ? MIXER_DEFAULT_WIN : zpos;
241 263
242 DRM_DEBUG_KMS("%s\n", __FILE__); 264 DRM_DEBUG_KMS("%s\n", __FILE__);
243 265
266 if (win < 0 || win > MIXER_WIN_NR) {
267 DRM_ERROR("mixer window[%d] is wrong\n", win);
268 return;
269 }
270
244 if (mixer_ops && mixer_ops->win_disable) 271 if (mixer_ops && mixer_ops->win_disable)
245 mixer_ops->win_disable(ctx->mixer_ctx->ctx, zpos); 272 mixer_ops->win_disable(ctx->mixer_ctx->ctx, win);
273
274 ctx->enabled[win] = false;
246} 275}
247 276
248static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = { 277static struct exynos_drm_overlay_ops drm_hdmi_overlay_ops = {
@@ -335,25 +364,6 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
335 return 0; 364 return 0;
336} 365}
337 366
338static int hdmi_runtime_suspend(struct device *dev)
339{
340 DRM_DEBUG_KMS("%s\n", __FILE__);
341
342 return 0;
343}
344
345static int hdmi_runtime_resume(struct device *dev)
346{
347 DRM_DEBUG_KMS("%s\n", __FILE__);
348
349 return 0;
350}
351
352static const struct dev_pm_ops hdmi_pm_ops = {
353 .runtime_suspend = hdmi_runtime_suspend,
354 .runtime_resume = hdmi_runtime_resume,
355};
356
357static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev) 367static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)
358{ 368{
359 struct drm_hdmi_context *ctx = platform_get_drvdata(pdev); 369 struct drm_hdmi_context *ctx = platform_get_drvdata(pdev);
@@ -372,6 +382,5 @@ struct platform_driver exynos_drm_common_hdmi_driver = {
372 .driver = { 382 .driver = {
373 .name = "exynos-drm-hdmi", 383 .name = "exynos-drm-hdmi",
374 .owner = THIS_MODULE, 384 .owner = THIS_MODULE,
375 .pm = &hdmi_pm_ops,
376 }, 385 },
377}; 386};
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
index f3ae192c8dcf..bd8126996e52 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
@@ -26,6 +26,9 @@
26#ifndef _EXYNOS_DRM_HDMI_H_ 26#ifndef _EXYNOS_DRM_HDMI_H_
27#define _EXYNOS_DRM_HDMI_H_ 27#define _EXYNOS_DRM_HDMI_H_
28 28
29#define MIXER_WIN_NR 3
30#define MIXER_DEFAULT_WIN 0
31
29/* 32/*
30 * exynos hdmi common context structure. 33 * exynos hdmi common context structure.
31 * 34 *
@@ -54,13 +57,14 @@ struct exynos_hdmi_ops {
54 void (*get_max_resol)(void *ctx, unsigned int *width, 57 void (*get_max_resol)(void *ctx, unsigned int *width,
55 unsigned int *height); 58 unsigned int *height);
56 void (*commit)(void *ctx); 59 void (*commit)(void *ctx);
57 void (*disable)(void *ctx); 60 void (*dpms)(void *ctx, int mode);
58}; 61};
59 62
60struct exynos_mixer_ops { 63struct exynos_mixer_ops {
61 /* manager */ 64 /* manager */
62 int (*enable_vblank)(void *ctx, int pipe); 65 int (*enable_vblank)(void *ctx, int pipe);
63 void (*disable_vblank)(void *ctx); 66 void (*disable_vblank)(void *ctx);
67 void (*dpms)(void *ctx, int mode);
64 68
65 /* overlay */ 69 /* overlay */
66 void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay); 70 void (*win_mode_set)(void *ctx, struct exynos_drm_overlay *overlay);
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 5b04af145fa7..9212d7d53f3a 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -57,13 +57,15 @@ struct hdmi_resources {
57struct hdmi_context { 57struct hdmi_context {
58 struct device *dev; 58 struct device *dev;
59 struct drm_device *drm_dev; 59 struct drm_device *drm_dev;
60 bool hpd_handle; 60 bool hpd;
61 bool enabled; 61 bool powered;
62 bool is_v13; 62 bool is_v13;
63 struct mutex hdmi_mutex;
63 64
64 struct resource *regs_res; 65 struct resource *regs_res;
65 void __iomem *regs; 66 void __iomem *regs;
66 unsigned int irq; 67 unsigned int external_irq;
68 unsigned int internal_irq;
67 69
68 struct i2c_client *ddc_port; 70 struct i2c_client *ddc_port;
69 struct i2c_client *hdmiphy_port; 71 struct i2c_client *hdmiphy_port;
@@ -1192,12 +1194,8 @@ static int hdmi_conf_index(struct hdmi_context *hdata,
1192static bool hdmi_is_connected(void *ctx) 1194static bool hdmi_is_connected(void *ctx)
1193{ 1195{
1194 struct hdmi_context *hdata = ctx; 1196 struct hdmi_context *hdata = ctx;
1195 u32 val = hdmi_reg_read(hdata, HDMI_HPD_STATUS);
1196 1197
1197 if (val) 1198 return hdata->hpd;
1198 return true;
1199
1200 return false;
1201} 1199}
1202 1200
1203static int hdmi_get_edid(void *ctx, struct drm_connector *connector, 1201static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
@@ -1287,28 +1285,6 @@ static int hdmi_check_timing(void *ctx, void *timing)
1287 return hdmi_v14_check_timing(check_timing); 1285 return hdmi_v14_check_timing(check_timing);
1288} 1286}
1289 1287
1290static int hdmi_display_power_on(void *ctx, int mode)
1291{
1292 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1293
1294 switch (mode) {
1295 case DRM_MODE_DPMS_ON:
1296 DRM_DEBUG_KMS("hdmi [on]\n");
1297 break;
1298 case DRM_MODE_DPMS_STANDBY:
1299 break;
1300 case DRM_MODE_DPMS_SUSPEND:
1301 break;
1302 case DRM_MODE_DPMS_OFF:
1303 DRM_DEBUG_KMS("hdmi [off]\n");
1304 break;
1305 default:
1306 break;
1307 }
1308
1309 return 0;
1310}
1311
1312static void hdmi_set_acr(u32 freq, u8 *acr) 1288static void hdmi_set_acr(u32 freq, u8 *acr)
1313{ 1289{
1314 u32 n, cts; 1290 u32 n, cts;
@@ -1476,9 +1452,6 @@ static void hdmi_conf_reset(struct hdmi_context *hdata)
1476{ 1452{
1477 u32 reg; 1453 u32 reg;
1478 1454
1479 /* disable hpd handle for drm */
1480 hdata->hpd_handle = false;
1481
1482 if (hdata->is_v13) 1455 if (hdata->is_v13)
1483 reg = HDMI_V13_CORE_RSTOUT; 1456 reg = HDMI_V13_CORE_RSTOUT;
1484 else 1457 else
@@ -1489,16 +1462,10 @@ static void hdmi_conf_reset(struct hdmi_context *hdata)
1489 mdelay(10); 1462 mdelay(10);
1490 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT); 1463 hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
1491 mdelay(10); 1464 mdelay(10);
1492
1493 /* enable hpd handle for drm */
1494 hdata->hpd_handle = true;
1495} 1465}
1496 1466
1497static void hdmi_conf_init(struct hdmi_context *hdata) 1467static void hdmi_conf_init(struct hdmi_context *hdata)
1498{ 1468{
1499 /* disable hpd handle for drm */
1500 hdata->hpd_handle = false;
1501
1502 /* enable HPD interrupts */ 1469 /* enable HPD interrupts */
1503 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL | 1470 hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
1504 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG); 1471 HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
@@ -1533,9 +1500,6 @@ static void hdmi_conf_init(struct hdmi_context *hdata)
1533 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5); 1500 hdmi_reg_writeb(hdata, HDMI_AVI_BYTE(1), 2 << 5);
1534 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5); 1501 hdmi_reg_writemask(hdata, HDMI_CON_1, 2, 3 << 5);
1535 } 1502 }
1536
1537 /* enable hpd handle for drm */
1538 hdata->hpd_handle = true;
1539} 1503}
1540 1504
1541static void hdmi_v13_timing_apply(struct hdmi_context *hdata) 1505static void hdmi_v13_timing_apply(struct hdmi_context *hdata)
@@ -1888,8 +1852,11 @@ static void hdmi_conf_apply(struct hdmi_context *hdata)
1888 hdmiphy_conf_reset(hdata); 1852 hdmiphy_conf_reset(hdata);
1889 hdmiphy_conf_apply(hdata); 1853 hdmiphy_conf_apply(hdata);
1890 1854
1855 mutex_lock(&hdata->hdmi_mutex);
1891 hdmi_conf_reset(hdata); 1856 hdmi_conf_reset(hdata);
1892 hdmi_conf_init(hdata); 1857 hdmi_conf_init(hdata);
1858 mutex_unlock(&hdata->hdmi_mutex);
1859
1893 hdmi_audio_init(hdata); 1860 hdmi_audio_init(hdata);
1894 1861
1895 /* setting core registers */ 1862 /* setting core registers */
@@ -1969,20 +1936,86 @@ static void hdmi_commit(void *ctx)
1969 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 1936 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1970 1937
1971 hdmi_conf_apply(hdata); 1938 hdmi_conf_apply(hdata);
1939}
1940
1941static void hdmi_poweron(struct hdmi_context *hdata)
1942{
1943 struct hdmi_resources *res = &hdata->res;
1944
1945 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1946
1947 mutex_lock(&hdata->hdmi_mutex);
1948 if (hdata->powered) {
1949 mutex_unlock(&hdata->hdmi_mutex);
1950 return;
1951 }
1972 1952
1973 hdata->enabled = true; 1953 hdata->powered = true;
1954
1955 if (hdata->cfg_hpd)
1956 hdata->cfg_hpd(true);
1957 mutex_unlock(&hdata->hdmi_mutex);
1958
1959 pm_runtime_get_sync(hdata->dev);
1960
1961 regulator_bulk_enable(res->regul_count, res->regul_bulk);
1962 clk_enable(res->hdmiphy);
1963 clk_enable(res->hdmi);
1964 clk_enable(res->sclk_hdmi);
1965}
1966
1967static void hdmi_poweroff(struct hdmi_context *hdata)
1968{
1969 struct hdmi_resources *res = &hdata->res;
1970
1971 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1972
1973 mutex_lock(&hdata->hdmi_mutex);
1974 if (!hdata->powered)
1975 goto out;
1976 mutex_unlock(&hdata->hdmi_mutex);
1977
1978 /*
1979 * The TV power domain needs any condition of hdmiphy to turn off and
1980 * its reset state seems to meet the condition.
1981 */
1982 hdmiphy_conf_reset(hdata);
1983
1984 clk_disable(res->sclk_hdmi);
1985 clk_disable(res->hdmi);
1986 clk_disable(res->hdmiphy);
1987 regulator_bulk_disable(res->regul_count, res->regul_bulk);
1988
1989 pm_runtime_put_sync(hdata->dev);
1990
1991 mutex_lock(&hdata->hdmi_mutex);
1992 if (hdata->cfg_hpd)
1993 hdata->cfg_hpd(false);
1994
1995 hdata->powered = false;
1996
1997out:
1998 mutex_unlock(&hdata->hdmi_mutex);
1974} 1999}
1975 2000
1976static void hdmi_disable(void *ctx) 2001static void hdmi_dpms(void *ctx, int mode)
1977{ 2002{
1978 struct hdmi_context *hdata = ctx; 2003 struct hdmi_context *hdata = ctx;
1979 2004
1980 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 2005 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
1981 2006
1982 if (hdata->enabled) { 2007 switch (mode) {
1983 hdmi_audio_control(hdata, false); 2008 case DRM_MODE_DPMS_ON:
1984 hdmiphy_conf_reset(hdata); 2009 hdmi_poweron(hdata);
1985 hdmi_conf_reset(hdata); 2010 break;
2011 case DRM_MODE_DPMS_STANDBY:
2012 case DRM_MODE_DPMS_SUSPEND:
2013 case DRM_MODE_DPMS_OFF:
2014 hdmi_poweroff(hdata);
2015 break;
2016 default:
2017 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
2018 break;
1986 } 2019 }
1987} 2020}
1988 2021
@@ -1991,17 +2024,35 @@ static struct exynos_hdmi_ops hdmi_ops = {
1991 .is_connected = hdmi_is_connected, 2024 .is_connected = hdmi_is_connected,
1992 .get_edid = hdmi_get_edid, 2025 .get_edid = hdmi_get_edid,
1993 .check_timing = hdmi_check_timing, 2026 .check_timing = hdmi_check_timing,
1994 .power_on = hdmi_display_power_on,
1995 2027
1996 /* manager */ 2028 /* manager */
1997 .mode_fixup = hdmi_mode_fixup, 2029 .mode_fixup = hdmi_mode_fixup,
1998 .mode_set = hdmi_mode_set, 2030 .mode_set = hdmi_mode_set,
1999 .get_max_resol = hdmi_get_max_resol, 2031 .get_max_resol = hdmi_get_max_resol,
2000 .commit = hdmi_commit, 2032 .commit = hdmi_commit,
2001 .disable = hdmi_disable, 2033 .dpms = hdmi_dpms,
2002}; 2034};
2003 2035
2004static irqreturn_t hdmi_irq_thread(int irq, void *arg) 2036static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
2037{
2038 struct exynos_drm_hdmi_context *ctx = arg;
2039 struct hdmi_context *hdata = ctx->ctx;
2040
2041 if (!hdata->get_hpd)
2042 goto out;
2043
2044 mutex_lock(&hdata->hdmi_mutex);
2045 hdata->hpd = hdata->get_hpd();
2046 mutex_unlock(&hdata->hdmi_mutex);
2047
2048 if (ctx->drm_dev)
2049 drm_helper_hpd_irq_event(ctx->drm_dev);
2050
2051out:
2052 return IRQ_HANDLED;
2053}
2054
2055static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
2005{ 2056{
2006 struct exynos_drm_hdmi_context *ctx = arg; 2057 struct exynos_drm_hdmi_context *ctx = arg;
2007 struct hdmi_context *hdata = ctx->ctx; 2058 struct hdmi_context *hdata = ctx->ctx;
@@ -2010,19 +2061,28 @@ static irqreturn_t hdmi_irq_thread(int irq, void *arg)
2010 intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG); 2061 intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
2011 /* clearing flags for HPD plug/unplug */ 2062 /* clearing flags for HPD plug/unplug */
2012 if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) { 2063 if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
2013 DRM_DEBUG_KMS("unplugged, handling:%d\n", hdata->hpd_handle); 2064 DRM_DEBUG_KMS("unplugged\n");
2014 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, 2065 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2015 HDMI_INTC_FLAG_HPD_UNPLUG); 2066 HDMI_INTC_FLAG_HPD_UNPLUG);
2016 } 2067 }
2017 if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) { 2068 if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
2018 DRM_DEBUG_KMS("plugged, handling:%d\n", hdata->hpd_handle); 2069 DRM_DEBUG_KMS("plugged\n");
2019 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0, 2070 hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
2020 HDMI_INTC_FLAG_HPD_PLUG); 2071 HDMI_INTC_FLAG_HPD_PLUG);
2021 } 2072 }
2022 2073
2023 if (ctx->drm_dev && hdata->hpd_handle) 2074 mutex_lock(&hdata->hdmi_mutex);
2075 hdata->hpd = hdmi_reg_read(hdata, HDMI_HPD_STATUS);
2076 if (hdata->powered && hdata->hpd) {
2077 mutex_unlock(&hdata->hdmi_mutex);
2078 goto out;
2079 }
2080 mutex_unlock(&hdata->hdmi_mutex);
2081
2082 if (ctx->drm_dev)
2024 drm_helper_hpd_irq_event(ctx->drm_dev); 2083 drm_helper_hpd_irq_event(ctx->drm_dev);
2025 2084
2085out:
2026 return IRQ_HANDLED; 2086 return IRQ_HANDLED;
2027} 2087}
2028 2088
@@ -2116,68 +2176,6 @@ static int hdmi_resources_cleanup(struct hdmi_context *hdata)
2116 return 0; 2176 return 0;
2117} 2177}
2118 2178
2119static void hdmi_resource_poweron(struct hdmi_context *hdata)
2120{
2121 struct hdmi_resources *res = &hdata->res;
2122
2123 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2124
2125 /* turn HDMI power on */
2126 regulator_bulk_enable(res->regul_count, res->regul_bulk);
2127 /* power-on hdmi physical interface */
2128 clk_enable(res->hdmiphy);
2129 /* turn clocks on */
2130 clk_enable(res->hdmi);
2131 clk_enable(res->sclk_hdmi);
2132
2133 hdmiphy_conf_reset(hdata);
2134 hdmi_conf_reset(hdata);
2135 hdmi_conf_init(hdata);
2136 hdmi_audio_init(hdata);
2137}
2138
2139static void hdmi_resource_poweroff(struct hdmi_context *hdata)
2140{
2141 struct hdmi_resources *res = &hdata->res;
2142
2143 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2144
2145 /* turn clocks off */
2146 clk_disable(res->sclk_hdmi);
2147 clk_disable(res->hdmi);
2148 /* power-off hdmiphy */
2149 clk_disable(res->hdmiphy);
2150 /* turn HDMI power off */
2151 regulator_bulk_disable(res->regul_count, res->regul_bulk);
2152}
2153
2154static int hdmi_runtime_suspend(struct device *dev)
2155{
2156 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2157
2158 DRM_DEBUG_KMS("%s\n", __func__);
2159
2160 hdmi_resource_poweroff(ctx->ctx);
2161
2162 return 0;
2163}
2164
2165static int hdmi_runtime_resume(struct device *dev)
2166{
2167 struct exynos_drm_hdmi_context *ctx = get_hdmi_context(dev);
2168
2169 DRM_DEBUG_KMS("%s\n", __func__);
2170
2171 hdmi_resource_poweron(ctx->ctx);
2172
2173 return 0;
2174}
2175
2176static const struct dev_pm_ops hdmi_pm_ops = {
2177 .runtime_suspend = hdmi_runtime_suspend,
2178 .runtime_resume = hdmi_runtime_resume,
2179};
2180
2181static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy; 2179static struct i2c_client *hdmi_ddc, *hdmi_hdmiphy;
2182 2180
2183void hdmi_attach_ddc_client(struct i2c_client *ddc) 2181void hdmi_attach_ddc_client(struct i2c_client *ddc)
@@ -2222,6 +2220,8 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
2222 return -ENOMEM; 2220 return -ENOMEM;
2223 } 2221 }
2224 2222
2223 mutex_init(&hdata->hdmi_mutex);
2224
2225 drm_hdmi_ctx->ctx = (void *)hdata; 2225 drm_hdmi_ctx->ctx = (void *)hdata;
2226 hdata->parent_ctx = (void *)drm_hdmi_ctx; 2226 hdata->parent_ctx = (void *)drm_hdmi_ctx;
2227 2227
@@ -2278,28 +2278,49 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
2278 2278
2279 hdata->hdmiphy_port = hdmi_hdmiphy; 2279 hdata->hdmiphy_port = hdmi_hdmiphy;
2280 2280
2281 hdata->irq = platform_get_irq_byname(pdev, "internal_irq"); 2281 hdata->external_irq = platform_get_irq_byname(pdev, "external_irq");
2282 if (hdata->irq < 0) { 2282 if (hdata->external_irq < 0) {
2283 DRM_ERROR("failed to get platform irq\n"); 2283 DRM_ERROR("failed to get platform irq\n");
2284 ret = hdata->irq; 2284 ret = hdata->external_irq;
2285 goto err_hdmiphy; 2285 goto err_hdmiphy;
2286 } 2286 }
2287 2287
2288 /* register hpd interrupt */ 2288 hdata->internal_irq = platform_get_irq_byname(pdev, "internal_irq");
2289 ret = request_threaded_irq(hdata->irq, NULL, hdmi_irq_thread, 2289 if (hdata->internal_irq < 0) {
2290 IRQF_ONESHOT, "drm_hdmi", drm_hdmi_ctx); 2290 DRM_ERROR("failed to get platform internal irq\n");
2291 ret = hdata->internal_irq;
2292 goto err_hdmiphy;
2293 }
2294
2295 ret = request_threaded_irq(hdata->external_irq, NULL,
2296 hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
2297 IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
2298 "hdmi_external", drm_hdmi_ctx);
2291 if (ret) { 2299 if (ret) {
2292 DRM_ERROR("request interrupt failed.\n"); 2300 DRM_ERROR("failed to register hdmi internal interrupt\n");
2293 goto err_hdmiphy; 2301 goto err_hdmiphy;
2294 } 2302 }
2295 2303
2304 if (hdata->cfg_hpd)
2305 hdata->cfg_hpd(false);
2306
2307 ret = request_threaded_irq(hdata->internal_irq, NULL,
2308 hdmi_internal_irq_thread, IRQF_ONESHOT,
2309 "hdmi_internal", drm_hdmi_ctx);
2310 if (ret) {
2311 DRM_ERROR("failed to register hdmi internal interrupt\n");
2312 goto err_free_irq;
2313 }
2314
2296 /* register specific callbacks to common hdmi. */ 2315 /* register specific callbacks to common hdmi. */
2297 exynos_hdmi_ops_register(&hdmi_ops); 2316 exynos_hdmi_ops_register(&hdmi_ops);
2298 2317
2299 hdmi_resource_poweron(hdata); 2318 pm_runtime_enable(dev);
2300 2319
2301 return 0; 2320 return 0;
2302 2321
2322err_free_irq:
2323 free_irq(hdata->external_irq, drm_hdmi_ctx);
2303err_hdmiphy: 2324err_hdmiphy:
2304 i2c_del_driver(&hdmiphy_driver); 2325 i2c_del_driver(&hdmiphy_driver);
2305err_ddc: 2326err_ddc:
@@ -2319,15 +2340,15 @@ err_data:
2319 2340
2320static int __devexit hdmi_remove(struct platform_device *pdev) 2341static int __devexit hdmi_remove(struct platform_device *pdev)
2321{ 2342{
2343 struct device *dev = &pdev->dev;
2322 struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev); 2344 struct exynos_drm_hdmi_context *ctx = platform_get_drvdata(pdev);
2323 struct hdmi_context *hdata = ctx->ctx; 2345 struct hdmi_context *hdata = ctx->ctx;
2324 2346
2325 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__); 2347 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
2326 2348
2327 hdmi_resource_poweroff(hdata); 2349 pm_runtime_disable(dev);
2328 2350
2329 disable_irq(hdata->irq); 2351 free_irq(hdata->internal_irq, hdata);
2330 free_irq(hdata->irq, hdata);
2331 2352
2332 hdmi_resources_cleanup(hdata); 2353 hdmi_resources_cleanup(hdata);
2333 2354
@@ -2352,6 +2373,5 @@ struct platform_driver hdmi_driver = {
2352 .driver = { 2373 .driver = {
2353 .name = "exynos4-hdmi", 2374 .name = "exynos4-hdmi",
2354 .owner = THIS_MODULE, 2375 .owner = THIS_MODULE,
2355 .pm = &hdmi_pm_ops,
2356 }, 2376 },
2357}; 2377};
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index e15438c01129..a29a9a8b2312 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -37,9 +37,6 @@
37#include "exynos_drm_drv.h" 37#include "exynos_drm_drv.h"
38#include "exynos_drm_hdmi.h" 38#include "exynos_drm_hdmi.h"
39 39
40#define MIXER_WIN_NR 3
41#define MIXER_DEFAULT_WIN 0
42
43#define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev)) 40#define get_mixer_context(dev) platform_get_drvdata(to_platform_device(dev))
44 41
45struct hdmi_win_data { 42struct hdmi_win_data {
@@ -63,7 +60,6 @@ struct hdmi_win_data {
63}; 60};
64 61
65struct mixer_resources { 62struct mixer_resources {
66 struct device *dev;
67 int irq; 63 int irq;
68 void __iomem *mixer_regs; 64 void __iomem *mixer_regs;
69 void __iomem *vp_regs; 65 void __iomem *vp_regs;
@@ -76,10 +72,13 @@ struct mixer_resources {
76}; 72};
77 73
78struct mixer_context { 74struct mixer_context {
79 unsigned int irq; 75 struct device *dev;
80 int pipe; 76 int pipe;
81 bool interlace; 77 bool interlace;
78 bool powered;
79 u32 int_en;
82 80
81 struct mutex mixer_mutex;
83 struct mixer_resources mixer_res; 82 struct mixer_resources mixer_res;
84 struct hdmi_win_data win_data[MIXER_WIN_NR]; 83 struct hdmi_win_data win_data[MIXER_WIN_NR];
85}; 84};
@@ -591,6 +590,116 @@ static void vp_win_reset(struct mixer_context *ctx)
591 WARN(tries == 0, "failed to reset Video Processor\n"); 590 WARN(tries == 0, "failed to reset Video Processor\n");
592} 591}
593 592
593static void mixer_win_reset(struct mixer_context *ctx)
594{
595 struct mixer_resources *res = &ctx->mixer_res;
596 unsigned long flags;
597 u32 val; /* value stored to register */
598
599 spin_lock_irqsave(&res->reg_slock, flags);
600 mixer_vsync_set_update(ctx, false);
601
602 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
603
604 /* set output in RGB888 mode */
605 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
606
607 /* 16 beat burst in DMA */
608 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
609 MXR_STATUS_BURST_MASK);
610
611 /* setting default layer priority: layer1 > layer0 > video
612 * because typical usage scenario would be
613 * layer1 - OSD
614 * layer0 - framebuffer
615 * video - video overlay
616 */
617 val = MXR_LAYER_CFG_GRP1_VAL(3);
618 val |= MXR_LAYER_CFG_GRP0_VAL(2);
619 val |= MXR_LAYER_CFG_VP_VAL(1);
620 mixer_reg_write(res, MXR_LAYER_CFG, val);
621
622 /* setting background color */
623 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
624 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
625 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
626
627 /* setting graphical layers */
628
629 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
630 val |= MXR_GRP_CFG_WIN_BLEND_EN;
631 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
632
633 /* the same configuration for both layers */
634 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
635
636 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
637 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
638 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
639
640 /* configuration of Video Processor Registers */
641 vp_win_reset(ctx);
642 vp_default_filter(res);
643
644 /* disable all layers */
645 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
646 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
647 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
648
649 mixer_vsync_set_update(ctx, true);
650 spin_unlock_irqrestore(&res->reg_slock, flags);
651}
652
653static void mixer_poweron(struct mixer_context *ctx)
654{
655 struct mixer_resources *res = &ctx->mixer_res;
656
657 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
658
659 mutex_lock(&ctx->mixer_mutex);
660 if (ctx->powered) {
661 mutex_unlock(&ctx->mixer_mutex);
662 return;
663 }
664 ctx->powered = true;
665 mutex_unlock(&ctx->mixer_mutex);
666
667 pm_runtime_get_sync(ctx->dev);
668
669 clk_enable(res->mixer);
670 clk_enable(res->vp);
671 clk_enable(res->sclk_mixer);
672
673 mixer_reg_write(res, MXR_INT_EN, ctx->int_en);
674 mixer_win_reset(ctx);
675}
676
677static void mixer_poweroff(struct mixer_context *ctx)
678{
679 struct mixer_resources *res = &ctx->mixer_res;
680
681 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
682
683 mutex_lock(&ctx->mixer_mutex);
684 if (!ctx->powered)
685 goto out;
686 mutex_unlock(&ctx->mixer_mutex);
687
688 ctx->int_en = mixer_reg_read(res, MXR_INT_EN);
689
690 clk_disable(res->mixer);
691 clk_disable(res->vp);
692 clk_disable(res->sclk_mixer);
693
694 pm_runtime_put_sync(ctx->dev);
695
696 mutex_lock(&ctx->mixer_mutex);
697 ctx->powered = false;
698
699out:
700 mutex_unlock(&ctx->mixer_mutex);
701}
702
594static int mixer_enable_vblank(void *ctx, int pipe) 703static int mixer_enable_vblank(void *ctx, int pipe)
595{ 704{
596 struct mixer_context *mixer_ctx = ctx; 705 struct mixer_context *mixer_ctx = ctx;
@@ -618,6 +727,27 @@ static void mixer_disable_vblank(void *ctx)
618 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC); 727 mixer_reg_writemask(res, MXR_INT_EN, 0, MXR_INT_EN_VSYNC);
619} 728}
620 729
730static void mixer_dpms(void *ctx, int mode)
731{
732 struct mixer_context *mixer_ctx = ctx;
733
734 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
735
736 switch (mode) {
737 case DRM_MODE_DPMS_ON:
738 mixer_poweron(mixer_ctx);
739 break;
740 case DRM_MODE_DPMS_STANDBY:
741 case DRM_MODE_DPMS_SUSPEND:
742 case DRM_MODE_DPMS_OFF:
743 mixer_poweroff(mixer_ctx);
744 break;
745 default:
746 DRM_DEBUG_KMS("unknown dpms mode: %d\n", mode);
747 break;
748 }
749}
750
621static void mixer_win_mode_set(void *ctx, 751static void mixer_win_mode_set(void *ctx,
622 struct exynos_drm_overlay *overlay) 752 struct exynos_drm_overlay *overlay)
623{ 753{
@@ -643,7 +773,7 @@ static void mixer_win_mode_set(void *ctx,
643 win = MIXER_DEFAULT_WIN; 773 win = MIXER_DEFAULT_WIN;
644 774
645 if (win < 0 || win > MIXER_WIN_NR) { 775 if (win < 0 || win > MIXER_WIN_NR) {
646 DRM_ERROR("overlay plane[%d] is wrong\n", win); 776 DRM_ERROR("mixer window[%d] is wrong\n", win);
647 return; 777 return;
648 } 778 }
649 779
@@ -672,44 +802,26 @@ static void mixer_win_mode_set(void *ctx,
672 win_data->scan_flags = overlay->scan_flag; 802 win_data->scan_flags = overlay->scan_flag;
673} 803}
674 804
675static void mixer_win_commit(void *ctx, int zpos) 805static void mixer_win_commit(void *ctx, int win)
676{ 806{
677 struct mixer_context *mixer_ctx = ctx; 807 struct mixer_context *mixer_ctx = ctx;
678 int win = zpos;
679 808
680 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); 809 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
681 810
682 if (win == DEFAULT_ZPOS)
683 win = MIXER_DEFAULT_WIN;
684
685 if (win < 0 || win > MIXER_WIN_NR) {
686 DRM_ERROR("overlay plane[%d] is wrong\n", win);
687 return;
688 }
689
690 if (win > 1) 811 if (win > 1)
691 vp_video_buffer(mixer_ctx, win); 812 vp_video_buffer(mixer_ctx, win);
692 else 813 else
693 mixer_graph_buffer(mixer_ctx, win); 814 mixer_graph_buffer(mixer_ctx, win);
694} 815}
695 816
696static void mixer_win_disable(void *ctx, int zpos) 817static void mixer_win_disable(void *ctx, int win)
697{ 818{
698 struct mixer_context *mixer_ctx = ctx; 819 struct mixer_context *mixer_ctx = ctx;
699 struct mixer_resources *res = &mixer_ctx->mixer_res; 820 struct mixer_resources *res = &mixer_ctx->mixer_res;
700 unsigned long flags; 821 unsigned long flags;
701 int win = zpos;
702 822
703 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win); 823 DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
704 824
705 if (win == DEFAULT_ZPOS)
706 win = MIXER_DEFAULT_WIN;
707
708 if (win < 0 || win > MIXER_WIN_NR) {
709 DRM_ERROR("overlay plane[%d] is wrong\n", win);
710 return;
711 }
712
713 spin_lock_irqsave(&res->reg_slock, flags); 825 spin_lock_irqsave(&res->reg_slock, flags);
714 mixer_vsync_set_update(mixer_ctx, false); 826 mixer_vsync_set_update(mixer_ctx, false);
715 827
@@ -723,6 +835,7 @@ static struct exynos_mixer_ops mixer_ops = {
723 /* manager */ 835 /* manager */
724 .enable_vblank = mixer_enable_vblank, 836 .enable_vblank = mixer_enable_vblank,
725 .disable_vblank = mixer_disable_vblank, 837 .disable_vblank = mixer_disable_vblank,
838 .dpms = mixer_dpms,
726 839
727 /* overlay */ 840 /* overlay */
728 .win_mode_set = mixer_win_mode_set, 841 .win_mode_set = mixer_win_mode_set,
@@ -811,117 +924,6 @@ out:
811 return IRQ_HANDLED; 924 return IRQ_HANDLED;
812} 925}
813 926
814static void mixer_win_reset(struct mixer_context *ctx)
815{
816 struct mixer_resources *res = &ctx->mixer_res;
817 unsigned long flags;
818 u32 val; /* value stored to register */
819
820 spin_lock_irqsave(&res->reg_slock, flags);
821 mixer_vsync_set_update(ctx, false);
822
823 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_DST_HDMI, MXR_CFG_DST_MASK);
824
825 /* set output in RGB888 mode */
826 mixer_reg_writemask(res, MXR_CFG, MXR_CFG_OUT_RGB888, MXR_CFG_OUT_MASK);
827
828 /* 16 beat burst in DMA */
829 mixer_reg_writemask(res, MXR_STATUS, MXR_STATUS_16_BURST,
830 MXR_STATUS_BURST_MASK);
831
832 /* setting default layer priority: layer1 > layer0 > video
833 * because typical usage scenario would be
834 * layer1 - OSD
835 * layer0 - framebuffer
836 * video - video overlay
837 */
838 val = MXR_LAYER_CFG_GRP1_VAL(3);
839 val |= MXR_LAYER_CFG_GRP0_VAL(2);
840 val |= MXR_LAYER_CFG_VP_VAL(1);
841 mixer_reg_write(res, MXR_LAYER_CFG, val);
842
843 /* setting background color */
844 mixer_reg_write(res, MXR_BG_COLOR0, 0x008080);
845 mixer_reg_write(res, MXR_BG_COLOR1, 0x008080);
846 mixer_reg_write(res, MXR_BG_COLOR2, 0x008080);
847
848 /* setting graphical layers */
849
850 val = MXR_GRP_CFG_COLOR_KEY_DISABLE; /* no blank key */
851 val |= MXR_GRP_CFG_WIN_BLEND_EN;
852 val |= MXR_GRP_CFG_ALPHA_VAL(0xff); /* non-transparent alpha */
853
854 /* the same configuration for both layers */
855 mixer_reg_write(res, MXR_GRAPHIC_CFG(0), val);
856
857 val |= MXR_GRP_CFG_BLEND_PRE_MUL;
858 val |= MXR_GRP_CFG_PIXEL_BLEND_EN;
859 mixer_reg_write(res, MXR_GRAPHIC_CFG(1), val);
860
861 /* configuration of Video Processor Registers */
862 vp_win_reset(ctx);
863 vp_default_filter(res);
864
865 /* disable all layers */
866 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP0_ENABLE);
867 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_GRP1_ENABLE);
868 mixer_reg_writemask(res, MXR_CFG, 0, MXR_CFG_VP_ENABLE);
869
870 mixer_vsync_set_update(ctx, true);
871 spin_unlock_irqrestore(&res->reg_slock, flags);
872}
873
874static void mixer_resource_poweron(struct mixer_context *ctx)
875{
876 struct mixer_resources *res = &ctx->mixer_res;
877
878 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
879
880 clk_enable(res->mixer);
881 clk_enable(res->vp);
882 clk_enable(res->sclk_mixer);
883
884 mixer_win_reset(ctx);
885}
886
887static void mixer_resource_poweroff(struct mixer_context *ctx)
888{
889 struct mixer_resources *res = &ctx->mixer_res;
890
891 DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
892
893 clk_disable(res->mixer);
894 clk_disable(res->vp);
895 clk_disable(res->sclk_mixer);
896}
897
898static int mixer_runtime_resume(struct device *dev)
899{
900 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
901
902 DRM_DEBUG_KMS("resume - start\n");
903
904 mixer_resource_poweron(ctx->ctx);
905
906 return 0;
907}
908
909static int mixer_runtime_suspend(struct device *dev)
910{
911 struct exynos_drm_hdmi_context *ctx = get_mixer_context(dev);
912
913 DRM_DEBUG_KMS("suspend - start\n");
914
915 mixer_resource_poweroff(ctx->ctx);
916
917 return 0;
918}
919
920static const struct dev_pm_ops mixer_pm_ops = {
921 .runtime_suspend = mixer_runtime_suspend,
922 .runtime_resume = mixer_runtime_resume,
923};
924
925static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx, 927static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
926 struct platform_device *pdev) 928 struct platform_device *pdev)
927{ 929{
@@ -931,7 +933,6 @@ static int __devinit mixer_resources_init(struct exynos_drm_hdmi_context *ctx,
931 struct resource *res; 933 struct resource *res;
932 int ret; 934 int ret;
933 935
934 mixer_res->dev = dev;
935 spin_lock_init(&mixer_res->reg_slock); 936 spin_lock_init(&mixer_res->reg_slock);
936 937
937 mixer_res->mixer = clk_get(dev, "mixer"); 938 mixer_res->mixer = clk_get(dev, "mixer");
@@ -1027,7 +1028,6 @@ fail:
1027 clk_put(mixer_res->vp); 1028 clk_put(mixer_res->vp);
1028 if (!IS_ERR_OR_NULL(mixer_res->mixer)) 1029 if (!IS_ERR_OR_NULL(mixer_res->mixer))
1029 clk_put(mixer_res->mixer); 1030 clk_put(mixer_res->mixer);
1030 mixer_res->dev = NULL;
1031 return ret; 1031 return ret;
1032} 1032}
1033 1033
@@ -1035,7 +1035,6 @@ static void mixer_resources_cleanup(struct mixer_context *ctx)
1035{ 1035{
1036 struct mixer_resources *res = &ctx->mixer_res; 1036 struct mixer_resources *res = &ctx->mixer_res;
1037 1037
1038 disable_irq(res->irq);
1039 free_irq(res->irq, ctx); 1038 free_irq(res->irq, ctx);
1040 1039
1041 iounmap(res->vp_regs); 1040 iounmap(res->vp_regs);
@@ -1064,6 +1063,9 @@ static int __devinit mixer_probe(struct platform_device *pdev)
1064 return -ENOMEM; 1063 return -ENOMEM;
1065 } 1064 }
1066 1065
1066 mutex_init(&ctx->mixer_mutex);
1067
1068 ctx->dev = &pdev->dev;
1067 drm_hdmi_ctx->ctx = (void *)ctx; 1069 drm_hdmi_ctx->ctx = (void *)ctx;
1068 1070
1069 platform_set_drvdata(pdev, drm_hdmi_ctx); 1071 platform_set_drvdata(pdev, drm_hdmi_ctx);
@@ -1076,7 +1078,7 @@ static int __devinit mixer_probe(struct platform_device *pdev)
1076 /* register specific callback point to common hdmi. */ 1078 /* register specific callback point to common hdmi. */
1077 exynos_mixer_ops_register(&mixer_ops); 1079 exynos_mixer_ops_register(&mixer_ops);
1078 1080
1079 mixer_resource_poweron(ctx); 1081 pm_runtime_enable(dev);
1080 1082
1081 return 0; 1083 return 0;
1082 1084
@@ -1095,7 +1097,8 @@ static int mixer_remove(struct platform_device *pdev)
1095 1097
1096 dev_info(dev, "remove successful\n"); 1098 dev_info(dev, "remove successful\n");
1097 1099
1098 mixer_resource_poweroff(ctx); 1100 pm_runtime_disable(&pdev->dev);
1101
1099 mixer_resources_cleanup(ctx); 1102 mixer_resources_cleanup(ctx);
1100 1103
1101 return 0; 1104 return 0;
@@ -1105,7 +1108,6 @@ struct platform_driver mixer_driver = {
1105 .driver = { 1108 .driver = {
1106 .name = "s5p-mixer", 1109 .name = "s5p-mixer",
1107 .owner = THIS_MODULE, 1110 .owner = THIS_MODULE,
1108 .pm = &mixer_pm_ops,
1109 }, 1111 },
1110 .probe = mixer_probe, 1112 .probe = mixer_probe,
1111 .remove = __devexit_p(mixer_remove), 1113 .remove = __devexit_p(mixer_remove),