diff options
author | Liu Ying <Ying.Liu@freescale.com> | 2014-03-11 02:41:02 -0400 |
---|---|---|
committer | Nitin Garg <nitin.garg@freescale.com> | 2014-04-16 09:57:57 -0400 |
commit | 697a4cf1e037b8f92515691223ecf79f8c2e67f5 (patch) | |
tree | 3d2d811d57fdc36d57b0e1e3eea416adecbe6d84 | |
parent | b8cc2d947d30dc68640d9b82cec6f68ec364b1c9 (diff) |
ENGR00302472-10 video: mxsfb: Add mxc disp driver support
This patch adds mxc display driver support for the mxsfb
driver so that it may interactive with encoder drivers.
Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
-rw-r--r-- | Documentation/devicetree/bindings/fb/mxsfb.txt | 15 | ||||
-rw-r--r-- | drivers/video/mxsfb.c | 70 |
2 files changed, 75 insertions, 10 deletions
diff --git a/Documentation/devicetree/bindings/fb/mxsfb.txt b/Documentation/devicetree/bindings/fb/mxsfb.txt index db41376d503e..9fdc0ee9aa24 100644 --- a/Documentation/devicetree/bindings/fb/mxsfb.txt +++ b/Documentation/devicetree/bindings/fb/mxsfb.txt | |||
@@ -3,21 +3,28 @@ | |||
3 | Required properties: | 3 | Required properties: |
4 | - compatible: Should be "fsl,<chip>-lcdif". Supported chips include | 4 | - compatible: Should be "fsl,<chip>-lcdif". Supported chips include |
5 | imx23 and imx28. | 5 | imx23 and imx28. |
6 | - pinctrl-names: Should be "default" | ||
7 | - pinctrl-0: pinctrl setting for lcd | ||
8 | - lcd-supply: lcd power supply, usually via GPIO | ||
9 | - reg: Address and length of the register set for lcdif | 6 | - reg: Address and length of the register set for lcdif |
10 | - interrupts: Should contain lcdif interrupts | 7 | - interrupts: Should contain lcdif interrupts |
11 | - display : phandle to display node (see below for details) | 8 | - display : phandle to display node (see below for details) |
12 | 9 | ||
10 | Optional sub-node: | ||
11 | These properties are required only when driving LCD panels directly: | ||
12 | - pinctrl-names: Should be "default" | ||
13 | - pinctrl-0: pinctrl setting for lcd | ||
14 | - lcd-supply: lcd power supply, usually via GPIO | ||
15 | |||
16 | This property is required only when driving LDB: | ||
17 | - disp-dev: Should be "ldb". | ||
18 | |||
13 | * display node | 19 | * display node |
14 | 20 | ||
15 | Required properties: | 21 | Required properties: |
16 | - bits-per-pixel : <16> for RGB565, <32> for RGB888/666. | 22 | - bits-per-pixel : <16> for RGB565, <32> for RGB888/666. |
17 | - bus-width : number of data lines. Could be <8>, <16>, <18> or <24>. | 23 | - bus-width : number of data lines. Could be <8>, <16>, <18> or <24>. |
18 | 24 | ||
19 | Required sub-node: | 25 | Optional sub-node: |
20 | - display-timings : Refer to binding doc display-timing.txt for details. | 26 | - display-timings : Refer to binding doc display-timing.txt for details. |
27 | This property is required only when driving LCD panels directly. | ||
21 | 28 | ||
22 | Examples: | 29 | Examples: |
23 | 30 | ||
diff --git a/drivers/video/mxsfb.c b/drivers/video/mxsfb.c index aeacadb996c0..e4d08e3fb4ad 100644 --- a/drivers/video/mxsfb.c +++ b/drivers/video/mxsfb.c | |||
@@ -57,6 +57,8 @@ | |||
57 | #include <video/of_display_timing.h> | 57 | #include <video/of_display_timing.h> |
58 | #include <video/videomode.h> | 58 | #include <video/videomode.h> |
59 | 59 | ||
60 | #include "mxc/mxc_dispdrv.h" | ||
61 | |||
60 | #define REG_SET 4 | 62 | #define REG_SET 4 |
61 | #define REG_CLR 8 | 63 | #define REG_CLR 8 |
62 | 64 | ||
@@ -204,6 +206,8 @@ struct mxsfb_info { | |||
204 | struct semaphore flip_sem; | 206 | struct semaphore flip_sem; |
205 | int cur_blank; | 207 | int cur_blank; |
206 | int restore_blank; | 208 | int restore_blank; |
209 | char disp_dev[32]; | ||
210 | struct mxc_dispdrv_handle *dispdrv; | ||
207 | }; | 211 | }; |
208 | 212 | ||
209 | #define mxsfb_is_v3(host) (host->devdata->ipversion == 3) | 213 | #define mxsfb_is_v3(host) (host->devdata->ipversion == 3) |
@@ -438,6 +442,15 @@ static void mxsfb_enable_controller(struct fb_info *fb_info) | |||
438 | 442 | ||
439 | dev_dbg(&host->pdev->dev, "%s\n", __func__); | 443 | dev_dbg(&host->pdev->dev, "%s\n", __func__); |
440 | 444 | ||
445 | if (host->dispdrv && host->dispdrv->drv->setup) { | ||
446 | ret = host->dispdrv->drv->setup(host->dispdrv, fb_info); | ||
447 | if (ret < 0) { | ||
448 | dev_err(&host->pdev->dev, "failed to setup" | ||
449 | "dispdrv:%s\n", host->dispdrv->drv->name); | ||
450 | return; | ||
451 | } | ||
452 | } | ||
453 | |||
441 | if (host->reg_lcd) { | 454 | if (host->reg_lcd) { |
442 | ret = regulator_enable(host->reg_lcd); | 455 | ret = regulator_enable(host->reg_lcd); |
443 | if (ret) { | 456 | if (ret) { |
@@ -476,6 +489,13 @@ static void mxsfb_enable_controller(struct fb_info *fb_info) | |||
476 | writel(CTRL1_RECOVERY_ON_UNDERFLOW, host->base + LCDC_CTRL1 + REG_SET); | 489 | writel(CTRL1_RECOVERY_ON_UNDERFLOW, host->base + LCDC_CTRL1 + REG_SET); |
477 | 490 | ||
478 | host->enabled = 1; | 491 | host->enabled = 1; |
492 | |||
493 | if (host->dispdrv && host->dispdrv->drv->enable) { | ||
494 | ret = host->dispdrv->drv->enable(host->dispdrv, fb_info); | ||
495 | if (ret < 0) | ||
496 | dev_err(&host->pdev->dev, "failed to enable " | ||
497 | "dispdrv:%s\n", host->dispdrv->drv->name); | ||
498 | } | ||
479 | } | 499 | } |
480 | 500 | ||
481 | static void mxsfb_disable_controller(struct fb_info *fb_info) | 501 | static void mxsfb_disable_controller(struct fb_info *fb_info) |
@@ -487,6 +507,9 @@ static void mxsfb_disable_controller(struct fb_info *fb_info) | |||
487 | 507 | ||
488 | dev_dbg(&host->pdev->dev, "%s\n", __func__); | 508 | dev_dbg(&host->pdev->dev, "%s\n", __func__); |
489 | 509 | ||
510 | if (host->dispdrv && host->dispdrv->drv->disable) | ||
511 | host->dispdrv->drv->disable(host->dispdrv, fb_info); | ||
512 | |||
490 | clk_enable_axi(host); | 513 | clk_enable_axi(host); |
491 | clk_enable_disp_axi(host); | 514 | clk_enable_disp_axi(host); |
492 | /* | 515 | /* |
@@ -954,6 +977,7 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host) | |||
954 | struct device_node *display_np; | 977 | struct device_node *display_np; |
955 | struct device_node *timings_np; | 978 | struct device_node *timings_np; |
956 | struct display_timings *timings; | 979 | struct display_timings *timings; |
980 | const char *disp_dev; | ||
957 | u32 width; | 981 | u32 width; |
958 | int i; | 982 | int i; |
959 | int ret = 0; | 983 | int ret = 0; |
@@ -996,6 +1020,13 @@ static int mxsfb_init_fbinfo_dt(struct mxsfb_info *host) | |||
996 | goto put_display_node; | 1020 | goto put_display_node; |
997 | } | 1021 | } |
998 | 1022 | ||
1023 | ret = of_property_read_string(np, "disp-dev", &disp_dev); | ||
1024 | if (!ret) { | ||
1025 | memcpy(host->disp_dev, disp_dev, strlen(disp_dev)); | ||
1026 | /* Timing is from encoder driver */ | ||
1027 | goto put_display_node; | ||
1028 | } | ||
1029 | |||
999 | timings = of_get_display_timings(display_np); | 1030 | timings = of_get_display_timings(display_np); |
1000 | if (!timings) { | 1031 | if (!timings) { |
1001 | dev_err(dev, "failed to get display timings\n"); | 1032 | dev_err(dev, "failed to get display timings\n"); |
@@ -1081,6 +1112,29 @@ static int mxsfb_init_fbinfo(struct mxsfb_info *host) | |||
1081 | return 0; | 1112 | return 0; |
1082 | } | 1113 | } |
1083 | 1114 | ||
1115 | static void mxsfb_dispdrv_init(struct platform_device *pdev, | ||
1116 | struct fb_info *fbi) | ||
1117 | { | ||
1118 | struct mxsfb_info *host = to_imxfb_host(fbi); | ||
1119 | struct mxc_dispdrv_setting setting; | ||
1120 | struct device *dev = &pdev->dev; | ||
1121 | char disp_dev[32]; | ||
1122 | |||
1123 | setting.fbi = fbi; | ||
1124 | memcpy(disp_dev, host->disp_dev, strlen(host->disp_dev)); | ||
1125 | disp_dev[strlen(host->disp_dev)] = '\0'; | ||
1126 | |||
1127 | host->dispdrv = mxc_dispdrv_gethandle(disp_dev, &setting); | ||
1128 | if (IS_ERR(host->dispdrv)) { | ||
1129 | host->dispdrv = NULL; | ||
1130 | dev_info(dev, "failed to find mxc display driver %s\n", | ||
1131 | disp_dev); | ||
1132 | } else { | ||
1133 | dev_info(dev, "registered mxc display driver %s\n", | ||
1134 | disp_dev); | ||
1135 | } | ||
1136 | } | ||
1137 | |||
1084 | static void mxsfb_free_videomem(struct mxsfb_info *host) | 1138 | static void mxsfb_free_videomem(struct mxsfb_info *host) |
1085 | { | 1139 | { |
1086 | struct fb_info *fb_info = &host->fb_info; | 1140 | struct fb_info *fb_info = &host->fb_info; |
@@ -1211,12 +1265,6 @@ static int mxsfb_probe(struct platform_device *pdev) | |||
1211 | 1265 | ||
1212 | host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data]; | 1266 | host->devdata = &mxsfb_devdata[pdev->id_entry->driver_data]; |
1213 | 1267 | ||
1214 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
1215 | if (IS_ERR(pinctrl)) { | ||
1216 | ret = PTR_ERR(pinctrl); | ||
1217 | goto fb_release; | ||
1218 | } | ||
1219 | |||
1220 | host->clk_pix = devm_clk_get(&host->pdev->dev, "pix"); | 1268 | host->clk_pix = devm_clk_get(&host->pdev->dev, "pix"); |
1221 | if (IS_ERR(host->clk_pix)) { | 1269 | if (IS_ERR(host->clk_pix)) { |
1222 | host->clk_pix = NULL; | 1270 | host->clk_pix = NULL; |
@@ -1257,6 +1305,16 @@ static int mxsfb_probe(struct platform_device *pdev) | |||
1257 | if (ret != 0) | 1305 | if (ret != 0) |
1258 | goto fb_pm_runtime_disable; | 1306 | goto fb_pm_runtime_disable; |
1259 | 1307 | ||
1308 | mxsfb_dispdrv_init(pdev, fb_info); | ||
1309 | |||
1310 | if (!host->dispdrv) { | ||
1311 | pinctrl = devm_pinctrl_get_select_default(&pdev->dev); | ||
1312 | if (IS_ERR(pinctrl)) { | ||
1313 | ret = PTR_ERR(pinctrl); | ||
1314 | goto fb_pm_runtime_disable; | ||
1315 | } | ||
1316 | } | ||
1317 | |||
1260 | platform_set_drvdata(pdev, fb_info); | 1318 | platform_set_drvdata(pdev, fb_info); |
1261 | 1319 | ||
1262 | if (!host->enabled) { | 1320 | if (!host->enabled) { |