aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2014-08-04 01:07:21 -0400
committerDave Airlie <airlied@redhat.com>2014-08-04 01:07:21 -0400
commit1fae6dfeb63cddea9b9cd19f236c40f73c72f61d (patch)
treecfbd52dcaa4d239c24ebdc7ca4ee14ae464da2a3
parent08d645c181e9b9482c249e82a061c279a986db15 (diff)
parentef7ce055a9e00f6376416466b996515a27b7cb31 (diff)
Merge branch 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos into drm-next
This pull request includes i80 interface support, module auto-loading ipp consolidation, and trivail fixups and cleanups. Summary: - Add i80 interface support. For this, we added some features to Exynos drm framework, which don't affect any other SoC and common framework because they are specific to Exynos drm. - Add module auto-loading support. For this, sub drivers of Exynos drm exports their of match tables to userspace. This allows modules to be loaded automatically based on devicetree information - Consolidate ipp driver. This patch just just includes cleanups and a littl bit refactoring codes. If there is any problem, please kindly let me know. * 'exynos-drm-next' of git://git.kernel.org/pub/scm/linux/kernel/git/daeinki/drm-exynos: (38 commits) drm/exynos: g2d: let exynos_g2d_get_ver_ioctl fail drm/exynos: g2d: make ioctls more robust drm/exynos: hdmi: add null check for hdmiphy_port drm/exynos: control blending of mixer graphic layer 0 drm/exynos: Add MODULE_DEVICE_TABLE entries for various components Subject: Revert "drm/exynos: remove MODULE_DEVICE_TABLE definitions" Subject: Revert "drm/exynos: fix module build error" drm/exynos/ipp: simplify ipp_find_driver drm/exynos/ipp: simplify ipp_create_id drm/exynos/ipp: remove redundant messages drm/exynos/ipp: simplify ipp_find_obj drm/exynos/ipp: remove useless registration checks drm/exynos/ipp: simplify memory check function drm/exynos/ipp: remove incorrect checks of list_first_entry result drm/exynos/ipp: remove temporary variable drm/exynos/ipp: correct address type drm/exynos/ipp: remove struct exynos_drm_ipp_private drm/exynos/ipp: remove unused field from exynos_drm_ipp_private drm/exynos/ipp: remove type casting drm/exynos: g2d: add exynos4212 as a compatible device. ...
-rw-r--r--Documentation/devicetree/bindings/video/exynos_dsim.txt4
-rw-r--r--Documentation/devicetree/bindings/video/exynos_mixer.txt5
-rw-r--r--Documentation/devicetree/bindings/video/samsung-fimd.txt28
-rw-r--r--arch/arm/boot/dts/exynos4.dtsi1
-rw-r--r--arch/arm/boot/dts/exynos5.dtsi1
-rw-r--r--arch/arm/boot/dts/exynos5420.dtsi20
-rw-r--r--drivers/gpu/drm/exynos/Kconfig1
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp_core.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.c15
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_crtc.h7
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.h10
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c270
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c277
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c29
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c3
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.c259
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_ipp.h4
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.c1
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c36
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c57
-rw-r--r--include/video/samsung_fimd.h3
23 files changed, 739 insertions, 300 deletions
diff --git a/Documentation/devicetree/bindings/video/exynos_dsim.txt b/Documentation/devicetree/bindings/video/exynos_dsim.txt
index 33b5730d07ba..31036c667d54 100644
--- a/Documentation/devicetree/bindings/video/exynos_dsim.txt
+++ b/Documentation/devicetree/bindings/video/exynos_dsim.txt
@@ -1,7 +1,9 @@
1Exynos MIPI DSI Master 1Exynos MIPI DSI Master
2 2
3Required properties: 3Required properties:
4 - compatible: "samsung,exynos4210-mipi-dsi" 4 - compatible: value should be one of the following
5 "samsung,exynos4210-mipi-dsi" /* for Exynos4 SoCs */
6 "samsung,exynos5410-mipi-dsi" /* for Exynos5410/5420/5440 SoCs */
5 - reg: physical base address and length of the registers set for the device 7 - reg: physical base address and length of the registers set for the device
6 - interrupts: should contain DSI interrupt 8 - interrupts: should contain DSI interrupt
7 - clocks: list of clock specifiers, must contain an entry for each required 9 - clocks: list of clock specifiers, must contain an entry for each required
diff --git a/Documentation/devicetree/bindings/video/exynos_mixer.txt b/Documentation/devicetree/bindings/video/exynos_mixer.txt
index 7bfde9c9d658..08b394b1edbf 100644
--- a/Documentation/devicetree/bindings/video/exynos_mixer.txt
+++ b/Documentation/devicetree/bindings/video/exynos_mixer.txt
@@ -4,8 +4,9 @@ Required properties:
4- compatible: value should be one of the following: 4- compatible: value should be one of the following:
5 1) "samsung,exynos5-mixer" <DEPRECATED> 5 1) "samsung,exynos5-mixer" <DEPRECATED>
6 2) "samsung,exynos4210-mixer" 6 2) "samsung,exynos4210-mixer"
7 3) "samsung,exynos5250-mixer" 7 3) "samsung,exynos4212-mixer"
8 4) "samsung,exynos5420-mixer" 8 4) "samsung,exynos5250-mixer"
9 5) "samsung,exynos5420-mixer"
9 10
10- reg: physical base address of the mixer and length of memory mapped 11- reg: physical base address of the mixer and length of memory mapped
11 region. 12 region.
diff --git a/Documentation/devicetree/bindings/video/samsung-fimd.txt b/Documentation/devicetree/bindings/video/samsung-fimd.txt
index 2dad41b689af..8428fcff8037 100644
--- a/Documentation/devicetree/bindings/video/samsung-fimd.txt
+++ b/Documentation/devicetree/bindings/video/samsung-fimd.txt
@@ -44,6 +44,34 @@ Optional Properties:
44- display-timings: timing settings for FIMD, as described in document [1]. 44- display-timings: timing settings for FIMD, as described in document [1].
45 Can be used in case timings cannot be provided otherwise 45 Can be used in case timings cannot be provided otherwise
46 or to override timings provided by the panel. 46 or to override timings provided by the panel.
47- samsung,sysreg: handle to syscon used to control the system registers
48- i80-if-timings: timing configuration for lcd i80 interface support.
49 - cs-setup: clock cycles for the active period of address signal is enabled
50 until chip select is enabled.
51 If not specified, the default value(0) will be used.
52 - wr-setup: clock cycles for the active period of CS signal is enabled until
53 write signal is enabled.
54 If not specified, the default value(0) will be used.
55 - wr-active: clock cycles for the active period of CS is enabled.
56 If not specified, the default value(1) will be used.
57 - wr-hold: clock cycles for the active period of CS is disabled until write
58 signal is disabled.
59 If not specified, the default value(0) will be used.
60
61 The parameters are defined as:
62
63 VCLK(internal) __|??????|_____|??????|_____|??????|_____|??????|_____|??
64 : : : : :
65 Address Output --:<XXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XXXXXXXXXXXX:XX
66 | cs-setup+1 | : : :
67 |<---------->| : : :
68 Chip Select ???????????????|____________:____________:____________|??
69 | wr-setup+1 | | wr-hold+1 |
70 |<---------->| |<---------->|
71 Write Enable ????????????????????????????|____________|???????????????
72 | wr-active+1|
73 |<---------->|
74 Video Data ----------------------------<XXXXXXXXXXXXXXXXXXXXXXXXX>--
47 75
48The device node can contain 'port' child nodes according to the bindings defined 76The device node can contain 'port' child nodes according to the bindings defined
49in [2]. The following are properties specific to those nodes: 77in [2]. The following are properties specific to those nodes:
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index fbaf426d2daa..379388121268 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -608,6 +608,7 @@
608 clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>; 608 clocks = <&clock CLK_SCLK_FIMD0>, <&clock CLK_FIMD0>;
609 clock-names = "sclk_fimd", "fimd"; 609 clock-names = "sclk_fimd", "fimd";
610 samsung,power-domain = <&pd_lcd0>; 610 samsung,power-domain = <&pd_lcd0>;
611 samsung,sysreg = <&sys_reg>;
611 status = "disabled"; 612 status = "disabled";
612 }; 613 };
613}; 614};
diff --git a/arch/arm/boot/dts/exynos5.dtsi b/arch/arm/boot/dts/exynos5.dtsi
index 79d0608d6dcc..fdead12952a1 100644
--- a/arch/arm/boot/dts/exynos5.dtsi
+++ b/arch/arm/boot/dts/exynos5.dtsi
@@ -87,6 +87,7 @@
87 reg = <0x14400000 0x40000>; 87 reg = <0x14400000 0x40000>;
88 interrupt-names = "fifo", "vsync", "lcd_sys"; 88 interrupt-names = "fifo", "vsync", "lcd_sys";
89 interrupts = <18 4>, <18 5>, <18 6>; 89 interrupts = <18 4>, <18 5>, <18 6>;
90 samsung,sysreg = <&sysreg_system_controller>;
90 status = "disabled"; 91 status = "disabled";
91 }; 92 };
92 93
diff --git a/arch/arm/boot/dts/exynos5420.dtsi b/arch/arm/boot/dts/exynos5420.dtsi
index e38532271ef9..3a7862bc5f3e 100644
--- a/arch/arm/boot/dts/exynos5420.dtsi
+++ b/arch/arm/boot/dts/exynos5420.dtsi
@@ -517,6 +517,26 @@
517 phy-names = "dp"; 517 phy-names = "dp";
518 }; 518 };
519 519
520 mipi_phy: video-phy@10040714 {
521 compatible = "samsung,s5pv210-mipi-video-phy";
522 reg = <0x10040714 12>;
523 #phy-cells = <1>;
524 };
525
526 dsi@14500000 {
527 compatible = "samsung,exynos5410-mipi-dsi";
528 reg = <0x14500000 0x10000>;
529 interrupts = <0 82 0>;
530 samsung,power-domain = <&disp_pd>;
531 phys = <&mipi_phy 1>;
532 phy-names = "dsim";
533 clocks = <&clock CLK_DSIM1>, <&clock CLK_SCLK_MIPI1>;
534 clock-names = "bus_clk", "pll_clk";
535 #address-cells = <1>;
536 #size-cells = <0>;
537 status = "disabled";
538 };
539
520 fimd: fimd@14400000 { 540 fimd: fimd@14400000 {
521 samsung,power-domain = <&disp_pd>; 541 samsung,power-domain = <&disp_pd>;
522 clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>; 542 clocks = <&clock CLK_SCLK_FIMD1>, <&clock CLK_FIMD1>;
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 178d2a9672a8..9ba1aaeb8070 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -28,6 +28,7 @@ config DRM_EXYNOS_FIMD
28 bool "Exynos DRM FIMD" 28 bool "Exynos DRM FIMD"
29 depends on DRM_EXYNOS && !FB_S3C 29 depends on DRM_EXYNOS && !FB_S3C
30 select FB_MODE_HELPERS 30 select FB_MODE_HELPERS
31 select MFD_SYSCON
31 help 32 help
32 Choose this option if you want to use Exynos FIMD for DRM. 33 Choose this option if you want to use Exynos FIMD for DRM.
33 34
diff --git a/drivers/gpu/drm/exynos/exynos_dp_core.c b/drivers/gpu/drm/exynos/exynos_dp_core.c
index 86dc69d9eabb..31c3de98b885 100644
--- a/drivers/gpu/drm/exynos/exynos_dp_core.c
+++ b/drivers/gpu/drm/exynos/exynos_dp_core.c
@@ -1376,6 +1376,7 @@ static const struct of_device_id exynos_dp_match[] = {
1376 { .compatible = "samsung,exynos5-dp" }, 1376 { .compatible = "samsung,exynos5-dp" },
1377 {}, 1377 {},
1378}; 1378};
1379MODULE_DEVICE_TABLE(of, exynos_dp_match);
1379 1380
1380struct platform_driver dp_driver = { 1381struct platform_driver dp_driver = {
1381 .probe = exynos_dp_probe, 1382 .probe = exynos_dp_probe,
@@ -1390,4 +1391,4 @@ struct platform_driver dp_driver = {
1390 1391
1391MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>"); 1392MODULE_AUTHOR("Jingoo Han <jg1.han@samsung.com>");
1392MODULE_DESCRIPTION("Samsung SoC DP Driver"); 1393MODULE_DESCRIPTION("Samsung SoC DP Driver");
1393MODULE_LICENSE("GPL"); 1394MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.c b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
index 95c9435d0266..b68e58f78cd1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.c
@@ -69,8 +69,10 @@ static void exynos_drm_crtc_dpms(struct drm_crtc *crtc, int mode)
69 69
70 if (mode > DRM_MODE_DPMS_ON) { 70 if (mode > DRM_MODE_DPMS_ON) {
71 /* wait for the completion of page flip. */ 71 /* wait for the completion of page flip. */
72 wait_event(exynos_crtc->pending_flip_queue, 72 if (!wait_event_timeout(exynos_crtc->pending_flip_queue,
73 atomic_read(&exynos_crtc->pending_flip) == 0); 73 !atomic_read(&exynos_crtc->pending_flip),
74 HZ/20))
75 atomic_set(&exynos_crtc->pending_flip, 0);
74 drm_vblank_off(crtc->dev, exynos_crtc->pipe); 76 drm_vblank_off(crtc->dev, exynos_crtc->pipe);
75 } 77 }
76 78
@@ -259,6 +261,7 @@ static int exynos_drm_crtc_page_flip(struct drm_crtc *crtc,
259 spin_lock_irq(&dev->event_lock); 261 spin_lock_irq(&dev->event_lock);
260 drm_vblank_put(dev, exynos_crtc->pipe); 262 drm_vblank_put(dev, exynos_crtc->pipe);
261 list_del(&event->base.link); 263 list_del(&event->base.link);
264 atomic_set(&exynos_crtc->pending_flip, 0);
262 spin_unlock_irq(&dev->event_lock); 265 spin_unlock_irq(&dev->event_lock);
263 266
264 goto out; 267 goto out;
@@ -508,3 +511,11 @@ int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
508 511
509 return -EPERM; 512 return -EPERM;
510} 513}
514
515void exynos_drm_crtc_te_handler(struct drm_crtc *crtc)
516{
517 struct exynos_drm_manager *manager = to_exynos_crtc(crtc)->manager;
518
519 if (manager->ops->te_handler)
520 manager->ops->te_handler(manager);
521}
diff --git a/drivers/gpu/drm/exynos/exynos_drm_crtc.h b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
index 9f74b10a8a01..690dcddab725 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_crtc.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_crtc.h
@@ -36,4 +36,11 @@ void exynos_drm_crtc_plane_disable(struct drm_crtc *crtc, int zpos);
36int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev, 36int exynos_drm_crtc_get_pipe_from_type(struct drm_device *drm_dev,
37 unsigned int out_type); 37 unsigned int out_type);
38 38
39/*
40 * This function calls the crtc device(manager)'s te_handler() callback
41 * to trigger to transfer video image at the tearing effect synchronization
42 * signal.
43 */
44void exynos_drm_crtc_te_handler(struct drm_crtc *crtc);
45
39#endif 46#endif
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index d82e3cb8a70d..0d74e9b99c4e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -358,7 +358,7 @@ static int exynos_drm_sys_suspend(struct device *dev)
358 struct drm_device *drm_dev = dev_get_drvdata(dev); 358 struct drm_device *drm_dev = dev_get_drvdata(dev);
359 pm_message_t message; 359 pm_message_t message;
360 360
361 if (pm_runtime_suspended(dev)) 361 if (pm_runtime_suspended(dev) || !drm_dev)
362 return 0; 362 return 0;
363 363
364 message.event = PM_EVENT_SUSPEND; 364 message.event = PM_EVENT_SUSPEND;
@@ -369,7 +369,7 @@ static int exynos_drm_sys_resume(struct device *dev)
369{ 369{
370 struct drm_device *drm_dev = dev_get_drvdata(dev); 370 struct drm_device *drm_dev = dev_get_drvdata(dev);
371 371
372 if (pm_runtime_suspended(dev)) 372 if (pm_runtime_suspended(dev) || !drm_dev)
373 return 0; 373 return 0;
374 374
375 return exynos_drm_resume(drm_dev); 375 return exynos_drm_resume(drm_dev);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index 02f3b3dcb9f8..69a6fa397d75 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -186,6 +186,8 @@ struct exynos_drm_display {
186 * @win_commit: apply hardware specific overlay data to registers. 186 * @win_commit: apply hardware specific overlay data to registers.
187 * @win_enable: enable hardware specific overlay. 187 * @win_enable: enable hardware specific overlay.
188 * @win_disable: disable hardware specific overlay. 188 * @win_disable: disable hardware specific overlay.
189 * @te_handler: trigger to transfer video image at the tearing effect
190 * synchronization signal if there is a page flip request.
189 */ 191 */
190struct exynos_drm_manager; 192struct exynos_drm_manager;
191struct exynos_drm_manager_ops { 193struct exynos_drm_manager_ops {
@@ -204,6 +206,7 @@ struct exynos_drm_manager_ops {
204 void (*win_commit)(struct exynos_drm_manager *mgr, int zpos); 206 void (*win_commit)(struct exynos_drm_manager *mgr, int zpos);
205 void (*win_enable)(struct exynos_drm_manager *mgr, int zpos); 207 void (*win_enable)(struct exynos_drm_manager *mgr, int zpos);
206 void (*win_disable)(struct exynos_drm_manager *mgr, int zpos); 208 void (*win_disable)(struct exynos_drm_manager *mgr, int zpos);
209 void (*te_handler)(struct exynos_drm_manager *mgr);
207}; 210};
208 211
209/* 212/*
@@ -234,14 +237,9 @@ struct exynos_drm_g2d_private {
234 struct list_head userptr_list; 237 struct list_head userptr_list;
235}; 238};
236 239
237struct exynos_drm_ipp_private {
238 struct device *dev;
239 struct list_head event_list;
240};
241
242struct drm_exynos_file_private { 240struct drm_exynos_file_private {
243 struct exynos_drm_g2d_private *g2d_priv; 241 struct exynos_drm_g2d_private *g2d_priv;
244 struct exynos_drm_ipp_private *ipp_priv; 242 struct device *ipp_dev;
245 struct file *anon_filp; 243 struct file *anon_filp;
246}; 244};
247 245
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index 2df3592166de..86aebd83a71b 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -16,7 +16,10 @@
16#include <drm/drm_panel.h> 16#include <drm/drm_panel.h>
17 17
18#include <linux/clk.h> 18#include <linux/clk.h>
19#include <linux/gpio/consumer.h>
19#include <linux/irq.h> 20#include <linux/irq.h>
21#include <linux/of_device.h>
22#include <linux/of_gpio.h>
20#include <linux/phy/phy.h> 23#include <linux/phy/phy.h>
21#include <linux/regulator/consumer.h> 24#include <linux/regulator/consumer.h>
22#include <linux/component.h> 25#include <linux/component.h>
@@ -24,6 +27,7 @@
24#include <video/mipi_display.h> 27#include <video/mipi_display.h>
25#include <video/videomode.h> 28#include <video/videomode.h>
26 29
30#include "exynos_drm_crtc.h"
27#include "exynos_drm_drv.h" 31#include "exynos_drm_drv.h"
28 32
29/* returns true iff both arguments logically differs */ 33/* returns true iff both arguments logically differs */
@@ -54,9 +58,12 @@
54 58
55/* FIFO memory AC characteristic register */ 59/* FIFO memory AC characteristic register */
56#define DSIM_PLLCTRL_REG 0x4c /* PLL control register */ 60#define DSIM_PLLCTRL_REG 0x4c /* PLL control register */
57#define DSIM_PLLTMR_REG 0x50 /* PLL timer register */
58#define DSIM_PHYACCHR_REG 0x54 /* D-PHY AC characteristic register */ 61#define DSIM_PHYACCHR_REG 0x54 /* D-PHY AC characteristic register */
59#define DSIM_PHYACCHR1_REG 0x58 /* D-PHY AC characteristic register1 */ 62#define DSIM_PHYACCHR1_REG 0x58 /* D-PHY AC characteristic register1 */
63#define DSIM_PHYCTRL_REG 0x5c
64#define DSIM_PHYTIMING_REG 0x64
65#define DSIM_PHYTIMING1_REG 0x68
66#define DSIM_PHYTIMING2_REG 0x6c
60 67
61/* DSIM_STATUS */ 68/* DSIM_STATUS */
62#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0) 69#define DSIM_STOP_STATE_DAT(x) (((x) & 0xf) << 0)
@@ -200,6 +207,24 @@
200#define DSIM_PLL_M(x) ((x) << 4) 207#define DSIM_PLL_M(x) ((x) << 4)
201#define DSIM_PLL_S(x) ((x) << 1) 208#define DSIM_PLL_S(x) ((x) << 1)
202 209
210/* DSIM_PHYCTRL */
211#define DSIM_PHYCTRL_ULPS_EXIT(x) (((x) & 0x1ff) << 0)
212
213/* DSIM_PHYTIMING */
214#define DSIM_PHYTIMING_LPX(x) ((x) << 8)
215#define DSIM_PHYTIMING_HS_EXIT(x) ((x) << 0)
216
217/* DSIM_PHYTIMING1 */
218#define DSIM_PHYTIMING1_CLK_PREPARE(x) ((x) << 24)
219#define DSIM_PHYTIMING1_CLK_ZERO(x) ((x) << 16)
220#define DSIM_PHYTIMING1_CLK_POST(x) ((x) << 8)
221#define DSIM_PHYTIMING1_CLK_TRAIL(x) ((x) << 0)
222
223/* DSIM_PHYTIMING2 */
224#define DSIM_PHYTIMING2_HS_PREPARE(x) ((x) << 16)
225#define DSIM_PHYTIMING2_HS_ZERO(x) ((x) << 8)
226#define DSIM_PHYTIMING2_HS_TRAIL(x) ((x) << 0)
227
203#define DSI_MAX_BUS_WIDTH 4 228#define DSI_MAX_BUS_WIDTH 4
204#define DSI_NUM_VIRTUAL_CHANNELS 4 229#define DSI_NUM_VIRTUAL_CHANNELS 4
205#define DSI_TX_FIFO_SIZE 2048 230#define DSI_TX_FIFO_SIZE 2048
@@ -233,6 +258,12 @@ struct exynos_dsi_transfer {
233#define DSIM_STATE_INITIALIZED BIT(1) 258#define DSIM_STATE_INITIALIZED BIT(1)
234#define DSIM_STATE_CMD_LPM BIT(2) 259#define DSIM_STATE_CMD_LPM BIT(2)
235 260
261struct exynos_dsi_driver_data {
262 unsigned int plltmr_reg;
263
264 unsigned int has_freqband:1;
265};
266
236struct exynos_dsi { 267struct exynos_dsi {
237 struct mipi_dsi_host dsi_host; 268 struct mipi_dsi_host dsi_host;
238 struct drm_connector connector; 269 struct drm_connector connector;
@@ -247,6 +278,7 @@ struct exynos_dsi {
247 struct clk *bus_clk; 278 struct clk *bus_clk;
248 struct regulator_bulk_data supplies[2]; 279 struct regulator_bulk_data supplies[2];
249 int irq; 280 int irq;
281 int te_gpio;
250 282
251 u32 pll_clk_rate; 283 u32 pll_clk_rate;
252 u32 burst_clk_rate; 284 u32 burst_clk_rate;
@@ -262,11 +294,39 @@ struct exynos_dsi {
262 294
263 spinlock_t transfer_lock; /* protects transfer_list */ 295 spinlock_t transfer_lock; /* protects transfer_list */
264 struct list_head transfer_list; 296 struct list_head transfer_list;
297
298 struct exynos_dsi_driver_data *driver_data;
265}; 299};
266 300
267#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host) 301#define host_to_dsi(host) container_of(host, struct exynos_dsi, dsi_host)
268#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector) 302#define connector_to_dsi(c) container_of(c, struct exynos_dsi, connector)
269 303
304static struct exynos_dsi_driver_data exynos4_dsi_driver_data = {
305 .plltmr_reg = 0x50,
306 .has_freqband = 1,
307};
308
309static struct exynos_dsi_driver_data exynos5_dsi_driver_data = {
310 .plltmr_reg = 0x58,
311};
312
313static struct of_device_id exynos_dsi_of_match[] = {
314 { .compatible = "samsung,exynos4210-mipi-dsi",
315 .data = &exynos4_dsi_driver_data },
316 { .compatible = "samsung,exynos5410-mipi-dsi",
317 .data = &exynos5_dsi_driver_data },
318 { }
319};
320
321static inline struct exynos_dsi_driver_data *exynos_dsi_get_driver_data(
322 struct platform_device *pdev)
323{
324 const struct of_device_id *of_id =
325 of_match_device(exynos_dsi_of_match, &pdev->dev);
326
327 return (struct exynos_dsi_driver_data *)of_id->data;
328}
329
270static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi) 330static void exynos_dsi_wait_for_reset(struct exynos_dsi *dsi)
271{ 331{
272 if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300))) 332 if (wait_for_completion_timeout(&dsi->completed, msecs_to_jiffies(300)))
@@ -340,14 +400,9 @@ static unsigned long exynos_dsi_pll_find_pms(struct exynos_dsi *dsi,
340static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi, 400static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
341 unsigned long freq) 401 unsigned long freq)
342{ 402{
343 static const unsigned long freq_bands[] = { 403 struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
344 100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
345 270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
346 510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
347 770 * MHZ, 870 * MHZ, 950 * MHZ,
348 };
349 unsigned long fin, fout; 404 unsigned long fin, fout;
350 int timeout, band; 405 int timeout;
351 u8 p, s; 406 u8 p, s;
352 u16 m; 407 u16 m;
353 u32 reg; 408 u32 reg;
@@ -368,18 +423,30 @@ static unsigned long exynos_dsi_set_pll(struct exynos_dsi *dsi,
368 "failed to find PLL PMS for requested frequency\n"); 423 "failed to find PLL PMS for requested frequency\n");
369 return -EFAULT; 424 return -EFAULT;
370 } 425 }
426 dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d)\n", fout, p, m, s);
371 427
372 for (band = 0; band < ARRAY_SIZE(freq_bands); ++band) 428 writel(500, dsi->reg_base + driver_data->plltmr_reg);
373 if (fout < freq_bands[band]) 429
374 break; 430 reg = DSIM_PLL_EN | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
431
432 if (driver_data->has_freqband) {
433 static const unsigned long freq_bands[] = {
434 100 * MHZ, 120 * MHZ, 160 * MHZ, 200 * MHZ,
435 270 * MHZ, 320 * MHZ, 390 * MHZ, 450 * MHZ,
436 510 * MHZ, 560 * MHZ, 640 * MHZ, 690 * MHZ,
437 770 * MHZ, 870 * MHZ, 950 * MHZ,
438 };
439 int band;
375 440
376 dev_dbg(dsi->dev, "PLL freq %lu, (p %d, m %d, s %d), band %d\n", fout, 441 for (band = 0; band < ARRAY_SIZE(freq_bands); ++band)
377 p, m, s, band); 442 if (fout < freq_bands[band])
443 break;
378 444
379 writel(500, dsi->reg_base + DSIM_PLLTMR_REG); 445 dev_dbg(dsi->dev, "band %d\n", band);
446
447 reg |= DSIM_FREQ_BAND(band);
448 }
380 449
381 reg = DSIM_FREQ_BAND(band) | DSIM_PLL_EN
382 | DSIM_PLL_P(p) | DSIM_PLL_M(m) | DSIM_PLL_S(s);
383 writel(reg, dsi->reg_base + DSIM_PLLCTRL_REG); 450 writel(reg, dsi->reg_base + DSIM_PLLCTRL_REG);
384 451
385 timeout = 1000; 452 timeout = 1000;
@@ -433,6 +500,59 @@ static int exynos_dsi_enable_clock(struct exynos_dsi *dsi)
433 return 0; 500 return 0;
434} 501}
435 502
503static void exynos_dsi_set_phy_ctrl(struct exynos_dsi *dsi)
504{
505 struct exynos_dsi_driver_data *driver_data = dsi->driver_data;
506 u32 reg;
507
508 if (driver_data->has_freqband)
509 return;
510
511 /* B D-PHY: D-PHY Master & Slave Analog Block control */
512 reg = DSIM_PHYCTRL_ULPS_EXIT(0x0af);
513 writel(reg, dsi->reg_base + DSIM_PHYCTRL_REG);
514
515 /*
516 * T LPX: Transmitted length of any Low-Power state period
517 * T HS-EXIT: Time that the transmitter drives LP-11 following a HS
518 * burst
519 */
520 reg = DSIM_PHYTIMING_LPX(0x06) | DSIM_PHYTIMING_HS_EXIT(0x0b);
521 writel(reg, dsi->reg_base + DSIM_PHYTIMING_REG);
522
523 /*
524 * T CLK-PREPARE: Time that the transmitter drives the Clock Lane LP-00
525 * Line state immediately before the HS-0 Line state starting the
526 * HS transmission
527 * T CLK-ZERO: Time that the transmitter drives the HS-0 state prior to
528 * transmitting the Clock.
529 * T CLK_POST: Time that the transmitter continues to send HS clock
530 * after the last associated Data Lane has transitioned to LP Mode
531 * Interval is defined as the period from the end of T HS-TRAIL to
532 * the beginning of T CLK-TRAIL
533 * T CLK-TRAIL: Time that the transmitter drives the HS-0 state after
534 * the last payload clock bit of a HS transmission burst
535 */
536 reg = DSIM_PHYTIMING1_CLK_PREPARE(0x07) |
537 DSIM_PHYTIMING1_CLK_ZERO(0x27) |
538 DSIM_PHYTIMING1_CLK_POST(0x0d) |
539 DSIM_PHYTIMING1_CLK_TRAIL(0x08);
540 writel(reg, dsi->reg_base + DSIM_PHYTIMING1_REG);
541
542 /*
543 * T HS-PREPARE: Time that the transmitter drives the Data Lane LP-00
544 * Line state immediately before the HS-0 Line state starting the
545 * HS transmission
546 * T HS-ZERO: Time that the transmitter drives the HS-0 state prior to
547 * transmitting the Sync sequence.
548 * T HS-TRAIL: Time that the transmitter drives the flipped differential
549 * state after last payload data bit of a HS transmission burst
550 */
551 reg = DSIM_PHYTIMING2_HS_PREPARE(0x09) | DSIM_PHYTIMING2_HS_ZERO(0x0d) |
552 DSIM_PHYTIMING2_HS_TRAIL(0x0b);
553 writel(reg, dsi->reg_base + DSIM_PHYTIMING2_REG);
554}
555
436static void exynos_dsi_disable_clock(struct exynos_dsi *dsi) 556static void exynos_dsi_disable_clock(struct exynos_dsi *dsi)
437{ 557{
438 u32 reg; 558 u32 reg;
@@ -468,13 +588,20 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
468 /* DSI configuration */ 588 /* DSI configuration */
469 reg = 0; 589 reg = 0;
470 590
591 /*
592 * The first bit of mode_flags specifies display configuration.
593 * If this bit is set[= MIPI_DSI_MODE_VIDEO], dsi will support video
594 * mode, otherwise it will support command mode.
595 */
471 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) { 596 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO) {
472 reg |= DSIM_VIDEO_MODE; 597 reg |= DSIM_VIDEO_MODE;
473 598
599 /*
600 * The user manual describes that following bits are ignored in
601 * command mode.
602 */
474 if (!(dsi->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH)) 603 if (!(dsi->mode_flags & MIPI_DSI_MODE_VSYNC_FLUSH))
475 reg |= DSIM_MFLUSH_VS; 604 reg |= DSIM_MFLUSH_VS;
476 if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
477 reg |= DSIM_EOT_DISABLE;
478 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE) 605 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_SYNC_PULSE)
479 reg |= DSIM_SYNC_INFORM; 606 reg |= DSIM_SYNC_INFORM;
480 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST) 607 if (dsi->mode_flags & MIPI_DSI_MODE_VIDEO_BURST)
@@ -491,6 +618,9 @@ static int exynos_dsi_init_link(struct exynos_dsi *dsi)
491 reg |= DSIM_HSA_MODE; 618 reg |= DSIM_HSA_MODE;
492 } 619 }
493 620
621 if (!(dsi->mode_flags & MIPI_DSI_MODE_EOT_PACKET))
622 reg |= DSIM_EOT_DISABLE;
623
494 switch (dsi->format) { 624 switch (dsi->format) {
495 case MIPI_DSI_FMT_RGB888: 625 case MIPI_DSI_FMT_RGB888:
496 reg |= DSIM_MAIN_PIX_FORMAT_RGB888; 626 reg |= DSIM_MAIN_PIX_FORMAT_RGB888;
@@ -944,17 +1074,90 @@ static irqreturn_t exynos_dsi_irq(int irq, void *dev_id)
944 return IRQ_HANDLED; 1074 return IRQ_HANDLED;
945} 1075}
946 1076
1077static irqreturn_t exynos_dsi_te_irq_handler(int irq, void *dev_id)
1078{
1079 struct exynos_dsi *dsi = (struct exynos_dsi *)dev_id;
1080 struct drm_encoder *encoder = dsi->encoder;
1081
1082 if (dsi->state & DSIM_STATE_ENABLED)
1083 exynos_drm_crtc_te_handler(encoder->crtc);
1084
1085 return IRQ_HANDLED;
1086}
1087
1088static void exynos_dsi_enable_irq(struct exynos_dsi *dsi)
1089{
1090 enable_irq(dsi->irq);
1091
1092 if (gpio_is_valid(dsi->te_gpio))
1093 enable_irq(gpio_to_irq(dsi->te_gpio));
1094}
1095
1096static void exynos_dsi_disable_irq(struct exynos_dsi *dsi)
1097{
1098 if (gpio_is_valid(dsi->te_gpio))
1099 disable_irq(gpio_to_irq(dsi->te_gpio));
1100
1101 disable_irq(dsi->irq);
1102}
1103
947static int exynos_dsi_init(struct exynos_dsi *dsi) 1104static int exynos_dsi_init(struct exynos_dsi *dsi)
948{ 1105{
949 exynos_dsi_enable_clock(dsi);
950 exynos_dsi_reset(dsi); 1106 exynos_dsi_reset(dsi);
951 enable_irq(dsi->irq); 1107 exynos_dsi_enable_irq(dsi);
1108 exynos_dsi_enable_clock(dsi);
952 exynos_dsi_wait_for_reset(dsi); 1109 exynos_dsi_wait_for_reset(dsi);
1110 exynos_dsi_set_phy_ctrl(dsi);
953 exynos_dsi_init_link(dsi); 1111 exynos_dsi_init_link(dsi);
954 1112
955 return 0; 1113 return 0;
956} 1114}
957 1115
1116static int exynos_dsi_register_te_irq(struct exynos_dsi *dsi)
1117{
1118 int ret;
1119
1120 dsi->te_gpio = of_get_named_gpio(dsi->panel_node, "te-gpios", 0);
1121 if (!gpio_is_valid(dsi->te_gpio)) {
1122 dev_err(dsi->dev, "no te-gpios specified\n");
1123 ret = dsi->te_gpio;
1124 goto out;
1125 }
1126
1127 ret = gpio_request_one(dsi->te_gpio, GPIOF_IN, "te_gpio");
1128 if (ret) {
1129 dev_err(dsi->dev, "gpio request failed with %d\n", ret);
1130 goto out;
1131 }
1132
1133 /*
1134 * This TE GPIO IRQ should not be set to IRQ_NOAUTOEN, because panel
1135 * calls drm_panel_init() first then calls mipi_dsi_attach() in probe().
1136 * It means that te_gpio is invalid when exynos_dsi_enable_irq() is
1137 * called by drm_panel_init() before panel is attached.
1138 */
1139 ret = request_threaded_irq(gpio_to_irq(dsi->te_gpio),
1140 exynos_dsi_te_irq_handler, NULL,
1141 IRQF_TRIGGER_RISING, "TE", dsi);
1142 if (ret) {
1143 dev_err(dsi->dev, "request interrupt failed with %d\n", ret);
1144 gpio_free(dsi->te_gpio);
1145 goto out;
1146 }
1147
1148out:
1149 return ret;
1150}
1151
1152static void exynos_dsi_unregister_te_irq(struct exynos_dsi *dsi)
1153{
1154 if (gpio_is_valid(dsi->te_gpio)) {
1155 free_irq(gpio_to_irq(dsi->te_gpio), dsi);
1156 gpio_free(dsi->te_gpio);
1157 dsi->te_gpio = -ENOENT;
1158 }
1159}
1160
958static int exynos_dsi_host_attach(struct mipi_dsi_host *host, 1161static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
959 struct mipi_dsi_device *device) 1162 struct mipi_dsi_device *device)
960{ 1163{
@@ -968,6 +1171,19 @@ static int exynos_dsi_host_attach(struct mipi_dsi_host *host,
968 if (dsi->connector.dev) 1171 if (dsi->connector.dev)
969 drm_helper_hpd_irq_event(dsi->connector.dev); 1172 drm_helper_hpd_irq_event(dsi->connector.dev);
970 1173
1174 /*
1175 * This is a temporary solution and should be made by more generic way.
1176 *
1177 * If attached panel device is for command mode one, dsi should register
1178 * TE interrupt handler.
1179 */
1180 if (!(dsi->mode_flags & MIPI_DSI_MODE_VIDEO)) {
1181 int ret = exynos_dsi_register_te_irq(dsi);
1182
1183 if (ret)
1184 return ret;
1185 }
1186
971 return 0; 1187 return 0;
972} 1188}
973 1189
@@ -976,6 +1192,8 @@ static int exynos_dsi_host_detach(struct mipi_dsi_host *host,
976{ 1192{
977 struct exynos_dsi *dsi = host_to_dsi(host); 1193 struct exynos_dsi *dsi = host_to_dsi(host);
978 1194
1195 exynos_dsi_unregister_te_irq(dsi);
1196
979 dsi->panel_node = NULL; 1197 dsi->panel_node = NULL;
980 1198
981 if (dsi->connector.dev) 1199 if (dsi->connector.dev)
@@ -1089,7 +1307,7 @@ static void exynos_dsi_poweroff(struct exynos_dsi *dsi)
1089 1307
1090 exynos_dsi_disable_clock(dsi); 1308 exynos_dsi_disable_clock(dsi);
1091 1309
1092 disable_irq(dsi->irq); 1310 exynos_dsi_disable_irq(dsi);
1093 } 1311 }
1094 1312
1095 dsi->state &= ~DSIM_STATE_CMD_LPM; 1313 dsi->state &= ~DSIM_STATE_CMD_LPM;
@@ -1278,6 +1496,7 @@ static struct exynos_drm_display exynos_dsi_display = {
1278 .type = EXYNOS_DISPLAY_TYPE_LCD, 1496 .type = EXYNOS_DISPLAY_TYPE_LCD,
1279 .ops = &exynos_dsi_display_ops, 1497 .ops = &exynos_dsi_display_ops,
1280}; 1498};
1499MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
1281 1500
1282/* of_* functions will be removed after merge of of_graph patches */ 1501/* of_* functions will be removed after merge of of_graph patches */
1283static struct device_node * 1502static struct device_node *
@@ -1435,6 +1654,9 @@ static int exynos_dsi_probe(struct platform_device *pdev)
1435 goto err_del_component; 1654 goto err_del_component;
1436 } 1655 }
1437 1656
1657 /* To be checked as invalid one */
1658 dsi->te_gpio = -ENOENT;
1659
1438 init_completion(&dsi->completed); 1660 init_completion(&dsi->completed);
1439 spin_lock_init(&dsi->transfer_lock); 1661 spin_lock_init(&dsi->transfer_lock);
1440 INIT_LIST_HEAD(&dsi->transfer_list); 1662 INIT_LIST_HEAD(&dsi->transfer_list);
@@ -1443,6 +1665,7 @@ static int exynos_dsi_probe(struct platform_device *pdev)
1443 dsi->dsi_host.dev = &pdev->dev; 1665 dsi->dsi_host.dev = &pdev->dev;
1444 1666
1445 dsi->dev = &pdev->dev; 1667 dsi->dev = &pdev->dev;
1668 dsi->driver_data = exynos_dsi_get_driver_data(pdev);
1446 1669
1447 ret = exynos_dsi_parse_dt(dsi); 1670 ret = exynos_dsi_parse_dt(dsi);
1448 if (ret) 1671 if (ret)
@@ -1525,11 +1748,6 @@ static int exynos_dsi_remove(struct platform_device *pdev)
1525 return 0; 1748 return 0;
1526} 1749}
1527 1750
1528static struct of_device_id exynos_dsi_of_match[] = {
1529 { .compatible = "samsung,exynos4210-mipi-dsi" },
1530 { }
1531};
1532
1533struct platform_driver dsi_driver = { 1751struct platform_driver dsi_driver = {
1534 .probe = exynos_dsi_probe, 1752 .probe = exynos_dsi_probe,
1535 .remove = exynos_dsi_remove, 1753 .remove = exynos_dsi_remove,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 831dde9034c6..ec7cc9ea50df 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -1887,6 +1887,7 @@ static const struct of_device_id fimc_of_match[] = {
1887 { .compatible = "samsung,exynos4212-fimc" }, 1887 { .compatible = "samsung,exynos4212-fimc" },
1888 { }, 1888 { },
1889}; 1889};
1890MODULE_DEVICE_TABLE(of, fimc_of_match);
1890 1891
1891struct platform_driver fimc_driver = { 1892struct platform_driver fimc_driver = {
1892 .probe = fimc_probe, 1893 .probe = fimc_probe,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index 33161ad38201..5d09e33fef87 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -20,6 +20,8 @@
20#include <linux/of_device.h> 20#include <linux/of_device.h>
21#include <linux/pm_runtime.h> 21#include <linux/pm_runtime.h>
22#include <linux/component.h> 22#include <linux/component.h>
23#include <linux/mfd/syscon.h>
24#include <linux/regmap.h>
23 25
24#include <video/of_display_timing.h> 26#include <video/of_display_timing.h>
25#include <video/of_videomode.h> 27#include <video/of_videomode.h>
@@ -61,6 +63,24 @@
61/* color key value register for hardware window 1 ~ 4. */ 63/* color key value register for hardware window 1 ~ 4. */
62#define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8)) 64#define WKEYCON1_BASE(x) ((WKEYCON1 + 0x140) + ((x - 1) * 8))
63 65
66/* I80 / RGB trigger control register */
67#define TRIGCON 0x1A4
68#define TRGMODE_I80_RGB_ENABLE_I80 (1 << 0)
69#define SWTRGCMD_I80_RGB_ENABLE (1 << 1)
70
71/* display mode change control register except exynos4 */
72#define VIDOUT_CON 0x000
73#define VIDOUT_CON_F_I80_LDI0 (0x2 << 8)
74
75/* I80 interface control for main LDI register */
76#define I80IFCONFAx(x) (0x1B0 + (x) * 4)
77#define I80IFCONFBx(x) (0x1B8 + (x) * 4)
78#define LCD_CS_SETUP(x) ((x) << 16)
79#define LCD_WR_SETUP(x) ((x) << 12)
80#define LCD_WR_ACTIVE(x) ((x) << 8)
81#define LCD_WR_HOLD(x) ((x) << 4)
82#define I80IFEN_ENABLE (1 << 0)
83
64/* FIMD has totally five hardware windows. */ 84/* FIMD has totally five hardware windows. */
65#define WINDOWS_NR 5 85#define WINDOWS_NR 5
66 86
@@ -68,10 +88,14 @@
68 88
69struct fimd_driver_data { 89struct fimd_driver_data {
70 unsigned int timing_base; 90 unsigned int timing_base;
91 unsigned int lcdblk_offset;
92 unsigned int lcdblk_vt_shift;
93 unsigned int lcdblk_bypass_shift;
71 94
72 unsigned int has_shadowcon:1; 95 unsigned int has_shadowcon:1;
73 unsigned int has_clksel:1; 96 unsigned int has_clksel:1;
74 unsigned int has_limited_fmt:1; 97 unsigned int has_limited_fmt:1;
98 unsigned int has_vidoutcon:1;
75}; 99};
76 100
77static struct fimd_driver_data s3c64xx_fimd_driver_data = { 101static struct fimd_driver_data s3c64xx_fimd_driver_data = {
@@ -82,12 +106,19 @@ static struct fimd_driver_data s3c64xx_fimd_driver_data = {
82 106
83static struct fimd_driver_data exynos4_fimd_driver_data = { 107static struct fimd_driver_data exynos4_fimd_driver_data = {
84 .timing_base = 0x0, 108 .timing_base = 0x0,
109 .lcdblk_offset = 0x210,
110 .lcdblk_vt_shift = 10,
111 .lcdblk_bypass_shift = 1,
85 .has_shadowcon = 1, 112 .has_shadowcon = 1,
86}; 113};
87 114
88static struct fimd_driver_data exynos5_fimd_driver_data = { 115static struct fimd_driver_data exynos5_fimd_driver_data = {
89 .timing_base = 0x20000, 116 .timing_base = 0x20000,
117 .lcdblk_offset = 0x214,
118 .lcdblk_vt_shift = 24,
119 .lcdblk_bypass_shift = 15,
90 .has_shadowcon = 1, 120 .has_shadowcon = 1,
121 .has_vidoutcon = 1,
91}; 122};
92 123
93struct fimd_win_data { 124struct fimd_win_data {
@@ -112,15 +143,22 @@ struct fimd_context {
112 struct clk *bus_clk; 143 struct clk *bus_clk;
113 struct clk *lcd_clk; 144 struct clk *lcd_clk;
114 void __iomem *regs; 145 void __iomem *regs;
146 struct regmap *sysreg;
115 struct drm_display_mode mode; 147 struct drm_display_mode mode;
116 struct fimd_win_data win_data[WINDOWS_NR]; 148 struct fimd_win_data win_data[WINDOWS_NR];
117 unsigned int default_win; 149 unsigned int default_win;
118 unsigned long irq_flags; 150 unsigned long irq_flags;
151 u32 vidcon0;
119 u32 vidcon1; 152 u32 vidcon1;
153 u32 vidout_con;
154 u32 i80ifcon;
155 bool i80_if;
120 bool suspended; 156 bool suspended;
121 int pipe; 157 int pipe;
122 wait_queue_head_t wait_vsync_queue; 158 wait_queue_head_t wait_vsync_queue;
123 atomic_t wait_vsync_event; 159 atomic_t wait_vsync_event;
160 atomic_t win_updated;
161 atomic_t triggering;
124 162
125 struct exynos_drm_panel_info panel; 163 struct exynos_drm_panel_info panel;
126 struct fimd_driver_data *driver_data; 164 struct fimd_driver_data *driver_data;
@@ -136,6 +174,7 @@ static const struct of_device_id fimd_driver_dt_match[] = {
136 .data = &exynos5_fimd_driver_data }, 174 .data = &exynos5_fimd_driver_data },
137 {}, 175 {},
138}; 176};
177MODULE_DEVICE_TABLE(of, fimd_driver_dt_match);
139 178
140static inline struct fimd_driver_data *drm_fimd_get_driver_data( 179static inline struct fimd_driver_data *drm_fimd_get_driver_data(
141 struct platform_device *pdev) 180 struct platform_device *pdev)
@@ -243,6 +282,14 @@ static u32 fimd_calc_clkdiv(struct fimd_context *ctx,
243 unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh; 282 unsigned long ideal_clk = mode->htotal * mode->vtotal * mode->vrefresh;
244 u32 clkdiv; 283 u32 clkdiv;
245 284
285 if (ctx->i80_if) {
286 /*
287 * The frame done interrupt should be occurred prior to the
288 * next TE signal.
289 */
290 ideal_clk *= 2;
291 }
292
246 /* Find the clock divider value that gets us closest to ideal_clk */ 293 /* Find the clock divider value that gets us closest to ideal_clk */
247 clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->lcd_clk), ideal_clk); 294 clkdiv = DIV_ROUND_UP(clk_get_rate(ctx->lcd_clk), ideal_clk);
248 295
@@ -271,11 +318,10 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
271{ 318{
272 struct fimd_context *ctx = mgr->ctx; 319 struct fimd_context *ctx = mgr->ctx;
273 struct drm_display_mode *mode = &ctx->mode; 320 struct drm_display_mode *mode = &ctx->mode;
274 struct fimd_driver_data *driver_data; 321 struct fimd_driver_data *driver_data = ctx->driver_data;
275 u32 val, clkdiv, vidcon1; 322 void *timing_base = ctx->regs + driver_data->timing_base;
276 int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd; 323 u32 val, clkdiv;
277 324
278 driver_data = ctx->driver_data;
279 if (ctx->suspended) 325 if (ctx->suspended)
280 return; 326 return;
281 327
@@ -283,33 +329,65 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
283 if (mode->htotal == 0 || mode->vtotal == 0) 329 if (mode->htotal == 0 || mode->vtotal == 0)
284 return; 330 return;
285 331
286 /* setup polarity values */ 332 if (ctx->i80_if) {
287 vidcon1 = ctx->vidcon1; 333 val = ctx->i80ifcon | I80IFEN_ENABLE;
288 if (mode->flags & DRM_MODE_FLAG_NVSYNC) 334 writel(val, timing_base + I80IFCONFAx(0));
289 vidcon1 |= VIDCON1_INV_VSYNC; 335
290 if (mode->flags & DRM_MODE_FLAG_NHSYNC) 336 /* disable auto frame rate */
291 vidcon1 |= VIDCON1_INV_HSYNC; 337 writel(0, timing_base + I80IFCONFBx(0));
292 writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1); 338
293 339 /* set video type selection to I80 interface */
294 /* setup vertical timing values. */ 340 if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
295 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start; 341 driver_data->lcdblk_offset,
296 vbpd = mode->crtc_vtotal - mode->crtc_vsync_end; 342 0x3 << driver_data->lcdblk_vt_shift,
297 vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay; 343 0x1 << driver_data->lcdblk_vt_shift)) {
298 344 DRM_ERROR("Failed to update sysreg for I80 i/f.\n");
299 val = VIDTCON0_VBPD(vbpd - 1) | 345 return;
300 VIDTCON0_VFPD(vfpd - 1) | 346 }
301 VIDTCON0_VSPW(vsync_len - 1); 347 } else {
302 writel(val, ctx->regs + driver_data->timing_base + VIDTCON0); 348 int vsync_len, vbpd, vfpd, hsync_len, hbpd, hfpd;
303 349 u32 vidcon1;
304 /* setup horizontal timing values. */ 350
305 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start; 351 /* setup polarity values */
306 hbpd = mode->crtc_htotal - mode->crtc_hsync_end; 352 vidcon1 = ctx->vidcon1;
307 hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay; 353 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
308 354 vidcon1 |= VIDCON1_INV_VSYNC;
309 val = VIDTCON1_HBPD(hbpd - 1) | 355 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
310 VIDTCON1_HFPD(hfpd - 1) | 356 vidcon1 |= VIDCON1_INV_HSYNC;
311 VIDTCON1_HSPW(hsync_len - 1); 357 writel(vidcon1, ctx->regs + driver_data->timing_base + VIDCON1);
312 writel(val, ctx->regs + driver_data->timing_base + VIDTCON1); 358
359 /* setup vertical timing values. */
360 vsync_len = mode->crtc_vsync_end - mode->crtc_vsync_start;
361 vbpd = mode->crtc_vtotal - mode->crtc_vsync_end;
362 vfpd = mode->crtc_vsync_start - mode->crtc_vdisplay;
363
364 val = VIDTCON0_VBPD(vbpd - 1) |
365 VIDTCON0_VFPD(vfpd - 1) |
366 VIDTCON0_VSPW(vsync_len - 1);
367 writel(val, ctx->regs + driver_data->timing_base + VIDTCON0);
368
369 /* setup horizontal timing values. */
370 hsync_len = mode->crtc_hsync_end - mode->crtc_hsync_start;
371 hbpd = mode->crtc_htotal - mode->crtc_hsync_end;
372 hfpd = mode->crtc_hsync_start - mode->crtc_hdisplay;
373
374 val = VIDTCON1_HBPD(hbpd - 1) |
375 VIDTCON1_HFPD(hfpd - 1) |
376 VIDTCON1_HSPW(hsync_len - 1);
377 writel(val, ctx->regs + driver_data->timing_base + VIDTCON1);
378 }
379
380 if (driver_data->has_vidoutcon)
381 writel(ctx->vidout_con, timing_base + VIDOUT_CON);
382
383 /* set bypass selection */
384 if (ctx->sysreg && regmap_update_bits(ctx->sysreg,
385 driver_data->lcdblk_offset,
386 0x1 << driver_data->lcdblk_bypass_shift,
387 0x1 << driver_data->lcdblk_bypass_shift)) {
388 DRM_ERROR("Failed to update sysreg for bypass setting.\n");
389 return;
390 }
313 391
314 /* setup horizontal and vertical display size. */ 392 /* setup horizontal and vertical display size. */
315 val = VIDTCON2_LINEVAL(mode->vdisplay - 1) | 393 val = VIDTCON2_LINEVAL(mode->vdisplay - 1) |
@@ -322,7 +400,8 @@ static void fimd_commit(struct exynos_drm_manager *mgr)
322 * fields of register with prefix '_F' would be updated 400 * fields of register with prefix '_F' would be updated
323 * at vsync(same as dma start) 401 * at vsync(same as dma start)
324 */ 402 */
325 val = VIDCON0_ENVID | VIDCON0_ENVID_F; 403 val = ctx->vidcon0;
404 val |= VIDCON0_ENVID | VIDCON0_ENVID_F;
326 405
327 if (ctx->driver_data->has_clksel) 406 if (ctx->driver_data->has_clksel)
328 val |= VIDCON0_CLKSEL_LCD; 407 val |= VIDCON0_CLKSEL_LCD;
@@ -660,6 +739,9 @@ static void fimd_win_commit(struct exynos_drm_manager *mgr, int zpos)
660 } 739 }
661 740
662 win_data->enabled = true; 741 win_data->enabled = true;
742
743 if (ctx->i80_if)
744 atomic_set(&ctx->win_updated, 1);
663} 745}
664 746
665static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos) 747static void fimd_win_disable(struct exynos_drm_manager *mgr, int zpos)
@@ -838,6 +920,58 @@ static void fimd_dpms(struct exynos_drm_manager *mgr, int mode)
838 } 920 }
839} 921}
840 922
923static void fimd_trigger(struct device *dev)
924{
925 struct exynos_drm_manager *mgr = get_fimd_manager(dev);
926 struct fimd_context *ctx = mgr->ctx;
927 struct fimd_driver_data *driver_data = ctx->driver_data;
928 void *timing_base = ctx->regs + driver_data->timing_base;
929 u32 reg;
930
931 atomic_set(&ctx->triggering, 1);
932
933 reg = readl(ctx->regs + VIDINTCON0);
934 reg |= (VIDINTCON0_INT_ENABLE | VIDINTCON0_INT_I80IFDONE |
935 VIDINTCON0_INT_SYSMAINCON);
936 writel(reg, ctx->regs + VIDINTCON0);
937
938 reg = readl(timing_base + TRIGCON);
939 reg |= (TRGMODE_I80_RGB_ENABLE_I80 | SWTRGCMD_I80_RGB_ENABLE);
940 writel(reg, timing_base + TRIGCON);
941}
942
943static void fimd_te_handler(struct exynos_drm_manager *mgr)
944{
945 struct fimd_context *ctx = mgr->ctx;
946
947 /* Checks the crtc is detached already from encoder */
948 if (ctx->pipe < 0 || !ctx->drm_dev)
949 return;
950
951 /*
952 * Skips to trigger if in triggering state, because multiple triggering
953 * requests can cause panel reset.
954 */
955 if (atomic_read(&ctx->triggering))
956 return;
957
958 /*
959 * If there is a page flip request, triggers and handles the page flip
960 * event so that current fb can be updated into panel GRAM.
961 */
962 if (atomic_add_unless(&ctx->win_updated, -1, 0))
963 fimd_trigger(ctx->dev);
964
965 /* Wakes up vsync event queue */
966 if (atomic_read(&ctx->wait_vsync_event)) {
967 atomic_set(&ctx->wait_vsync_event, 0);
968 wake_up(&ctx->wait_vsync_queue);
969
970 if (!atomic_read(&ctx->triggering))
971 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
972 }
973}
974
841static struct exynos_drm_manager_ops fimd_manager_ops = { 975static struct exynos_drm_manager_ops fimd_manager_ops = {
842 .dpms = fimd_dpms, 976 .dpms = fimd_dpms,
843 .mode_fixup = fimd_mode_fixup, 977 .mode_fixup = fimd_mode_fixup,
@@ -849,6 +983,7 @@ static struct exynos_drm_manager_ops fimd_manager_ops = {
849 .win_mode_set = fimd_win_mode_set, 983 .win_mode_set = fimd_win_mode_set,
850 .win_commit = fimd_win_commit, 984 .win_commit = fimd_win_commit,
851 .win_disable = fimd_win_disable, 985 .win_disable = fimd_win_disable,
986 .te_handler = fimd_te_handler,
852}; 987};
853 988
854static struct exynos_drm_manager fimd_manager = { 989static struct exynos_drm_manager fimd_manager = {
@@ -859,26 +994,40 @@ static struct exynos_drm_manager fimd_manager = {
859static irqreturn_t fimd_irq_handler(int irq, void *dev_id) 994static irqreturn_t fimd_irq_handler(int irq, void *dev_id)
860{ 995{
861 struct fimd_context *ctx = (struct fimd_context *)dev_id; 996 struct fimd_context *ctx = (struct fimd_context *)dev_id;
862 u32 val; 997 u32 val, clear_bit;
863 998
864 val = readl(ctx->regs + VIDINTCON1); 999 val = readl(ctx->regs + VIDINTCON1);
865 1000
866 if (val & VIDINTCON1_INT_FRAME) 1001 clear_bit = ctx->i80_if ? VIDINTCON1_INT_I80 : VIDINTCON1_INT_FRAME;
867 /* VSYNC interrupt */ 1002 if (val & clear_bit)
868 writel(VIDINTCON1_INT_FRAME, ctx->regs + VIDINTCON1); 1003 writel(clear_bit, ctx->regs + VIDINTCON1);
869 1004
870 /* check the crtc is detached already from encoder */ 1005 /* check the crtc is detached already from encoder */
871 if (ctx->pipe < 0 || !ctx->drm_dev) 1006 if (ctx->pipe < 0 || !ctx->drm_dev)
872 goto out; 1007 goto out;
873 1008
874 drm_handle_vblank(ctx->drm_dev, ctx->pipe); 1009 if (ctx->i80_if) {
875 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe); 1010 /* unset I80 frame done interrupt */
1011 val = readl(ctx->regs + VIDINTCON0);
1012 val &= ~(VIDINTCON0_INT_I80IFDONE | VIDINTCON0_INT_SYSMAINCON);
1013 writel(val, ctx->regs + VIDINTCON0);
876 1014
877 /* set wait vsync event to zero and wake up queue. */ 1015 /* exit triggering mode */
878 if (atomic_read(&ctx->wait_vsync_event)) { 1016 atomic_set(&ctx->triggering, 0);
879 atomic_set(&ctx->wait_vsync_event, 0); 1017
880 wake_up(&ctx->wait_vsync_queue); 1018 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
1019 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
1020 } else {
1021 drm_handle_vblank(ctx->drm_dev, ctx->pipe);
1022 exynos_drm_crtc_finish_pageflip(ctx->drm_dev, ctx->pipe);
1023
1024 /* set wait vsync event to zero and wake up queue. */
1025 if (atomic_read(&ctx->wait_vsync_event)) {
1026 atomic_set(&ctx->wait_vsync_event, 0);
1027 wake_up(&ctx->wait_vsync_queue);
1028 }
881 } 1029 }
1030
882out: 1031out:
883 return IRQ_HANDLED; 1032 return IRQ_HANDLED;
884} 1033}
@@ -923,6 +1072,7 @@ static int fimd_probe(struct platform_device *pdev)
923{ 1072{
924 struct device *dev = &pdev->dev; 1073 struct device *dev = &pdev->dev;
925 struct fimd_context *ctx; 1074 struct fimd_context *ctx;
1075 struct device_node *i80_if_timings;
926 struct resource *res; 1076 struct resource *res;
927 int ret = -EINVAL; 1077 int ret = -EINVAL;
928 1078
@@ -944,12 +1094,51 @@ static int fimd_probe(struct platform_device *pdev)
944 1094
945 ctx->dev = dev; 1095 ctx->dev = dev;
946 ctx->suspended = true; 1096 ctx->suspended = true;
1097 ctx->driver_data = drm_fimd_get_driver_data(pdev);
947 1098
948 if (of_property_read_bool(dev->of_node, "samsung,invert-vden")) 1099 if (of_property_read_bool(dev->of_node, "samsung,invert-vden"))
949 ctx->vidcon1 |= VIDCON1_INV_VDEN; 1100 ctx->vidcon1 |= VIDCON1_INV_VDEN;
950 if (of_property_read_bool(dev->of_node, "samsung,invert-vclk")) 1101 if (of_property_read_bool(dev->of_node, "samsung,invert-vclk"))
951 ctx->vidcon1 |= VIDCON1_INV_VCLK; 1102 ctx->vidcon1 |= VIDCON1_INV_VCLK;
952 1103
1104 i80_if_timings = of_get_child_by_name(dev->of_node, "i80-if-timings");
1105 if (i80_if_timings) {
1106 u32 val;
1107
1108 ctx->i80_if = true;
1109
1110 if (ctx->driver_data->has_vidoutcon)
1111 ctx->vidout_con |= VIDOUT_CON_F_I80_LDI0;
1112 else
1113 ctx->vidcon0 |= VIDCON0_VIDOUT_I80_LDI0;
1114 /*
1115 * The user manual describes that this "DSI_EN" bit is required
1116 * to enable I80 24-bit data interface.
1117 */
1118 ctx->vidcon0 |= VIDCON0_DSI_EN;
1119
1120 if (of_property_read_u32(i80_if_timings, "cs-setup", &val))
1121 val = 0;
1122 ctx->i80ifcon = LCD_CS_SETUP(val);
1123 if (of_property_read_u32(i80_if_timings, "wr-setup", &val))
1124 val = 0;
1125 ctx->i80ifcon |= LCD_WR_SETUP(val);
1126 if (of_property_read_u32(i80_if_timings, "wr-active", &val))
1127 val = 1;
1128 ctx->i80ifcon |= LCD_WR_ACTIVE(val);
1129 if (of_property_read_u32(i80_if_timings, "wr-hold", &val))
1130 val = 0;
1131 ctx->i80ifcon |= LCD_WR_HOLD(val);
1132 }
1133 of_node_put(i80_if_timings);
1134
1135 ctx->sysreg = syscon_regmap_lookup_by_phandle(dev->of_node,
1136 "samsung,sysreg");
1137 if (IS_ERR(ctx->sysreg)) {
1138 dev_warn(dev, "failed to get system register.\n");
1139 ctx->sysreg = NULL;
1140 }
1141
953 ctx->bus_clk = devm_clk_get(dev, "fimd"); 1142 ctx->bus_clk = devm_clk_get(dev, "fimd");
954 if (IS_ERR(ctx->bus_clk)) { 1143 if (IS_ERR(ctx->bus_clk)) {
955 dev_err(dev, "failed to get bus clock\n"); 1144 dev_err(dev, "failed to get bus clock\n");
@@ -972,7 +1161,8 @@ static int fimd_probe(struct platform_device *pdev)
972 goto err_del_component; 1161 goto err_del_component;
973 } 1162 }
974 1163
975 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "vsync"); 1164 res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
1165 ctx->i80_if ? "lcd_sys" : "vsync");
976 if (!res) { 1166 if (!res) {
977 dev_err(dev, "irq request failed.\n"); 1167 dev_err(dev, "irq request failed.\n");
978 ret = -ENXIO; 1168 ret = -ENXIO;
@@ -986,7 +1176,6 @@ static int fimd_probe(struct platform_device *pdev)
986 goto err_del_component; 1176 goto err_del_component;
987 } 1177 }
988 1178
989 ctx->driver_data = drm_fimd_get_driver_data(pdev);
990 init_waitqueue_head(&ctx->wait_vsync_queue); 1179 init_waitqueue_head(&ctx->wait_vsync_queue);
991 atomic_set(&ctx->wait_vsync_event, 0); 1180 atomic_set(&ctx->wait_vsync_event, 0);
992 1181
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 800158714473..df7a77d3eff8 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -1042,8 +1042,23 @@ err:
1042int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data, 1042int exynos_g2d_get_ver_ioctl(struct drm_device *drm_dev, void *data,
1043 struct drm_file *file) 1043 struct drm_file *file)
1044{ 1044{
1045 struct drm_exynos_file_private *file_priv = file->driver_priv;
1046 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
1047 struct device *dev;
1048 struct g2d_data *g2d;
1045 struct drm_exynos_g2d_get_ver *ver = data; 1049 struct drm_exynos_g2d_get_ver *ver = data;
1046 1050
1051 if (!g2d_priv)
1052 return -ENODEV;
1053
1054 dev = g2d_priv->dev;
1055 if (!dev)
1056 return -ENODEV;
1057
1058 g2d = dev_get_drvdata(dev);
1059 if (!g2d)
1060 return -EFAULT;
1061
1047 ver->major = G2D_HW_MAJOR_VER; 1062 ver->major = G2D_HW_MAJOR_VER;
1048 ver->minor = G2D_HW_MINOR_VER; 1063 ver->minor = G2D_HW_MINOR_VER;
1049 1064
@@ -1056,7 +1071,7 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
1056{ 1071{
1057 struct drm_exynos_file_private *file_priv = file->driver_priv; 1072 struct drm_exynos_file_private *file_priv = file->driver_priv;
1058 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv; 1073 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
1059 struct device *dev = g2d_priv->dev; 1074 struct device *dev;
1060 struct g2d_data *g2d; 1075 struct g2d_data *g2d;
1061 struct drm_exynos_g2d_set_cmdlist *req = data; 1076 struct drm_exynos_g2d_set_cmdlist *req = data;
1062 struct drm_exynos_g2d_cmd *cmd; 1077 struct drm_exynos_g2d_cmd *cmd;
@@ -1067,6 +1082,10 @@ int exynos_g2d_set_cmdlist_ioctl(struct drm_device *drm_dev, void *data,
1067 int size; 1082 int size;
1068 int ret; 1083 int ret;
1069 1084
1085 if (!g2d_priv)
1086 return -ENODEV;
1087
1088 dev = g2d_priv->dev;
1070 if (!dev) 1089 if (!dev)
1071 return -ENODEV; 1090 return -ENODEV;
1072 1091
@@ -1223,13 +1242,17 @@ int exynos_g2d_exec_ioctl(struct drm_device *drm_dev, void *data,
1223{ 1242{
1224 struct drm_exynos_file_private *file_priv = file->driver_priv; 1243 struct drm_exynos_file_private *file_priv = file->driver_priv;
1225 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv; 1244 struct exynos_drm_g2d_private *g2d_priv = file_priv->g2d_priv;
1226 struct device *dev = g2d_priv->dev; 1245 struct device *dev;
1227 struct g2d_data *g2d; 1246 struct g2d_data *g2d;
1228 struct drm_exynos_g2d_exec *req = data; 1247 struct drm_exynos_g2d_exec *req = data;
1229 struct g2d_runqueue_node *runqueue_node; 1248 struct g2d_runqueue_node *runqueue_node;
1230 struct list_head *run_cmdlist; 1249 struct list_head *run_cmdlist;
1231 struct list_head *event_list; 1250 struct list_head *event_list;
1232 1251
1252 if (!g2d_priv)
1253 return -ENODEV;
1254
1255 dev = g2d_priv->dev;
1233 if (!dev) 1256 if (!dev)
1234 return -ENODEV; 1257 return -ENODEV;
1235 1258
@@ -1544,8 +1567,10 @@ static const struct dev_pm_ops g2d_pm_ops = {
1544 1567
1545static const struct of_device_id exynos_g2d_match[] = { 1568static const struct of_device_id exynos_g2d_match[] = {
1546 { .compatible = "samsung,exynos5250-g2d" }, 1569 { .compatible = "samsung,exynos5250-g2d" },
1570 { .compatible = "samsung,exynos4212-g2d" },
1547 {}, 1571 {},
1548}; 1572};
1573MODULE_DEVICE_TABLE(of, exynos_g2d_match);
1549 1574
1550struct platform_driver g2d_driver = { 1575struct platform_driver g2d_driver = {
1551 .probe = g2d_probe, 1576 .probe = g2d_probe,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 163a054922cb..15db80138382 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -301,7 +301,6 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
301 unsigned int gem_handle, 301 unsigned int gem_handle,
302 struct drm_file *filp) 302 struct drm_file *filp)
303{ 303{
304 struct exynos_drm_gem_obj *exynos_gem_obj;
305 struct drm_gem_object *obj; 304 struct drm_gem_object *obj;
306 305
307 obj = drm_gem_object_lookup(dev, filp, gem_handle); 306 obj = drm_gem_object_lookup(dev, filp, gem_handle);
@@ -310,8 +309,6 @@ void exynos_drm_gem_put_dma_addr(struct drm_device *dev,
310 return; 309 return;
311 } 310 }
312 311
313 exynos_gem_obj = to_exynos_gem_obj(obj);
314
315 drm_gem_object_unreference_unlocked(obj); 312 drm_gem_object_unreference_unlocked(obj);
316 313
317 /* 314 /*
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index a1888e128f1d..c411399070d6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -129,9 +129,6 @@ void exynos_platform_device_ipp_unregister(void)
129 129
130int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv) 130int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
131{ 131{
132 if (!ippdrv)
133 return -EINVAL;
134
135 mutex_lock(&exynos_drm_ippdrv_lock); 132 mutex_lock(&exynos_drm_ippdrv_lock);
136 list_add_tail(&ippdrv->drv_list, &exynos_drm_ippdrv_list); 133 list_add_tail(&ippdrv->drv_list, &exynos_drm_ippdrv_list);
137 mutex_unlock(&exynos_drm_ippdrv_lock); 134 mutex_unlock(&exynos_drm_ippdrv_lock);
@@ -141,9 +138,6 @@ int exynos_drm_ippdrv_register(struct exynos_drm_ippdrv *ippdrv)
141 138
142int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv) 139int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
143{ 140{
144 if (!ippdrv)
145 return -EINVAL;
146
147 mutex_lock(&exynos_drm_ippdrv_lock); 141 mutex_lock(&exynos_drm_ippdrv_lock);
148 list_del(&ippdrv->drv_list); 142 list_del(&ippdrv->drv_list);
149 mutex_unlock(&exynos_drm_ippdrv_lock); 143 mutex_unlock(&exynos_drm_ippdrv_lock);
@@ -151,20 +145,15 @@ int exynos_drm_ippdrv_unregister(struct exynos_drm_ippdrv *ippdrv)
151 return 0; 145 return 0;
152} 146}
153 147
154static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj, 148static int ipp_create_id(struct idr *id_idr, struct mutex *lock, void *obj)
155 u32 *idp)
156{ 149{
157 int ret; 150 int ret;
158 151
159 /* do the allocation under our mutexlock */
160 mutex_lock(lock); 152 mutex_lock(lock);
161 ret = idr_alloc(id_idr, obj, 1, 0, GFP_KERNEL); 153 ret = idr_alloc(id_idr, obj, 1, 0, GFP_KERNEL);
162 mutex_unlock(lock); 154 mutex_unlock(lock);
163 if (ret < 0)
164 return ret;
165 155
166 *idp = ret; 156 return ret;
167 return 0;
168} 157}
169 158
170static void ipp_remove_id(struct idr *id_idr, struct mutex *lock, u32 id) 159static void ipp_remove_id(struct idr *id_idr, struct mutex *lock, u32 id)
@@ -178,35 +167,25 @@ static void *ipp_find_obj(struct idr *id_idr, struct mutex *lock, u32 id)
178{ 167{
179 void *obj; 168 void *obj;
180 169
181 DRM_DEBUG_KMS("id[%d]\n", id);
182
183 mutex_lock(lock); 170 mutex_lock(lock);
184
185 /* find object using handle */
186 obj = idr_find(id_idr, id); 171 obj = idr_find(id_idr, id);
187 if (!obj) {
188 DRM_ERROR("failed to find object.\n");
189 mutex_unlock(lock);
190 return ERR_PTR(-ENODEV);
191 }
192
193 mutex_unlock(lock); 172 mutex_unlock(lock);
194 173
195 return obj; 174 return obj;
196} 175}
197 176
198static inline bool ipp_check_dedicated(struct exynos_drm_ippdrv *ippdrv, 177static int ipp_check_driver(struct exynos_drm_ippdrv *ippdrv,
199 enum drm_exynos_ipp_cmd cmd) 178 struct drm_exynos_ipp_property *property)
200{ 179{
201 /* 180 if (ippdrv->dedicated || (!ipp_is_m2m_cmd(property->cmd) &&
202 * check dedicated flag and WB, OUTPUT operation with 181 !pm_runtime_suspended(ippdrv->dev)))
203 * power on state. 182 return -EBUSY;
204 */
205 if (ippdrv->dedicated || (!ipp_is_m2m_cmd(cmd) &&
206 !pm_runtime_suspended(ippdrv->dev)))
207 return true;
208 183
209 return false; 184 if (ippdrv->check_property &&
185 ippdrv->check_property(ippdrv->dev, property))
186 return -EINVAL;
187
188 return 0;
210} 189}
211 190
212static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx, 191static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
@@ -214,62 +193,30 @@ static struct exynos_drm_ippdrv *ipp_find_driver(struct ipp_context *ctx,
214{ 193{
215 struct exynos_drm_ippdrv *ippdrv; 194 struct exynos_drm_ippdrv *ippdrv;
216 u32 ipp_id = property->ipp_id; 195 u32 ipp_id = property->ipp_id;
217 196 int ret;
218 DRM_DEBUG_KMS("ipp_id[%d]\n", ipp_id);
219 197
220 if (ipp_id) { 198 if (ipp_id) {
221 /* find ipp driver using idr */ 199 ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock, ipp_id);
222 ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock, 200 if (!ippdrv) {
223 ipp_id); 201 DRM_DEBUG("ipp%d driver not found\n", ipp_id);
224 if (IS_ERR(ippdrv)) { 202 return ERR_PTR(-ENODEV);
225 DRM_ERROR("not found ipp%d driver.\n", ipp_id);
226 return ippdrv;
227 } 203 }
228 204
229 /* 205 ret = ipp_check_driver(ippdrv, property);
230 * WB, OUTPUT opertion not supported multi-operation. 206 if (ret < 0) {
231 * so, make dedicated state at set property ioctl. 207 DRM_DEBUG("ipp%d driver check error %d\n", ipp_id, ret);
232 * when ipp driver finished operations, clear dedicated flags. 208 return ERR_PTR(ret);
233 */
234 if (ipp_check_dedicated(ippdrv, property->cmd)) {
235 DRM_ERROR("already used choose device.\n");
236 return ERR_PTR(-EBUSY);
237 }
238
239 /*
240 * This is necessary to find correct device in ipp drivers.
241 * ipp drivers have different abilities,
242 * so need to check property.
243 */
244 if (ippdrv->check_property &&
245 ippdrv->check_property(ippdrv->dev, property)) {
246 DRM_ERROR("not support property.\n");
247 return ERR_PTR(-EINVAL);
248 } 209 }
249 210
250 return ippdrv; 211 return ippdrv;
251 } else { 212 } else {
252 /*
253 * This case is search all ipp driver for finding.
254 * user application don't set ipp_id in this case,
255 * so ipp subsystem search correct driver in driver list.
256 */
257 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { 213 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
258 if (ipp_check_dedicated(ippdrv, property->cmd)) { 214 ret = ipp_check_driver(ippdrv, property);
259 DRM_DEBUG_KMS("used device.\n"); 215 if (ret == 0)
260 continue; 216 return ippdrv;
261 }
262
263 if (ippdrv->check_property &&
264 ippdrv->check_property(ippdrv->dev, property)) {
265 DRM_DEBUG_KMS("not support property.\n");
266 continue;
267 }
268
269 return ippdrv;
270 } 217 }
271 218
272 DRM_ERROR("not support ipp driver operations.\n"); 219 DRM_DEBUG("cannot find driver suitable for given property.\n");
273 } 220 }
274 221
275 return ERR_PTR(-ENODEV); 222 return ERR_PTR(-ENODEV);
@@ -308,8 +255,7 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
308 struct drm_file *file) 255 struct drm_file *file)
309{ 256{
310 struct drm_exynos_file_private *file_priv = file->driver_priv; 257 struct drm_exynos_file_private *file_priv = file->driver_priv;
311 struct exynos_drm_ipp_private *priv = file_priv->ipp_priv; 258 struct device *dev = file_priv->ipp_dev;
312 struct device *dev = priv->dev;
313 struct ipp_context *ctx = get_ipp_context(dev); 259 struct ipp_context *ctx = get_ipp_context(dev);
314 struct drm_exynos_ipp_prop_list *prop_list = data; 260 struct drm_exynos_ipp_prop_list *prop_list = data;
315 struct exynos_drm_ippdrv *ippdrv; 261 struct exynos_drm_ippdrv *ippdrv;
@@ -346,10 +292,10 @@ int exynos_drm_ipp_get_property(struct drm_device *drm_dev, void *data,
346 */ 292 */
347 ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock, 293 ippdrv = ipp_find_obj(&ctx->ipp_idr, &ctx->ipp_lock,
348 prop_list->ipp_id); 294 prop_list->ipp_id);
349 if (IS_ERR(ippdrv)) { 295 if (!ippdrv) {
350 DRM_ERROR("not found ipp%d driver.\n", 296 DRM_ERROR("not found ipp%d driver.\n",
351 prop_list->ipp_id); 297 prop_list->ipp_id);
352 return PTR_ERR(ippdrv); 298 return -ENODEV;
353 } 299 }
354 300
355 *prop_list = ippdrv->prop_list; 301 *prop_list = ippdrv->prop_list;
@@ -432,7 +378,7 @@ static struct drm_exynos_ipp_event_work *ipp_create_event_work(void)
432 if (!event_work) 378 if (!event_work)
433 return ERR_PTR(-ENOMEM); 379 return ERR_PTR(-ENOMEM);
434 380
435 INIT_WORK((struct work_struct *)event_work, ipp_sched_event); 381 INIT_WORK(&event_work->work, ipp_sched_event);
436 382
437 return event_work; 383 return event_work;
438} 384}
@@ -441,8 +387,7 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
441 struct drm_file *file) 387 struct drm_file *file)
442{ 388{
443 struct drm_exynos_file_private *file_priv = file->driver_priv; 389 struct drm_exynos_file_private *file_priv = file->driver_priv;
444 struct exynos_drm_ipp_private *priv = file_priv->ipp_priv; 390 struct device *dev = file_priv->ipp_dev;
445 struct device *dev = priv->dev;
446 struct ipp_context *ctx = get_ipp_context(dev); 391 struct ipp_context *ctx = get_ipp_context(dev);
447 struct drm_exynos_ipp_property *property = data; 392 struct drm_exynos_ipp_property *property = data;
448 struct exynos_drm_ippdrv *ippdrv; 393 struct exynos_drm_ippdrv *ippdrv;
@@ -489,19 +434,18 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
489 if (!c_node) 434 if (!c_node)
490 return -ENOMEM; 435 return -ENOMEM;
491 436
492 /* create property id */ 437 ret = ipp_create_id(&ctx->prop_idr, &ctx->prop_lock, c_node);
493 ret = ipp_create_id(&ctx->prop_idr, &ctx->prop_lock, c_node, 438 if (ret < 0) {
494 &property->prop_id);
495 if (ret) {
496 DRM_ERROR("failed to create id.\n"); 439 DRM_ERROR("failed to create id.\n");
497 goto err_clear; 440 goto err_clear;
498 } 441 }
442 property->prop_id = ret;
499 443
500 DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[0x%x]\n", 444 DRM_DEBUG_KMS("created prop_id[%d]cmd[%d]ippdrv[0x%x]\n",
501 property->prop_id, property->cmd, (int)ippdrv); 445 property->prop_id, property->cmd, (int)ippdrv);
502 446
503 /* stored property information and ippdrv in private data */ 447 /* stored property information and ippdrv in private data */
504 c_node->priv = priv; 448 c_node->dev = dev;
505 c_node->property = *property; 449 c_node->property = *property;
506 c_node->state = IPP_STATE_IDLE; 450 c_node->state = IPP_STATE_IDLE;
507 451
@@ -534,7 +478,6 @@ int exynos_drm_ipp_set_property(struct drm_device *drm_dev, void *data,
534 INIT_LIST_HEAD(&c_node->mem_list[i]); 478 INIT_LIST_HEAD(&c_node->mem_list[i]);
535 479
536 INIT_LIST_HEAD(&c_node->event_list); 480 INIT_LIST_HEAD(&c_node->event_list);
537 list_splice_init(&priv->event_list, &c_node->event_list);
538 mutex_lock(&ippdrv->cmd_lock); 481 mutex_lock(&ippdrv->cmd_lock);
539 list_add_tail(&c_node->list, &ippdrv->cmd_list); 482 list_add_tail(&c_node->list, &ippdrv->cmd_list);
540 mutex_unlock(&ippdrv->cmd_lock); 483 mutex_unlock(&ippdrv->cmd_lock);
@@ -577,42 +520,18 @@ static void ipp_clean_cmd_node(struct ipp_context *ctx,
577 kfree(c_node); 520 kfree(c_node);
578} 521}
579 522
580static int ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node) 523static bool ipp_check_mem_list(struct drm_exynos_ipp_cmd_node *c_node)
581{ 524{
582 struct drm_exynos_ipp_property *property = &c_node->property; 525 switch (c_node->property.cmd) {
583 struct drm_exynos_ipp_mem_node *m_node; 526 case IPP_CMD_WB:
584 struct list_head *head; 527 return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_DST]);
585 int ret, i, count[EXYNOS_DRM_OPS_MAX] = { 0, }; 528 case IPP_CMD_OUTPUT:
586 529 return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_SRC]);
587 for_each_ipp_ops(i) { 530 case IPP_CMD_M2M:
588 /* source/destination memory list */ 531 default:
589 head = &c_node->mem_list[i]; 532 return !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_SRC]) &&
590 533 !list_empty(&c_node->mem_list[EXYNOS_DRM_OPS_DST]);
591 /* find memory node entry */
592 list_for_each_entry(m_node, head, list) {
593 DRM_DEBUG_KMS("%s,count[%d]m_node[0x%x]\n",
594 i ? "dst" : "src", count[i], (int)m_node);
595 count[i]++;
596 }
597 } 534 }
598
599 DRM_DEBUG_KMS("min[%d]max[%d]\n",
600 min(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]),
601 max(count[EXYNOS_DRM_OPS_SRC], count[EXYNOS_DRM_OPS_DST]));
602
603 /*
604 * M2M operations should be need paired memory address.
605 * so, need to check minimum count about src, dst.
606 * other case not use paired memory, so use maximum count
607 */
608 if (ipp_is_m2m_cmd(property->cmd))
609 ret = min(count[EXYNOS_DRM_OPS_SRC],
610 count[EXYNOS_DRM_OPS_DST]);
611 else
612 ret = max(count[EXYNOS_DRM_OPS_SRC],
613 count[EXYNOS_DRM_OPS_DST]);
614
615 return ret;
616} 535}
617 536
618static struct drm_exynos_ipp_mem_node 537static struct drm_exynos_ipp_mem_node
@@ -683,16 +602,14 @@ static struct drm_exynos_ipp_mem_node
683 struct drm_exynos_ipp_queue_buf *qbuf) 602 struct drm_exynos_ipp_queue_buf *qbuf)
684{ 603{
685 struct drm_exynos_ipp_mem_node *m_node; 604 struct drm_exynos_ipp_mem_node *m_node;
686 struct drm_exynos_ipp_buf_info buf_info; 605 struct drm_exynos_ipp_buf_info *buf_info;
687 void *addr;
688 int i; 606 int i;
689 607
690 m_node = kzalloc(sizeof(*m_node), GFP_KERNEL); 608 m_node = kzalloc(sizeof(*m_node), GFP_KERNEL);
691 if (!m_node) 609 if (!m_node)
692 return ERR_PTR(-ENOMEM); 610 return ERR_PTR(-ENOMEM);
693 611
694 /* clear base address for error handling */ 612 buf_info = &m_node->buf_info;
695 memset(&buf_info, 0x0, sizeof(buf_info));
696 613
697 /* operations, buffer id */ 614 /* operations, buffer id */
698 m_node->ops_id = qbuf->ops_id; 615 m_node->ops_id = qbuf->ops_id;
@@ -707,6 +624,8 @@ static struct drm_exynos_ipp_mem_node
707 624
708 /* get dma address by handle */ 625 /* get dma address by handle */
709 if (qbuf->handle[i]) { 626 if (qbuf->handle[i]) {
627 dma_addr_t *addr;
628
710 addr = exynos_drm_gem_get_dma_addr(drm_dev, 629 addr = exynos_drm_gem_get_dma_addr(drm_dev,
711 qbuf->handle[i], file); 630 qbuf->handle[i], file);
712 if (IS_ERR(addr)) { 631 if (IS_ERR(addr)) {
@@ -714,15 +633,14 @@ static struct drm_exynos_ipp_mem_node
714 goto err_clear; 633 goto err_clear;
715 } 634 }
716 635
717 buf_info.handles[i] = qbuf->handle[i]; 636 buf_info->handles[i] = qbuf->handle[i];
718 buf_info.base[i] = *(dma_addr_t *) addr; 637 buf_info->base[i] = *addr;
719 DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%x]\n", 638 DRM_DEBUG_KMS("i[%d]base[0x%x]hd[0x%lx]\n", i,
720 i, buf_info.base[i], (int)buf_info.handles[i]); 639 buf_info->base[i], buf_info->handles[i]);
721 } 640 }
722 } 641 }
723 642
724 m_node->filp = file; 643 m_node->filp = file;
725 m_node->buf_info = buf_info;
726 mutex_lock(&c_node->mem_lock); 644 mutex_lock(&c_node->mem_lock);
727 list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]); 645 list_add_tail(&m_node->list, &c_node->mem_list[qbuf->ops_id]);
728 mutex_unlock(&c_node->mem_lock); 646 mutex_unlock(&c_node->mem_lock);
@@ -930,8 +848,7 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
930 struct drm_file *file) 848 struct drm_file *file)
931{ 849{
932 struct drm_exynos_file_private *file_priv = file->driver_priv; 850 struct drm_exynos_file_private *file_priv = file->driver_priv;
933 struct exynos_drm_ipp_private *priv = file_priv->ipp_priv; 851 struct device *dev = file_priv->ipp_dev;
934 struct device *dev = priv->dev;
935 struct ipp_context *ctx = get_ipp_context(dev); 852 struct ipp_context *ctx = get_ipp_context(dev);
936 struct drm_exynos_ipp_queue_buf *qbuf = data; 853 struct drm_exynos_ipp_queue_buf *qbuf = data;
937 struct drm_exynos_ipp_cmd_node *c_node; 854 struct drm_exynos_ipp_cmd_node *c_node;
@@ -955,9 +872,9 @@ int exynos_drm_ipp_queue_buf(struct drm_device *drm_dev, void *data,
955 /* find command node */ 872 /* find command node */
956 c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock, 873 c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock,
957 qbuf->prop_id); 874 qbuf->prop_id);
958 if (IS_ERR(c_node)) { 875 if (!c_node) {
959 DRM_ERROR("failed to get command node.\n"); 876 DRM_ERROR("failed to get command node.\n");
960 return PTR_ERR(c_node); 877 return -ENODEV;
961 } 878 }
962 879
963 /* buffer control */ 880 /* buffer control */
@@ -1062,9 +979,8 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
1062 struct drm_file *file) 979 struct drm_file *file)
1063{ 980{
1064 struct drm_exynos_file_private *file_priv = file->driver_priv; 981 struct drm_exynos_file_private *file_priv = file->driver_priv;
1065 struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
1066 struct exynos_drm_ippdrv *ippdrv = NULL; 982 struct exynos_drm_ippdrv *ippdrv = NULL;
1067 struct device *dev = priv->dev; 983 struct device *dev = file_priv->ipp_dev;
1068 struct ipp_context *ctx = get_ipp_context(dev); 984 struct ipp_context *ctx = get_ipp_context(dev);
1069 struct drm_exynos_ipp_cmd_ctrl *cmd_ctrl = data; 985 struct drm_exynos_ipp_cmd_ctrl *cmd_ctrl = data;
1070 struct drm_exynos_ipp_cmd_work *cmd_work; 986 struct drm_exynos_ipp_cmd_work *cmd_work;
@@ -1091,9 +1007,9 @@ int exynos_drm_ipp_cmd_ctrl(struct drm_device *drm_dev, void *data,
1091 1007
1092 c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock, 1008 c_node = ipp_find_obj(&ctx->prop_idr, &ctx->prop_lock,
1093 cmd_ctrl->prop_id); 1009 cmd_ctrl->prop_id);
1094 if (IS_ERR(c_node)) { 1010 if (!c_node) {
1095 DRM_ERROR("invalid command node list.\n"); 1011 DRM_ERROR("invalid command node list.\n");
1096 return PTR_ERR(c_node); 1012 return -ENODEV;
1097 } 1013 }
1098 1014
1099 if (!exynos_drm_ipp_check_valid(ippdrv->dev, cmd_ctrl->ctrl, 1015 if (!exynos_drm_ipp_check_valid(ippdrv->dev, cmd_ctrl->ctrl,
@@ -1198,7 +1114,6 @@ static int ipp_set_property(struct exynos_drm_ippdrv *ippdrv,
1198 /* reset h/w block */ 1114 /* reset h/w block */
1199 if (ippdrv->reset && 1115 if (ippdrv->reset &&
1200 ippdrv->reset(ippdrv->dev)) { 1116 ippdrv->reset(ippdrv->dev)) {
1201 DRM_ERROR("failed to reset.\n");
1202 return -EINVAL; 1117 return -EINVAL;
1203 } 1118 }
1204 1119
@@ -1216,30 +1131,24 @@ static int ipp_set_property(struct exynos_drm_ippdrv *ippdrv,
1216 /* set format */ 1131 /* set format */
1217 if (ops->set_fmt) { 1132 if (ops->set_fmt) {
1218 ret = ops->set_fmt(ippdrv->dev, config->fmt); 1133 ret = ops->set_fmt(ippdrv->dev, config->fmt);
1219 if (ret) { 1134 if (ret)
1220 DRM_ERROR("not support format.\n");
1221 return ret; 1135 return ret;
1222 }
1223 } 1136 }
1224 1137
1225 /* set transform for rotation, flip */ 1138 /* set transform for rotation, flip */
1226 if (ops->set_transf) { 1139 if (ops->set_transf) {
1227 ret = ops->set_transf(ippdrv->dev, config->degree, 1140 ret = ops->set_transf(ippdrv->dev, config->degree,
1228 config->flip, &swap); 1141 config->flip, &swap);
1229 if (ret) { 1142 if (ret)
1230 DRM_ERROR("not support tranf.\n"); 1143 return ret;
1231 return -EINVAL;
1232 }
1233 } 1144 }
1234 1145
1235 /* set size */ 1146 /* set size */
1236 if (ops->set_size) { 1147 if (ops->set_size) {
1237 ret = ops->set_size(ippdrv->dev, swap, &config->pos, 1148 ret = ops->set_size(ippdrv->dev, swap, &config->pos,
1238 &config->sz); 1149 &config->sz);
1239 if (ret) { 1150 if (ret)
1240 DRM_ERROR("not support size.\n");
1241 return ret; 1151 return ret;
1242 }
1243 } 1152 }
1244 } 1153 }
1245 1154
@@ -1283,11 +1192,6 @@ static int ipp_start_property(struct exynos_drm_ippdrv *ippdrv,
1283 1192
1284 m_node = list_first_entry(head, 1193 m_node = list_first_entry(head,
1285 struct drm_exynos_ipp_mem_node, list); 1194 struct drm_exynos_ipp_mem_node, list);
1286 if (!m_node) {
1287 DRM_ERROR("failed to get node.\n");
1288 ret = -EFAULT;
1289 goto err_unlock;
1290 }
1291 1195
1292 DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node); 1196 DRM_DEBUG_KMS("m_node[0x%x]\n", (int)m_node);
1293 1197
@@ -1545,11 +1449,6 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
1545 1449
1546 m_node = list_first_entry(head, 1450 m_node = list_first_entry(head,
1547 struct drm_exynos_ipp_mem_node, list); 1451 struct drm_exynos_ipp_mem_node, list);
1548 if (!m_node) {
1549 DRM_ERROR("empty memory node.\n");
1550 ret = -ENOMEM;
1551 goto err_mem_unlock;
1552 }
1553 1452
1554 tbuf_id[i] = m_node->buf_id; 1453 tbuf_id[i] = m_node->buf_id;
1555 DRM_DEBUG_KMS("%s buf_id[%d]\n", 1454 DRM_DEBUG_KMS("%s buf_id[%d]\n",
@@ -1586,11 +1485,6 @@ static int ipp_send_event(struct exynos_drm_ippdrv *ippdrv,
1586 1485
1587 m_node = list_first_entry(head, 1486 m_node = list_first_entry(head,
1588 struct drm_exynos_ipp_mem_node, list); 1487 struct drm_exynos_ipp_mem_node, list);
1589 if (!m_node) {
1590 DRM_ERROR("empty memory node.\n");
1591 ret = -ENOMEM;
1592 goto err_mem_unlock;
1593 }
1594 1488
1595 tbuf_id[EXYNOS_DRM_OPS_SRC] = m_node->buf_id; 1489 tbuf_id[EXYNOS_DRM_OPS_SRC] = m_node->buf_id;
1596 1490
@@ -1704,21 +1598,17 @@ static int ipp_subdrv_probe(struct drm_device *drm_dev, struct device *dev)
1704 1598
1705 /* get ipp driver entry */ 1599 /* get ipp driver entry */
1706 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { 1600 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
1707 u32 ipp_id;
1708
1709 ippdrv->drm_dev = drm_dev; 1601 ippdrv->drm_dev = drm_dev;
1710 1602
1711 ret = ipp_create_id(&ctx->ipp_idr, &ctx->ipp_lock, ippdrv, 1603 ret = ipp_create_id(&ctx->ipp_idr, &ctx->ipp_lock, ippdrv);
1712 &ipp_id); 1604 if (ret < 0) {
1713 if (ret || ipp_id == 0) {
1714 DRM_ERROR("failed to create id.\n"); 1605 DRM_ERROR("failed to create id.\n");
1715 goto err; 1606 goto err;
1716 } 1607 }
1608 ippdrv->prop_list.ipp_id = ret;
1717 1609
1718 DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n", 1610 DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]ipp_id[%d]\n",
1719 count++, (int)ippdrv, ipp_id); 1611 count++, (int)ippdrv, ret);
1720
1721 ippdrv->prop_list.ipp_id = ipp_id;
1722 1612
1723 /* store parent device for node */ 1613 /* store parent device for node */
1724 ippdrv->parent_dev = dev; 1614 ippdrv->parent_dev = dev;
@@ -1776,17 +1666,10 @@ static int ipp_subdrv_open(struct drm_device *drm_dev, struct device *dev,
1776 struct drm_file *file) 1666 struct drm_file *file)
1777{ 1667{
1778 struct drm_exynos_file_private *file_priv = file->driver_priv; 1668 struct drm_exynos_file_private *file_priv = file->driver_priv;
1779 struct exynos_drm_ipp_private *priv;
1780
1781 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
1782 if (!priv)
1783 return -ENOMEM;
1784 priv->dev = dev;
1785 file_priv->ipp_priv = priv;
1786 1669
1787 INIT_LIST_HEAD(&priv->event_list); 1670 file_priv->ipp_dev = dev;
1788 1671
1789 DRM_DEBUG_KMS("done priv[0x%x]\n", (int)priv); 1672 DRM_DEBUG_KMS("done priv[0x%x]\n", (int)dev);
1790 1673
1791 return 0; 1674 return 0;
1792} 1675}
@@ -1795,13 +1678,12 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
1795 struct drm_file *file) 1678 struct drm_file *file)
1796{ 1679{
1797 struct drm_exynos_file_private *file_priv = file->driver_priv; 1680 struct drm_exynos_file_private *file_priv = file->driver_priv;
1798 struct exynos_drm_ipp_private *priv = file_priv->ipp_priv;
1799 struct exynos_drm_ippdrv *ippdrv = NULL; 1681 struct exynos_drm_ippdrv *ippdrv = NULL;
1800 struct ipp_context *ctx = get_ipp_context(dev); 1682 struct ipp_context *ctx = get_ipp_context(dev);
1801 struct drm_exynos_ipp_cmd_node *c_node, *tc_node; 1683 struct drm_exynos_ipp_cmd_node *c_node, *tc_node;
1802 int count = 0; 1684 int count = 0;
1803 1685
1804 DRM_DEBUG_KMS("for priv[0x%x]\n", (int)priv); 1686 DRM_DEBUG_KMS("for priv[0x%x]\n", (int)file_priv->ipp_dev);
1805 1687
1806 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) { 1688 list_for_each_entry(ippdrv, &exynos_drm_ippdrv_list, drv_list) {
1807 mutex_lock(&ippdrv->cmd_lock); 1689 mutex_lock(&ippdrv->cmd_lock);
@@ -1810,7 +1692,7 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
1810 DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n", 1692 DRM_DEBUG_KMS("count[%d]ippdrv[0x%x]\n",
1811 count++, (int)ippdrv); 1693 count++, (int)ippdrv);
1812 1694
1813 if (c_node->priv == priv) { 1695 if (c_node->dev == file_priv->ipp_dev) {
1814 /* 1696 /*
1815 * userland goto unnormal state. process killed. 1697 * userland goto unnormal state. process killed.
1816 * and close the file. 1698 * and close the file.
@@ -1832,7 +1714,6 @@ static void ipp_subdrv_close(struct drm_device *drm_dev, struct device *dev,
1832 mutex_unlock(&ippdrv->cmd_lock); 1714 mutex_unlock(&ippdrv->cmd_lock);
1833 } 1715 }
1834 1716
1835 kfree(priv);
1836 return; 1717 return;
1837} 1718}
1838 1719
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.h b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
index 7aaeaae757c2..6f48d62aeb30 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.h
@@ -48,7 +48,7 @@ struct drm_exynos_ipp_cmd_work {
48/* 48/*
49 * A structure of command node. 49 * A structure of command node.
50 * 50 *
51 * @priv: IPP private information. 51 * @dev: IPP device.
52 * @list: list head to command queue information. 52 * @list: list head to command queue information.
53 * @event_list: list head of event. 53 * @event_list: list head of event.
54 * @mem_list: list head to source,destination memory queue information. 54 * @mem_list: list head to source,destination memory queue information.
@@ -64,7 +64,7 @@ struct drm_exynos_ipp_cmd_work {
64 * @state: state of command node. 64 * @state: state of command node.
65 */ 65 */
66struct drm_exynos_ipp_cmd_node { 66struct drm_exynos_ipp_cmd_node {
67 struct exynos_drm_ipp_private *priv; 67 struct device *dev;
68 struct list_head list; 68 struct list_head list;
69 struct list_head event_list; 69 struct list_head event_list;
70 struct list_head mem_list[EXYNOS_DRM_OPS_MAX]; 70 struct list_head mem_list[EXYNOS_DRM_OPS_MAX];
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index f01fbb6dc1f0..55af6b41c1df 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -691,6 +691,7 @@ static const struct of_device_id exynos_rotator_match[] = {
691 }, 691 },
692 {}, 692 {},
693}; 693};
694MODULE_DEVICE_TABLE(of, exynos_rotator_match);
694 695
695static int rotator_probe(struct platform_device *pdev) 696static int rotator_probe(struct platform_device *pdev)
696{ 697{
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 81df11d57673..562966db2aa1 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -84,6 +84,7 @@ struct hdmi_resources {
84 struct clk *sclk_hdmiphy; 84 struct clk *sclk_hdmiphy;
85 struct clk *mout_hdmi; 85 struct clk *mout_hdmi;
86 struct regulator_bulk_data *regul_bulk; 86 struct regulator_bulk_data *regul_bulk;
87 struct regulator *reg_hdmi_en;
87 int regul_count; 88 int regul_count;
88}; 89};
89 90
@@ -592,6 +593,13 @@ static struct hdmi_driver_data exynos4212_hdmi_driver_data = {
592 .is_apb_phy = 0, 593 .is_apb_phy = 0,
593}; 594};
594 595
596static struct hdmi_driver_data exynos4210_hdmi_driver_data = {
597 .type = HDMI_TYPE13,
598 .phy_confs = hdmiphy_v13_configs,
599 .phy_conf_count = ARRAY_SIZE(hdmiphy_v13_configs),
600 .is_apb_phy = 0,
601};
602
595static struct hdmi_driver_data exynos5_hdmi_driver_data = { 603static struct hdmi_driver_data exynos5_hdmi_driver_data = {
596 .type = HDMI_TYPE14, 604 .type = HDMI_TYPE14,
597 .phy_confs = hdmiphy_v13_configs, 605 .phy_confs = hdmiphy_v13_configs,
@@ -1241,14 +1249,13 @@ static void hdmi_reg_acr(struct hdmi_context *hdata, u8 *acr)
1241 1249
1242static void hdmi_audio_init(struct hdmi_context *hdata) 1250static void hdmi_audio_init(struct hdmi_context *hdata)
1243{ 1251{
1244 u32 sample_rate, bits_per_sample, frame_size_code; 1252 u32 sample_rate, bits_per_sample;
1245 u32 data_num, bit_ch, sample_frq; 1253 u32 data_num, bit_ch, sample_frq;
1246 u32 val; 1254 u32 val;
1247 u8 acr[7]; 1255 u8 acr[7];
1248 1256
1249 sample_rate = 44100; 1257 sample_rate = 44100;
1250 bits_per_sample = 16; 1258 bits_per_sample = 16;
1251 frame_size_code = 0;
1252 1259
1253 switch (bits_per_sample) { 1260 switch (bits_per_sample) {
1254 case 20: 1261 case 20:
@@ -2168,7 +2175,6 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
2168 struct device *dev = hdata->dev; 2175 struct device *dev = hdata->dev;
2169 struct hdmi_resources *res = &hdata->res; 2176 struct hdmi_resources *res = &hdata->res;
2170 static char *supply[] = { 2177 static char *supply[] = {
2171 "hdmi-en",
2172 "vdd", 2178 "vdd",
2173 "vdd_osc", 2179 "vdd_osc",
2174 "vdd_pll", 2180 "vdd_pll",
@@ -2228,6 +2234,20 @@ static int hdmi_resources_init(struct hdmi_context *hdata)
2228 } 2234 }
2229 res->regul_count = ARRAY_SIZE(supply); 2235 res->regul_count = ARRAY_SIZE(supply);
2230 2236
2237 res->reg_hdmi_en = devm_regulator_get(dev, "hdmi-en");
2238 if (IS_ERR(res->reg_hdmi_en) && PTR_ERR(res->reg_hdmi_en) != -ENOENT) {
2239 DRM_ERROR("failed to get hdmi-en regulator\n");
2240 return PTR_ERR(res->reg_hdmi_en);
2241 }
2242 if (!IS_ERR(res->reg_hdmi_en)) {
2243 ret = regulator_enable(res->reg_hdmi_en);
2244 if (ret) {
2245 DRM_ERROR("failed to enable hdmi-en regulator\n");
2246 return ret;
2247 }
2248 } else
2249 res->reg_hdmi_en = NULL;
2250
2231 return ret; 2251 return ret;
2232fail: 2252fail:
2233 DRM_ERROR("HDMI resource init - failed\n"); 2253 DRM_ERROR("HDMI resource init - failed\n");
@@ -2263,6 +2283,9 @@ static struct of_device_id hdmi_match_types[] = {
2263 .compatible = "samsung,exynos5-hdmi", 2283 .compatible = "samsung,exynos5-hdmi",
2264 .data = &exynos5_hdmi_driver_data, 2284 .data = &exynos5_hdmi_driver_data,
2265 }, { 2285 }, {
2286 .compatible = "samsung,exynos4210-hdmi",
2287 .data = &exynos4210_hdmi_driver_data,
2288 }, {
2266 .compatible = "samsung,exynos4212-hdmi", 2289 .compatible = "samsung,exynos4212-hdmi",
2267 .data = &exynos4212_hdmi_driver_data, 2290 .data = &exynos4212_hdmi_driver_data,
2268 }, { 2291 }, {
@@ -2272,6 +2295,7 @@ static struct of_device_id hdmi_match_types[] = {
2272 /* end node */ 2295 /* end node */
2273 } 2296 }
2274}; 2297};
2298MODULE_DEVICE_TABLE (of, hdmi_match_types);
2275 2299
2276static int hdmi_bind(struct device *dev, struct device *master, void *data) 2300static int hdmi_bind(struct device *dev, struct device *master, void *data)
2277{ 2301{
@@ -2494,7 +2518,11 @@ static int hdmi_remove(struct platform_device *pdev)
2494 2518
2495 cancel_delayed_work_sync(&hdata->hotplug_work); 2519 cancel_delayed_work_sync(&hdata->hotplug_work);
2496 2520
2497 put_device(&hdata->hdmiphy_port->dev); 2521 if (hdata->res.reg_hdmi_en)
2522 regulator_disable(hdata->res.reg_hdmi_en);
2523
2524 if (hdata->hdmiphy_port)
2525 put_device(&hdata->hdmiphy_port->dev);
2498 put_device(&hdata->ddc_adpt->dev); 2526 put_device(&hdata->ddc_adpt->dev);
2499 2527
2500 pm_runtime_disable(&pdev->dev); 2528 pm_runtime_disable(&pdev->dev);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 7529946d0a74..e8b4ec84b312 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -76,7 +76,7 @@ struct mixer_resources {
76 struct clk *vp; 76 struct clk *vp;
77 struct clk *sclk_mixer; 77 struct clk *sclk_mixer;
78 struct clk *sclk_hdmi; 78 struct clk *sclk_hdmi;
79 struct clk *sclk_dac; 79 struct clk *mout_mixer;
80}; 80};
81 81
82enum mixer_version_id { 82enum mixer_version_id {
@@ -93,6 +93,7 @@ struct mixer_context {
93 bool interlace; 93 bool interlace;
94 bool powered; 94 bool powered;
95 bool vp_enabled; 95 bool vp_enabled;
96 bool has_sclk;
96 u32 int_en; 97 u32 int_en;
97 98
98 struct mutex mixer_mutex; 99 struct mutex mixer_mutex;
@@ -106,6 +107,7 @@ struct mixer_context {
106struct mixer_drv_data { 107struct mixer_drv_data {
107 enum mixer_version_id version; 108 enum mixer_version_id version;
108 bool is_vp_enabled; 109 bool is_vp_enabled;
110 bool has_sclk;
109}; 111};
110 112
111static const u8 filter_y_horiz_tap8[] = { 113static const u8 filter_y_horiz_tap8[] = {
@@ -363,6 +365,11 @@ static void mixer_cfg_layer(struct mixer_context *ctx, int win, bool enable)
363 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON); 365 vp_reg_writemask(res, VP_ENABLE, val, VP_ENABLE_ON);
364 mixer_reg_writemask(res, MXR_CFG, val, 366 mixer_reg_writemask(res, MXR_CFG, val,
365 MXR_CFG_VP_ENABLE); 367 MXR_CFG_VP_ENABLE);
368
369 /* control blending of graphic layer 0 */
370 mixer_reg_writemask(res, MXR_GRAPHIC_CFG(0), val,
371 MXR_GRP_CFG_BLEND_PRE_MUL |
372 MXR_GRP_CFG_PIXEL_BLEND_EN);
366 } 373 }
367 break; 374 break;
368 } 375 }
@@ -809,19 +816,23 @@ static int vp_resources_init(struct mixer_context *mixer_ctx)
809 dev_err(dev, "failed to get clock 'vp'\n"); 816 dev_err(dev, "failed to get clock 'vp'\n");
810 return -ENODEV; 817 return -ENODEV;
811 } 818 }
812 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
813 if (IS_ERR(mixer_res->sclk_mixer)) {
814 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
815 return -ENODEV;
816 }
817 mixer_res->sclk_dac = devm_clk_get(dev, "sclk_dac");
818 if (IS_ERR(mixer_res->sclk_dac)) {
819 dev_err(dev, "failed to get clock 'sclk_dac'\n");
820 return -ENODEV;
821 }
822 819
823 if (mixer_res->sclk_hdmi) 820 if (mixer_ctx->has_sclk) {
824 clk_set_parent(mixer_res->sclk_mixer, mixer_res->sclk_hdmi); 821 mixer_res->sclk_mixer = devm_clk_get(dev, "sclk_mixer");
822 if (IS_ERR(mixer_res->sclk_mixer)) {
823 dev_err(dev, "failed to get clock 'sclk_mixer'\n");
824 return -ENODEV;
825 }
826 mixer_res->mout_mixer = devm_clk_get(dev, "mout_mixer");
827 if (IS_ERR(mixer_res->mout_mixer)) {
828 dev_err(dev, "failed to get clock 'mout_mixer'\n");
829 return -ENODEV;
830 }
831
832 if (mixer_res->sclk_hdmi && mixer_res->mout_mixer)
833 clk_set_parent(mixer_res->mout_mixer,
834 mixer_res->sclk_hdmi);
835 }
825 836
826 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1); 837 res = platform_get_resource(mixer_ctx->pdev, IORESOURCE_MEM, 1);
827 if (res == NULL) { 838 if (res == NULL) {
@@ -1082,7 +1093,8 @@ static void mixer_poweron(struct exynos_drm_manager *mgr)
1082 clk_prepare_enable(res->mixer); 1093 clk_prepare_enable(res->mixer);
1083 if (ctx->vp_enabled) { 1094 if (ctx->vp_enabled) {
1084 clk_prepare_enable(res->vp); 1095 clk_prepare_enable(res->vp);
1085 clk_prepare_enable(res->sclk_mixer); 1096 if (ctx->has_sclk)
1097 clk_prepare_enable(res->sclk_mixer);
1086 } 1098 }
1087 1099
1088 mutex_lock(&ctx->mixer_mutex); 1100 mutex_lock(&ctx->mixer_mutex);
@@ -1121,7 +1133,8 @@ static void mixer_poweroff(struct exynos_drm_manager *mgr)
1121 clk_disable_unprepare(res->mixer); 1133 clk_disable_unprepare(res->mixer);
1122 if (ctx->vp_enabled) { 1134 if (ctx->vp_enabled) {
1123 clk_disable_unprepare(res->vp); 1135 clk_disable_unprepare(res->vp);
1124 clk_disable_unprepare(res->sclk_mixer); 1136 if (ctx->has_sclk)
1137 clk_disable_unprepare(res->sclk_mixer);
1125 } 1138 }
1126 1139
1127 pm_runtime_put_sync(ctx->dev); 1140 pm_runtime_put_sync(ctx->dev);
@@ -1189,9 +1202,15 @@ static struct mixer_drv_data exynos5250_mxr_drv_data = {
1189 .is_vp_enabled = 0, 1202 .is_vp_enabled = 0,
1190}; 1203};
1191 1204
1205static struct mixer_drv_data exynos4212_mxr_drv_data = {
1206 .version = MXR_VER_0_0_0_16,
1207 .is_vp_enabled = 1,
1208};
1209
1192static struct mixer_drv_data exynos4210_mxr_drv_data = { 1210static struct mixer_drv_data exynos4210_mxr_drv_data = {
1193 .version = MXR_VER_0_0_0_16, 1211 .version = MXR_VER_0_0_0_16,
1194 .is_vp_enabled = 1, 1212 .is_vp_enabled = 1,
1213 .has_sclk = 1,
1195}; 1214};
1196 1215
1197static struct platform_device_id mixer_driver_types[] = { 1216static struct platform_device_id mixer_driver_types[] = {
@@ -1208,6 +1227,12 @@ static struct platform_device_id mixer_driver_types[] = {
1208 1227
1209static struct of_device_id mixer_match_types[] = { 1228static struct of_device_id mixer_match_types[] = {
1210 { 1229 {
1230 .compatible = "samsung,exynos4210-mixer",
1231 .data = &exynos4210_mxr_drv_data,
1232 }, {
1233 .compatible = "samsung,exynos4212-mixer",
1234 .data = &exynos4212_mxr_drv_data,
1235 }, {
1211 .compatible = "samsung,exynos5-mixer", 1236 .compatible = "samsung,exynos5-mixer",
1212 .data = &exynos5250_mxr_drv_data, 1237 .data = &exynos5250_mxr_drv_data,
1213 }, { 1238 }, {
@@ -1220,6 +1245,7 @@ static struct of_device_id mixer_match_types[] = {
1220 /* end node */ 1245 /* end node */
1221 } 1246 }
1222}; 1247};
1248MODULE_DEVICE_TABLE(of, mixer_match_types);
1223 1249
1224static int mixer_bind(struct device *dev, struct device *manager, void *data) 1250static int mixer_bind(struct device *dev, struct device *manager, void *data)
1225{ 1251{
@@ -1251,6 +1277,7 @@ static int mixer_bind(struct device *dev, struct device *manager, void *data)
1251 ctx->pdev = pdev; 1277 ctx->pdev = pdev;
1252 ctx->dev = dev; 1278 ctx->dev = dev;
1253 ctx->vp_enabled = drv->is_vp_enabled; 1279 ctx->vp_enabled = drv->is_vp_enabled;
1280 ctx->has_sclk = drv->has_sclk;
1254 ctx->mxr_ver = drv->version; 1281 ctx->mxr_ver = drv->version;
1255 init_waitqueue_head(&ctx->wait_vsync_queue); 1282 init_waitqueue_head(&ctx->wait_vsync_queue);
1256 atomic_set(&ctx->wait_vsync_event, 0); 1283 atomic_set(&ctx->wait_vsync_event, 0);
diff --git a/include/video/samsung_fimd.h b/include/video/samsung_fimd.h
index b0393209679b..eaad58b5be4a 100644
--- a/include/video/samsung_fimd.h
+++ b/include/video/samsung_fimd.h
@@ -19,6 +19,7 @@
19/* VIDCON0 */ 19/* VIDCON0 */
20 20
21#define VIDCON0 0x00 21#define VIDCON0 0x00
22#define VIDCON0_DSI_EN (1 << 30)
22#define VIDCON0_INTERLACE (1 << 29) 23#define VIDCON0_INTERLACE (1 << 29)
23#define VIDCON0_VIDOUT_MASK (0x7 << 26) 24#define VIDCON0_VIDOUT_MASK (0x7 << 26)
24#define VIDCON0_VIDOUT_SHIFT 26 25#define VIDCON0_VIDOUT_SHIFT 26
@@ -355,7 +356,7 @@
355#define VIDINTCON0_INT_ENABLE (1 << 0) 356#define VIDINTCON0_INT_ENABLE (1 << 0)
356 357
357#define VIDINTCON1 0x134 358#define VIDINTCON1 0x134
358#define VIDINTCON1_INT_I180 (1 << 2) 359#define VIDINTCON1_INT_I80 (1 << 2)
359#define VIDINTCON1_INT_FRAME (1 << 1) 360#define VIDINTCON1_INT_FRAME (1 << 1)
360#define VIDINTCON1_INT_FIFO (1 << 0) 361#define VIDINTCON1_INT_FIFO (1 << 0)
361 362