diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 22:40:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-05-02 22:40:34 -0400 |
commit | 20a2078ce7705a6e0722ef5184336eb8657a58d8 (patch) | |
tree | 5b927c96516380aa0ecd68d8a609f7cd72120ad5 /drivers/video | |
parent | 0279b3c0ada1d78882f24acf94ac4595bd657a89 (diff) | |
parent | 307b9c022720f9de90d58e51743e01e9a42aec59 (diff) |
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie:
"This is the main drm pull request for 3.10.
Wierd bits:
- OMAP drm changes required OMAP dss changes, in drivers/video, so I
took them in here.
- one more fbcon fix for font handover
- VT switch avoidance in pm code
- scatterlist helpers for gpu drivers - have acks from akpm
Highlights:
- qxl kms driver - driver for the spice qxl virtual GPU
Nouveau:
- fermi/kepler VRAM compression
- GK110/nvf0 modesetting support.
Tegra:
- host1x core merged with 2D engine support
i915:
- vt switchless resume
- more valleyview support
- vblank fixes
- modesetting pipe config rework
radeon:
- UVD engine support
- SI chip tiling support
- GPU registers initialisation from golden values.
exynos:
- device tree changes
- fimc block support
Otherwise:
- bunches of fixes all over the place."
* 'drm-next' of git://people.freedesktop.org/~airlied/linux: (513 commits)
qxl: update to new idr interfaces.
drm/nouveau: fix build with nv50->nvc0
drm/radeon: fix handling of v6 power tables
drm/radeon: clarify family checks in pm table parsing
drm/radeon: consolidate UVD clock programming
drm/radeon: fix UPLL_REF_DIV_MASK definition
radeon: add bo tracking debugfs
drm/radeon: add new richland pci ids
drm/radeon: add some new SI PCI ids
drm/radeon: fix scratch reg handling for UVD fence
drm/radeon: allocate SA bo in the requested domain
drm/radeon: fix possible segfault when parsing pm tables
drm/radeon: fix endian bugs in atom_allocate_fb_scratch()
OMAPDSS: TFP410: return EPROBE_DEFER if the i2c adapter not found
OMAPDSS: VENC: Add error handling for venc_probe_pdata
OMAPDSS: HDMI: Add error handling for hdmi_probe_pdata
OMAPDSS: RFBI: Add error handling for rfbi_probe_pdata
OMAPDSS: DSI: Add error handling for dsi_probe_pdata
OMAPDSS: SDI: Add error handling for sdi_probe_pdata
OMAPDSS: DPI: Add error handling for dpi_probe_pdata
...
Diffstat (limited to 'drivers/video')
30 files changed, 1736 insertions, 1554 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 76be61701c97..ab5ba3d49e14 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig | |||
@@ -21,6 +21,8 @@ source "drivers/gpu/vga/Kconfig" | |||
21 | 21 | ||
22 | source "drivers/gpu/drm/Kconfig" | 22 | source "drivers/gpu/drm/Kconfig" |
23 | 23 | ||
24 | source "drivers/gpu/host1x/Kconfig" | ||
25 | |||
24 | config VGASTATE | 26 | config VGASTATE |
25 | tristate | 27 | tristate |
26 | default n | 28 | default n |
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c index 3cd675927826..a92783e480e6 100644 --- a/drivers/video/console/fbcon.c +++ b/drivers/video/console/fbcon.c | |||
@@ -1228,6 +1228,8 @@ static void fbcon_deinit(struct vc_data *vc) | |||
1228 | finished: | 1228 | finished: |
1229 | 1229 | ||
1230 | fbcon_free_font(p, free_font); | 1230 | fbcon_free_font(p, free_font); |
1231 | if (free_font) | ||
1232 | vc->vc_font.data = NULL; | ||
1231 | 1233 | ||
1232 | if (!con_is_bound(&fb_con)) | 1234 | if (!con_is_bound(&fb_con)) |
1233 | fbcon_exit(); | 1235 | fbcon_exit(); |
diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index dcb669eb4532..098bfc64cfb9 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c | |||
@@ -1639,6 +1639,11 @@ static int do_register_framebuffer(struct fb_info *fb_info) | |||
1639 | if (!fb_info->modelist.prev || !fb_info->modelist.next) | 1639 | if (!fb_info->modelist.prev || !fb_info->modelist.next) |
1640 | INIT_LIST_HEAD(&fb_info->modelist); | 1640 | INIT_LIST_HEAD(&fb_info->modelist); |
1641 | 1641 | ||
1642 | if (fb_info->skip_vt_switch) | ||
1643 | pm_vt_switch_required(fb_info->dev, false); | ||
1644 | else | ||
1645 | pm_vt_switch_required(fb_info->dev, true); | ||
1646 | |||
1642 | fb_var_to_videomode(&mode, &fb_info->var); | 1647 | fb_var_to_videomode(&mode, &fb_info->var); |
1643 | fb_add_videomode(&mode, &fb_info->modelist); | 1648 | fb_add_videomode(&mode, &fb_info->modelist); |
1644 | registered_fb[i] = fb_info; | 1649 | registered_fb[i] = fb_info; |
@@ -1673,6 +1678,8 @@ static int do_unregister_framebuffer(struct fb_info *fb_info) | |||
1673 | if (ret) | 1678 | if (ret) |
1674 | return -EINVAL; | 1679 | return -EINVAL; |
1675 | 1680 | ||
1681 | pm_vt_switch_unregister(fb_info->dev); | ||
1682 | |||
1676 | unlink_framebuffer(fb_info); | 1683 | unlink_framebuffer(fb_info); |
1677 | if (fb_info->pixmap.addr && | 1684 | if (fb_info->pixmap.addr && |
1678 | (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) | 1685 | (fb_info->pixmap.flags & FB_PIXMAP_DEFAULT)) |
diff --git a/drivers/video/hdmi.c b/drivers/video/hdmi.c index ab23c9b79143..40178338b619 100644 --- a/drivers/video/hdmi.c +++ b/drivers/video/hdmi.c | |||
@@ -1,9 +1,24 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2012 Avionic Design GmbH | 2 | * Copyright (C) 2012 Avionic Design GmbH |
3 | * | 3 | * |
4 | * This program is free software; you can redistribute it and/or modify | 4 | * Permission is hereby granted, free of charge, to any person obtaining a |
5 | * it under the terms of the GNU General Public License version 2 as | 5 | * copy of this software and associated documentation files (the "Software"), |
6 | * published by the Free Software Foundation. | 6 | * to deal in the Software without restriction, including without limitation |
7 | * the rights to use, copy, modify, merge, publish, distribute, sub license, | ||
8 | * and/or sell copies of the Software, and to permit persons to whom the | ||
9 | * Software is furnished to do so, subject to the following conditions: | ||
10 | * | ||
11 | * The above copyright notice and this permission notice (including the | ||
12 | * next paragraph) shall be included in all copies or substantial portions | ||
13 | * of the Software. | ||
14 | * | ||
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
17 | * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL | ||
18 | * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING | ||
20 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
21 | * DEALINGS IN THE SOFTWARE. | ||
7 | */ | 22 | */ |
8 | 23 | ||
9 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
diff --git a/drivers/video/omap2/Makefile b/drivers/video/omap2/Makefile index 5ea7cb9aed17..296e5c5281c5 100644 --- a/drivers/video/omap2/Makefile +++ b/drivers/video/omap2/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | obj-$(CONFIG_OMAP2_VRFB) += vrfb.o | 1 | obj-$(CONFIG_OMAP2_VRFB) += vrfb.o |
2 | 2 | ||
3 | obj-$(CONFIG_OMAP2_DSS) += dss/ | 3 | obj-$(CONFIG_OMAP2_DSS) += dss/ |
4 | obj-$(CONFIG_FB_OMAP2) += omapfb/ | ||
5 | obj-y += displays/ | 4 | obj-y += displays/ |
5 | obj-$(CONFIG_FB_OMAP2) += omapfb/ | ||
diff --git a/drivers/video/omap2/displays/panel-acx565akm.c b/drivers/video/omap2/displays/panel-acx565akm.c index 72699f88c002..d7f69c09ecf1 100644 --- a/drivers/video/omap2/displays/panel-acx565akm.c +++ b/drivers/video/omap2/displays/panel-acx565akm.c | |||
@@ -29,8 +29,10 @@ | |||
29 | #include <linux/sched.h> | 29 | #include <linux/sched.h> |
30 | #include <linux/backlight.h> | 30 | #include <linux/backlight.h> |
31 | #include <linux/fb.h> | 31 | #include <linux/fb.h> |
32 | #include <linux/gpio.h> | ||
32 | 33 | ||
33 | #include <video/omapdss.h> | 34 | #include <video/omapdss.h> |
35 | #include <video/omap-panel-data.h> | ||
34 | 36 | ||
35 | #define MIPID_CMD_READ_DISP_ID 0x04 | 37 | #define MIPID_CMD_READ_DISP_ID 0x04 |
36 | #define MIPID_CMD_READ_RED 0x06 | 38 | #define MIPID_CMD_READ_RED 0x06 |
@@ -336,8 +338,6 @@ static int acx565akm_bl_update_status(struct backlight_device *dev) | |||
336 | r = 0; | 338 | r = 0; |
337 | if (md->has_bc) | 339 | if (md->has_bc) |
338 | acx565akm_set_brightness(md, level); | 340 | acx565akm_set_brightness(md, level); |
339 | else if (md->dssdev->set_backlight) | ||
340 | r = md->dssdev->set_backlight(md->dssdev, level); | ||
341 | else | 341 | else |
342 | r = -ENODEV; | 342 | r = -ENODEV; |
343 | 343 | ||
@@ -352,7 +352,7 @@ static int acx565akm_bl_get_intensity(struct backlight_device *dev) | |||
352 | 352 | ||
353 | dev_dbg(&dev->dev, "%s\n", __func__); | 353 | dev_dbg(&dev->dev, "%s\n", __func__); |
354 | 354 | ||
355 | if (!md->has_bc && md->dssdev->set_backlight == NULL) | 355 | if (!md->has_bc) |
356 | return -ENODEV; | 356 | return -ENODEV; |
357 | 357 | ||
358 | if (dev->props.fb_blank == FB_BLANK_UNBLANK && | 358 | if (dev->props.fb_blank == FB_BLANK_UNBLANK && |
@@ -496,21 +496,38 @@ static struct omap_video_timings acx_panel_timings = { | |||
496 | .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, | 496 | .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, |
497 | }; | 497 | }; |
498 | 498 | ||
499 | static struct panel_acx565akm_data *get_panel_data(struct omap_dss_device *dssdev) | ||
500 | { | ||
501 | return (struct panel_acx565akm_data *) dssdev->data; | ||
502 | } | ||
503 | |||
499 | static int acx_panel_probe(struct omap_dss_device *dssdev) | 504 | static int acx_panel_probe(struct omap_dss_device *dssdev) |
500 | { | 505 | { |
501 | int r; | 506 | int r; |
502 | struct acx565akm_device *md = &acx_dev; | 507 | struct acx565akm_device *md = &acx_dev; |
508 | struct panel_acx565akm_data *panel_data = get_panel_data(dssdev); | ||
503 | struct backlight_device *bldev; | 509 | struct backlight_device *bldev; |
504 | int max_brightness, brightness; | 510 | int max_brightness, brightness; |
505 | struct backlight_properties props; | 511 | struct backlight_properties props; |
506 | 512 | ||
507 | dev_dbg(&dssdev->dev, "%s\n", __func__); | 513 | dev_dbg(&dssdev->dev, "%s\n", __func__); |
508 | 514 | ||
515 | if (!panel_data) | ||
516 | return -EINVAL; | ||
517 | |||
509 | /* FIXME AC bias ? */ | 518 | /* FIXME AC bias ? */ |
510 | dssdev->panel.timings = acx_panel_timings; | 519 | dssdev->panel.timings = acx_panel_timings; |
511 | 520 | ||
512 | if (dssdev->platform_enable) | 521 | if (gpio_is_valid(panel_data->reset_gpio)) { |
513 | dssdev->platform_enable(dssdev); | 522 | r = devm_gpio_request_one(&dssdev->dev, panel_data->reset_gpio, |
523 | GPIOF_OUT_INIT_LOW, "lcd reset"); | ||
524 | if (r) | ||
525 | return r; | ||
526 | } | ||
527 | |||
528 | if (gpio_is_valid(panel_data->reset_gpio)) | ||
529 | gpio_set_value(panel_data->reset_gpio, 1); | ||
530 | |||
514 | /* | 531 | /* |
515 | * After reset we have to wait 5 msec before the first | 532 | * After reset we have to wait 5 msec before the first |
516 | * command can be sent. | 533 | * command can be sent. |
@@ -522,8 +539,9 @@ static int acx_panel_probe(struct omap_dss_device *dssdev) | |||
522 | r = panel_detect(md); | 539 | r = panel_detect(md); |
523 | if (r) { | 540 | if (r) { |
524 | dev_err(&dssdev->dev, "%s panel detect error\n", __func__); | 541 | dev_err(&dssdev->dev, "%s panel detect error\n", __func__); |
525 | if (!md->enabled && dssdev->platform_disable) | 542 | if (!md->enabled && gpio_is_valid(panel_data->reset_gpio)) |
526 | dssdev->platform_disable(dssdev); | 543 | gpio_set_value(panel_data->reset_gpio, 0); |
544 | |||
527 | return r; | 545 | return r; |
528 | } | 546 | } |
529 | 547 | ||
@@ -532,8 +550,8 @@ static int acx_panel_probe(struct omap_dss_device *dssdev) | |||
532 | mutex_unlock(&acx_dev.mutex); | 550 | mutex_unlock(&acx_dev.mutex); |
533 | 551 | ||
534 | if (!md->enabled) { | 552 | if (!md->enabled) { |
535 | if (dssdev->platform_disable) | 553 | if (gpio_is_valid(panel_data->reset_gpio)) |
536 | dssdev->platform_disable(dssdev); | 554 | gpio_set_value(panel_data->reset_gpio, 0); |
537 | } | 555 | } |
538 | 556 | ||
539 | /*------- Backlight control --------*/ | 557 | /*------- Backlight control --------*/ |
@@ -557,15 +575,10 @@ static int acx_panel_probe(struct omap_dss_device *dssdev) | |||
557 | md->cabc_mode = get_hw_cabc_mode(md); | 575 | md->cabc_mode = get_hw_cabc_mode(md); |
558 | } | 576 | } |
559 | 577 | ||
560 | if (md->has_bc) | 578 | max_brightness = 255; |
561 | max_brightness = 255; | ||
562 | else | ||
563 | max_brightness = dssdev->max_backlight_level; | ||
564 | 579 | ||
565 | if (md->has_bc) | 580 | if (md->has_bc) |
566 | brightness = acx565akm_get_actual_brightness(md); | 581 | brightness = acx565akm_get_actual_brightness(md); |
567 | else if (dssdev->get_backlight) | ||
568 | brightness = dssdev->get_backlight(dssdev); | ||
569 | else | 582 | else |
570 | brightness = 0; | 583 | brightness = 0; |
571 | 584 | ||
@@ -591,6 +604,7 @@ static void acx_panel_remove(struct omap_dss_device *dssdev) | |||
591 | static int acx_panel_power_on(struct omap_dss_device *dssdev) | 604 | static int acx_panel_power_on(struct omap_dss_device *dssdev) |
592 | { | 605 | { |
593 | struct acx565akm_device *md = &acx_dev; | 606 | struct acx565akm_device *md = &acx_dev; |
607 | struct panel_acx565akm_data *panel_data = get_panel_data(dssdev); | ||
594 | int r; | 608 | int r; |
595 | 609 | ||
596 | dev_dbg(&dssdev->dev, "%s\n", __func__); | 610 | dev_dbg(&dssdev->dev, "%s\n", __func__); |
@@ -612,11 +626,8 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev) | |||
612 | /*FIXME tweak me */ | 626 | /*FIXME tweak me */ |
613 | msleep(50); | 627 | msleep(50); |
614 | 628 | ||
615 | if (dssdev->platform_enable) { | 629 | if (gpio_is_valid(panel_data->reset_gpio)) |
616 | r = dssdev->platform_enable(dssdev); | 630 | gpio_set_value(panel_data->reset_gpio, 1); |
617 | if (r) | ||
618 | goto fail; | ||
619 | } | ||
620 | 631 | ||
621 | if (md->enabled) { | 632 | if (md->enabled) { |
622 | dev_dbg(&md->spi->dev, "panel already enabled\n"); | 633 | dev_dbg(&md->spi->dev, "panel already enabled\n"); |
@@ -645,8 +656,7 @@ static int acx_panel_power_on(struct omap_dss_device *dssdev) | |||
645 | mutex_unlock(&md->mutex); | 656 | mutex_unlock(&md->mutex); |
646 | 657 | ||
647 | return acx565akm_bl_update_status(md->bl_dev); | 658 | return acx565akm_bl_update_status(md->bl_dev); |
648 | fail: | 659 | |
649 | omapdss_sdi_display_disable(dssdev); | ||
650 | fail_unlock: | 660 | fail_unlock: |
651 | mutex_unlock(&md->mutex); | 661 | mutex_unlock(&md->mutex); |
652 | return r; | 662 | return r; |
@@ -655,6 +665,7 @@ fail_unlock: | |||
655 | static void acx_panel_power_off(struct omap_dss_device *dssdev) | 665 | static void acx_panel_power_off(struct omap_dss_device *dssdev) |
656 | { | 666 | { |
657 | struct acx565akm_device *md = &acx_dev; | 667 | struct acx565akm_device *md = &acx_dev; |
668 | struct panel_acx565akm_data *panel_data = get_panel_data(dssdev); | ||
658 | 669 | ||
659 | dev_dbg(&dssdev->dev, "%s\n", __func__); | 670 | dev_dbg(&dssdev->dev, "%s\n", __func__); |
660 | 671 | ||
@@ -678,8 +689,8 @@ static void acx_panel_power_off(struct omap_dss_device *dssdev) | |||
678 | */ | 689 | */ |
679 | msleep(50); | 690 | msleep(50); |
680 | 691 | ||
681 | if (dssdev->platform_disable) | 692 | if (gpio_is_valid(panel_data->reset_gpio)) |
682 | dssdev->platform_disable(dssdev); | 693 | gpio_set_value(panel_data->reset_gpio, 0); |
683 | 694 | ||
684 | /* FIXME need to tweak this delay */ | 695 | /* FIXME need to tweak this delay */ |
685 | msleep(100); | 696 | msleep(100); |
diff --git a/drivers/video/omap2/displays/panel-generic-dpi.c b/drivers/video/omap2/displays/panel-generic-dpi.c index c904f42d81c1..97363f733683 100644 --- a/drivers/video/omap2/displays/panel-generic-dpi.c +++ b/drivers/video/omap2/displays/panel-generic-dpi.c | |||
@@ -33,9 +33,10 @@ | |||
33 | #include <linux/module.h> | 33 | #include <linux/module.h> |
34 | #include <linux/delay.h> | 34 | #include <linux/delay.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/gpio.h> | ||
36 | #include <video/omapdss.h> | 37 | #include <video/omapdss.h> |
37 | 38 | ||
38 | #include <video/omap-panel-generic-dpi.h> | 39 | #include <video/omap-panel-data.h> |
39 | 40 | ||
40 | struct panel_config { | 41 | struct panel_config { |
41 | struct omap_video_timings timings; | 42 | struct omap_video_timings timings; |
@@ -533,7 +534,7 @@ static inline struct panel_generic_dpi_data | |||
533 | 534 | ||
534 | static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev) | 535 | static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev) |
535 | { | 536 | { |
536 | int r; | 537 | int r, i; |
537 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); | 538 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); |
538 | struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); | 539 | struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); |
539 | struct panel_config *panel_config = drv_data->panel_config; | 540 | struct panel_config *panel_config = drv_data->panel_config; |
@@ -552,15 +553,13 @@ static int generic_dpi_panel_power_on(struct omap_dss_device *dssdev) | |||
552 | if (panel_config->power_on_delay) | 553 | if (panel_config->power_on_delay) |
553 | msleep(panel_config->power_on_delay); | 554 | msleep(panel_config->power_on_delay); |
554 | 555 | ||
555 | if (panel_data->platform_enable) { | 556 | for (i = 0; i < panel_data->num_gpios; ++i) { |
556 | r = panel_data->platform_enable(dssdev); | 557 | gpio_set_value_cansleep(panel_data->gpios[i], |
557 | if (r) | 558 | panel_data->gpio_invert[i] ? 0 : 1); |
558 | goto err1; | ||
559 | } | 559 | } |
560 | 560 | ||
561 | return 0; | 561 | return 0; |
562 | err1: | 562 | |
563 | omapdss_dpi_display_disable(dssdev); | ||
564 | err0: | 563 | err0: |
565 | return r; | 564 | return r; |
566 | } | 565 | } |
@@ -570,12 +569,15 @@ static void generic_dpi_panel_power_off(struct omap_dss_device *dssdev) | |||
570 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); | 569 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); |
571 | struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); | 570 | struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); |
572 | struct panel_config *panel_config = drv_data->panel_config; | 571 | struct panel_config *panel_config = drv_data->panel_config; |
572 | int i; | ||
573 | 573 | ||
574 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 574 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
575 | return; | 575 | return; |
576 | 576 | ||
577 | if (panel_data->platform_disable) | 577 | for (i = panel_data->num_gpios - 1; i >= 0; --i) { |
578 | panel_data->platform_disable(dssdev); | 578 | gpio_set_value_cansleep(panel_data->gpios[i], |
579 | panel_data->gpio_invert[i] ? 1 : 0); | ||
580 | } | ||
579 | 581 | ||
580 | /* wait couple of vsyncs after disabling the LCD */ | 582 | /* wait couple of vsyncs after disabling the LCD */ |
581 | if (panel_config->power_off_delay) | 583 | if (panel_config->power_off_delay) |
@@ -589,7 +591,7 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev) | |||
589 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); | 591 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); |
590 | struct panel_config *panel_config = NULL; | 592 | struct panel_config *panel_config = NULL; |
591 | struct panel_drv_data *drv_data = NULL; | 593 | struct panel_drv_data *drv_data = NULL; |
592 | int i; | 594 | int i, r; |
593 | 595 | ||
594 | dev_dbg(&dssdev->dev, "probe\n"); | 596 | dev_dbg(&dssdev->dev, "probe\n"); |
595 | 597 | ||
@@ -606,9 +608,18 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev) | |||
606 | if (!panel_config) | 608 | if (!panel_config) |
607 | return -EINVAL; | 609 | return -EINVAL; |
608 | 610 | ||
611 | for (i = 0; i < panel_data->num_gpios; ++i) { | ||
612 | r = devm_gpio_request_one(&dssdev->dev, panel_data->gpios[i], | ||
613 | panel_data->gpio_invert[i] ? | ||
614 | GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, | ||
615 | "panel gpio"); | ||
616 | if (r) | ||
617 | return r; | ||
618 | } | ||
619 | |||
609 | dssdev->panel.timings = panel_config->timings; | 620 | dssdev->panel.timings = panel_config->timings; |
610 | 621 | ||
611 | drv_data = kzalloc(sizeof(*drv_data), GFP_KERNEL); | 622 | drv_data = devm_kzalloc(&dssdev->dev, sizeof(*drv_data), GFP_KERNEL); |
612 | if (!drv_data) | 623 | if (!drv_data) |
613 | return -ENOMEM; | 624 | return -ENOMEM; |
614 | 625 | ||
@@ -624,12 +635,8 @@ static int generic_dpi_panel_probe(struct omap_dss_device *dssdev) | |||
624 | 635 | ||
625 | static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev) | 636 | static void __exit generic_dpi_panel_remove(struct omap_dss_device *dssdev) |
626 | { | 637 | { |
627 | struct panel_drv_data *drv_data = dev_get_drvdata(&dssdev->dev); | ||
628 | |||
629 | dev_dbg(&dssdev->dev, "remove\n"); | 638 | dev_dbg(&dssdev->dev, "remove\n"); |
630 | 639 | ||
631 | kfree(drv_data); | ||
632 | |||
633 | dev_set_drvdata(&dssdev->dev, NULL); | 640 | dev_set_drvdata(&dssdev->dev, NULL); |
634 | } | 641 | } |
635 | 642 | ||
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c index 6e5abe8fd2dd..4ea6548c0ae9 100644 --- a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c +++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c | |||
@@ -20,8 +20,10 @@ | |||
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/mutex.h> | 22 | #include <linux/mutex.h> |
23 | #include <linux/gpio.h> | ||
23 | 24 | ||
24 | #include <video/omapdss.h> | 25 | #include <video/omapdss.h> |
26 | #include <video/omap-panel-data.h> | ||
25 | 27 | ||
26 | struct lb035q02_data { | 28 | struct lb035q02_data { |
27 | struct mutex lock; | 29 | struct mutex lock; |
@@ -48,9 +50,16 @@ static struct omap_video_timings lb035q02_timings = { | |||
48 | .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, | 50 | .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, |
49 | }; | 51 | }; |
50 | 52 | ||
53 | static inline struct panel_generic_dpi_data | ||
54 | *get_panel_data(const struct omap_dss_device *dssdev) | ||
55 | { | ||
56 | return (struct panel_generic_dpi_data *) dssdev->data; | ||
57 | } | ||
58 | |||
51 | static int lb035q02_panel_power_on(struct omap_dss_device *dssdev) | 59 | static int lb035q02_panel_power_on(struct omap_dss_device *dssdev) |
52 | { | 60 | { |
53 | int r; | 61 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); |
62 | int r, i; | ||
54 | 63 | ||
55 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | 64 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) |
56 | return 0; | 65 | return 0; |
@@ -62,54 +71,65 @@ static int lb035q02_panel_power_on(struct omap_dss_device *dssdev) | |||
62 | if (r) | 71 | if (r) |
63 | goto err0; | 72 | goto err0; |
64 | 73 | ||
65 | if (dssdev->platform_enable) { | 74 | for (i = 0; i < panel_data->num_gpios; ++i) { |
66 | r = dssdev->platform_enable(dssdev); | 75 | gpio_set_value_cansleep(panel_data->gpios[i], |
67 | if (r) | 76 | panel_data->gpio_invert[i] ? 0 : 1); |
68 | goto err1; | ||
69 | } | 77 | } |
70 | 78 | ||
71 | return 0; | 79 | return 0; |
72 | err1: | 80 | |
73 | omapdss_dpi_display_disable(dssdev); | ||
74 | err0: | 81 | err0: |
75 | return r; | 82 | return r; |
76 | } | 83 | } |
77 | 84 | ||
78 | static void lb035q02_panel_power_off(struct omap_dss_device *dssdev) | 85 | static void lb035q02_panel_power_off(struct omap_dss_device *dssdev) |
79 | { | 86 | { |
87 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); | ||
88 | int i; | ||
89 | |||
80 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 90 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
81 | return; | 91 | return; |
82 | 92 | ||
83 | if (dssdev->platform_disable) | 93 | for (i = panel_data->num_gpios - 1; i >= 0; --i) { |
84 | dssdev->platform_disable(dssdev); | 94 | gpio_set_value_cansleep(panel_data->gpios[i], |
95 | panel_data->gpio_invert[i] ? 1 : 0); | ||
96 | } | ||
85 | 97 | ||
86 | omapdss_dpi_display_disable(dssdev); | 98 | omapdss_dpi_display_disable(dssdev); |
87 | } | 99 | } |
88 | 100 | ||
89 | static int lb035q02_panel_probe(struct omap_dss_device *dssdev) | 101 | static int lb035q02_panel_probe(struct omap_dss_device *dssdev) |
90 | { | 102 | { |
103 | struct panel_generic_dpi_data *panel_data = get_panel_data(dssdev); | ||
91 | struct lb035q02_data *ld; | 104 | struct lb035q02_data *ld; |
92 | int r; | 105 | int r, i; |
106 | |||
107 | if (!panel_data) | ||
108 | return -EINVAL; | ||
93 | 109 | ||
94 | dssdev->panel.timings = lb035q02_timings; | 110 | dssdev->panel.timings = lb035q02_timings; |
95 | 111 | ||
96 | ld = kzalloc(sizeof(*ld), GFP_KERNEL); | 112 | ld = devm_kzalloc(&dssdev->dev, sizeof(*ld), GFP_KERNEL); |
97 | if (!ld) { | 113 | if (!ld) |
98 | r = -ENOMEM; | 114 | return -ENOMEM; |
99 | goto err; | 115 | |
116 | for (i = 0; i < panel_data->num_gpios; ++i) { | ||
117 | r = devm_gpio_request_one(&dssdev->dev, panel_data->gpios[i], | ||
118 | panel_data->gpio_invert[i] ? | ||
119 | GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW, | ||
120 | "panel gpio"); | ||
121 | if (r) | ||
122 | return r; | ||
100 | } | 123 | } |
124 | |||
101 | mutex_init(&ld->lock); | 125 | mutex_init(&ld->lock); |
102 | dev_set_drvdata(&dssdev->dev, ld); | 126 | dev_set_drvdata(&dssdev->dev, ld); |
127 | |||
103 | return 0; | 128 | return 0; |
104 | err: | ||
105 | return r; | ||
106 | } | 129 | } |
107 | 130 | ||
108 | static void lb035q02_panel_remove(struct omap_dss_device *dssdev) | 131 | static void lb035q02_panel_remove(struct omap_dss_device *dssdev) |
109 | { | 132 | { |
110 | struct lb035q02_data *ld = dev_get_drvdata(&dssdev->dev); | ||
111 | |||
112 | kfree(ld); | ||
113 | } | 133 | } |
114 | 134 | ||
115 | static int lb035q02_panel_enable(struct omap_dss_device *dssdev) | 135 | static int lb035q02_panel_enable(struct omap_dss_device *dssdev) |
diff --git a/drivers/video/omap2/displays/panel-n8x0.c b/drivers/video/omap2/displays/panel-n8x0.c index dd1294750802..f94ead6a3183 100644 --- a/drivers/video/omap2/displays/panel-n8x0.c +++ b/drivers/video/omap2/displays/panel-n8x0.c | |||
@@ -5,11 +5,10 @@ | |||
5 | #include <linux/slab.h> | 5 | #include <linux/slab.h> |
6 | #include <linux/gpio.h> | 6 | #include <linux/gpio.h> |
7 | #include <linux/spi/spi.h> | 7 | #include <linux/spi/spi.h> |
8 | #include <linux/backlight.h> | ||
9 | #include <linux/fb.h> | 8 | #include <linux/fb.h> |
10 | 9 | ||
11 | #include <video/omapdss.h> | 10 | #include <video/omapdss.h> |
12 | #include <video/omap-panel-n8x0.h> | 11 | #include <video/omap-panel-data.h> |
13 | 12 | ||
14 | #define BLIZZARD_REV_CODE 0x00 | 13 | #define BLIZZARD_REV_CODE 0x00 |
15 | #define BLIZZARD_CONFIG 0x02 | 14 | #define BLIZZARD_CONFIG 0x02 |
@@ -69,7 +68,6 @@ static struct panel_drv_data { | |||
69 | 68 | ||
70 | struct omap_dss_device *dssdev; | 69 | struct omap_dss_device *dssdev; |
71 | struct spi_device *spidev; | 70 | struct spi_device *spidev; |
72 | struct backlight_device *bldev; | ||
73 | 71 | ||
74 | int blizzard_ver; | 72 | int blizzard_ver; |
75 | } s_drv_data; | 73 | } s_drv_data; |
@@ -297,12 +295,6 @@ static int n8x0_panel_power_on(struct omap_dss_device *dssdev) | |||
297 | 295 | ||
298 | gpio_direction_output(bdata->ctrl_pwrdown, 1); | 296 | gpio_direction_output(bdata->ctrl_pwrdown, 1); |
299 | 297 | ||
300 | if (bdata->platform_enable) { | ||
301 | r = bdata->platform_enable(dssdev); | ||
302 | if (r) | ||
303 | goto err_plat_en; | ||
304 | } | ||
305 | |||
306 | omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res, | 298 | omapdss_rfbi_set_size(dssdev, dssdev->panel.timings.x_res, |
307 | dssdev->panel.timings.y_res); | 299 | dssdev->panel.timings.y_res); |
308 | omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size); | 300 | omapdss_rfbi_set_pixel_size(dssdev, dssdev->ctrl.pixel_size); |
@@ -375,9 +367,6 @@ err_inv_panel: | |||
375 | err_inv_chip: | 367 | err_inv_chip: |
376 | omapdss_rfbi_display_disable(dssdev); | 368 | omapdss_rfbi_display_disable(dssdev); |
377 | err_rfbi_en: | 369 | err_rfbi_en: |
378 | if (bdata->platform_disable) | ||
379 | bdata->platform_disable(dssdev); | ||
380 | err_plat_en: | ||
381 | gpio_direction_output(bdata->ctrl_pwrdown, 0); | 370 | gpio_direction_output(bdata->ctrl_pwrdown, 0); |
382 | return r; | 371 | return r; |
383 | } | 372 | } |
@@ -394,9 +383,6 @@ static void n8x0_panel_power_off(struct omap_dss_device *dssdev) | |||
394 | send_display_off(spi); | 383 | send_display_off(spi); |
395 | send_sleep_in(spi); | 384 | send_sleep_in(spi); |
396 | 385 | ||
397 | if (bdata->platform_disable) | ||
398 | bdata->platform_disable(dssdev); | ||
399 | |||
400 | /* | 386 | /* |
401 | * HACK: we should turn off the panel here, but there is some problem | 387 | * HACK: we should turn off the panel here, but there is some problem |
402 | * with the initialization sequence, and we fail to init the panel if we | 388 | * with the initialization sequence, and we fail to init the panel if we |
@@ -424,54 +410,10 @@ static const struct rfbi_timings n8x0_panel_timings = { | |||
424 | .cs_pulse_width = 0, | 410 | .cs_pulse_width = 0, |
425 | }; | 411 | }; |
426 | 412 | ||
427 | static int n8x0_bl_update_status(struct backlight_device *dev) | ||
428 | { | ||
429 | struct omap_dss_device *dssdev = dev_get_drvdata(&dev->dev); | ||
430 | struct panel_n8x0_data *bdata = get_board_data(dssdev); | ||
431 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
432 | int r; | ||
433 | int level; | ||
434 | |||
435 | mutex_lock(&ddata->lock); | ||
436 | |||
437 | if (dev->props.fb_blank == FB_BLANK_UNBLANK && | ||
438 | dev->props.power == FB_BLANK_UNBLANK) | ||
439 | level = dev->props.brightness; | ||
440 | else | ||
441 | level = 0; | ||
442 | |||
443 | dev_dbg(&dssdev->dev, "update brightness to %d\n", level); | ||
444 | |||
445 | if (!bdata->set_backlight) | ||
446 | r = -EINVAL; | ||
447 | else | ||
448 | r = bdata->set_backlight(dssdev, level); | ||
449 | |||
450 | mutex_unlock(&ddata->lock); | ||
451 | |||
452 | return r; | ||
453 | } | ||
454 | |||
455 | static int n8x0_bl_get_intensity(struct backlight_device *dev) | ||
456 | { | ||
457 | if (dev->props.fb_blank == FB_BLANK_UNBLANK && | ||
458 | dev->props.power == FB_BLANK_UNBLANK) | ||
459 | return dev->props.brightness; | ||
460 | |||
461 | return 0; | ||
462 | } | ||
463 | |||
464 | static const struct backlight_ops n8x0_bl_ops = { | ||
465 | .get_brightness = n8x0_bl_get_intensity, | ||
466 | .update_status = n8x0_bl_update_status, | ||
467 | }; | ||
468 | |||
469 | static int n8x0_panel_probe(struct omap_dss_device *dssdev) | 413 | static int n8x0_panel_probe(struct omap_dss_device *dssdev) |
470 | { | 414 | { |
471 | struct panel_n8x0_data *bdata = get_board_data(dssdev); | 415 | struct panel_n8x0_data *bdata = get_board_data(dssdev); |
472 | struct panel_drv_data *ddata; | 416 | struct panel_drv_data *ddata; |
473 | struct backlight_device *bldev; | ||
474 | struct backlight_properties props; | ||
475 | int r; | 417 | int r; |
476 | 418 | ||
477 | dev_dbg(&dssdev->dev, "probe\n"); | 419 | dev_dbg(&dssdev->dev, "probe\n"); |
@@ -491,40 +433,27 @@ static int n8x0_panel_probe(struct omap_dss_device *dssdev) | |||
491 | dssdev->ctrl.rfbi_timings = n8x0_panel_timings; | 433 | dssdev->ctrl.rfbi_timings = n8x0_panel_timings; |
492 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; | 434 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE; |
493 | 435 | ||
494 | memset(&props, 0, sizeof(props)); | 436 | if (gpio_is_valid(bdata->panel_reset)) { |
495 | props.max_brightness = 127; | 437 | r = devm_gpio_request_one(&dssdev->dev, bdata->panel_reset, |
496 | props.type = BACKLIGHT_PLATFORM; | 438 | GPIOF_OUT_INIT_LOW, "PANEL RESET"); |
497 | bldev = backlight_device_register(dev_name(&dssdev->dev), &dssdev->dev, | 439 | if (r) |
498 | dssdev, &n8x0_bl_ops, &props); | 440 | return r; |
499 | if (IS_ERR(bldev)) { | ||
500 | r = PTR_ERR(bldev); | ||
501 | dev_err(&dssdev->dev, "register backlight failed\n"); | ||
502 | return r; | ||
503 | } | 441 | } |
504 | 442 | ||
505 | ddata->bldev = bldev; | 443 | if (gpio_is_valid(bdata->ctrl_pwrdown)) { |
506 | 444 | r = devm_gpio_request_one(&dssdev->dev, bdata->ctrl_pwrdown, | |
507 | bldev->props.fb_blank = FB_BLANK_UNBLANK; | 445 | GPIOF_OUT_INIT_LOW, "PANEL PWRDOWN"); |
508 | bldev->props.power = FB_BLANK_UNBLANK; | 446 | if (r) |
509 | bldev->props.brightness = 127; | 447 | return r; |
510 | 448 | } | |
511 | n8x0_bl_update_status(bldev); | ||
512 | 449 | ||
513 | return 0; | 450 | return 0; |
514 | } | 451 | } |
515 | 452 | ||
516 | static void n8x0_panel_remove(struct omap_dss_device *dssdev) | 453 | static void n8x0_panel_remove(struct omap_dss_device *dssdev) |
517 | { | 454 | { |
518 | struct panel_drv_data *ddata = get_drv_data(dssdev); | ||
519 | struct backlight_device *bldev; | ||
520 | |||
521 | dev_dbg(&dssdev->dev, "remove\n"); | 455 | dev_dbg(&dssdev->dev, "remove\n"); |
522 | 456 | ||
523 | bldev = ddata->bldev; | ||
524 | bldev->props.power = FB_BLANK_POWERDOWN; | ||
525 | n8x0_bl_update_status(bldev); | ||
526 | backlight_device_unregister(bldev); | ||
527 | |||
528 | dev_set_drvdata(&dssdev->dev, NULL); | 457 | dev_set_drvdata(&dssdev->dev, NULL); |
529 | } | 458 | } |
530 | 459 | ||
diff --git a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c index c4e9c2b1b465..20c3cd91ff9b 100644 --- a/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c +++ b/drivers/video/omap2/displays/panel-nec-nl8048hl11-01b.c | |||
@@ -19,10 +19,11 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/delay.h> | 20 | #include <linux/delay.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/backlight.h> | ||
23 | #include <linux/fb.h> | 22 | #include <linux/fb.h> |
23 | #include <linux/gpio.h> | ||
24 | 24 | ||
25 | #include <video/omapdss.h> | 25 | #include <video/omapdss.h> |
26 | #include <video/omap-panel-data.h> | ||
26 | 27 | ||
27 | #define LCD_XRES 800 | 28 | #define LCD_XRES 800 |
28 | #define LCD_YRES 480 | 29 | #define LCD_YRES 480 |
@@ -32,10 +33,6 @@ | |||
32 | */ | 33 | */ |
33 | #define LCD_PIXEL_CLOCK 23800 | 34 | #define LCD_PIXEL_CLOCK 23800 |
34 | 35 | ||
35 | struct nec_8048_data { | ||
36 | struct backlight_device *bl; | ||
37 | }; | ||
38 | |||
39 | static const struct { | 36 | static const struct { |
40 | unsigned char addr; | 37 | unsigned char addr; |
41 | unsigned char dat; | 38 | unsigned char dat; |
@@ -84,93 +81,47 @@ static struct omap_video_timings nec_8048_panel_timings = { | |||
84 | .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, | 81 | .sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE, |
85 | }; | 82 | }; |
86 | 83 | ||
87 | static int nec_8048_bl_update_status(struct backlight_device *bl) | 84 | static inline struct panel_nec_nl8048_data |
88 | { | 85 | *get_panel_data(const struct omap_dss_device *dssdev) |
89 | struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev); | ||
90 | int level; | ||
91 | |||
92 | if (!dssdev->set_backlight) | ||
93 | return -EINVAL; | ||
94 | |||
95 | if (bl->props.fb_blank == FB_BLANK_UNBLANK && | ||
96 | bl->props.power == FB_BLANK_UNBLANK) | ||
97 | level = bl->props.brightness; | ||
98 | else | ||
99 | level = 0; | ||
100 | |||
101 | return dssdev->set_backlight(dssdev, level); | ||
102 | } | ||
103 | |||
104 | static int nec_8048_bl_get_brightness(struct backlight_device *bl) | ||
105 | { | 86 | { |
106 | if (bl->props.fb_blank == FB_BLANK_UNBLANK && | 87 | return (struct panel_nec_nl8048_data *) dssdev->data; |
107 | bl->props.power == FB_BLANK_UNBLANK) | ||
108 | return bl->props.brightness; | ||
109 | |||
110 | return 0; | ||
111 | } | 88 | } |
112 | 89 | ||
113 | static const struct backlight_ops nec_8048_bl_ops = { | ||
114 | .get_brightness = nec_8048_bl_get_brightness, | ||
115 | .update_status = nec_8048_bl_update_status, | ||
116 | }; | ||
117 | |||
118 | static int nec_8048_panel_probe(struct omap_dss_device *dssdev) | 90 | static int nec_8048_panel_probe(struct omap_dss_device *dssdev) |
119 | { | 91 | { |
120 | struct backlight_device *bl; | 92 | struct panel_nec_nl8048_data *pd = get_panel_data(dssdev); |
121 | struct nec_8048_data *necd; | ||
122 | struct backlight_properties props; | ||
123 | int r; | 93 | int r; |
124 | 94 | ||
125 | dssdev->panel.timings = nec_8048_panel_timings; | 95 | if (!pd) |
126 | 96 | return -EINVAL; | |
127 | necd = kzalloc(sizeof(*necd), GFP_KERNEL); | ||
128 | if (!necd) | ||
129 | return -ENOMEM; | ||
130 | |||
131 | dev_set_drvdata(&dssdev->dev, necd); | ||
132 | 97 | ||
133 | memset(&props, 0, sizeof(struct backlight_properties)); | 98 | dssdev->panel.timings = nec_8048_panel_timings; |
134 | props.max_brightness = 255; | ||
135 | 99 | ||
136 | bl = backlight_device_register("nec-8048", &dssdev->dev, dssdev, | 100 | if (gpio_is_valid(pd->qvga_gpio)) { |
137 | &nec_8048_bl_ops, &props); | 101 | r = devm_gpio_request_one(&dssdev->dev, pd->qvga_gpio, |
138 | if (IS_ERR(bl)) { | 102 | GPIOF_OUT_INIT_HIGH, "lcd QVGA"); |
139 | r = PTR_ERR(bl); | 103 | if (r) |
140 | kfree(necd); | 104 | return r; |
141 | return r; | ||
142 | } | 105 | } |
143 | necd->bl = bl; | ||
144 | |||
145 | bl->props.fb_blank = FB_BLANK_UNBLANK; | ||
146 | bl->props.power = FB_BLANK_UNBLANK; | ||
147 | bl->props.max_brightness = dssdev->max_backlight_level; | ||
148 | bl->props.brightness = dssdev->max_backlight_level; | ||
149 | 106 | ||
150 | r = nec_8048_bl_update_status(bl); | 107 | if (gpio_is_valid(pd->res_gpio)) { |
151 | if (r < 0) | 108 | r = devm_gpio_request_one(&dssdev->dev, pd->res_gpio, |
152 | dev_err(&dssdev->dev, "failed to set lcd brightness\n"); | 109 | GPIOF_OUT_INIT_LOW, "lcd RES"); |
110 | if (r) | ||
111 | return r; | ||
112 | } | ||
153 | 113 | ||
154 | return 0; | 114 | return 0; |
155 | } | 115 | } |
156 | 116 | ||
157 | static void nec_8048_panel_remove(struct omap_dss_device *dssdev) | 117 | static void nec_8048_panel_remove(struct omap_dss_device *dssdev) |
158 | { | 118 | { |
159 | struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); | ||
160 | struct backlight_device *bl = necd->bl; | ||
161 | |||
162 | bl->props.power = FB_BLANK_POWERDOWN; | ||
163 | nec_8048_bl_update_status(bl); | ||
164 | backlight_device_unregister(bl); | ||
165 | |||
166 | kfree(necd); | ||
167 | } | 119 | } |
168 | 120 | ||
169 | static int nec_8048_panel_power_on(struct omap_dss_device *dssdev) | 121 | static int nec_8048_panel_power_on(struct omap_dss_device *dssdev) |
170 | { | 122 | { |
123 | struct panel_nec_nl8048_data *pd = get_panel_data(dssdev); | ||
171 | int r; | 124 | int r; |
172 | struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); | ||
173 | struct backlight_device *bl = necd->bl; | ||
174 | 125 | ||
175 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | 126 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) |
176 | return 0; | 127 | return 0; |
@@ -182,36 +133,24 @@ static int nec_8048_panel_power_on(struct omap_dss_device *dssdev) | |||
182 | if (r) | 133 | if (r) |
183 | goto err0; | 134 | goto err0; |
184 | 135 | ||
185 | if (dssdev->platform_enable) { | 136 | if (gpio_is_valid(pd->res_gpio)) |
186 | r = dssdev->platform_enable(dssdev); | 137 | gpio_set_value_cansleep(pd->res_gpio, 1); |
187 | if (r) | ||
188 | goto err1; | ||
189 | } | ||
190 | |||
191 | r = nec_8048_bl_update_status(bl); | ||
192 | if (r < 0) | ||
193 | dev_err(&dssdev->dev, "failed to set lcd brightness\n"); | ||
194 | 138 | ||
195 | return 0; | 139 | return 0; |
196 | err1: | 140 | |
197 | omapdss_dpi_display_disable(dssdev); | ||
198 | err0: | 141 | err0: |
199 | return r; | 142 | return r; |
200 | } | 143 | } |
201 | 144 | ||
202 | static void nec_8048_panel_power_off(struct omap_dss_device *dssdev) | 145 | static void nec_8048_panel_power_off(struct omap_dss_device *dssdev) |
203 | { | 146 | { |
204 | struct nec_8048_data *necd = dev_get_drvdata(&dssdev->dev); | 147 | struct panel_nec_nl8048_data *pd = get_panel_data(dssdev); |
205 | struct backlight_device *bl = necd->bl; | ||
206 | 148 | ||
207 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 149 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
208 | return; | 150 | return; |
209 | 151 | ||
210 | bl->props.brightness = 0; | 152 | if (gpio_is_valid(pd->res_gpio)) |
211 | nec_8048_bl_update_status(bl); | 153 | gpio_set_value_cansleep(pd->res_gpio, 0); |
212 | |||
213 | if (dssdev->platform_disable) | ||
214 | dssdev->platform_disable(dssdev); | ||
215 | 154 | ||
216 | omapdss_dpi_display_disable(dssdev); | 155 | omapdss_dpi_display_disable(dssdev); |
217 | } | 156 | } |
@@ -303,16 +242,22 @@ static int nec_8048_spi_remove(struct spi_device *spi) | |||
303 | return 0; | 242 | return 0; |
304 | } | 243 | } |
305 | 244 | ||
306 | static int nec_8048_spi_suspend(struct spi_device *spi, pm_message_t mesg) | 245 | #ifdef CONFIG_PM_SLEEP |
246 | |||
247 | static int nec_8048_spi_suspend(struct device *dev) | ||
307 | { | 248 | { |
249 | struct spi_device *spi = to_spi_device(dev); | ||
250 | |||
308 | nec_8048_spi_send(spi, 2, 0x01); | 251 | nec_8048_spi_send(spi, 2, 0x01); |
309 | mdelay(40); | 252 | mdelay(40); |
310 | 253 | ||
311 | return 0; | 254 | return 0; |
312 | } | 255 | } |
313 | 256 | ||
314 | static int nec_8048_spi_resume(struct spi_device *spi) | 257 | static int nec_8048_spi_resume(struct device *dev) |
315 | { | 258 | { |
259 | struct spi_device *spi = to_spi_device(dev); | ||
260 | |||
316 | /* reinitialize the panel */ | 261 | /* reinitialize the panel */ |
317 | spi_setup(spi); | 262 | spi_setup(spi); |
318 | nec_8048_spi_send(spi, 2, 0x00); | 263 | nec_8048_spi_send(spi, 2, 0x00); |
@@ -321,14 +266,20 @@ static int nec_8048_spi_resume(struct spi_device *spi) | |||
321 | return 0; | 266 | return 0; |
322 | } | 267 | } |
323 | 268 | ||
269 | static SIMPLE_DEV_PM_OPS(nec_8048_spi_pm_ops, nec_8048_spi_suspend, | ||
270 | nec_8048_spi_resume); | ||
271 | #define NEC_8048_SPI_PM_OPS (&nec_8048_spi_pm_ops) | ||
272 | #else | ||
273 | #define NEC_8048_SPI_PM_OPS NULL | ||
274 | #endif | ||
275 | |||
324 | static struct spi_driver nec_8048_spi_driver = { | 276 | static struct spi_driver nec_8048_spi_driver = { |
325 | .probe = nec_8048_spi_probe, | 277 | .probe = nec_8048_spi_probe, |
326 | .remove = nec_8048_spi_remove, | 278 | .remove = nec_8048_spi_remove, |
327 | .suspend = nec_8048_spi_suspend, | ||
328 | .resume = nec_8048_spi_resume, | ||
329 | .driver = { | 279 | .driver = { |
330 | .name = "nec_8048_spi", | 280 | .name = "nec_8048_spi", |
331 | .owner = THIS_MODULE, | 281 | .owner = THIS_MODULE, |
282 | .pm = NEC_8048_SPI_PM_OPS, | ||
332 | }, | 283 | }, |
333 | }; | 284 | }; |
334 | 285 | ||
diff --git a/drivers/video/omap2/displays/panel-picodlp.c b/drivers/video/omap2/displays/panel-picodlp.c index 1b94018aac3e..62f2db04fbc8 100644 --- a/drivers/video/omap2/displays/panel-picodlp.c +++ b/drivers/video/omap2/displays/panel-picodlp.c | |||
@@ -31,7 +31,7 @@ | |||
31 | #include <linux/gpio.h> | 31 | #include <linux/gpio.h> |
32 | 32 | ||
33 | #include <video/omapdss.h> | 33 | #include <video/omapdss.h> |
34 | #include <video/omap-panel-picodlp.h> | 34 | #include <video/omap-panel-data.h> |
35 | 35 | ||
36 | #include "panel-picodlp.h" | 36 | #include "panel-picodlp.h" |
37 | 37 | ||
@@ -354,12 +354,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev) | |||
354 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); | 354 | struct picodlp_data *picod = dev_get_drvdata(&dssdev->dev); |
355 | struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); | 355 | struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); |
356 | 356 | ||
357 | if (dssdev->platform_enable) { | ||
358 | r = dssdev->platform_enable(dssdev); | ||
359 | if (r) | ||
360 | return r; | ||
361 | } | ||
362 | |||
363 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); | 357 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); |
364 | msleep(1); | 358 | msleep(1); |
365 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 1); | 359 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 1); |
@@ -398,9 +392,6 @@ static int picodlp_panel_power_on(struct omap_dss_device *dssdev) | |||
398 | err: | 392 | err: |
399 | omapdss_dpi_display_disable(dssdev); | 393 | omapdss_dpi_display_disable(dssdev); |
400 | err1: | 394 | err1: |
401 | if (dssdev->platform_disable) | ||
402 | dssdev->platform_disable(dssdev); | ||
403 | |||
404 | return r; | 395 | return r; |
405 | } | 396 | } |
406 | 397 | ||
@@ -412,9 +403,6 @@ static void picodlp_panel_power_off(struct omap_dss_device *dssdev) | |||
412 | 403 | ||
413 | gpio_set_value(picodlp_pdata->emu_done_gpio, 0); | 404 | gpio_set_value(picodlp_pdata->emu_done_gpio, 0); |
414 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); | 405 | gpio_set_value(picodlp_pdata->pwrgood_gpio, 0); |
415 | |||
416 | if (dssdev->platform_disable) | ||
417 | dssdev->platform_disable(dssdev); | ||
418 | } | 406 | } |
419 | 407 | ||
420 | static int picodlp_panel_probe(struct omap_dss_device *dssdev) | 408 | static int picodlp_panel_probe(struct omap_dss_device *dssdev) |
@@ -423,11 +411,14 @@ static int picodlp_panel_probe(struct omap_dss_device *dssdev) | |||
423 | struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); | 411 | struct picodlp_panel_data *picodlp_pdata = get_panel_data(dssdev); |
424 | struct i2c_adapter *adapter; | 412 | struct i2c_adapter *adapter; |
425 | struct i2c_client *picodlp_i2c_client; | 413 | struct i2c_client *picodlp_i2c_client; |
426 | int r = 0, picodlp_adapter_id; | 414 | int r, picodlp_adapter_id; |
427 | 415 | ||
428 | dssdev->panel.timings = pico_ls_timings; | 416 | dssdev->panel.timings = pico_ls_timings; |
429 | 417 | ||
430 | picod = kzalloc(sizeof(struct picodlp_data), GFP_KERNEL); | 418 | if (!picodlp_pdata) |
419 | return -EINVAL; | ||
420 | |||
421 | picod = devm_kzalloc(&dssdev->dev, sizeof(*picod), GFP_KERNEL); | ||
431 | if (!picod) | 422 | if (!picod) |
432 | return -ENOMEM; | 423 | return -ENOMEM; |
433 | 424 | ||
@@ -438,25 +429,37 @@ static int picodlp_panel_probe(struct omap_dss_device *dssdev) | |||
438 | adapter = i2c_get_adapter(picodlp_adapter_id); | 429 | adapter = i2c_get_adapter(picodlp_adapter_id); |
439 | if (!adapter) { | 430 | if (!adapter) { |
440 | dev_err(&dssdev->dev, "can't get i2c adapter\n"); | 431 | dev_err(&dssdev->dev, "can't get i2c adapter\n"); |
441 | r = -ENODEV; | 432 | return -ENODEV; |
442 | goto err; | ||
443 | } | 433 | } |
444 | 434 | ||
445 | picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info); | 435 | picodlp_i2c_client = i2c_new_device(adapter, &picodlp_i2c_board_info); |
446 | if (!picodlp_i2c_client) { | 436 | if (!picodlp_i2c_client) { |
447 | dev_err(&dssdev->dev, "can't add i2c device::" | 437 | dev_err(&dssdev->dev, "can't add i2c device::" |
448 | " picodlp_i2c_client is NULL\n"); | 438 | " picodlp_i2c_client is NULL\n"); |
449 | r = -ENODEV; | 439 | return -ENODEV; |
450 | goto err; | ||
451 | } | 440 | } |
452 | 441 | ||
453 | picod->picodlp_i2c_client = picodlp_i2c_client; | 442 | picod->picodlp_i2c_client = picodlp_i2c_client; |
454 | 443 | ||
455 | dev_set_drvdata(&dssdev->dev, picod); | 444 | dev_set_drvdata(&dssdev->dev, picod); |
456 | return r; | 445 | |
457 | err: | 446 | if (gpio_is_valid(picodlp_pdata->emu_done_gpio)) { |
458 | kfree(picod); | 447 | r = devm_gpio_request_one(&dssdev->dev, |
459 | return r; | 448 | picodlp_pdata->emu_done_gpio, |
449 | GPIOF_IN, "DLP EMU DONE"); | ||
450 | if (r) | ||
451 | return r; | ||
452 | } | ||
453 | |||
454 | if (gpio_is_valid(picodlp_pdata->pwrgood_gpio)) { | ||
455 | r = devm_gpio_request_one(&dssdev->dev, | ||
456 | picodlp_pdata->pwrgood_gpio, | ||
457 | GPIOF_OUT_INIT_LOW, "DLP PWRGOOD"); | ||
458 | if (r) | ||
459 | return r; | ||
460 | } | ||
461 | |||
462 | return 0; | ||
460 | } | 463 | } |
461 | 464 | ||
462 | static void picodlp_panel_remove(struct omap_dss_device *dssdev) | 465 | static void picodlp_panel_remove(struct omap_dss_device *dssdev) |
diff --git a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c index cada8c621e01..74cb0eb45311 100644 --- a/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c +++ b/drivers/video/omap2/displays/panel-sharp-ls037v7dw01.c | |||
@@ -20,16 +20,13 @@ | |||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/delay.h> | 21 | #include <linux/delay.h> |
22 | #include <linux/device.h> | 22 | #include <linux/device.h> |
23 | #include <linux/backlight.h> | ||
24 | #include <linux/fb.h> | 23 | #include <linux/fb.h> |
25 | #include <linux/err.h> | 24 | #include <linux/err.h> |
26 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/gpio.h> | ||
27 | 27 | ||
28 | #include <video/omapdss.h> | 28 | #include <video/omapdss.h> |
29 | 29 | #include <video/omap-panel-data.h> | |
30 | struct sharp_data { | ||
31 | struct backlight_device *bl; | ||
32 | }; | ||
33 | 30 | ||
34 | static struct omap_video_timings sharp_ls_timings = { | 31 | static struct omap_video_timings sharp_ls_timings = { |
35 | .x_res = 480, | 32 | .x_res = 480, |
@@ -52,91 +49,67 @@ static struct omap_video_timings sharp_ls_timings = { | |||
52 | .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, | 49 | .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, |
53 | }; | 50 | }; |
54 | 51 | ||
55 | static int sharp_ls_bl_update_status(struct backlight_device *bl) | 52 | static inline struct panel_sharp_ls037v7dw01_data |
53 | *get_panel_data(const struct omap_dss_device *dssdev) | ||
56 | { | 54 | { |
57 | struct omap_dss_device *dssdev = dev_get_drvdata(&bl->dev); | 55 | return (struct panel_sharp_ls037v7dw01_data *) dssdev->data; |
58 | int level; | ||
59 | |||
60 | if (!dssdev->set_backlight) | ||
61 | return -EINVAL; | ||
62 | |||
63 | if (bl->props.fb_blank == FB_BLANK_UNBLANK && | ||
64 | bl->props.power == FB_BLANK_UNBLANK) | ||
65 | level = bl->props.brightness; | ||
66 | else | ||
67 | level = 0; | ||
68 | |||
69 | return dssdev->set_backlight(dssdev, level); | ||
70 | } | 56 | } |
71 | 57 | ||
72 | static int sharp_ls_bl_get_brightness(struct backlight_device *bl) | ||
73 | { | ||
74 | if (bl->props.fb_blank == FB_BLANK_UNBLANK && | ||
75 | bl->props.power == FB_BLANK_UNBLANK) | ||
76 | return bl->props.brightness; | ||
77 | |||
78 | return 0; | ||
79 | } | ||
80 | |||
81 | static const struct backlight_ops sharp_ls_bl_ops = { | ||
82 | .get_brightness = sharp_ls_bl_get_brightness, | ||
83 | .update_status = sharp_ls_bl_update_status, | ||
84 | }; | ||
85 | |||
86 | |||
87 | |||
88 | static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) | 58 | static int sharp_ls_panel_probe(struct omap_dss_device *dssdev) |
89 | { | 59 | { |
90 | struct backlight_properties props; | 60 | struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev); |
91 | struct backlight_device *bl; | ||
92 | struct sharp_data *sd; | ||
93 | int r; | 61 | int r; |
94 | 62 | ||
63 | if (!pd) | ||
64 | return -EINVAL; | ||
65 | |||
95 | dssdev->panel.timings = sharp_ls_timings; | 66 | dssdev->panel.timings = sharp_ls_timings; |
96 | 67 | ||
97 | sd = kzalloc(sizeof(*sd), GFP_KERNEL); | 68 | if (gpio_is_valid(pd->mo_gpio)) { |
98 | if (!sd) | 69 | r = devm_gpio_request_one(&dssdev->dev, pd->mo_gpio, |
99 | return -ENOMEM; | 70 | GPIOF_OUT_INIT_LOW, "lcd MO"); |
71 | if (r) | ||
72 | return r; | ||
73 | } | ||
100 | 74 | ||
101 | dev_set_drvdata(&dssdev->dev, sd); | 75 | if (gpio_is_valid(pd->lr_gpio)) { |
76 | r = devm_gpio_request_one(&dssdev->dev, pd->lr_gpio, | ||
77 | GPIOF_OUT_INIT_HIGH, "lcd LR"); | ||
78 | if (r) | ||
79 | return r; | ||
80 | } | ||
102 | 81 | ||
103 | memset(&props, 0, sizeof(struct backlight_properties)); | 82 | if (gpio_is_valid(pd->ud_gpio)) { |
104 | props.max_brightness = dssdev->max_backlight_level; | 83 | r = devm_gpio_request_one(&dssdev->dev, pd->ud_gpio, |
105 | props.type = BACKLIGHT_RAW; | 84 | GPIOF_OUT_INIT_HIGH, "lcd UD"); |
85 | if (r) | ||
86 | return r; | ||
87 | } | ||
106 | 88 | ||
107 | bl = backlight_device_register("sharp-ls", &dssdev->dev, dssdev, | 89 | if (gpio_is_valid(pd->resb_gpio)) { |
108 | &sharp_ls_bl_ops, &props); | 90 | r = devm_gpio_request_one(&dssdev->dev, pd->resb_gpio, |
109 | if (IS_ERR(bl)) { | 91 | GPIOF_OUT_INIT_LOW, "lcd RESB"); |
110 | r = PTR_ERR(bl); | 92 | if (r) |
111 | kfree(sd); | 93 | return r; |
112 | return r; | ||
113 | } | 94 | } |
114 | sd->bl = bl; | ||
115 | 95 | ||
116 | bl->props.fb_blank = FB_BLANK_UNBLANK; | 96 | if (gpio_is_valid(pd->ini_gpio)) { |
117 | bl->props.power = FB_BLANK_UNBLANK; | 97 | r = devm_gpio_request_one(&dssdev->dev, pd->ini_gpio, |
118 | bl->props.brightness = dssdev->max_backlight_level; | 98 | GPIOF_OUT_INIT_LOW, "lcd INI"); |
119 | r = sharp_ls_bl_update_status(bl); | 99 | if (r) |
120 | if (r < 0) | 100 | return r; |
121 | dev_err(&dssdev->dev, "failed to set lcd brightness\n"); | 101 | } |
122 | 102 | ||
123 | return 0; | 103 | return 0; |
124 | } | 104 | } |
125 | 105 | ||
126 | static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev) | 106 | static void __exit sharp_ls_panel_remove(struct omap_dss_device *dssdev) |
127 | { | 107 | { |
128 | struct sharp_data *sd = dev_get_drvdata(&dssdev->dev); | ||
129 | struct backlight_device *bl = sd->bl; | ||
130 | |||
131 | bl->props.power = FB_BLANK_POWERDOWN; | ||
132 | sharp_ls_bl_update_status(bl); | ||
133 | backlight_device_unregister(bl); | ||
134 | |||
135 | kfree(sd); | ||
136 | } | 108 | } |
137 | 109 | ||
138 | static int sharp_ls_power_on(struct omap_dss_device *dssdev) | 110 | static int sharp_ls_power_on(struct omap_dss_device *dssdev) |
139 | { | 111 | { |
112 | struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev); | ||
140 | int r = 0; | 113 | int r = 0; |
141 | 114 | ||
142 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) | 115 | if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE) |
@@ -152,26 +125,29 @@ static int sharp_ls_power_on(struct omap_dss_device *dssdev) | |||
152 | /* wait couple of vsyncs until enabling the LCD */ | 125 | /* wait couple of vsyncs until enabling the LCD */ |
153 | msleep(50); | 126 | msleep(50); |
154 | 127 | ||
155 | if (dssdev->platform_enable) { | 128 | if (gpio_is_valid(pd->resb_gpio)) |
156 | r = dssdev->platform_enable(dssdev); | 129 | gpio_set_value_cansleep(pd->resb_gpio, 1); |
157 | if (r) | 130 | |
158 | goto err1; | 131 | if (gpio_is_valid(pd->ini_gpio)) |
159 | } | 132 | gpio_set_value_cansleep(pd->ini_gpio, 1); |
160 | 133 | ||
161 | return 0; | 134 | return 0; |
162 | err1: | ||
163 | omapdss_dpi_display_disable(dssdev); | ||
164 | err0: | 135 | err0: |
165 | return r; | 136 | return r; |
166 | } | 137 | } |
167 | 138 | ||
168 | static void sharp_ls_power_off(struct omap_dss_device *dssdev) | 139 | static void sharp_ls_power_off(struct omap_dss_device *dssdev) |
169 | { | 140 | { |
141 | struct panel_sharp_ls037v7dw01_data *pd = get_panel_data(dssdev); | ||
142 | |||
170 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 143 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
171 | return; | 144 | return; |
172 | 145 | ||
173 | if (dssdev->platform_disable) | 146 | if (gpio_is_valid(pd->ini_gpio)) |
174 | dssdev->platform_disable(dssdev); | 147 | gpio_set_value_cansleep(pd->ini_gpio, 0); |
148 | |||
149 | if (gpio_is_valid(pd->resb_gpio)) | ||
150 | gpio_set_value_cansleep(pd->resb_gpio, 0); | ||
175 | 151 | ||
176 | /* wait at least 5 vsyncs after disabling the LCD */ | 152 | /* wait at least 5 vsyncs after disabling the LCD */ |
177 | 153 | ||
diff --git a/drivers/video/omap2/displays/panel-taal.c b/drivers/video/omap2/displays/panel-taal.c index a32407a5735a..c4f78bda115a 100644 --- a/drivers/video/omap2/displays/panel-taal.c +++ b/drivers/video/omap2/displays/panel-taal.c | |||
@@ -33,7 +33,7 @@ | |||
33 | #include <linux/mutex.h> | 33 | #include <linux/mutex.h> |
34 | 34 | ||
35 | #include <video/omapdss.h> | 35 | #include <video/omapdss.h> |
36 | #include <video/omap-panel-nokia-dsi.h> | 36 | #include <video/omap-panel-data.h> |
37 | #include <video/mipi_display.h> | 37 | #include <video/mipi_display.h> |
38 | 38 | ||
39 | /* DSI Virtual channel. Hardcoded for now. */ | 39 | /* DSI Virtual channel. Hardcoded for now. */ |
@@ -54,61 +54,6 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable); | |||
54 | 54 | ||
55 | static int taal_panel_reset(struct omap_dss_device *dssdev); | 55 | static int taal_panel_reset(struct omap_dss_device *dssdev); |
56 | 56 | ||
57 | /** | ||
58 | * struct panel_config - panel configuration | ||
59 | * @name: panel name | ||
60 | * @type: panel type | ||
61 | * @timings: panel resolution | ||
62 | * @sleep: various panel specific delays, passed to msleep() if non-zero | ||
63 | * @reset_sequence: reset sequence timings, passed to udelay() if non-zero | ||
64 | * @regulators: array of panel regulators | ||
65 | * @num_regulators: number of regulators in the array | ||
66 | */ | ||
67 | struct panel_config { | ||
68 | const char *name; | ||
69 | int type; | ||
70 | |||
71 | struct omap_video_timings timings; | ||
72 | |||
73 | struct { | ||
74 | unsigned int sleep_in; | ||
75 | unsigned int sleep_out; | ||
76 | unsigned int hw_reset; | ||
77 | unsigned int enable_te; | ||
78 | } sleep; | ||
79 | |||
80 | struct { | ||
81 | unsigned int high; | ||
82 | unsigned int low; | ||
83 | } reset_sequence; | ||
84 | |||
85 | }; | ||
86 | |||
87 | enum { | ||
88 | PANEL_TAAL, | ||
89 | }; | ||
90 | |||
91 | static struct panel_config panel_configs[] = { | ||
92 | { | ||
93 | .name = "taal", | ||
94 | .type = PANEL_TAAL, | ||
95 | .timings = { | ||
96 | .x_res = 864, | ||
97 | .y_res = 480, | ||
98 | }, | ||
99 | .sleep = { | ||
100 | .sleep_in = 5, | ||
101 | .sleep_out = 5, | ||
102 | .hw_reset = 5, | ||
103 | .enable_te = 100, /* possible panel bug */ | ||
104 | }, | ||
105 | .reset_sequence = { | ||
106 | .high = 10, | ||
107 | .low = 10, | ||
108 | }, | ||
109 | }, | ||
110 | }; | ||
111 | |||
112 | struct taal_data { | 57 | struct taal_data { |
113 | struct mutex lock; | 58 | struct mutex lock; |
114 | 59 | ||
@@ -121,9 +66,6 @@ struct taal_data { | |||
121 | 66 | ||
122 | struct omap_dss_device *dssdev; | 67 | struct omap_dss_device *dssdev; |
123 | 68 | ||
124 | /* panel specific HW info */ | ||
125 | struct panel_config *panel_config; | ||
126 | |||
127 | /* panel HW configuration from DT or platform data */ | 69 | /* panel HW configuration from DT or platform data */ |
128 | int reset_gpio; | 70 | int reset_gpio; |
129 | int ext_te_gpio; | 71 | int ext_te_gpio; |
@@ -134,8 +76,6 @@ struct taal_data { | |||
134 | 76 | ||
135 | /* runtime variables */ | 77 | /* runtime variables */ |
136 | bool enabled; | 78 | bool enabled; |
137 | u8 rotate; | ||
138 | bool mirror; | ||
139 | 79 | ||
140 | bool te_enabled; | 80 | bool te_enabled; |
141 | 81 | ||
@@ -221,8 +161,7 @@ static int taal_sleep_in(struct taal_data *td) | |||
221 | 161 | ||
222 | hw_guard_start(td, 120); | 162 | hw_guard_start(td, 120); |
223 | 163 | ||
224 | if (td->panel_config->sleep.sleep_in) | 164 | msleep(5); |
225 | msleep(td->panel_config->sleep.sleep_in); | ||
226 | 165 | ||
227 | return 0; | 166 | return 0; |
228 | } | 167 | } |
@@ -239,8 +178,7 @@ static int taal_sleep_out(struct taal_data *td) | |||
239 | 178 | ||
240 | hw_guard_start(td, 120); | 179 | hw_guard_start(td, 120); |
241 | 180 | ||
242 | if (td->panel_config->sleep.sleep_out) | 181 | msleep(5); |
243 | msleep(td->panel_config->sleep.sleep_out); | ||
244 | 182 | ||
245 | return 0; | 183 | return 0; |
246 | } | 184 | } |
@@ -262,49 +200,6 @@ static int taal_get_id(struct taal_data *td, u8 *id1, u8 *id2, u8 *id3) | |||
262 | return 0; | 200 | return 0; |
263 | } | 201 | } |
264 | 202 | ||
265 | static int taal_set_addr_mode(struct taal_data *td, u8 rotate, bool mirror) | ||
266 | { | ||
267 | int r; | ||
268 | u8 mode; | ||
269 | int b5, b6, b7; | ||
270 | |||
271 | r = taal_dcs_read_1(td, MIPI_DCS_GET_ADDRESS_MODE, &mode); | ||
272 | if (r) | ||
273 | return r; | ||
274 | |||
275 | switch (rotate) { | ||
276 | default: | ||
277 | case 0: | ||
278 | b7 = 0; | ||
279 | b6 = 0; | ||
280 | b5 = 0; | ||
281 | break; | ||
282 | case 1: | ||
283 | b7 = 0; | ||
284 | b6 = 1; | ||
285 | b5 = 1; | ||
286 | break; | ||
287 | case 2: | ||
288 | b7 = 1; | ||
289 | b6 = 1; | ||
290 | b5 = 0; | ||
291 | break; | ||
292 | case 3: | ||
293 | b7 = 1; | ||
294 | b6 = 0; | ||
295 | b5 = 1; | ||
296 | break; | ||
297 | } | ||
298 | |||
299 | if (mirror) | ||
300 | b6 = !b6; | ||
301 | |||
302 | mode &= ~((1<<7) | (1<<6) | (1<<5)); | ||
303 | mode |= (b7 << 7) | (b6 << 6) | (b5 << 5); | ||
304 | |||
305 | return taal_dcs_write_1(td, MIPI_DCS_SET_ADDRESS_MODE, mode); | ||
306 | } | ||
307 | |||
308 | static int taal_set_update_window(struct taal_data *td, | 203 | static int taal_set_update_window(struct taal_data *td, |
309 | u16 x, u16 y, u16 w, u16 h) | 204 | u16 x, u16 y, u16 w, u16 h) |
310 | { | 205 | { |
@@ -515,15 +410,8 @@ static const struct backlight_ops taal_bl_ops = { | |||
515 | static void taal_get_resolution(struct omap_dss_device *dssdev, | 410 | static void taal_get_resolution(struct omap_dss_device *dssdev, |
516 | u16 *xres, u16 *yres) | 411 | u16 *xres, u16 *yres) |
517 | { | 412 | { |
518 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 413 | *xres = dssdev->panel.timings.x_res; |
519 | 414 | *yres = dssdev->panel.timings.y_res; | |
520 | if (td->rotate == 0 || td->rotate == 2) { | ||
521 | *xres = dssdev->panel.timings.x_res; | ||
522 | *yres = dssdev->panel.timings.y_res; | ||
523 | } else { | ||
524 | *yres = dssdev->panel.timings.x_res; | ||
525 | *xres = dssdev->panel.timings.y_res; | ||
526 | } | ||
527 | } | 415 | } |
528 | 416 | ||
529 | static ssize_t taal_num_errors_show(struct device *dev, | 417 | static ssize_t taal_num_errors_show(struct device *dev, |
@@ -845,17 +733,14 @@ static void taal_hw_reset(struct omap_dss_device *dssdev) | |||
845 | return; | 733 | return; |
846 | 734 | ||
847 | gpio_set_value(td->reset_gpio, 1); | 735 | gpio_set_value(td->reset_gpio, 1); |
848 | if (td->panel_config->reset_sequence.high) | 736 | udelay(10); |
849 | udelay(td->panel_config->reset_sequence.high); | ||
850 | /* reset the panel */ | 737 | /* reset the panel */ |
851 | gpio_set_value(td->reset_gpio, 0); | 738 | gpio_set_value(td->reset_gpio, 0); |
852 | /* assert reset */ | 739 | /* assert reset */ |
853 | if (td->panel_config->reset_sequence.low) | 740 | udelay(10); |
854 | udelay(td->panel_config->reset_sequence.low); | ||
855 | gpio_set_value(td->reset_gpio, 1); | 741 | gpio_set_value(td->reset_gpio, 1); |
856 | /* wait after releasing reset */ | 742 | /* wait after releasing reset */ |
857 | if (td->panel_config->sleep.hw_reset) | 743 | msleep(5); |
858 | msleep(td->panel_config->sleep.hw_reset); | ||
859 | } | 744 | } |
860 | 745 | ||
861 | static void taal_probe_pdata(struct taal_data *td, | 746 | static void taal_probe_pdata(struct taal_data *td, |
@@ -881,8 +766,7 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
881 | struct backlight_properties props; | 766 | struct backlight_properties props; |
882 | struct taal_data *td; | 767 | struct taal_data *td; |
883 | struct backlight_device *bldev = NULL; | 768 | struct backlight_device *bldev = NULL; |
884 | int r, i; | 769 | int r; |
885 | const char *panel_name; | ||
886 | 770 | ||
887 | dev_dbg(&dssdev->dev, "probe\n"); | 771 | dev_dbg(&dssdev->dev, "probe\n"); |
888 | 772 | ||
@@ -897,26 +781,13 @@ static int taal_probe(struct omap_dss_device *dssdev) | |||
897 | const struct nokia_dsi_panel_data *pdata = dssdev->data; | 781 | const struct nokia_dsi_panel_data *pdata = dssdev->data; |
898 | 782 | ||
899 | taal_probe_pdata(td, pdata); | 783 | taal_probe_pdata(td, pdata); |
900 | |||
901 | panel_name = pdata->name; | ||
902 | } else { | 784 | } else { |
903 | return -ENODEV; | 785 | return -ENODEV; |
904 | } | 786 | } |
905 | 787 | ||
906 | if (panel_name == NULL) | 788 | dssdev->panel.timings.x_res = 864; |
907 | return -EINVAL; | 789 | dssdev->panel.timings.y_res = 480; |
908 | 790 | dssdev->panel.timings.pixel_clock = DIV_ROUND_UP(864 * 480 * 60, 1000); | |
909 | for (i = 0; i < ARRAY_SIZE(panel_configs); i++) { | ||
910 | if (strcmp(panel_name, panel_configs[i].name) == 0) { | ||
911 | td->panel_config = &panel_configs[i]; | ||
912 | break; | ||
913 | } | ||
914 | } | ||
915 | |||
916 | if (!td->panel_config) | ||
917 | return -EINVAL; | ||
918 | |||
919 | dssdev->panel.timings = td->panel_config->timings; | ||
920 | dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; | 791 | dssdev->panel.dsi_pix_fmt = OMAP_DSS_DSI_FMT_RGB888; |
921 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | | 792 | dssdev->caps = OMAP_DSS_DISPLAY_CAP_MANUAL_UPDATE | |
922 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; | 793 | OMAP_DSS_DISPLAY_CAP_TEAR_ELIM; |
@@ -1049,6 +920,15 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
1049 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 920 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
1050 | u8 id1, id2, id3; | 921 | u8 id1, id2, id3; |
1051 | int r; | 922 | int r; |
923 | struct omap_dss_dsi_config dsi_config = { | ||
924 | .mode = OMAP_DSS_DSI_CMD_MODE, | ||
925 | .pixel_format = OMAP_DSS_DSI_FMT_RGB888, | ||
926 | .timings = &dssdev->panel.timings, | ||
927 | .hs_clk_min = 150000000, | ||
928 | .hs_clk_max = 300000000, | ||
929 | .lp_clk_min = 7000000, | ||
930 | .lp_clk_max = 10000000, | ||
931 | }; | ||
1052 | 932 | ||
1053 | r = omapdss_dsi_configure_pins(dssdev, &td->pin_config); | 933 | r = omapdss_dsi_configure_pins(dssdev, &td->pin_config); |
1054 | if (r) { | 934 | if (r) { |
@@ -1056,14 +936,9 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
1056 | goto err0; | 936 | goto err0; |
1057 | }; | 937 | }; |
1058 | 938 | ||
1059 | omapdss_dsi_set_size(dssdev, dssdev->panel.timings.x_res, | 939 | r = omapdss_dsi_set_config(dssdev, &dsi_config); |
1060 | dssdev->panel.timings.y_res); | ||
1061 | omapdss_dsi_set_pixel_format(dssdev, OMAP_DSS_DSI_FMT_RGB888); | ||
1062 | omapdss_dsi_set_operation_mode(dssdev, OMAP_DSS_DSI_CMD_MODE); | ||
1063 | |||
1064 | r = omapdss_dsi_set_clocks(dssdev, 216000000, 10000000); | ||
1065 | if (r) { | 940 | if (r) { |
1066 | dev_err(&dssdev->dev, "failed to set HS and LP clocks\n"); | 941 | dev_err(&dssdev->dev, "failed to configure DSI\n"); |
1067 | goto err0; | 942 | goto err0; |
1068 | } | 943 | } |
1069 | 944 | ||
@@ -1086,8 +961,7 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
1086 | goto err; | 961 | goto err; |
1087 | 962 | ||
1088 | /* on early Taal revisions CABC is broken */ | 963 | /* on early Taal revisions CABC is broken */ |
1089 | if (td->panel_config->type == PANEL_TAAL && | 964 | if (id2 == 0x00 || id2 == 0xff || id2 == 0x81) |
1090 | (id2 == 0x00 || id2 == 0xff || id2 == 0x81)) | ||
1091 | td->cabc_broken = true; | 965 | td->cabc_broken = true; |
1092 | 966 | ||
1093 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff); | 967 | r = taal_dcs_write_1(td, DCS_BRIGHTNESS, 0xff); |
@@ -1104,10 +978,6 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
1104 | if (r) | 978 | if (r) |
1105 | goto err; | 979 | goto err; |
1106 | 980 | ||
1107 | r = taal_set_addr_mode(td, td->rotate, td->mirror); | ||
1108 | if (r) | ||
1109 | goto err; | ||
1110 | |||
1111 | if (!td->cabc_broken) { | 981 | if (!td->cabc_broken) { |
1112 | r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode); | 982 | r = taal_dcs_write_1(td, DCS_WRITE_CABC, td->cabc_mode); |
1113 | if (r) | 983 | if (r) |
@@ -1129,8 +999,8 @@ static int taal_power_on(struct omap_dss_device *dssdev) | |||
1129 | td->enabled = 1; | 999 | td->enabled = 1; |
1130 | 1000 | ||
1131 | if (!td->intro_printed) { | 1001 | if (!td->intro_printed) { |
1132 | dev_info(&dssdev->dev, "%s panel revision %02x.%02x.%02x\n", | 1002 | dev_info(&dssdev->dev, "panel revision %02x.%02x.%02x\n", |
1133 | td->panel_config->name, id1, id2, id3); | 1003 | id1, id2, id3); |
1134 | if (td->cabc_broken) | 1004 | if (td->cabc_broken) |
1135 | dev_info(&dssdev->dev, | 1005 | dev_info(&dssdev->dev, |
1136 | "old Taal version, CABC disabled\n"); | 1006 | "old Taal version, CABC disabled\n"); |
@@ -1311,8 +1181,8 @@ static int taal_update(struct omap_dss_device *dssdev, | |||
1311 | 1181 | ||
1312 | /* XXX no need to send this every frame, but dsi break if not done */ | 1182 | /* XXX no need to send this every frame, but dsi break if not done */ |
1313 | r = taal_set_update_window(td, 0, 0, | 1183 | r = taal_set_update_window(td, 0, 0, |
1314 | td->panel_config->timings.x_res, | 1184 | dssdev->panel.timings.x_res, |
1315 | td->panel_config->timings.y_res); | 1185 | dssdev->panel.timings.y_res); |
1316 | if (r) | 1186 | if (r) |
1317 | goto err; | 1187 | goto err; |
1318 | 1188 | ||
@@ -1365,8 +1235,8 @@ static int _taal_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
1365 | if (!gpio_is_valid(td->ext_te_gpio)) | 1235 | if (!gpio_is_valid(td->ext_te_gpio)) |
1366 | omapdss_dsi_enable_te(dssdev, enable); | 1236 | omapdss_dsi_enable_te(dssdev, enable); |
1367 | 1237 | ||
1368 | if (td->panel_config->sleep.enable_te) | 1238 | /* possible panel bug */ |
1369 | msleep(td->panel_config->sleep.enable_te); | 1239 | msleep(100); |
1370 | 1240 | ||
1371 | return r; | 1241 | return r; |
1372 | } | 1242 | } |
@@ -1419,112 +1289,6 @@ static int taal_get_te(struct omap_dss_device *dssdev) | |||
1419 | return r; | 1289 | return r; |
1420 | } | 1290 | } |
1421 | 1291 | ||
1422 | static int taal_rotate(struct omap_dss_device *dssdev, u8 rotate) | ||
1423 | { | ||
1424 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
1425 | u16 dw, dh; | ||
1426 | int r; | ||
1427 | |||
1428 | dev_dbg(&dssdev->dev, "rotate %d\n", rotate); | ||
1429 | |||
1430 | mutex_lock(&td->lock); | ||
1431 | |||
1432 | if (td->rotate == rotate) | ||
1433 | goto end; | ||
1434 | |||
1435 | dsi_bus_lock(dssdev); | ||
1436 | |||
1437 | if (td->enabled) { | ||
1438 | r = taal_wake_up(dssdev); | ||
1439 | if (r) | ||
1440 | goto err; | ||
1441 | |||
1442 | r = taal_set_addr_mode(td, rotate, td->mirror); | ||
1443 | if (r) | ||
1444 | goto err; | ||
1445 | } | ||
1446 | |||
1447 | if (rotate == 0 || rotate == 2) { | ||
1448 | dw = dssdev->panel.timings.x_res; | ||
1449 | dh = dssdev->panel.timings.y_res; | ||
1450 | } else { | ||
1451 | dw = dssdev->panel.timings.y_res; | ||
1452 | dh = dssdev->panel.timings.x_res; | ||
1453 | } | ||
1454 | |||
1455 | omapdss_dsi_set_size(dssdev, dw, dh); | ||
1456 | |||
1457 | td->rotate = rotate; | ||
1458 | |||
1459 | dsi_bus_unlock(dssdev); | ||
1460 | end: | ||
1461 | mutex_unlock(&td->lock); | ||
1462 | return 0; | ||
1463 | err: | ||
1464 | dsi_bus_unlock(dssdev); | ||
1465 | mutex_unlock(&td->lock); | ||
1466 | return r; | ||
1467 | } | ||
1468 | |||
1469 | static u8 taal_get_rotate(struct omap_dss_device *dssdev) | ||
1470 | { | ||
1471 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
1472 | int r; | ||
1473 | |||
1474 | mutex_lock(&td->lock); | ||
1475 | r = td->rotate; | ||
1476 | mutex_unlock(&td->lock); | ||
1477 | |||
1478 | return r; | ||
1479 | } | ||
1480 | |||
1481 | static int taal_mirror(struct omap_dss_device *dssdev, bool enable) | ||
1482 | { | ||
1483 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
1484 | int r; | ||
1485 | |||
1486 | dev_dbg(&dssdev->dev, "mirror %d\n", enable); | ||
1487 | |||
1488 | mutex_lock(&td->lock); | ||
1489 | |||
1490 | if (td->mirror == enable) | ||
1491 | goto end; | ||
1492 | |||
1493 | dsi_bus_lock(dssdev); | ||
1494 | if (td->enabled) { | ||
1495 | r = taal_wake_up(dssdev); | ||
1496 | if (r) | ||
1497 | goto err; | ||
1498 | |||
1499 | r = taal_set_addr_mode(td, td->rotate, enable); | ||
1500 | if (r) | ||
1501 | goto err; | ||
1502 | } | ||
1503 | |||
1504 | td->mirror = enable; | ||
1505 | |||
1506 | dsi_bus_unlock(dssdev); | ||
1507 | end: | ||
1508 | mutex_unlock(&td->lock); | ||
1509 | return 0; | ||
1510 | err: | ||
1511 | dsi_bus_unlock(dssdev); | ||
1512 | mutex_unlock(&td->lock); | ||
1513 | return r; | ||
1514 | } | ||
1515 | |||
1516 | static bool taal_get_mirror(struct omap_dss_device *dssdev) | ||
1517 | { | ||
1518 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | ||
1519 | int r; | ||
1520 | |||
1521 | mutex_lock(&td->lock); | ||
1522 | r = td->mirror; | ||
1523 | mutex_unlock(&td->lock); | ||
1524 | |||
1525 | return r; | ||
1526 | } | ||
1527 | |||
1528 | static int taal_run_test(struct omap_dss_device *dssdev, int test_num) | 1292 | static int taal_run_test(struct omap_dss_device *dssdev, int test_num) |
1529 | { | 1293 | { |
1530 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); | 1294 | struct taal_data *td = dev_get_drvdata(&dssdev->dev); |
@@ -1758,10 +1522,6 @@ static struct omap_dss_driver taal_driver = { | |||
1758 | .enable_te = taal_enable_te, | 1522 | .enable_te = taal_enable_te, |
1759 | .get_te = taal_get_te, | 1523 | .get_te = taal_get_te, |
1760 | 1524 | ||
1761 | .set_rotate = taal_rotate, | ||
1762 | .get_rotate = taal_get_rotate, | ||
1763 | .set_mirror = taal_mirror, | ||
1764 | .get_mirror = taal_get_mirror, | ||
1765 | .run_test = taal_run_test, | 1525 | .run_test = taal_run_test, |
1766 | .memory_read = taal_memory_read, | 1526 | .memory_read = taal_memory_read, |
1767 | 1527 | ||
diff --git a/drivers/video/omap2/displays/panel-tfp410.c b/drivers/video/omap2/displays/panel-tfp410.c index 8281baafe1ef..46039c4bf1ed 100644 --- a/drivers/video/omap2/displays/panel-tfp410.c +++ b/drivers/video/omap2/displays/panel-tfp410.c | |||
@@ -24,7 +24,7 @@ | |||
24 | #include <linux/gpio.h> | 24 | #include <linux/gpio.h> |
25 | #include <drm/drm_edid.h> | 25 | #include <drm/drm_edid.h> |
26 | 26 | ||
27 | #include <video/omap-panel-tfp410.h> | 27 | #include <video/omap-panel-data.h> |
28 | 28 | ||
29 | static const struct omap_video_timings tfp410_default_timings = { | 29 | static const struct omap_video_timings tfp410_default_timings = { |
30 | .x_res = 640, | 30 | .x_res = 640, |
@@ -135,7 +135,7 @@ static int tfp410_probe(struct omap_dss_device *dssdev) | |||
135 | if (!adapter) { | 135 | if (!adapter) { |
136 | dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n", | 136 | dev_err(&dssdev->dev, "Failed to get I2C adapter, bus %d\n", |
137 | i2c_bus_num); | 137 | i2c_bus_num); |
138 | return -EINVAL; | 138 | return -EPROBE_DEFER; |
139 | } | 139 | } |
140 | 140 | ||
141 | ddata->i2c_adapter = adapter; | 141 | ddata->i2c_adapter = adapter; |
diff --git a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c index 048c98381ef6..abf2bc4a18ab 100644 --- a/drivers/video/omap2/displays/panel-tpo-td043mtea1.c +++ b/drivers/video/omap2/displays/panel-tpo-td043mtea1.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | 19 | ||
20 | #include <video/omapdss.h> | 20 | #include <video/omapdss.h> |
21 | #include <video/omap-panel-data.h> | ||
21 | 22 | ||
22 | #define TPO_R02_MODE(x) ((x) & 7) | 23 | #define TPO_R02_MODE(x) ((x) & 7) |
23 | #define TPO_R02_MODE_800x480 7 | 24 | #define TPO_R02_MODE_800x480 7 |
@@ -278,9 +279,14 @@ static const struct omap_video_timings tpo_td043_timings = { | |||
278 | .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, | 279 | .sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES, |
279 | }; | 280 | }; |
280 | 281 | ||
282 | static inline struct panel_tpo_td043_data | ||
283 | *get_panel_data(const struct omap_dss_device *dssdev) | ||
284 | { | ||
285 | return (struct panel_tpo_td043_data *) dssdev->data; | ||
286 | } | ||
287 | |||
281 | static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) | 288 | static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) |
282 | { | 289 | { |
283 | int nreset_gpio = tpo_td043->nreset_gpio; | ||
284 | int r; | 290 | int r; |
285 | 291 | ||
286 | if (tpo_td043->powered_on) | 292 | if (tpo_td043->powered_on) |
@@ -293,8 +299,8 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) | |||
293 | /* wait for panel to stabilize */ | 299 | /* wait for panel to stabilize */ |
294 | msleep(160); | 300 | msleep(160); |
295 | 301 | ||
296 | if (gpio_is_valid(nreset_gpio)) | 302 | if (gpio_is_valid(tpo_td043->nreset_gpio)) |
297 | gpio_set_value(nreset_gpio, 1); | 303 | gpio_set_value(tpo_td043->nreset_gpio, 1); |
298 | 304 | ||
299 | tpo_td043_write(tpo_td043->spi, 2, | 305 | tpo_td043_write(tpo_td043->spi, 2, |
300 | TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING); | 306 | TPO_R02_MODE(tpo_td043->mode) | TPO_R02_NCLK_RISING); |
@@ -311,16 +317,14 @@ static int tpo_td043_power_on(struct tpo_td043_device *tpo_td043) | |||
311 | 317 | ||
312 | static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043) | 318 | static void tpo_td043_power_off(struct tpo_td043_device *tpo_td043) |
313 | { | 319 | { |
314 | int nreset_gpio = tpo_td043->nreset_gpio; | ||
315 | |||
316 | if (!tpo_td043->powered_on) | 320 | if (!tpo_td043->powered_on) |
317 | return; | 321 | return; |
318 | 322 | ||
319 | tpo_td043_write(tpo_td043->spi, 3, | 323 | tpo_td043_write(tpo_td043->spi, 3, |
320 | TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM); | 324 | TPO_R03_VAL_STANDBY | TPO_R03_EN_PWM); |
321 | 325 | ||
322 | if (gpio_is_valid(nreset_gpio)) | 326 | if (gpio_is_valid(tpo_td043->nreset_gpio)) |
323 | gpio_set_value(nreset_gpio, 0); | 327 | gpio_set_value(tpo_td043->nreset_gpio, 0); |
324 | 328 | ||
325 | /* wait for at least 2 vsyncs before cutting off power */ | 329 | /* wait for at least 2 vsyncs before cutting off power */ |
326 | msleep(50); | 330 | msleep(50); |
@@ -347,12 +351,6 @@ static int tpo_td043_enable_dss(struct omap_dss_device *dssdev) | |||
347 | if (r) | 351 | if (r) |
348 | goto err0; | 352 | goto err0; |
349 | 353 | ||
350 | if (dssdev->platform_enable) { | ||
351 | r = dssdev->platform_enable(dssdev); | ||
352 | if (r) | ||
353 | goto err1; | ||
354 | } | ||
355 | |||
356 | /* | 354 | /* |
357 | * If we are resuming from system suspend, SPI clocks might not be | 355 | * If we are resuming from system suspend, SPI clocks might not be |
358 | * enabled yet, so we'll program the LCD from SPI PM resume callback. | 356 | * enabled yet, so we'll program the LCD from SPI PM resume callback. |
@@ -379,9 +377,6 @@ static void tpo_td043_disable_dss(struct omap_dss_device *dssdev) | |||
379 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) | 377 | if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE) |
380 | return; | 378 | return; |
381 | 379 | ||
382 | if (dssdev->platform_disable) | ||
383 | dssdev->platform_disable(dssdev); | ||
384 | |||
385 | omapdss_dpi_display_disable(dssdev); | 380 | omapdss_dpi_display_disable(dssdev); |
386 | 381 | ||
387 | if (!tpo_td043->spi_suspended) | 382 | if (!tpo_td043->spi_suspended) |
@@ -407,7 +402,7 @@ static void tpo_td043_disable(struct omap_dss_device *dssdev) | |||
407 | static int tpo_td043_probe(struct omap_dss_device *dssdev) | 402 | static int tpo_td043_probe(struct omap_dss_device *dssdev) |
408 | { | 403 | { |
409 | struct tpo_td043_device *tpo_td043 = g_tpo_td043; | 404 | struct tpo_td043_device *tpo_td043 = g_tpo_td043; |
410 | int nreset_gpio = dssdev->reset_gpio; | 405 | struct panel_tpo_td043_data *pdata = get_panel_data(dssdev); |
411 | int ret = 0; | 406 | int ret = 0; |
412 | 407 | ||
413 | dev_dbg(&dssdev->dev, "probe\n"); | 408 | dev_dbg(&dssdev->dev, "probe\n"); |
@@ -417,6 +412,11 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev) | |||
417 | return -ENODEV; | 412 | return -ENODEV; |
418 | } | 413 | } |
419 | 414 | ||
415 | if (!pdata) | ||
416 | return -EINVAL; | ||
417 | |||
418 | tpo_td043->nreset_gpio = pdata->nreset_gpio; | ||
419 | |||
420 | dssdev->panel.timings = tpo_td043_timings; | 420 | dssdev->panel.timings = tpo_td043_timings; |
421 | dssdev->ctrl.pixel_size = 24; | 421 | dssdev->ctrl.pixel_size = 24; |
422 | 422 | ||
@@ -430,9 +430,10 @@ static int tpo_td043_probe(struct omap_dss_device *dssdev) | |||
430 | goto fail_regulator; | 430 | goto fail_regulator; |
431 | } | 431 | } |
432 | 432 | ||
433 | if (gpio_is_valid(nreset_gpio)) { | 433 | if (gpio_is_valid(tpo_td043->nreset_gpio)) { |
434 | ret = gpio_request_one(nreset_gpio, GPIOF_OUT_INIT_LOW, | 434 | ret = devm_gpio_request_one(&dssdev->dev, |
435 | "lcd reset"); | 435 | tpo_td043->nreset_gpio, GPIOF_OUT_INIT_LOW, |
436 | "lcd reset"); | ||
436 | if (ret < 0) { | 437 | if (ret < 0) { |
437 | dev_err(&dssdev->dev, "couldn't request reset GPIO\n"); | 438 | dev_err(&dssdev->dev, "couldn't request reset GPIO\n"); |
438 | goto fail_gpio_req; | 439 | goto fail_gpio_req; |
@@ -457,14 +458,11 @@ fail_regulator: | |||
457 | static void tpo_td043_remove(struct omap_dss_device *dssdev) | 458 | static void tpo_td043_remove(struct omap_dss_device *dssdev) |
458 | { | 459 | { |
459 | struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); | 460 | struct tpo_td043_device *tpo_td043 = dev_get_drvdata(&dssdev->dev); |
460 | int nreset_gpio = dssdev->reset_gpio; | ||
461 | 461 | ||
462 | dev_dbg(&dssdev->dev, "remove\n"); | 462 | dev_dbg(&dssdev->dev, "remove\n"); |
463 | 463 | ||
464 | sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group); | 464 | sysfs_remove_group(&dssdev->dev.kobj, &tpo_td043_attr_group); |
465 | regulator_put(tpo_td043->vcc_reg); | 465 | regulator_put(tpo_td043->vcc_reg); |
466 | if (gpio_is_valid(nreset_gpio)) | ||
467 | gpio_free(nreset_gpio); | ||
468 | } | 466 | } |
469 | 467 | ||
470 | static void tpo_td043_set_timings(struct omap_dss_device *dssdev, | 468 | static void tpo_td043_set_timings(struct omap_dss_device *dssdev, |
@@ -527,7 +525,6 @@ static int tpo_td043_spi_probe(struct spi_device *spi) | |||
527 | return -ENOMEM; | 525 | return -ENOMEM; |
528 | 526 | ||
529 | tpo_td043->spi = spi; | 527 | tpo_td043->spi = spi; |
530 | tpo_td043->nreset_gpio = dssdev->reset_gpio; | ||
531 | dev_set_drvdata(&spi->dev, tpo_td043); | 528 | dev_set_drvdata(&spi->dev, tpo_td043); |
532 | g_tpo_td043 = tpo_td043; | 529 | g_tpo_td043 = tpo_td043; |
533 | 530 | ||
diff --git a/drivers/video/omap2/dss/apply.c b/drivers/video/omap2/dss/apply.c index d446bdfc4c82..a4b356a9780d 100644 --- a/drivers/video/omap2/dss/apply.c +++ b/drivers/video/omap2/dss/apply.c | |||
@@ -435,20 +435,27 @@ static inline struct omap_dss_device *dss_mgr_get_device(struct omap_overlay_man | |||
435 | static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) | 435 | static int dss_mgr_wait_for_vsync(struct omap_overlay_manager *mgr) |
436 | { | 436 | { |
437 | unsigned long timeout = msecs_to_jiffies(500); | 437 | unsigned long timeout = msecs_to_jiffies(500); |
438 | struct omap_dss_device *dssdev = mgr->get_device(mgr); | ||
439 | u32 irq; | 438 | u32 irq; |
440 | int r; | 439 | int r; |
441 | 440 | ||
441 | if (mgr->output == NULL) | ||
442 | return -ENODEV; | ||
443 | |||
442 | r = dispc_runtime_get(); | 444 | r = dispc_runtime_get(); |
443 | if (r) | 445 | if (r) |
444 | return r; | 446 | return r; |
445 | 447 | ||
446 | if (dssdev->type == OMAP_DISPLAY_TYPE_VENC) | 448 | switch (mgr->output->id) { |
449 | case OMAP_DSS_OUTPUT_VENC: | ||
447 | irq = DISPC_IRQ_EVSYNC_ODD; | 450 | irq = DISPC_IRQ_EVSYNC_ODD; |
448 | else if (dssdev->type == OMAP_DISPLAY_TYPE_HDMI) | 451 | break; |
452 | case OMAP_DSS_OUTPUT_HDMI: | ||
449 | irq = DISPC_IRQ_EVSYNC_EVEN; | 453 | irq = DISPC_IRQ_EVSYNC_EVEN; |
450 | else | 454 | break; |
455 | default: | ||
451 | irq = dispc_mgr_get_vsync_irq(mgr->id); | 456 | irq = dispc_mgr_get_vsync_irq(mgr->id); |
457 | break; | ||
458 | } | ||
452 | 459 | ||
453 | r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); | 460 | r = omap_dispc_wait_for_irq_interruptible_timeout(irq, timeout); |
454 | 461 | ||
diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c index f8779d4750ba..60cc6fee6548 100644 --- a/drivers/video/omap2/dss/core.c +++ b/drivers/video/omap2/dss/core.c | |||
@@ -181,10 +181,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *)) | |||
181 | d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, | 181 | d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir, |
182 | write, &dss_debug_fops); | 182 | write, &dss_debug_fops); |
183 | 183 | ||
184 | if (IS_ERR(d)) | 184 | return PTR_RET(d); |
185 | return PTR_ERR(d); | ||
186 | |||
187 | return 0; | ||
188 | } | 185 | } |
189 | #else /* CONFIG_OMAP2_DSS_DEBUGFS */ | 186 | #else /* CONFIG_OMAP2_DSS_DEBUGFS */ |
190 | static inline int dss_initialize_debugfs(void) | 187 | static inline int dss_initialize_debugfs(void) |
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c index 05ff2b91d9e8..b33b0169bb3b 100644 --- a/drivers/video/omap2/dss/dispc.c +++ b/drivers/video/omap2/dss/dispc.c | |||
@@ -69,6 +69,8 @@ struct dispc_features { | |||
69 | u8 mgr_height_start; | 69 | u8 mgr_height_start; |
70 | u16 mgr_width_max; | 70 | u16 mgr_width_max; |
71 | u16 mgr_height_max; | 71 | u16 mgr_height_max; |
72 | unsigned long max_lcd_pclk; | ||
73 | unsigned long max_tv_pclk; | ||
72 | int (*calc_scaling) (unsigned long pclk, unsigned long lclk, | 74 | int (*calc_scaling) (unsigned long pclk, unsigned long lclk, |
73 | const struct omap_video_timings *mgr_timings, | 75 | const struct omap_video_timings *mgr_timings, |
74 | u16 width, u16 height, u16 out_width, u16 out_height, | 76 | u16 width, u16 height, u16 out_width, u16 out_height, |
@@ -85,6 +87,9 @@ struct dispc_features { | |||
85 | 87 | ||
86 | /* no DISPC_IRQ_FRAMEDONETV on this SoC */ | 88 | /* no DISPC_IRQ_FRAMEDONETV on this SoC */ |
87 | bool no_framedone_tv:1; | 89 | bool no_framedone_tv:1; |
90 | |||
91 | /* revert to the OMAP4 mechanism of DISPC Smart Standby operation */ | ||
92 | bool mstandby_workaround:1; | ||
88 | }; | 93 | }; |
89 | 94 | ||
90 | #define DISPC_MAX_NR_FIFOS 5 | 95 | #define DISPC_MAX_NR_FIFOS 5 |
@@ -97,6 +102,8 @@ static struct { | |||
97 | 102 | ||
98 | int irq; | 103 | int irq; |
99 | 104 | ||
105 | unsigned long core_clk_rate; | ||
106 | |||
100 | u32 fifo_size[DISPC_MAX_NR_FIFOS]; | 107 | u32 fifo_size[DISPC_MAX_NR_FIFOS]; |
101 | /* maps which plane is using a fifo. fifo-id -> plane-id */ | 108 | /* maps which plane is using a fifo. fifo-id -> plane-id */ |
102 | int fifo_assignment[DISPC_MAX_NR_FIFOS]; | 109 | int fifo_assignment[DISPC_MAX_NR_FIFOS]; |
@@ -1584,6 +1591,7 @@ static void dispc_ovl_set_scaling(enum omap_plane plane, | |||
1584 | } | 1591 | } |
1585 | 1592 | ||
1586 | static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, | 1593 | static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, |
1594 | enum omap_dss_rotation_type rotation_type, | ||
1587 | bool mirroring, enum omap_color_mode color_mode) | 1595 | bool mirroring, enum omap_color_mode color_mode) |
1588 | { | 1596 | { |
1589 | bool row_repeat = false; | 1597 | bool row_repeat = false; |
@@ -1634,6 +1642,15 @@ static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, | |||
1634 | if (dss_has_feature(FEAT_ROWREPEATENABLE)) | 1642 | if (dss_has_feature(FEAT_ROWREPEATENABLE)) |
1635 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), | 1643 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), |
1636 | row_repeat ? 1 : 0, 18, 18); | 1644 | row_repeat ? 1 : 0, 18, 18); |
1645 | |||
1646 | if (color_mode == OMAP_DSS_COLOR_NV12) { | ||
1647 | bool doublestride = (rotation_type == OMAP_DSS_ROT_TILER) && | ||
1648 | (rotation == OMAP_DSS_ROT_0 || | ||
1649 | rotation == OMAP_DSS_ROT_180); | ||
1650 | /* DOUBLESTRIDE */ | ||
1651 | REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), doublestride, 22, 22); | ||
1652 | } | ||
1653 | |||
1637 | } | 1654 | } |
1638 | 1655 | ||
1639 | static int color_mode_to_bpp(enum omap_color_mode color_mode) | 1656 | static int color_mode_to_bpp(enum omap_color_mode color_mode) |
@@ -2512,7 +2529,8 @@ static int dispc_ovl_setup_common(enum omap_plane plane, | |||
2512 | dispc_ovl_set_vid_color_conv(plane, cconv); | 2529 | dispc_ovl_set_vid_color_conv(plane, cconv); |
2513 | } | 2530 | } |
2514 | 2531 | ||
2515 | dispc_ovl_set_rotation_attrs(plane, rotation, mirror, color_mode); | 2532 | dispc_ovl_set_rotation_attrs(plane, rotation, rotation_type, mirror, |
2533 | color_mode); | ||
2516 | 2534 | ||
2517 | dispc_ovl_set_zorder(plane, caps, zorder); | 2535 | dispc_ovl_set_zorder(plane, caps, zorder); |
2518 | dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha); | 2536 | dispc_ovl_set_pre_mult_alpha(plane, caps, pre_mult_alpha); |
@@ -2823,6 +2841,15 @@ static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp, | |||
2823 | return true; | 2841 | return true; |
2824 | } | 2842 | } |
2825 | 2843 | ||
2844 | static bool _dispc_mgr_pclk_ok(enum omap_channel channel, | ||
2845 | unsigned long pclk) | ||
2846 | { | ||
2847 | if (dss_mgr_is_lcd(channel)) | ||
2848 | return pclk <= dispc.feat->max_lcd_pclk ? true : false; | ||
2849 | else | ||
2850 | return pclk <= dispc.feat->max_tv_pclk ? true : false; | ||
2851 | } | ||
2852 | |||
2826 | bool dispc_mgr_timings_ok(enum omap_channel channel, | 2853 | bool dispc_mgr_timings_ok(enum omap_channel channel, |
2827 | const struct omap_video_timings *timings) | 2854 | const struct omap_video_timings *timings) |
2828 | { | 2855 | { |
@@ -2830,11 +2857,13 @@ bool dispc_mgr_timings_ok(enum omap_channel channel, | |||
2830 | 2857 | ||
2831 | timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res); | 2858 | timings_ok = _dispc_mgr_size_ok(timings->x_res, timings->y_res); |
2832 | 2859 | ||
2833 | if (dss_mgr_is_lcd(channel)) | 2860 | timings_ok &= _dispc_mgr_pclk_ok(channel, timings->pixel_clock * 1000); |
2834 | timings_ok = timings_ok && _dispc_lcd_timings_ok(timings->hsw, | 2861 | |
2835 | timings->hfp, timings->hbp, | 2862 | if (dss_mgr_is_lcd(channel)) { |
2836 | timings->vsw, timings->vfp, | 2863 | timings_ok &= _dispc_lcd_timings_ok(timings->hsw, timings->hfp, |
2837 | timings->vbp); | 2864 | timings->hbp, timings->vsw, timings->vfp, |
2865 | timings->vbp); | ||
2866 | } | ||
2838 | 2867 | ||
2839 | return timings_ok; | 2868 | return timings_ok; |
2840 | } | 2869 | } |
@@ -2951,6 +2980,10 @@ static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, | |||
2951 | 2980 | ||
2952 | dispc_write_reg(DISPC_DIVISORo(channel), | 2981 | dispc_write_reg(DISPC_DIVISORo(channel), |
2953 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); | 2982 | FLD_VAL(lck_div, 23, 16) | FLD_VAL(pck_div, 7, 0)); |
2983 | |||
2984 | if (dss_has_feature(FEAT_CORE_CLK_DIV) == false && | ||
2985 | channel == OMAP_DSS_CHANNEL_LCD) | ||
2986 | dispc.core_clk_rate = dispc_fclk_rate() / lck_div; | ||
2954 | } | 2987 | } |
2955 | 2988 | ||
2956 | static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div, | 2989 | static void dispc_mgr_get_lcd_divisor(enum omap_channel channel, int *lck_div, |
@@ -3056,15 +3089,7 @@ unsigned long dispc_mgr_pclk_rate(enum omap_channel channel) | |||
3056 | 3089 | ||
3057 | unsigned long dispc_core_clk_rate(void) | 3090 | unsigned long dispc_core_clk_rate(void) |
3058 | { | 3091 | { |
3059 | int lcd; | 3092 | return dispc.core_clk_rate; |
3060 | unsigned long fclk = dispc_fclk_rate(); | ||
3061 | |||
3062 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | ||
3063 | lcd = REG_GET(DISPC_DIVISOR, 23, 16); | ||
3064 | else | ||
3065 | lcd = REG_GET(DISPC_DIVISORo(OMAP_DSS_CHANNEL_LCD), 23, 16); | ||
3066 | |||
3067 | return fclk / lcd; | ||
3068 | } | 3093 | } |
3069 | 3094 | ||
3070 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) | 3095 | static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) |
@@ -3313,67 +3338,79 @@ static void dispc_dump_regs(struct seq_file *s) | |||
3313 | #undef DUMPREG | 3338 | #undef DUMPREG |
3314 | } | 3339 | } |
3315 | 3340 | ||
3316 | /* with fck as input clock rate, find dispc dividers that produce req_pck */ | 3341 | /* calculate clock rates using dividers in cinfo */ |
3317 | void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck, | 3342 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, |
3318 | struct dispc_clock_info *cinfo) | 3343 | struct dispc_clock_info *cinfo) |
3319 | { | 3344 | { |
3320 | u16 pcd_min, pcd_max; | 3345 | if (cinfo->lck_div > 255 || cinfo->lck_div == 0) |
3321 | unsigned long best_pck; | 3346 | return -EINVAL; |
3322 | u16 best_ld, cur_ld; | 3347 | if (cinfo->pck_div < 1 || cinfo->pck_div > 255) |
3323 | u16 best_pd, cur_pd; | 3348 | return -EINVAL; |
3324 | 3349 | ||
3325 | pcd_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); | 3350 | cinfo->lck = dispc_fclk_rate / cinfo->lck_div; |
3326 | pcd_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); | 3351 | cinfo->pck = cinfo->lck / cinfo->pck_div; |
3327 | 3352 | ||
3328 | best_pck = 0; | 3353 | return 0; |
3329 | best_ld = 0; | 3354 | } |
3330 | best_pd = 0; | ||
3331 | 3355 | ||
3332 | for (cur_ld = 1; cur_ld <= 255; ++cur_ld) { | 3356 | bool dispc_div_calc(unsigned long dispc, |
3333 | unsigned long lck = fck / cur_ld; | 3357 | unsigned long pck_min, unsigned long pck_max, |
3358 | dispc_div_calc_func func, void *data) | ||
3359 | { | ||
3360 | int lckd, lckd_start, lckd_stop; | ||
3361 | int pckd, pckd_start, pckd_stop; | ||
3362 | unsigned long pck, lck; | ||
3363 | unsigned long lck_max; | ||
3364 | unsigned long pckd_hw_min, pckd_hw_max; | ||
3365 | unsigned min_fck_per_pck; | ||
3366 | unsigned long fck; | ||
3334 | 3367 | ||
3335 | for (cur_pd = pcd_min; cur_pd <= pcd_max; ++cur_pd) { | 3368 | #ifdef CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK |
3336 | unsigned long pck = lck / cur_pd; | 3369 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; |
3337 | long old_delta = abs(best_pck - req_pck); | 3370 | #else |
3338 | long new_delta = abs(pck - req_pck); | 3371 | min_fck_per_pck = 0; |
3372 | #endif | ||
3339 | 3373 | ||
3340 | if (best_pck == 0 || new_delta < old_delta) { | 3374 | pckd_hw_min = dss_feat_get_param_min(FEAT_PARAM_DSS_PCD); |
3341 | best_pck = pck; | 3375 | pckd_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_PCD); |
3342 | best_ld = cur_ld; | ||
3343 | best_pd = cur_pd; | ||
3344 | 3376 | ||
3345 | if (pck == req_pck) | 3377 | lck_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); |
3346 | goto found; | ||
3347 | } | ||
3348 | 3378 | ||
3349 | if (pck < req_pck) | 3379 | pck_min = pck_min ? pck_min : 1; |
3350 | break; | 3380 | pck_max = pck_max ? pck_max : ULONG_MAX; |
3351 | } | ||
3352 | 3381 | ||
3353 | if (lck / pcd_min < req_pck) | 3382 | lckd_start = max(DIV_ROUND_UP(dispc, lck_max), 1ul); |
3354 | break; | 3383 | lckd_stop = min(dispc / pck_min, 255ul); |
3355 | } | ||
3356 | 3384 | ||
3357 | found: | 3385 | for (lckd = lckd_start; lckd <= lckd_stop; ++lckd) { |
3358 | cinfo->lck_div = best_ld; | 3386 | lck = dispc / lckd; |
3359 | cinfo->pck_div = best_pd; | ||
3360 | cinfo->lck = fck / cinfo->lck_div; | ||
3361 | cinfo->pck = cinfo->lck / cinfo->pck_div; | ||
3362 | } | ||
3363 | 3387 | ||
3364 | /* calculate clock rates using dividers in cinfo */ | 3388 | pckd_start = max(DIV_ROUND_UP(lck, pck_max), pckd_hw_min); |
3365 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | 3389 | pckd_stop = min(lck / pck_min, pckd_hw_max); |
3366 | struct dispc_clock_info *cinfo) | ||
3367 | { | ||
3368 | if (cinfo->lck_div > 255 || cinfo->lck_div == 0) | ||
3369 | return -EINVAL; | ||
3370 | if (cinfo->pck_div < 1 || cinfo->pck_div > 255) | ||
3371 | return -EINVAL; | ||
3372 | 3390 | ||
3373 | cinfo->lck = dispc_fclk_rate / cinfo->lck_div; | 3391 | for (pckd = pckd_start; pckd <= pckd_stop; ++pckd) { |
3374 | cinfo->pck = cinfo->lck / cinfo->pck_div; | 3392 | pck = lck / pckd; |
3375 | 3393 | ||
3376 | return 0; | 3394 | /* |
3395 | * For OMAP2/3 the DISPC fclk is the same as LCD's logic | ||
3396 | * clock, which means we're configuring DISPC fclk here | ||
3397 | * also. Thus we need to use the calculated lck. For | ||
3398 | * OMAP4+ the DISPC fclk is a separate clock. | ||
3399 | */ | ||
3400 | if (dss_has_feature(FEAT_CORE_CLK_DIV)) | ||
3401 | fck = dispc_core_clk_rate(); | ||
3402 | else | ||
3403 | fck = lck; | ||
3404 | |||
3405 | if (fck < pck * min_fck_per_pck) | ||
3406 | continue; | ||
3407 | |||
3408 | if (func(lckd, pckd, lck, pck, data)) | ||
3409 | return true; | ||
3410 | } | ||
3411 | } | ||
3412 | |||
3413 | return false; | ||
3377 | } | 3414 | } |
3378 | 3415 | ||
3379 | void dispc_mgr_set_clock_div(enum omap_channel channel, | 3416 | void dispc_mgr_set_clock_div(enum omap_channel channel, |
@@ -3451,6 +3488,8 @@ static void _omap_dispc_initial_config(void) | |||
3451 | l = FLD_MOD(l, 1, 0, 0); | 3488 | l = FLD_MOD(l, 1, 0, 0); |
3452 | l = FLD_MOD(l, 1, 23, 16); | 3489 | l = FLD_MOD(l, 1, 23, 16); |
3453 | dispc_write_reg(DISPC_DIVISOR, l); | 3490 | dispc_write_reg(DISPC_DIVISOR, l); |
3491 | |||
3492 | dispc.core_clk_rate = dispc_fclk_rate(); | ||
3454 | } | 3493 | } |
3455 | 3494 | ||
3456 | /* FUNCGATED */ | 3495 | /* FUNCGATED */ |
@@ -3466,6 +3505,9 @@ static void _omap_dispc_initial_config(void) | |||
3466 | dispc_configure_burst_sizes(); | 3505 | dispc_configure_burst_sizes(); |
3467 | 3506 | ||
3468 | dispc_ovl_enable_zorder_planes(); | 3507 | dispc_ovl_enable_zorder_planes(); |
3508 | |||
3509 | if (dispc.feat->mstandby_workaround) | ||
3510 | REG_FLD_MOD(DISPC_MSTANDBY_CTRL, 1, 0, 0); | ||
3469 | } | 3511 | } |
3470 | 3512 | ||
3471 | static const struct dispc_features omap24xx_dispc_feats __initconst = { | 3513 | static const struct dispc_features omap24xx_dispc_feats __initconst = { |
@@ -3479,6 +3521,7 @@ static const struct dispc_features omap24xx_dispc_feats __initconst = { | |||
3479 | .mgr_height_start = 26, | 3521 | .mgr_height_start = 26, |
3480 | .mgr_width_max = 2048, | 3522 | .mgr_width_max = 2048, |
3481 | .mgr_height_max = 2048, | 3523 | .mgr_height_max = 2048, |
3524 | .max_lcd_pclk = 66500000, | ||
3482 | .calc_scaling = dispc_ovl_calc_scaling_24xx, | 3525 | .calc_scaling = dispc_ovl_calc_scaling_24xx, |
3483 | .calc_core_clk = calc_core_clk_24xx, | 3526 | .calc_core_clk = calc_core_clk_24xx, |
3484 | .num_fifos = 3, | 3527 | .num_fifos = 3, |
@@ -3496,6 +3539,8 @@ static const struct dispc_features omap34xx_rev1_0_dispc_feats __initconst = { | |||
3496 | .mgr_height_start = 26, | 3539 | .mgr_height_start = 26, |
3497 | .mgr_width_max = 2048, | 3540 | .mgr_width_max = 2048, |
3498 | .mgr_height_max = 2048, | 3541 | .mgr_height_max = 2048, |
3542 | .max_lcd_pclk = 173000000, | ||
3543 | .max_tv_pclk = 59000000, | ||
3499 | .calc_scaling = dispc_ovl_calc_scaling_34xx, | 3544 | .calc_scaling = dispc_ovl_calc_scaling_34xx, |
3500 | .calc_core_clk = calc_core_clk_34xx, | 3545 | .calc_core_clk = calc_core_clk_34xx, |
3501 | .num_fifos = 3, | 3546 | .num_fifos = 3, |
@@ -3513,6 +3558,8 @@ static const struct dispc_features omap34xx_rev3_0_dispc_feats __initconst = { | |||
3513 | .mgr_height_start = 26, | 3558 | .mgr_height_start = 26, |
3514 | .mgr_width_max = 2048, | 3559 | .mgr_width_max = 2048, |
3515 | .mgr_height_max = 2048, | 3560 | .mgr_height_max = 2048, |
3561 | .max_lcd_pclk = 173000000, | ||
3562 | .max_tv_pclk = 59000000, | ||
3516 | .calc_scaling = dispc_ovl_calc_scaling_34xx, | 3563 | .calc_scaling = dispc_ovl_calc_scaling_34xx, |
3517 | .calc_core_clk = calc_core_clk_34xx, | 3564 | .calc_core_clk = calc_core_clk_34xx, |
3518 | .num_fifos = 3, | 3565 | .num_fifos = 3, |
@@ -3530,6 +3577,8 @@ static const struct dispc_features omap44xx_dispc_feats __initconst = { | |||
3530 | .mgr_height_start = 26, | 3577 | .mgr_height_start = 26, |
3531 | .mgr_width_max = 2048, | 3578 | .mgr_width_max = 2048, |
3532 | .mgr_height_max = 2048, | 3579 | .mgr_height_max = 2048, |
3580 | .max_lcd_pclk = 170000000, | ||
3581 | .max_tv_pclk = 185625000, | ||
3533 | .calc_scaling = dispc_ovl_calc_scaling_44xx, | 3582 | .calc_scaling = dispc_ovl_calc_scaling_44xx, |
3534 | .calc_core_clk = calc_core_clk_44xx, | 3583 | .calc_core_clk = calc_core_clk_44xx, |
3535 | .num_fifos = 5, | 3584 | .num_fifos = 5, |
@@ -3547,10 +3596,13 @@ static const struct dispc_features omap54xx_dispc_feats __initconst = { | |||
3547 | .mgr_height_start = 27, | 3596 | .mgr_height_start = 27, |
3548 | .mgr_width_max = 4096, | 3597 | .mgr_width_max = 4096, |
3549 | .mgr_height_max = 4096, | 3598 | .mgr_height_max = 4096, |
3599 | .max_lcd_pclk = 170000000, | ||
3600 | .max_tv_pclk = 186000000, | ||
3550 | .calc_scaling = dispc_ovl_calc_scaling_44xx, | 3601 | .calc_scaling = dispc_ovl_calc_scaling_44xx, |
3551 | .calc_core_clk = calc_core_clk_44xx, | 3602 | .calc_core_clk = calc_core_clk_44xx, |
3552 | .num_fifos = 5, | 3603 | .num_fifos = 5, |
3553 | .gfx_fifo_workaround = true, | 3604 | .gfx_fifo_workaround = true, |
3605 | .mstandby_workaround = true, | ||
3554 | }; | 3606 | }; |
3555 | 3607 | ||
3556 | static int __init dispc_init_features(struct platform_device *pdev) | 3608 | static int __init dispc_init_features(struct platform_device *pdev) |
diff --git a/drivers/video/omap2/dss/dispc.h b/drivers/video/omap2/dss/dispc.h index 222363c6e623..de4863d21ab7 100644 --- a/drivers/video/omap2/dss/dispc.h +++ b/drivers/video/omap2/dss/dispc.h | |||
@@ -39,6 +39,7 @@ | |||
39 | #define DISPC_GLOBAL_BUFFER 0x0800 | 39 | #define DISPC_GLOBAL_BUFFER 0x0800 |
40 | #define DISPC_CONTROL3 0x0848 | 40 | #define DISPC_CONTROL3 0x0848 |
41 | #define DISPC_CONFIG3 0x084C | 41 | #define DISPC_CONFIG3 0x084C |
42 | #define DISPC_MSTANDBY_CTRL 0x0858 | ||
42 | 43 | ||
43 | /* DISPC overlay registers */ | 44 | /* DISPC overlay registers */ |
44 | #define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \ | 45 | #define DISPC_OVL_BA0(n) (DISPC_OVL_BASE(n) + \ |
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c index 4af136a04e53..757b57f7275a 100644 --- a/drivers/video/omap2/dss/dpi.c +++ b/drivers/video/omap2/dss/dpi.c | |||
@@ -63,15 +63,29 @@ static struct platform_device *dpi_get_dsidev(enum omap_channel channel) | |||
63 | case OMAPDSS_VER_OMAP3630: | 63 | case OMAPDSS_VER_OMAP3630: |
64 | case OMAPDSS_VER_AM35xx: | 64 | case OMAPDSS_VER_AM35xx: |
65 | return NULL; | 65 | return NULL; |
66 | default: | ||
67 | break; | ||
68 | } | ||
69 | 66 | ||
70 | switch (channel) { | 67 | case OMAPDSS_VER_OMAP4430_ES1: |
71 | case OMAP_DSS_CHANNEL_LCD: | 68 | case OMAPDSS_VER_OMAP4430_ES2: |
72 | return dsi_get_dsidev_from_id(0); | 69 | case OMAPDSS_VER_OMAP4: |
73 | case OMAP_DSS_CHANNEL_LCD2: | 70 | switch (channel) { |
74 | return dsi_get_dsidev_from_id(1); | 71 | case OMAP_DSS_CHANNEL_LCD: |
72 | return dsi_get_dsidev_from_id(0); | ||
73 | case OMAP_DSS_CHANNEL_LCD2: | ||
74 | return dsi_get_dsidev_from_id(1); | ||
75 | default: | ||
76 | return NULL; | ||
77 | } | ||
78 | |||
79 | case OMAPDSS_VER_OMAP5: | ||
80 | switch (channel) { | ||
81 | case OMAP_DSS_CHANNEL_LCD: | ||
82 | return dsi_get_dsidev_from_id(0); | ||
83 | case OMAP_DSS_CHANNEL_LCD3: | ||
84 | return dsi_get_dsidev_from_id(1); | ||
85 | default: | ||
86 | return NULL; | ||
87 | } | ||
88 | |||
75 | default: | 89 | default: |
76 | return NULL; | 90 | return NULL; |
77 | } | 91 | } |
@@ -91,75 +105,211 @@ static enum omap_dss_clk_source dpi_get_alt_clk_src(enum omap_channel channel) | |||
91 | } | 105 | } |
92 | } | 106 | } |
93 | 107 | ||
94 | static int dpi_set_dsi_clk(struct omap_dss_device *dssdev, | 108 | struct dpi_clk_calc_ctx { |
109 | struct platform_device *dsidev; | ||
110 | |||
111 | /* inputs */ | ||
112 | |||
113 | unsigned long pck_min, pck_max; | ||
114 | |||
115 | /* outputs */ | ||
116 | |||
117 | struct dsi_clock_info dsi_cinfo; | ||
118 | struct dss_clock_info dss_cinfo; | ||
119 | struct dispc_clock_info dispc_cinfo; | ||
120 | }; | ||
121 | |||
122 | static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck, | ||
123 | unsigned long pck, void *data) | ||
124 | { | ||
125 | struct dpi_clk_calc_ctx *ctx = data; | ||
126 | |||
127 | /* | ||
128 | * Odd dividers give us uneven duty cycle, causing problem when level | ||
129 | * shifted. So skip all odd dividers when the pixel clock is on the | ||
130 | * higher side. | ||
131 | */ | ||
132 | if (ctx->pck_min >= 1000000) { | ||
133 | if (lckd > 1 && lckd % 2 != 0) | ||
134 | return false; | ||
135 | |||
136 | if (pckd > 1 && pckd % 2 != 0) | ||
137 | return false; | ||
138 | } | ||
139 | |||
140 | ctx->dispc_cinfo.lck_div = lckd; | ||
141 | ctx->dispc_cinfo.pck_div = pckd; | ||
142 | ctx->dispc_cinfo.lck = lck; | ||
143 | ctx->dispc_cinfo.pck = pck; | ||
144 | |||
145 | return true; | ||
146 | } | ||
147 | |||
148 | |||
149 | static bool dpi_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, | ||
150 | void *data) | ||
151 | { | ||
152 | struct dpi_clk_calc_ctx *ctx = data; | ||
153 | |||
154 | /* | ||
155 | * Odd dividers give us uneven duty cycle, causing problem when level | ||
156 | * shifted. So skip all odd dividers when the pixel clock is on the | ||
157 | * higher side. | ||
158 | */ | ||
159 | if (regm_dispc > 1 && regm_dispc % 2 != 0 && ctx->pck_min >= 1000000) | ||
160 | return false; | ||
161 | |||
162 | ctx->dsi_cinfo.regm_dispc = regm_dispc; | ||
163 | ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc; | ||
164 | |||
165 | return dispc_div_calc(dispc, ctx->pck_min, ctx->pck_max, | ||
166 | dpi_calc_dispc_cb, ctx); | ||
167 | } | ||
168 | |||
169 | |||
170 | static bool dpi_calc_pll_cb(int regn, int regm, unsigned long fint, | ||
171 | unsigned long pll, | ||
172 | void *data) | ||
173 | { | ||
174 | struct dpi_clk_calc_ctx *ctx = data; | ||
175 | |||
176 | ctx->dsi_cinfo.regn = regn; | ||
177 | ctx->dsi_cinfo.regm = regm; | ||
178 | ctx->dsi_cinfo.fint = fint; | ||
179 | ctx->dsi_cinfo.clkin4ddr = pll; | ||
180 | |||
181 | return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->pck_min, | ||
182 | dpi_calc_hsdiv_cb, ctx); | ||
183 | } | ||
184 | |||
185 | static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data) | ||
186 | { | ||
187 | struct dpi_clk_calc_ctx *ctx = data; | ||
188 | |||
189 | ctx->dss_cinfo.fck = fck; | ||
190 | ctx->dss_cinfo.fck_div = fckd; | ||
191 | |||
192 | return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max, | ||
193 | dpi_calc_dispc_cb, ctx); | ||
194 | } | ||
195 | |||
196 | static bool dpi_dsi_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) | ||
197 | { | ||
198 | unsigned long clkin; | ||
199 | unsigned long pll_min, pll_max; | ||
200 | |||
201 | clkin = dsi_get_pll_clkin(dpi.dsidev); | ||
202 | |||
203 | memset(ctx, 0, sizeof(*ctx)); | ||
204 | ctx->dsidev = dpi.dsidev; | ||
205 | ctx->pck_min = pck - 1000; | ||
206 | ctx->pck_max = pck + 1000; | ||
207 | ctx->dsi_cinfo.clkin = clkin; | ||
208 | |||
209 | pll_min = 0; | ||
210 | pll_max = 0; | ||
211 | |||
212 | return dsi_pll_calc(dpi.dsidev, clkin, | ||
213 | pll_min, pll_max, | ||
214 | dpi_calc_pll_cb, ctx); | ||
215 | } | ||
216 | |||
217 | static bool dpi_dss_clk_calc(unsigned long pck, struct dpi_clk_calc_ctx *ctx) | ||
218 | { | ||
219 | int i; | ||
220 | |||
221 | /* | ||
222 | * DSS fck gives us very few possibilities, so finding a good pixel | ||
223 | * clock may not be possible. We try multiple times to find the clock, | ||
224 | * each time widening the pixel clock range we look for, up to | ||
225 | * +/- ~15MHz. | ||
226 | */ | ||
227 | |||
228 | for (i = 0; i < 25; ++i) { | ||
229 | bool ok; | ||
230 | |||
231 | memset(ctx, 0, sizeof(*ctx)); | ||
232 | if (pck > 1000 * i * i * i) | ||
233 | ctx->pck_min = max(pck - 1000 * i * i * i, 0lu); | ||
234 | else | ||
235 | ctx->pck_min = 0; | ||
236 | ctx->pck_max = pck + 1000 * i * i * i; | ||
237 | |||
238 | ok = dss_div_calc(ctx->pck_min, dpi_calc_dss_cb, ctx); | ||
239 | if (ok) | ||
240 | return ok; | ||
241 | } | ||
242 | |||
243 | return false; | ||
244 | } | ||
245 | |||
246 | |||
247 | |||
248 | static int dpi_set_dsi_clk(enum omap_channel channel, | ||
95 | unsigned long pck_req, unsigned long *fck, int *lck_div, | 249 | unsigned long pck_req, unsigned long *fck, int *lck_div, |
96 | int *pck_div) | 250 | int *pck_div) |
97 | { | 251 | { |
98 | struct omap_overlay_manager *mgr = dssdev->output->manager; | 252 | struct dpi_clk_calc_ctx ctx; |
99 | struct dsi_clock_info dsi_cinfo; | ||
100 | struct dispc_clock_info dispc_cinfo; | ||
101 | int r; | 253 | int r; |
254 | bool ok; | ||
102 | 255 | ||
103 | r = dsi_pll_calc_clock_div_pck(dpi.dsidev, pck_req, &dsi_cinfo, | 256 | ok = dpi_dsi_clk_calc(pck_req, &ctx); |
104 | &dispc_cinfo); | 257 | if (!ok) |
105 | if (r) | 258 | return -EINVAL; |
106 | return r; | ||
107 | 259 | ||
108 | r = dsi_pll_set_clock_div(dpi.dsidev, &dsi_cinfo); | 260 | r = dsi_pll_set_clock_div(dpi.dsidev, &ctx.dsi_cinfo); |
109 | if (r) | 261 | if (r) |
110 | return r; | 262 | return r; |
111 | 263 | ||
112 | dss_select_lcd_clk_source(mgr->id, | 264 | dss_select_lcd_clk_source(channel, |
113 | dpi_get_alt_clk_src(mgr->id)); | 265 | dpi_get_alt_clk_src(channel)); |
114 | 266 | ||
115 | dpi.mgr_config.clock_info = dispc_cinfo; | 267 | dpi.mgr_config.clock_info = ctx.dispc_cinfo; |
116 | 268 | ||
117 | *fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; | 269 | *fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
118 | *lck_div = dispc_cinfo.lck_div; | 270 | *lck_div = ctx.dispc_cinfo.lck_div; |
119 | *pck_div = dispc_cinfo.pck_div; | 271 | *pck_div = ctx.dispc_cinfo.pck_div; |
120 | 272 | ||
121 | return 0; | 273 | return 0; |
122 | } | 274 | } |
123 | 275 | ||
124 | static int dpi_set_dispc_clk(struct omap_dss_device *dssdev, | 276 | static int dpi_set_dispc_clk(unsigned long pck_req, unsigned long *fck, |
125 | unsigned long pck_req, unsigned long *fck, int *lck_div, | 277 | int *lck_div, int *pck_div) |
126 | int *pck_div) | ||
127 | { | 278 | { |
128 | struct dss_clock_info dss_cinfo; | 279 | struct dpi_clk_calc_ctx ctx; |
129 | struct dispc_clock_info dispc_cinfo; | ||
130 | int r; | 280 | int r; |
281 | bool ok; | ||
131 | 282 | ||
132 | r = dss_calc_clock_div(pck_req, &dss_cinfo, &dispc_cinfo); | 283 | ok = dpi_dss_clk_calc(pck_req, &ctx); |
133 | if (r) | 284 | if (!ok) |
134 | return r; | 285 | return -EINVAL; |
135 | 286 | ||
136 | r = dss_set_clock_div(&dss_cinfo); | 287 | r = dss_set_clock_div(&ctx.dss_cinfo); |
137 | if (r) | 288 | if (r) |
138 | return r; | 289 | return r; |
139 | 290 | ||
140 | dpi.mgr_config.clock_info = dispc_cinfo; | 291 | dpi.mgr_config.clock_info = ctx.dispc_cinfo; |
141 | 292 | ||
142 | *fck = dss_cinfo.fck; | 293 | *fck = ctx.dss_cinfo.fck; |
143 | *lck_div = dispc_cinfo.lck_div; | 294 | *lck_div = ctx.dispc_cinfo.lck_div; |
144 | *pck_div = dispc_cinfo.pck_div; | 295 | *pck_div = ctx.dispc_cinfo.pck_div; |
145 | 296 | ||
146 | return 0; | 297 | return 0; |
147 | } | 298 | } |
148 | 299 | ||
149 | static int dpi_set_mode(struct omap_dss_device *dssdev) | 300 | static int dpi_set_mode(struct omap_overlay_manager *mgr) |
150 | { | 301 | { |
151 | struct omap_video_timings *t = &dpi.timings; | 302 | struct omap_video_timings *t = &dpi.timings; |
152 | struct omap_overlay_manager *mgr = dssdev->output->manager; | ||
153 | int lck_div = 0, pck_div = 0; | 303 | int lck_div = 0, pck_div = 0; |
154 | unsigned long fck = 0; | 304 | unsigned long fck = 0; |
155 | unsigned long pck; | 305 | unsigned long pck; |
156 | int r = 0; | 306 | int r = 0; |
157 | 307 | ||
158 | if (dpi.dsidev) | 308 | if (dpi.dsidev) |
159 | r = dpi_set_dsi_clk(dssdev, t->pixel_clock * 1000, &fck, | 309 | r = dpi_set_dsi_clk(mgr->id, t->pixel_clock * 1000, &fck, |
160 | &lck_div, &pck_div); | 310 | &lck_div, &pck_div); |
161 | else | 311 | else |
162 | r = dpi_set_dispc_clk(dssdev, t->pixel_clock * 1000, &fck, | 312 | r = dpi_set_dispc_clk(t->pixel_clock * 1000, &fck, |
163 | &lck_div, &pck_div); | 313 | &lck_div, &pck_div); |
164 | if (r) | 314 | if (r) |
165 | return r; | 315 | return r; |
@@ -179,10 +329,8 @@ static int dpi_set_mode(struct omap_dss_device *dssdev) | |||
179 | return 0; | 329 | return 0; |
180 | } | 330 | } |
181 | 331 | ||
182 | static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) | 332 | static void dpi_config_lcd_manager(struct omap_overlay_manager *mgr) |
183 | { | 333 | { |
184 | struct omap_overlay_manager *mgr = dssdev->output->manager; | ||
185 | |||
186 | dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; | 334 | dpi.mgr_config.io_pad_mode = DSS_IO_PAD_MODE_BYPASS; |
187 | 335 | ||
188 | dpi.mgr_config.stallmode = false; | 336 | dpi.mgr_config.stallmode = false; |
@@ -197,7 +345,7 @@ static void dpi_config_lcd_manager(struct omap_dss_device *dssdev) | |||
197 | 345 | ||
198 | int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | 346 | int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) |
199 | { | 347 | { |
200 | struct omap_dss_output *out = dssdev->output; | 348 | struct omap_dss_output *out = &dpi.output; |
201 | int r; | 349 | int r; |
202 | 350 | ||
203 | mutex_lock(&dpi.lock); | 351 | mutex_lock(&dpi.lock); |
@@ -230,7 +378,7 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
230 | if (r) | 378 | if (r) |
231 | goto err_get_dispc; | 379 | goto err_get_dispc; |
232 | 380 | ||
233 | r = dss_dpi_select_source(dssdev->channel); | 381 | r = dss_dpi_select_source(out->manager->id); |
234 | if (r) | 382 | if (r) |
235 | goto err_src_sel; | 383 | goto err_src_sel; |
236 | 384 | ||
@@ -244,11 +392,11 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev) | |||
244 | goto err_dsi_pll_init; | 392 | goto err_dsi_pll_init; |
245 | } | 393 | } |
246 | 394 | ||
247 | r = dpi_set_mode(dssdev); | 395 | r = dpi_set_mode(out->manager); |
248 | if (r) | 396 | if (r) |
249 | goto err_set_mode; | 397 | goto err_set_mode; |
250 | 398 | ||
251 | dpi_config_lcd_manager(dssdev); | 399 | dpi_config_lcd_manager(out->manager); |
252 | 400 | ||
253 | mdelay(2); | 401 | mdelay(2); |
254 | 402 | ||
@@ -285,7 +433,7 @@ EXPORT_SYMBOL(omapdss_dpi_display_enable); | |||
285 | 433 | ||
286 | void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) | 434 | void omapdss_dpi_display_disable(struct omap_dss_device *dssdev) |
287 | { | 435 | { |
288 | struct omap_overlay_manager *mgr = dssdev->output->manager; | 436 | struct omap_overlay_manager *mgr = dpi.output.manager; |
289 | 437 | ||
290 | mutex_lock(&dpi.lock); | 438 | mutex_lock(&dpi.lock); |
291 | 439 | ||
@@ -324,12 +472,12 @@ EXPORT_SYMBOL(omapdss_dpi_set_timings); | |||
324 | int dpi_check_timings(struct omap_dss_device *dssdev, | 472 | int dpi_check_timings(struct omap_dss_device *dssdev, |
325 | struct omap_video_timings *timings) | 473 | struct omap_video_timings *timings) |
326 | { | 474 | { |
327 | int r; | 475 | struct omap_overlay_manager *mgr = dpi.output.manager; |
328 | struct omap_overlay_manager *mgr = dssdev->output->manager; | ||
329 | int lck_div, pck_div; | 476 | int lck_div, pck_div; |
330 | unsigned long fck; | 477 | unsigned long fck; |
331 | unsigned long pck; | 478 | unsigned long pck; |
332 | struct dispc_clock_info dispc_cinfo; | 479 | struct dpi_clk_calc_ctx ctx; |
480 | bool ok; | ||
333 | 481 | ||
334 | if (mgr && !dispc_mgr_timings_ok(mgr->id, timings)) | 482 | if (mgr && !dispc_mgr_timings_ok(mgr->id, timings)) |
335 | return -EINVAL; | 483 | return -EINVAL; |
@@ -338,28 +486,21 @@ int dpi_check_timings(struct omap_dss_device *dssdev, | |||
338 | return -EINVAL; | 486 | return -EINVAL; |
339 | 487 | ||
340 | if (dpi.dsidev) { | 488 | if (dpi.dsidev) { |
341 | struct dsi_clock_info dsi_cinfo; | 489 | ok = dpi_dsi_clk_calc(timings->pixel_clock * 1000, &ctx); |
342 | r = dsi_pll_calc_clock_div_pck(dpi.dsidev, | 490 | if (!ok) |
343 | timings->pixel_clock * 1000, | 491 | return -EINVAL; |
344 | &dsi_cinfo, &dispc_cinfo); | ||
345 | 492 | ||
346 | if (r) | 493 | fck = ctx.dsi_cinfo.dsi_pll_hsdiv_dispc_clk; |
347 | return r; | ||
348 | |||
349 | fck = dsi_cinfo.dsi_pll_hsdiv_dispc_clk; | ||
350 | } else { | 494 | } else { |
351 | struct dss_clock_info dss_cinfo; | 495 | ok = dpi_dss_clk_calc(timings->pixel_clock * 1000, &ctx); |
352 | r = dss_calc_clock_div(timings->pixel_clock * 1000, | 496 | if (!ok) |
353 | &dss_cinfo, &dispc_cinfo); | 497 | return -EINVAL; |
354 | 498 | ||
355 | if (r) | 499 | fck = ctx.dss_cinfo.fck; |
356 | return r; | ||
357 | |||
358 | fck = dss_cinfo.fck; | ||
359 | } | 500 | } |
360 | 501 | ||
361 | lck_div = dispc_cinfo.lck_div; | 502 | lck_div = ctx.dispc_cinfo.lck_div; |
362 | pck_div = dispc_cinfo.pck_div; | 503 | pck_div = ctx.dispc_cinfo.pck_div; |
363 | 504 | ||
364 | pck = fck / lck_div / pck_div / 1000; | 505 | pck = fck / lck_div / pck_div / 1000; |
365 | 506 | ||
@@ -379,7 +520,7 @@ void omapdss_dpi_set_data_lines(struct omap_dss_device *dssdev, int data_lines) | |||
379 | } | 520 | } |
380 | EXPORT_SYMBOL(omapdss_dpi_set_data_lines); | 521 | EXPORT_SYMBOL(omapdss_dpi_set_data_lines); |
381 | 522 | ||
382 | static int __init dpi_verify_dsi_pll(struct platform_device *dsidev) | 523 | static int dpi_verify_dsi_pll(struct platform_device *dsidev) |
383 | { | 524 | { |
384 | int r; | 525 | int r; |
385 | 526 | ||
@@ -401,7 +542,37 @@ static int __init dpi_verify_dsi_pll(struct platform_device *dsidev) | |||
401 | return 0; | 542 | return 0; |
402 | } | 543 | } |
403 | 544 | ||
404 | static int __init dpi_init_display(struct omap_dss_device *dssdev) | 545 | /* |
546 | * Return a hardcoded channel for the DPI output. This should work for | ||
547 | * current use cases, but this can be later expanded to either resolve | ||
548 | * the channel in some more dynamic manner, or get the channel as a user | ||
549 | * parameter. | ||
550 | */ | ||
551 | static enum omap_channel dpi_get_channel(void) | ||
552 | { | ||
553 | switch (omapdss_get_version()) { | ||
554 | case OMAPDSS_VER_OMAP24xx: | ||
555 | case OMAPDSS_VER_OMAP34xx_ES1: | ||
556 | case OMAPDSS_VER_OMAP34xx_ES3: | ||
557 | case OMAPDSS_VER_OMAP3630: | ||
558 | case OMAPDSS_VER_AM35xx: | ||
559 | return OMAP_DSS_CHANNEL_LCD; | ||
560 | |||
561 | case OMAPDSS_VER_OMAP4430_ES1: | ||
562 | case OMAPDSS_VER_OMAP4430_ES2: | ||
563 | case OMAPDSS_VER_OMAP4: | ||
564 | return OMAP_DSS_CHANNEL_LCD2; | ||
565 | |||
566 | case OMAPDSS_VER_OMAP5: | ||
567 | return OMAP_DSS_CHANNEL_LCD3; | ||
568 | |||
569 | default: | ||
570 | DSSWARN("unsupported DSS version\n"); | ||
571 | return OMAP_DSS_CHANNEL_LCD; | ||
572 | } | ||
573 | } | ||
574 | |||
575 | static int dpi_init_display(struct omap_dss_device *dssdev) | ||
405 | { | 576 | { |
406 | struct platform_device *dsidev; | 577 | struct platform_device *dsidev; |
407 | 578 | ||
@@ -421,12 +592,7 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev) | |||
421 | dpi.vdds_dsi_reg = vdds_dsi; | 592 | dpi.vdds_dsi_reg = vdds_dsi; |
422 | } | 593 | } |
423 | 594 | ||
424 | /* | 595 | dsidev = dpi_get_dsidev(dpi.output.dispc_channel); |
425 | * XXX We shouldn't need dssdev->channel for this. The dsi pll clock | ||
426 | * source for DPI is SoC integration detail, not something that should | ||
427 | * be configured in the dssdev | ||
428 | */ | ||
429 | dsidev = dpi_get_dsidev(dssdev->channel); | ||
430 | 596 | ||
431 | if (dsidev && dpi_verify_dsi_pll(dsidev)) { | 597 | if (dsidev && dpi_verify_dsi_pll(dsidev)) { |
432 | dsidev = NULL; | 598 | dsidev = NULL; |
@@ -441,7 +607,7 @@ static int __init dpi_init_display(struct omap_dss_device *dssdev) | |||
441 | return 0; | 607 | return 0; |
442 | } | 608 | } |
443 | 609 | ||
444 | static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *pdev) | 610 | static struct omap_dss_device *dpi_find_dssdev(struct platform_device *pdev) |
445 | { | 611 | { |
446 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 612 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
447 | const char *def_disp_name = omapdss_get_default_display_name(); | 613 | const char *def_disp_name = omapdss_get_default_display_name(); |
@@ -469,7 +635,7 @@ static struct omap_dss_device * __init dpi_find_dssdev(struct platform_device *p | |||
469 | return def_dssdev; | 635 | return def_dssdev; |
470 | } | 636 | } |
471 | 637 | ||
472 | static void __init dpi_probe_pdata(struct platform_device *dpidev) | 638 | static int dpi_probe_pdata(struct platform_device *dpidev) |
473 | { | 639 | { |
474 | struct omap_dss_device *plat_dssdev; | 640 | struct omap_dss_device *plat_dssdev; |
475 | struct omap_dss_device *dssdev; | 641 | struct omap_dss_device *dssdev; |
@@ -478,11 +644,11 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev) | |||
478 | plat_dssdev = dpi_find_dssdev(dpidev); | 644 | plat_dssdev = dpi_find_dssdev(dpidev); |
479 | 645 | ||
480 | if (!plat_dssdev) | 646 | if (!plat_dssdev) |
481 | return; | 647 | return 0; |
482 | 648 | ||
483 | dssdev = dss_alloc_and_init_device(&dpidev->dev); | 649 | dssdev = dss_alloc_and_init_device(&dpidev->dev); |
484 | if (!dssdev) | 650 | if (!dssdev) |
485 | return; | 651 | return -ENOMEM; |
486 | 652 | ||
487 | dss_copy_device_pdata(dssdev, plat_dssdev); | 653 | dss_copy_device_pdata(dssdev, plat_dssdev); |
488 | 654 | ||
@@ -490,7 +656,7 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev) | |||
490 | if (r) { | 656 | if (r) { |
491 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | 657 | DSSERR("device %s init failed: %d\n", dssdev->name, r); |
492 | dss_put_device(dssdev); | 658 | dss_put_device(dssdev); |
493 | return; | 659 | return r; |
494 | } | 660 | } |
495 | 661 | ||
496 | r = omapdss_output_set_device(&dpi.output, dssdev); | 662 | r = omapdss_output_set_device(&dpi.output, dssdev); |
@@ -498,7 +664,7 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev) | |||
498 | DSSERR("failed to connect output to new device: %s\n", | 664 | DSSERR("failed to connect output to new device: %s\n", |
499 | dssdev->name); | 665 | dssdev->name); |
500 | dss_put_device(dssdev); | 666 | dss_put_device(dssdev); |
501 | return; | 667 | return r; |
502 | } | 668 | } |
503 | 669 | ||
504 | r = dss_add_device(dssdev); | 670 | r = dss_add_device(dssdev); |
@@ -506,17 +672,21 @@ static void __init dpi_probe_pdata(struct platform_device *dpidev) | |||
506 | DSSERR("device %s register failed: %d\n", dssdev->name, r); | 672 | DSSERR("device %s register failed: %d\n", dssdev->name, r); |
507 | omapdss_output_unset_device(&dpi.output); | 673 | omapdss_output_unset_device(&dpi.output); |
508 | dss_put_device(dssdev); | 674 | dss_put_device(dssdev); |
509 | return; | 675 | return r; |
510 | } | 676 | } |
677 | |||
678 | return 0; | ||
511 | } | 679 | } |
512 | 680 | ||
513 | static void __init dpi_init_output(struct platform_device *pdev) | 681 | static void dpi_init_output(struct platform_device *pdev) |
514 | { | 682 | { |
515 | struct omap_dss_output *out = &dpi.output; | 683 | struct omap_dss_output *out = &dpi.output; |
516 | 684 | ||
517 | out->pdev = pdev; | 685 | out->pdev = pdev; |
518 | out->id = OMAP_DSS_OUTPUT_DPI; | 686 | out->id = OMAP_DSS_OUTPUT_DPI; |
519 | out->type = OMAP_DISPLAY_TYPE_DPI; | 687 | out->type = OMAP_DISPLAY_TYPE_DPI; |
688 | out->name = "dpi.0"; | ||
689 | out->dispc_channel = dpi_get_channel(); | ||
520 | 690 | ||
521 | dss_register_output(out); | 691 | dss_register_output(out); |
522 | } | 692 | } |
@@ -528,13 +698,19 @@ static void __exit dpi_uninit_output(struct platform_device *pdev) | |||
528 | dss_unregister_output(out); | 698 | dss_unregister_output(out); |
529 | } | 699 | } |
530 | 700 | ||
531 | static int __init omap_dpi_probe(struct platform_device *pdev) | 701 | static int omap_dpi_probe(struct platform_device *pdev) |
532 | { | 702 | { |
703 | int r; | ||
704 | |||
533 | mutex_init(&dpi.lock); | 705 | mutex_init(&dpi.lock); |
534 | 706 | ||
535 | dpi_init_output(pdev); | 707 | dpi_init_output(pdev); |
536 | 708 | ||
537 | dpi_probe_pdata(pdev); | 709 | r = dpi_probe_pdata(pdev); |
710 | if (r) { | ||
711 | dpi_uninit_output(pdev); | ||
712 | return r; | ||
713 | } | ||
538 | 714 | ||
539 | return 0; | 715 | return 0; |
540 | } | 716 | } |
@@ -549,6 +725,7 @@ static int __exit omap_dpi_remove(struct platform_device *pdev) | |||
549 | } | 725 | } |
550 | 726 | ||
551 | static struct platform_driver omap_dpi_driver = { | 727 | static struct platform_driver omap_dpi_driver = { |
728 | .probe = omap_dpi_probe, | ||
552 | .remove = __exit_p(omap_dpi_remove), | 729 | .remove = __exit_p(omap_dpi_remove), |
553 | .driver = { | 730 | .driver = { |
554 | .name = "omapdss_dpi", | 731 | .name = "omapdss_dpi", |
@@ -558,7 +735,7 @@ static struct platform_driver omap_dpi_driver = { | |||
558 | 735 | ||
559 | int __init dpi_init_platform_driver(void) | 736 | int __init dpi_init_platform_driver(void) |
560 | { | 737 | { |
561 | return platform_driver_probe(&omap_dpi_driver, omap_dpi_probe); | 738 | return platform_driver_register(&omap_dpi_driver); |
562 | } | 739 | } |
563 | 740 | ||
564 | void __exit dpi_uninit_platform_driver(void) | 741 | void __exit dpi_uninit_platform_driver(void) |
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c index 28d41d16b7be..a73dedc33101 100644 --- a/drivers/video/omap2/dss/dsi.c +++ b/drivers/video/omap2/dss/dsi.c | |||
@@ -200,6 +200,11 @@ struct dsi_reg { u16 idx; }; | |||
200 | 200 | ||
201 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); | 201 | typedef void (*omap_dsi_isr_t) (void *arg, u32 mask); |
202 | 202 | ||
203 | static int dsi_display_init_dispc(struct platform_device *dsidev, | ||
204 | struct omap_overlay_manager *mgr); | ||
205 | static void dsi_display_uninit_dispc(struct platform_device *dsidev, | ||
206 | struct omap_overlay_manager *mgr); | ||
207 | |||
203 | #define DSI_MAX_NR_ISRS 2 | 208 | #define DSI_MAX_NR_ISRS 2 |
204 | #define DSI_MAX_NR_LANES 5 | 209 | #define DSI_MAX_NR_LANES 5 |
205 | 210 | ||
@@ -250,6 +255,24 @@ struct dsi_isr_tables { | |||
250 | struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; | 255 | struct dsi_isr_data isr_table_cio[DSI_MAX_NR_ISRS]; |
251 | }; | 256 | }; |
252 | 257 | ||
258 | struct dsi_clk_calc_ctx { | ||
259 | struct platform_device *dsidev; | ||
260 | |||
261 | /* inputs */ | ||
262 | |||
263 | const struct omap_dss_dsi_config *config; | ||
264 | |||
265 | unsigned long req_pck_min, req_pck_nom, req_pck_max; | ||
266 | |||
267 | /* outputs */ | ||
268 | |||
269 | struct dsi_clock_info dsi_cinfo; | ||
270 | struct dispc_clock_info dispc_cinfo; | ||
271 | |||
272 | struct omap_video_timings dispc_vm; | ||
273 | struct omap_dss_dsi_videomode_timings dsi_vm; | ||
274 | }; | ||
275 | |||
253 | struct dsi_data { | 276 | struct dsi_data { |
254 | struct platform_device *pdev; | 277 | struct platform_device *pdev; |
255 | void __iomem *base; | 278 | void __iomem *base; |
@@ -261,6 +284,9 @@ struct dsi_data { | |||
261 | struct clk *dss_clk; | 284 | struct clk *dss_clk; |
262 | struct clk *sys_clk; | 285 | struct clk *sys_clk; |
263 | 286 | ||
287 | struct dispc_clock_info user_dispc_cinfo; | ||
288 | struct dsi_clock_info user_dsi_cinfo; | ||
289 | |||
264 | struct dsi_clock_info current_cinfo; | 290 | struct dsi_clock_info current_cinfo; |
265 | 291 | ||
266 | bool vdds_dsi_enabled; | 292 | bool vdds_dsi_enabled; |
@@ -324,6 +350,7 @@ struct dsi_data { | |||
324 | unsigned long lpdiv_max; | 350 | unsigned long lpdiv_max; |
325 | 351 | ||
326 | unsigned num_lanes_supported; | 352 | unsigned num_lanes_supported; |
353 | unsigned line_buffer_size; | ||
327 | 354 | ||
328 | struct dsi_lane_config lanes[DSI_MAX_NR_LANES]; | 355 | struct dsi_lane_config lanes[DSI_MAX_NR_LANES]; |
329 | unsigned num_lanes_used; | 356 | unsigned num_lanes_used; |
@@ -1192,15 +1219,33 @@ static unsigned long dsi_fclk_rate(struct platform_device *dsidev) | |||
1192 | return r; | 1219 | return r; |
1193 | } | 1220 | } |
1194 | 1221 | ||
1195 | static int dsi_set_lp_clk_divisor(struct omap_dss_device *dssdev) | 1222 | static int dsi_lp_clock_calc(struct dsi_clock_info *cinfo, |
1223 | unsigned long lp_clk_min, unsigned long lp_clk_max) | ||
1224 | { | ||
1225 | unsigned long dsi_fclk = cinfo->dsi_pll_hsdiv_dsi_clk; | ||
1226 | unsigned lp_clk_div; | ||
1227 | unsigned long lp_clk; | ||
1228 | |||
1229 | lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk_max * 2); | ||
1230 | lp_clk = dsi_fclk / 2 / lp_clk_div; | ||
1231 | |||
1232 | if (lp_clk < lp_clk_min || lp_clk > lp_clk_max) | ||
1233 | return -EINVAL; | ||
1234 | |||
1235 | cinfo->lp_clk_div = lp_clk_div; | ||
1236 | cinfo->lp_clk = lp_clk; | ||
1237 | |||
1238 | return 0; | ||
1239 | } | ||
1240 | |||
1241 | static int dsi_set_lp_clk_divisor(struct platform_device *dsidev) | ||
1196 | { | 1242 | { |
1197 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
1198 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 1243 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
1199 | unsigned long dsi_fclk; | 1244 | unsigned long dsi_fclk; |
1200 | unsigned lp_clk_div; | 1245 | unsigned lp_clk_div; |
1201 | unsigned long lp_clk; | 1246 | unsigned long lp_clk; |
1202 | 1247 | ||
1203 | lp_clk_div = dssdev->clocks.dsi.lp_clk_div; | 1248 | lp_clk_div = dsi->user_dsi_cinfo.lp_clk_div; |
1204 | 1249 | ||
1205 | if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max) | 1250 | if (lp_clk_div == 0 || lp_clk_div > dsi->lpdiv_max) |
1206 | return -EINVAL; | 1251 | return -EINVAL; |
@@ -1272,6 +1317,75 @@ static int dsi_pll_power(struct platform_device *dsidev, | |||
1272 | return 0; | 1317 | return 0; |
1273 | } | 1318 | } |
1274 | 1319 | ||
1320 | unsigned long dsi_get_pll_clkin(struct platform_device *dsidev) | ||
1321 | { | ||
1322 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1323 | return clk_get_rate(dsi->sys_clk); | ||
1324 | } | ||
1325 | |||
1326 | bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll, | ||
1327 | unsigned long out_min, dsi_hsdiv_calc_func func, void *data) | ||
1328 | { | ||
1329 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1330 | int regm, regm_start, regm_stop; | ||
1331 | unsigned long out_max; | ||
1332 | unsigned long out; | ||
1333 | |||
1334 | out_min = out_min ? out_min : 1; | ||
1335 | out_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); | ||
1336 | |||
1337 | regm_start = max(DIV_ROUND_UP(pll, out_max), 1ul); | ||
1338 | regm_stop = min(pll / out_min, dsi->regm_dispc_max); | ||
1339 | |||
1340 | for (regm = regm_start; regm <= regm_stop; ++regm) { | ||
1341 | out = pll / regm; | ||
1342 | |||
1343 | if (func(regm, out, data)) | ||
1344 | return true; | ||
1345 | } | ||
1346 | |||
1347 | return false; | ||
1348 | } | ||
1349 | |||
1350 | bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin, | ||
1351 | unsigned long pll_min, unsigned long pll_max, | ||
1352 | dsi_pll_calc_func func, void *data) | ||
1353 | { | ||
1354 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1355 | int regn, regn_start, regn_stop; | ||
1356 | int regm, regm_start, regm_stop; | ||
1357 | unsigned long fint, pll; | ||
1358 | const unsigned long pll_hw_max = 1800000000; | ||
1359 | unsigned long fint_hw_min, fint_hw_max; | ||
1360 | |||
1361 | fint_hw_min = dsi->fint_min; | ||
1362 | fint_hw_max = dsi->fint_max; | ||
1363 | |||
1364 | regn_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); | ||
1365 | regn_stop = min(clkin / fint_hw_min, dsi->regn_max); | ||
1366 | |||
1367 | pll_max = pll_max ? pll_max : ULONG_MAX; | ||
1368 | |||
1369 | for (regn = regn_start; regn <= regn_stop; ++regn) { | ||
1370 | fint = clkin / regn; | ||
1371 | |||
1372 | regm_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2), | ||
1373 | 1ul); | ||
1374 | regm_stop = min3(pll_max / fint / 2, | ||
1375 | pll_hw_max / fint / 2, | ||
1376 | dsi->regm_max); | ||
1377 | |||
1378 | for (regm = regm_start; regm <= regm_stop; ++regm) { | ||
1379 | pll = 2 * regm * fint; | ||
1380 | |||
1381 | if (func(regn, regm, fint, pll, data)) | ||
1382 | return true; | ||
1383 | } | ||
1384 | } | ||
1385 | |||
1386 | return false; | ||
1387 | } | ||
1388 | |||
1275 | /* calculate clock rates using dividers in cinfo */ | 1389 | /* calculate clock rates using dividers in cinfo */ |
1276 | static int dsi_calc_clock_rates(struct platform_device *dsidev, | 1390 | static int dsi_calc_clock_rates(struct platform_device *dsidev, |
1277 | struct dsi_clock_info *cinfo) | 1391 | struct dsi_clock_info *cinfo) |
@@ -1316,192 +1430,7 @@ static int dsi_calc_clock_rates(struct platform_device *dsidev, | |||
1316 | return 0; | 1430 | return 0; |
1317 | } | 1431 | } |
1318 | 1432 | ||
1319 | int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, | 1433 | static void dsi_pll_calc_dsi_fck(struct dsi_clock_info *cinfo) |
1320 | unsigned long req_pck, struct dsi_clock_info *dsi_cinfo, | ||
1321 | struct dispc_clock_info *dispc_cinfo) | ||
1322 | { | ||
1323 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1324 | struct dsi_clock_info cur, best; | ||
1325 | struct dispc_clock_info best_dispc; | ||
1326 | int min_fck_per_pck; | ||
1327 | int match = 0; | ||
1328 | unsigned long dss_sys_clk, max_dss_fck; | ||
1329 | |||
1330 | dss_sys_clk = clk_get_rate(dsi->sys_clk); | ||
1331 | |||
1332 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); | ||
1333 | |||
1334 | if (req_pck == dsi->cache_req_pck && | ||
1335 | dsi->cache_cinfo.clkin == dss_sys_clk) { | ||
1336 | DSSDBG("DSI clock info found from cache\n"); | ||
1337 | *dsi_cinfo = dsi->cache_cinfo; | ||
1338 | dispc_find_clk_divs(req_pck, dsi_cinfo->dsi_pll_hsdiv_dispc_clk, | ||
1339 | dispc_cinfo); | ||
1340 | return 0; | ||
1341 | } | ||
1342 | |||
1343 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | ||
1344 | |||
1345 | if (min_fck_per_pck && | ||
1346 | req_pck * min_fck_per_pck > max_dss_fck) { | ||
1347 | DSSERR("Requested pixel clock not possible with the current " | ||
1348 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " | ||
1349 | "the constraint off.\n"); | ||
1350 | min_fck_per_pck = 0; | ||
1351 | } | ||
1352 | |||
1353 | DSSDBG("dsi_pll_calc\n"); | ||
1354 | |||
1355 | retry: | ||
1356 | memset(&best, 0, sizeof(best)); | ||
1357 | memset(&best_dispc, 0, sizeof(best_dispc)); | ||
1358 | |||
1359 | memset(&cur, 0, sizeof(cur)); | ||
1360 | cur.clkin = dss_sys_clk; | ||
1361 | |||
1362 | /* 0.75MHz < Fint = clkin / regn < 2.1MHz */ | ||
1363 | /* To reduce PLL lock time, keep Fint high (around 2 MHz) */ | ||
1364 | for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { | ||
1365 | cur.fint = cur.clkin / cur.regn; | ||
1366 | |||
1367 | if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) | ||
1368 | continue; | ||
1369 | |||
1370 | /* DSIPHY(MHz) = (2 * regm / regn) * clkin */ | ||
1371 | for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { | ||
1372 | unsigned long a, b; | ||
1373 | |||
1374 | a = 2 * cur.regm * (cur.clkin/1000); | ||
1375 | b = cur.regn; | ||
1376 | cur.clkin4ddr = a / b * 1000; | ||
1377 | |||
1378 | if (cur.clkin4ddr > 1800 * 1000 * 1000) | ||
1379 | break; | ||
1380 | |||
1381 | /* dsi_pll_hsdiv_dispc_clk(MHz) = | ||
1382 | * DSIPHY(MHz) / regm_dispc < 173MHz/186Mhz */ | ||
1383 | for (cur.regm_dispc = 1; cur.regm_dispc < | ||
1384 | dsi->regm_dispc_max; ++cur.regm_dispc) { | ||
1385 | struct dispc_clock_info cur_dispc; | ||
1386 | cur.dsi_pll_hsdiv_dispc_clk = | ||
1387 | cur.clkin4ddr / cur.regm_dispc; | ||
1388 | |||
1389 | if (cur.regm_dispc > 1 && | ||
1390 | cur.regm_dispc % 2 != 0 && | ||
1391 | req_pck >= 1000000) | ||
1392 | continue; | ||
1393 | |||
1394 | /* this will narrow down the search a bit, | ||
1395 | * but still give pixclocks below what was | ||
1396 | * requested */ | ||
1397 | if (cur.dsi_pll_hsdiv_dispc_clk < req_pck) | ||
1398 | break; | ||
1399 | |||
1400 | if (cur.dsi_pll_hsdiv_dispc_clk > max_dss_fck) | ||
1401 | continue; | ||
1402 | |||
1403 | if (min_fck_per_pck && | ||
1404 | cur.dsi_pll_hsdiv_dispc_clk < | ||
1405 | req_pck * min_fck_per_pck) | ||
1406 | continue; | ||
1407 | |||
1408 | match = 1; | ||
1409 | |||
1410 | dispc_find_clk_divs(req_pck, | ||
1411 | cur.dsi_pll_hsdiv_dispc_clk, | ||
1412 | &cur_dispc); | ||
1413 | |||
1414 | if (abs(cur_dispc.pck - req_pck) < | ||
1415 | abs(best_dispc.pck - req_pck)) { | ||
1416 | best = cur; | ||
1417 | best_dispc = cur_dispc; | ||
1418 | |||
1419 | if (cur_dispc.pck == req_pck) | ||
1420 | goto found; | ||
1421 | } | ||
1422 | } | ||
1423 | } | ||
1424 | } | ||
1425 | found: | ||
1426 | if (!match) { | ||
1427 | if (min_fck_per_pck) { | ||
1428 | DSSERR("Could not find suitable clock settings.\n" | ||
1429 | "Turning FCK/PCK constraint off and" | ||
1430 | "trying again.\n"); | ||
1431 | min_fck_per_pck = 0; | ||
1432 | goto retry; | ||
1433 | } | ||
1434 | |||
1435 | DSSERR("Could not find suitable clock settings.\n"); | ||
1436 | |||
1437 | return -EINVAL; | ||
1438 | } | ||
1439 | |||
1440 | /* dsi_pll_hsdiv_dsi_clk (regm_dsi) is not used */ | ||
1441 | best.regm_dsi = 0; | ||
1442 | best.dsi_pll_hsdiv_dsi_clk = 0; | ||
1443 | |||
1444 | if (dsi_cinfo) | ||
1445 | *dsi_cinfo = best; | ||
1446 | if (dispc_cinfo) | ||
1447 | *dispc_cinfo = best_dispc; | ||
1448 | |||
1449 | dsi->cache_req_pck = req_pck; | ||
1450 | dsi->cache_clk_freq = 0; | ||
1451 | dsi->cache_cinfo = best; | ||
1452 | |||
1453 | return 0; | ||
1454 | } | ||
1455 | |||
1456 | static int dsi_pll_calc_ddrfreq(struct platform_device *dsidev, | ||
1457 | unsigned long req_clkin4ddr, struct dsi_clock_info *cinfo) | ||
1458 | { | ||
1459 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1460 | struct dsi_clock_info cur, best; | ||
1461 | |||
1462 | DSSDBG("dsi_pll_calc_ddrfreq\n"); | ||
1463 | |||
1464 | memset(&best, 0, sizeof(best)); | ||
1465 | memset(&cur, 0, sizeof(cur)); | ||
1466 | |||
1467 | cur.clkin = clk_get_rate(dsi->sys_clk); | ||
1468 | |||
1469 | for (cur.regn = 1; cur.regn < dsi->regn_max; ++cur.regn) { | ||
1470 | cur.fint = cur.clkin / cur.regn; | ||
1471 | |||
1472 | if (cur.fint > dsi->fint_max || cur.fint < dsi->fint_min) | ||
1473 | continue; | ||
1474 | |||
1475 | /* DSIPHY(MHz) = (2 * regm / regn) * clkin */ | ||
1476 | for (cur.regm = 1; cur.regm < dsi->regm_max; ++cur.regm) { | ||
1477 | unsigned long a, b; | ||
1478 | |||
1479 | a = 2 * cur.regm * (cur.clkin/1000); | ||
1480 | b = cur.regn; | ||
1481 | cur.clkin4ddr = a / b * 1000; | ||
1482 | |||
1483 | if (cur.clkin4ddr > 1800 * 1000 * 1000) | ||
1484 | break; | ||
1485 | |||
1486 | if (abs(cur.clkin4ddr - req_clkin4ddr) < | ||
1487 | abs(best.clkin4ddr - req_clkin4ddr)) { | ||
1488 | best = cur; | ||
1489 | DSSDBG("best %ld\n", best.clkin4ddr); | ||
1490 | } | ||
1491 | |||
1492 | if (cur.clkin4ddr == req_clkin4ddr) | ||
1493 | goto found; | ||
1494 | } | ||
1495 | } | ||
1496 | found: | ||
1497 | if (cinfo) | ||
1498 | *cinfo = best; | ||
1499 | |||
1500 | return 0; | ||
1501 | } | ||
1502 | |||
1503 | static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev, | ||
1504 | struct dsi_clock_info *cinfo) | ||
1505 | { | 1434 | { |
1506 | unsigned long max_dsi_fck; | 1435 | unsigned long max_dsi_fck; |
1507 | 1436 | ||
@@ -1511,90 +1440,6 @@ static void dsi_pll_calc_dsi_fck(struct platform_device *dsidev, | |||
1511 | cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi; | 1440 | cinfo->dsi_pll_hsdiv_dsi_clk = cinfo->clkin4ddr / cinfo->regm_dsi; |
1512 | } | 1441 | } |
1513 | 1442 | ||
1514 | static int dsi_pll_calc_dispc_fck(struct platform_device *dsidev, | ||
1515 | unsigned long req_pck, struct dsi_clock_info *cinfo, | ||
1516 | struct dispc_clock_info *dispc_cinfo) | ||
1517 | { | ||
1518 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
1519 | unsigned regm_dispc, best_regm_dispc; | ||
1520 | unsigned long dispc_clk, best_dispc_clk; | ||
1521 | int min_fck_per_pck; | ||
1522 | unsigned long max_dss_fck; | ||
1523 | struct dispc_clock_info best_dispc; | ||
1524 | bool match; | ||
1525 | |||
1526 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); | ||
1527 | |||
1528 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | ||
1529 | |||
1530 | if (min_fck_per_pck && | ||
1531 | req_pck * min_fck_per_pck > max_dss_fck) { | ||
1532 | DSSERR("Requested pixel clock not possible with the current " | ||
1533 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " | ||
1534 | "the constraint off.\n"); | ||
1535 | min_fck_per_pck = 0; | ||
1536 | } | ||
1537 | |||
1538 | retry: | ||
1539 | best_regm_dispc = 0; | ||
1540 | best_dispc_clk = 0; | ||
1541 | memset(&best_dispc, 0, sizeof(best_dispc)); | ||
1542 | match = false; | ||
1543 | |||
1544 | for (regm_dispc = 1; regm_dispc < dsi->regm_dispc_max; ++regm_dispc) { | ||
1545 | struct dispc_clock_info cur_dispc; | ||
1546 | |||
1547 | dispc_clk = cinfo->clkin4ddr / regm_dispc; | ||
1548 | |||
1549 | /* this will narrow down the search a bit, | ||
1550 | * but still give pixclocks below what was | ||
1551 | * requested */ | ||
1552 | if (dispc_clk < req_pck) | ||
1553 | break; | ||
1554 | |||
1555 | if (dispc_clk > max_dss_fck) | ||
1556 | continue; | ||
1557 | |||
1558 | if (min_fck_per_pck && dispc_clk < req_pck * min_fck_per_pck) | ||
1559 | continue; | ||
1560 | |||
1561 | match = true; | ||
1562 | |||
1563 | dispc_find_clk_divs(req_pck, dispc_clk, &cur_dispc); | ||
1564 | |||
1565 | if (abs(cur_dispc.pck - req_pck) < | ||
1566 | abs(best_dispc.pck - req_pck)) { | ||
1567 | best_regm_dispc = regm_dispc; | ||
1568 | best_dispc_clk = dispc_clk; | ||
1569 | best_dispc = cur_dispc; | ||
1570 | |||
1571 | if (cur_dispc.pck == req_pck) | ||
1572 | goto found; | ||
1573 | } | ||
1574 | } | ||
1575 | |||
1576 | if (!match) { | ||
1577 | if (min_fck_per_pck) { | ||
1578 | DSSERR("Could not find suitable clock settings.\n" | ||
1579 | "Turning FCK/PCK constraint off and" | ||
1580 | "trying again.\n"); | ||
1581 | min_fck_per_pck = 0; | ||
1582 | goto retry; | ||
1583 | } | ||
1584 | |||
1585 | DSSERR("Could not find suitable clock settings.\n"); | ||
1586 | |||
1587 | return -EINVAL; | ||
1588 | } | ||
1589 | found: | ||
1590 | cinfo->regm_dispc = best_regm_dispc; | ||
1591 | cinfo->dsi_pll_hsdiv_dispc_clk = best_dispc_clk; | ||
1592 | |||
1593 | *dispc_cinfo = best_dispc; | ||
1594 | |||
1595 | return 0; | ||
1596 | } | ||
1597 | |||
1598 | int dsi_pll_set_clock_div(struct platform_device *dsidev, | 1443 | int dsi_pll_set_clock_div(struct platform_device *dsidev, |
1599 | struct dsi_clock_info *cinfo) | 1444 | struct dsi_clock_info *cinfo) |
1600 | { | 1445 | { |
@@ -2783,6 +2628,7 @@ static int dsi_vc_enable(struct platform_device *dsidev, int channel, | |||
2783 | 2628 | ||
2784 | static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) | 2629 | static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) |
2785 | { | 2630 | { |
2631 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
2786 | u32 r; | 2632 | u32 r; |
2787 | 2633 | ||
2788 | DSSDBG("Initial config of virtual channel %d", channel); | 2634 | DSSDBG("Initial config of virtual channel %d", channel); |
@@ -2807,6 +2653,8 @@ static void dsi_vc_initial_config(struct platform_device *dsidev, int channel) | |||
2807 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ | 2653 | r = FLD_MOD(r, 4, 23, 21); /* DMA_TX_REQ_NB = no dma */ |
2808 | 2654 | ||
2809 | dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); | 2655 | dsi_write_reg(dsidev, DSI_VC_CTRL(channel), r); |
2656 | |||
2657 | dsi->vc[channel].source = DSI_VC_SOURCE_L4; | ||
2810 | } | 2658 | } |
2811 | 2659 | ||
2812 | static int dsi_vc_config_source(struct platform_device *dsidev, int channel, | 2660 | static int dsi_vc_config_source(struct platform_device *dsidev, int channel, |
@@ -3777,13 +3625,12 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev) | |||
3777 | 3625 | ||
3778 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { | 3626 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { |
3779 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); | 3627 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
3780 | unsigned line_buf_size = dsi_get_line_buf_size(dsidev); | ||
3781 | struct omap_video_timings *timings = &dsi->timings; | 3628 | struct omap_video_timings *timings = &dsi->timings; |
3782 | /* | 3629 | /* |
3783 | * Don't use line buffers if width is greater than the video | 3630 | * Don't use line buffers if width is greater than the video |
3784 | * port's line buffer size | 3631 | * port's line buffer size |
3785 | */ | 3632 | */ |
3786 | if (line_buf_size <= timings->x_res * bpp / 8) | 3633 | if (dsi->line_buffer_size <= timings->x_res * bpp / 8) |
3787 | num_line_buffers = 0; | 3634 | num_line_buffers = 0; |
3788 | else | 3635 | else |
3789 | num_line_buffers = 2; | 3636 | num_line_buffers = 2; |
@@ -3799,18 +3646,22 @@ static void dsi_config_vp_num_line_buffers(struct platform_device *dsidev) | |||
3799 | static void dsi_config_vp_sync_events(struct platform_device *dsidev) | 3646 | static void dsi_config_vp_sync_events(struct platform_device *dsidev) |
3800 | { | 3647 | { |
3801 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 3648 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
3802 | bool vsync_end = dsi->vm_timings.vp_vsync_end; | 3649 | bool sync_end; |
3803 | bool hsync_end = dsi->vm_timings.vp_hsync_end; | ||
3804 | u32 r; | 3650 | u32 r; |
3805 | 3651 | ||
3652 | if (dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE) | ||
3653 | sync_end = true; | ||
3654 | else | ||
3655 | sync_end = false; | ||
3656 | |||
3806 | r = dsi_read_reg(dsidev, DSI_CTRL); | 3657 | r = dsi_read_reg(dsidev, DSI_CTRL); |
3807 | r = FLD_MOD(r, 1, 9, 9); /* VP_DE_POL */ | 3658 | r = FLD_MOD(r, 1, 9, 9); /* VP_DE_POL */ |
3808 | r = FLD_MOD(r, 1, 10, 10); /* VP_HSYNC_POL */ | 3659 | r = FLD_MOD(r, 1, 10, 10); /* VP_HSYNC_POL */ |
3809 | r = FLD_MOD(r, 1, 11, 11); /* VP_VSYNC_POL */ | 3660 | r = FLD_MOD(r, 1, 11, 11); /* VP_VSYNC_POL */ |
3810 | r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */ | 3661 | r = FLD_MOD(r, 1, 15, 15); /* VP_VSYNC_START */ |
3811 | r = FLD_MOD(r, vsync_end, 16, 16); /* VP_VSYNC_END */ | 3662 | r = FLD_MOD(r, sync_end, 16, 16); /* VP_VSYNC_END */ |
3812 | r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */ | 3663 | r = FLD_MOD(r, 1, 17, 17); /* VP_HSYNC_START */ |
3813 | r = FLD_MOD(r, hsync_end, 18, 18); /* VP_HSYNC_END */ | 3664 | r = FLD_MOD(r, sync_end, 18, 18); /* VP_HSYNC_END */ |
3814 | dsi_write_reg(dsidev, DSI_CTRL, r); | 3665 | dsi_write_reg(dsidev, DSI_CTRL, r); |
3815 | } | 3666 | } |
3816 | 3667 | ||
@@ -3897,9 +3748,8 @@ static int dsi_compute_interleave_lp(int blank, int enter_hs, int exit_hs, | |||
3897 | return max(lp_inter, 0); | 3748 | return max(lp_inter, 0); |
3898 | } | 3749 | } |
3899 | 3750 | ||
3900 | static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) | 3751 | static void dsi_config_cmd_mode_interleaving(struct platform_device *dsidev) |
3901 | { | 3752 | { |
3902 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
3903 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 3753 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
3904 | int blanking_mode; | 3754 | int blanking_mode; |
3905 | int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode; | 3755 | int hfp_blanking_mode, hbp_blanking_mode, hsa_blanking_mode; |
@@ -3910,7 +3760,7 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) | |||
3910 | struct omap_video_timings *timings = &dsi->timings; | 3760 | struct omap_video_timings *timings = &dsi->timings; |
3911 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); | 3761 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
3912 | int ndl = dsi->num_lanes_used - 1; | 3762 | int ndl = dsi->num_lanes_used - 1; |
3913 | int dsi_fclk_hsdiv = dssdev->clocks.dsi.regm_dsi + 1; | 3763 | int dsi_fclk_hsdiv = dsi->user_dsi_cinfo.regm_dsi + 1; |
3914 | int hsa_interleave_hs = 0, hsa_interleave_lp = 0; | 3764 | int hsa_interleave_hs = 0, hsa_interleave_lp = 0; |
3915 | int hfp_interleave_hs = 0, hfp_interleave_lp = 0; | 3765 | int hfp_interleave_hs = 0, hfp_interleave_lp = 0; |
3916 | int hbp_interleave_hs = 0, hbp_interleave_lp = 0; | 3766 | int hbp_interleave_hs = 0, hbp_interleave_lp = 0; |
@@ -4015,9 +3865,8 @@ static void dsi_config_cmd_mode_interleaving(struct omap_dss_device *dssdev) | |||
4015 | dsi_write_reg(dsidev, DSI_VM_TIMING6, r); | 3865 | dsi_write_reg(dsidev, DSI_VM_TIMING6, r); |
4016 | } | 3866 | } |
4017 | 3867 | ||
4018 | static int dsi_proto_config(struct omap_dss_device *dssdev) | 3868 | static int dsi_proto_config(struct platform_device *dsidev) |
4019 | { | 3869 | { |
4020 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4021 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 3870 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4022 | u32 r; | 3871 | u32 r; |
4023 | int buswidth = 0; | 3872 | int buswidth = 0; |
@@ -4075,7 +3924,7 @@ static int dsi_proto_config(struct omap_dss_device *dssdev) | |||
4075 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { | 3924 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { |
4076 | dsi_config_vp_sync_events(dsidev); | 3925 | dsi_config_vp_sync_events(dsidev); |
4077 | dsi_config_blanking_modes(dsidev); | 3926 | dsi_config_blanking_modes(dsidev); |
4078 | dsi_config_cmd_mode_interleaving(dssdev); | 3927 | dsi_config_cmd_mode_interleaving(dsidev); |
4079 | } | 3928 | } |
4080 | 3929 | ||
4081 | dsi_vc_initial_config(dsidev, 0); | 3930 | dsi_vc_initial_config(dsidev, 0); |
@@ -4159,11 +4008,12 @@ static void dsi_proto_timings(struct platform_device *dsidev) | |||
4159 | int vfp = dsi->vm_timings.vfp; | 4008 | int vfp = dsi->vm_timings.vfp; |
4160 | int vbp = dsi->vm_timings.vbp; | 4009 | int vbp = dsi->vm_timings.vbp; |
4161 | int window_sync = dsi->vm_timings.window_sync; | 4010 | int window_sync = dsi->vm_timings.window_sync; |
4162 | bool hsync_end = dsi->vm_timings.vp_hsync_end; | 4011 | bool hsync_end; |
4163 | struct omap_video_timings *timings = &dsi->timings; | 4012 | struct omap_video_timings *timings = &dsi->timings; |
4164 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); | 4013 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
4165 | int tl, t_he, width_bytes; | 4014 | int tl, t_he, width_bytes; |
4166 | 4015 | ||
4016 | hsync_end = dsi->vm_timings.trans_mode == OMAP_DSS_DSI_PULSE_MODE; | ||
4167 | t_he = hsync_end ? | 4017 | t_he = hsync_end ? |
4168 | ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; | 4018 | ((hsa == 0 && ndl == 3) ? 1 : DIV_ROUND_UP(4, ndl)) : 0; |
4169 | 4019 | ||
@@ -4266,82 +4116,26 @@ int omapdss_dsi_configure_pins(struct omap_dss_device *dssdev, | |||
4266 | } | 4116 | } |
4267 | EXPORT_SYMBOL(omapdss_dsi_configure_pins); | 4117 | EXPORT_SYMBOL(omapdss_dsi_configure_pins); |
4268 | 4118 | ||
4269 | int omapdss_dsi_set_clocks(struct omap_dss_device *dssdev, | ||
4270 | unsigned long ddr_clk, unsigned long lp_clk) | ||
4271 | { | ||
4272 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4273 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4274 | struct dsi_clock_info cinfo; | ||
4275 | struct dispc_clock_info dispc_cinfo; | ||
4276 | unsigned lp_clk_div; | ||
4277 | unsigned long dsi_fclk; | ||
4278 | int bpp = dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt); | ||
4279 | unsigned long pck; | ||
4280 | int r; | ||
4281 | |||
4282 | DSSDBG("Setting DSI clocks: ddr_clk %lu, lp_clk %lu", ddr_clk, lp_clk); | ||
4283 | |||
4284 | mutex_lock(&dsi->lock); | ||
4285 | |||
4286 | /* Calculate PLL output clock */ | ||
4287 | r = dsi_pll_calc_ddrfreq(dsidev, ddr_clk * 4, &cinfo); | ||
4288 | if (r) | ||
4289 | goto err; | ||
4290 | |||
4291 | /* Calculate PLL's DSI clock */ | ||
4292 | dsi_pll_calc_dsi_fck(dsidev, &cinfo); | ||
4293 | |||
4294 | /* Calculate PLL's DISPC clock and pck & lck divs */ | ||
4295 | pck = cinfo.clkin4ddr / 16 * (dsi->num_lanes_used - 1) * 8 / bpp; | ||
4296 | DSSDBG("finding dispc dividers for pck %lu\n", pck); | ||
4297 | r = dsi_pll_calc_dispc_fck(dsidev, pck, &cinfo, &dispc_cinfo); | ||
4298 | if (r) | ||
4299 | goto err; | ||
4300 | |||
4301 | /* Calculate LP clock */ | ||
4302 | dsi_fclk = cinfo.dsi_pll_hsdiv_dsi_clk; | ||
4303 | lp_clk_div = DIV_ROUND_UP(dsi_fclk, lp_clk * 2); | ||
4304 | |||
4305 | dssdev->clocks.dsi.regn = cinfo.regn; | ||
4306 | dssdev->clocks.dsi.regm = cinfo.regm; | ||
4307 | dssdev->clocks.dsi.regm_dispc = cinfo.regm_dispc; | ||
4308 | dssdev->clocks.dsi.regm_dsi = cinfo.regm_dsi; | ||
4309 | |||
4310 | dssdev->clocks.dsi.lp_clk_div = lp_clk_div; | ||
4311 | |||
4312 | dssdev->clocks.dispc.channel.lck_div = dispc_cinfo.lck_div; | ||
4313 | dssdev->clocks.dispc.channel.pck_div = dispc_cinfo.pck_div; | ||
4314 | |||
4315 | dssdev->clocks.dispc.dispc_fclk_src = OMAP_DSS_CLK_SRC_FCK; | ||
4316 | |||
4317 | dssdev->clocks.dispc.channel.lcd_clk_src = | ||
4318 | dsi->module_id == 0 ? | ||
4319 | OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : | ||
4320 | OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC; | ||
4321 | |||
4322 | dssdev->clocks.dsi.dsi_fclk_src = | ||
4323 | dsi->module_id == 0 ? | ||
4324 | OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : | ||
4325 | OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI; | ||
4326 | |||
4327 | mutex_unlock(&dsi->lock); | ||
4328 | return 0; | ||
4329 | err: | ||
4330 | mutex_unlock(&dsi->lock); | ||
4331 | return r; | ||
4332 | } | ||
4333 | EXPORT_SYMBOL(omapdss_dsi_set_clocks); | ||
4334 | |||
4335 | int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) | 4119 | int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) |
4336 | { | 4120 | { |
4337 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4121 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
4338 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4122 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4339 | struct omap_overlay_manager *mgr = dssdev->output->manager; | 4123 | struct omap_overlay_manager *mgr = dsi->output.manager; |
4340 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); | 4124 | int bpp = dsi_get_pixel_size(dsi->pix_fmt); |
4125 | struct omap_dss_output *out = &dsi->output; | ||
4341 | u8 data_type; | 4126 | u8 data_type; |
4342 | u16 word_count; | 4127 | u16 word_count; |
4343 | int r; | 4128 | int r; |
4344 | 4129 | ||
4130 | if (out == NULL || out->manager == NULL) { | ||
4131 | DSSERR("failed to enable display: no output/manager\n"); | ||
4132 | return -ENODEV; | ||
4133 | } | ||
4134 | |||
4135 | r = dsi_display_init_dispc(dsidev, mgr); | ||
4136 | if (r) | ||
4137 | goto err_init_dispc; | ||
4138 | |||
4345 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { | 4139 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { |
4346 | switch (dsi->pix_fmt) { | 4140 | switch (dsi->pix_fmt) { |
4347 | case OMAP_DSS_DSI_FMT_RGB888: | 4141 | case OMAP_DSS_DSI_FMT_RGB888: |
@@ -4357,8 +4151,8 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) | |||
4357 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; | 4151 | data_type = MIPI_DSI_PACKED_PIXEL_STREAM_16; |
4358 | break; | 4152 | break; |
4359 | default: | 4153 | default: |
4360 | BUG(); | 4154 | r = -EINVAL; |
4361 | return -EINVAL; | 4155 | goto err_pix_fmt; |
4362 | }; | 4156 | }; |
4363 | 4157 | ||
4364 | dsi_if_enable(dsidev, false); | 4158 | dsi_if_enable(dsidev, false); |
@@ -4377,16 +4171,20 @@ int dsi_enable_video_output(struct omap_dss_device *dssdev, int channel) | |||
4377 | } | 4171 | } |
4378 | 4172 | ||
4379 | r = dss_mgr_enable(mgr); | 4173 | r = dss_mgr_enable(mgr); |
4380 | if (r) { | 4174 | if (r) |
4381 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { | 4175 | goto err_mgr_enable; |
4382 | dsi_if_enable(dsidev, false); | ||
4383 | dsi_vc_enable(dsidev, channel, false); | ||
4384 | } | ||
4385 | |||
4386 | return r; | ||
4387 | } | ||
4388 | 4176 | ||
4389 | return 0; | 4177 | return 0; |
4178 | |||
4179 | err_mgr_enable: | ||
4180 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { | ||
4181 | dsi_if_enable(dsidev, false); | ||
4182 | dsi_vc_enable(dsidev, channel, false); | ||
4183 | } | ||
4184 | err_pix_fmt: | ||
4185 | dsi_display_uninit_dispc(dsidev, mgr); | ||
4186 | err_init_dispc: | ||
4187 | return r; | ||
4390 | } | 4188 | } |
4391 | EXPORT_SYMBOL(dsi_enable_video_output); | 4189 | EXPORT_SYMBOL(dsi_enable_video_output); |
4392 | 4190 | ||
@@ -4394,7 +4192,7 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) | |||
4394 | { | 4192 | { |
4395 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4193 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
4396 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4194 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4397 | struct omap_overlay_manager *mgr = dssdev->output->manager; | 4195 | struct omap_overlay_manager *mgr = dsi->output.manager; |
4398 | 4196 | ||
4399 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { | 4197 | if (dsi->mode == OMAP_DSS_DSI_VIDEO_MODE) { |
4400 | dsi_if_enable(dsidev, false); | 4198 | dsi_if_enable(dsidev, false); |
@@ -4408,14 +4206,15 @@ void dsi_disable_video_output(struct omap_dss_device *dssdev, int channel) | |||
4408 | } | 4206 | } |
4409 | 4207 | ||
4410 | dss_mgr_disable(mgr); | 4208 | dss_mgr_disable(mgr); |
4209 | |||
4210 | dsi_display_uninit_dispc(dsidev, mgr); | ||
4411 | } | 4211 | } |
4412 | EXPORT_SYMBOL(dsi_disable_video_output); | 4212 | EXPORT_SYMBOL(dsi_disable_video_output); |
4413 | 4213 | ||
4414 | static void dsi_update_screen_dispc(struct omap_dss_device *dssdev) | 4214 | static void dsi_update_screen_dispc(struct platform_device *dsidev) |
4415 | { | 4215 | { |
4416 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4417 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4216 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4418 | struct omap_overlay_manager *mgr = dssdev->output->manager; | 4217 | struct omap_overlay_manager *mgr = dsi->output.manager; |
4419 | unsigned bytespp; | 4218 | unsigned bytespp; |
4420 | unsigned bytespl; | 4219 | unsigned bytespl; |
4421 | unsigned bytespf; | 4220 | unsigned bytespf; |
@@ -4425,7 +4224,7 @@ static void dsi_update_screen_dispc(struct omap_dss_device *dssdev) | |||
4425 | u32 l; | 4224 | u32 l; |
4426 | int r; | 4225 | int r; |
4427 | const unsigned channel = dsi->update_channel; | 4226 | const unsigned channel = dsi->update_channel; |
4428 | const unsigned line_buf_size = dsi_get_line_buf_size(dsidev); | 4227 | const unsigned line_buf_size = dsi->line_buffer_size; |
4429 | u16 w = dsi->timings.x_res; | 4228 | u16 w = dsi->timings.x_res; |
4430 | u16 h = dsi->timings.y_res; | 4229 | u16 h = dsi->timings.y_res; |
4431 | 4230 | ||
@@ -4571,7 +4370,7 @@ int omap_dsi_update(struct omap_dss_device *dssdev, int channel, | |||
4571 | dsi->update_bytes = dw * dh * | 4370 | dsi->update_bytes = dw * dh * |
4572 | dsi_get_pixel_size(dsi->pix_fmt) / 8; | 4371 | dsi_get_pixel_size(dsi->pix_fmt) / 8; |
4573 | #endif | 4372 | #endif |
4574 | dsi_update_screen_dispc(dssdev); | 4373 | dsi_update_screen_dispc(dsidev); |
4575 | 4374 | ||
4576 | return 0; | 4375 | return 0; |
4577 | } | 4376 | } |
@@ -4579,18 +4378,17 @@ EXPORT_SYMBOL(omap_dsi_update); | |||
4579 | 4378 | ||
4580 | /* Display funcs */ | 4379 | /* Display funcs */ |
4581 | 4380 | ||
4582 | static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | 4381 | static int dsi_configure_dispc_clocks(struct platform_device *dsidev) |
4583 | { | 4382 | { |
4584 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4585 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4383 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4586 | struct dispc_clock_info dispc_cinfo; | 4384 | struct dispc_clock_info dispc_cinfo; |
4587 | int r; | 4385 | int r; |
4588 | unsigned long long fck; | 4386 | unsigned long fck; |
4589 | 4387 | ||
4590 | fck = dsi_get_pll_hsdiv_dispc_rate(dsidev); | 4388 | fck = dsi_get_pll_hsdiv_dispc_rate(dsidev); |
4591 | 4389 | ||
4592 | dispc_cinfo.lck_div = dssdev->clocks.dispc.channel.lck_div; | 4390 | dispc_cinfo.lck_div = dsi->user_dispc_cinfo.lck_div; |
4593 | dispc_cinfo.pck_div = dssdev->clocks.dispc.channel.pck_div; | 4391 | dispc_cinfo.pck_div = dsi->user_dispc_cinfo.pck_div; |
4594 | 4392 | ||
4595 | r = dispc_calc_clock_rates(fck, &dispc_cinfo); | 4393 | r = dispc_calc_clock_rates(fck, &dispc_cinfo); |
4596 | if (r) { | 4394 | if (r) { |
@@ -4603,21 +4401,17 @@ static int dsi_configure_dispc_clocks(struct omap_dss_device *dssdev) | |||
4603 | return 0; | 4401 | return 0; |
4604 | } | 4402 | } |
4605 | 4403 | ||
4606 | static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | 4404 | static int dsi_display_init_dispc(struct platform_device *dsidev, |
4405 | struct omap_overlay_manager *mgr) | ||
4607 | { | 4406 | { |
4608 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4609 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4407 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4610 | struct omap_overlay_manager *mgr = dssdev->output->manager; | ||
4611 | int r; | 4408 | int r; |
4612 | 4409 | ||
4613 | if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { | 4410 | dss_select_lcd_clk_source(mgr->id, dsi->module_id == 0 ? |
4614 | dsi->timings.hsw = 1; | 4411 | OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DISPC : |
4615 | dsi->timings.hfp = 1; | 4412 | OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DISPC); |
4616 | dsi->timings.hbp = 1; | ||
4617 | dsi->timings.vsw = 1; | ||
4618 | dsi->timings.vfp = 0; | ||
4619 | dsi->timings.vbp = 0; | ||
4620 | 4413 | ||
4414 | if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) { | ||
4621 | r = dss_mgr_register_framedone_handler(mgr, | 4415 | r = dss_mgr_register_framedone_handler(mgr, |
4622 | dsi_framedone_irq_callback, dsidev); | 4416 | dsi_framedone_irq_callback, dsidev); |
4623 | if (r) { | 4417 | if (r) { |
@@ -4645,7 +4439,7 @@ static int dsi_display_init_dispc(struct omap_dss_device *dssdev) | |||
4645 | 4439 | ||
4646 | dss_mgr_set_timings(mgr, &dsi->timings); | 4440 | dss_mgr_set_timings(mgr, &dsi->timings); |
4647 | 4441 | ||
4648 | r = dsi_configure_dispc_clocks(dssdev); | 4442 | r = dsi_configure_dispc_clocks(dsidev); |
4649 | if (r) | 4443 | if (r) |
4650 | goto err1; | 4444 | goto err1; |
4651 | 4445 | ||
@@ -4662,30 +4456,30 @@ err1: | |||
4662 | dss_mgr_unregister_framedone_handler(mgr, | 4456 | dss_mgr_unregister_framedone_handler(mgr, |
4663 | dsi_framedone_irq_callback, dsidev); | 4457 | dsi_framedone_irq_callback, dsidev); |
4664 | err: | 4458 | err: |
4459 | dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); | ||
4665 | return r; | 4460 | return r; |
4666 | } | 4461 | } |
4667 | 4462 | ||
4668 | static void dsi_display_uninit_dispc(struct omap_dss_device *dssdev) | 4463 | static void dsi_display_uninit_dispc(struct platform_device *dsidev, |
4464 | struct omap_overlay_manager *mgr) | ||
4669 | { | 4465 | { |
4670 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4671 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4466 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4672 | struct omap_overlay_manager *mgr = dssdev->output->manager; | ||
4673 | 4467 | ||
4674 | if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) | 4468 | if (dsi->mode == OMAP_DSS_DSI_CMD_MODE) |
4675 | dss_mgr_unregister_framedone_handler(mgr, | 4469 | dss_mgr_unregister_framedone_handler(mgr, |
4676 | dsi_framedone_irq_callback, dsidev); | 4470 | dsi_framedone_irq_callback, dsidev); |
4471 | |||
4472 | dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); | ||
4677 | } | 4473 | } |
4678 | 4474 | ||
4679 | static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | 4475 | static int dsi_configure_dsi_clocks(struct platform_device *dsidev) |
4680 | { | 4476 | { |
4681 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4477 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4682 | struct dsi_clock_info cinfo; | 4478 | struct dsi_clock_info cinfo; |
4683 | int r; | 4479 | int r; |
4684 | 4480 | ||
4685 | cinfo.regn = dssdev->clocks.dsi.regn; | 4481 | cinfo = dsi->user_dsi_cinfo; |
4686 | cinfo.regm = dssdev->clocks.dsi.regm; | 4482 | |
4687 | cinfo.regm_dispc = dssdev->clocks.dsi.regm_dispc; | ||
4688 | cinfo.regm_dsi = dssdev->clocks.dsi.regm_dsi; | ||
4689 | r = dsi_calc_clock_rates(dsidev, &cinfo); | 4483 | r = dsi_calc_clock_rates(dsidev, &cinfo); |
4690 | if (r) { | 4484 | if (r) { |
4691 | DSSERR("Failed to calc dsi clocks\n"); | 4485 | DSSERR("Failed to calc dsi clocks\n"); |
@@ -4701,24 +4495,22 @@ static int dsi_configure_dsi_clocks(struct omap_dss_device *dssdev) | |||
4701 | return 0; | 4495 | return 0; |
4702 | } | 4496 | } |
4703 | 4497 | ||
4704 | static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | 4498 | static int dsi_display_init_dsi(struct platform_device *dsidev) |
4705 | { | 4499 | { |
4706 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4707 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4500 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4708 | struct omap_overlay_manager *mgr = dssdev->output->manager; | ||
4709 | int r; | 4501 | int r; |
4710 | 4502 | ||
4711 | r = dsi_pll_init(dsidev, true, true); | 4503 | r = dsi_pll_init(dsidev, true, true); |
4712 | if (r) | 4504 | if (r) |
4713 | goto err0; | 4505 | goto err0; |
4714 | 4506 | ||
4715 | r = dsi_configure_dsi_clocks(dssdev); | 4507 | r = dsi_configure_dsi_clocks(dsidev); |
4716 | if (r) | 4508 | if (r) |
4717 | goto err1; | 4509 | goto err1; |
4718 | 4510 | ||
4719 | dss_select_dsi_clk_source(dsi->module_id, dssdev->clocks.dsi.dsi_fclk_src); | 4511 | dss_select_dsi_clk_source(dsi->module_id, dsi->module_id == 0 ? |
4720 | dss_select_lcd_clk_source(mgr->id, | 4512 | OMAP_DSS_CLK_SRC_DSI_PLL_HSDIV_DSI : |
4721 | dssdev->clocks.dispc.channel.lcd_clk_src); | 4513 | OMAP_DSS_CLK_SRC_DSI2_PLL_HSDIV_DSI); |
4722 | 4514 | ||
4723 | DSSDBG("PLL OK\n"); | 4515 | DSSDBG("PLL OK\n"); |
4724 | 4516 | ||
@@ -4729,12 +4521,12 @@ static int dsi_display_init_dsi(struct omap_dss_device *dssdev) | |||
4729 | _dsi_print_reset_status(dsidev); | 4521 | _dsi_print_reset_status(dsidev); |
4730 | 4522 | ||
4731 | dsi_proto_timings(dsidev); | 4523 | dsi_proto_timings(dsidev); |
4732 | dsi_set_lp_clk_divisor(dssdev); | 4524 | dsi_set_lp_clk_divisor(dsidev); |
4733 | 4525 | ||
4734 | if (1) | 4526 | if (1) |
4735 | _dsi_print_reset_status(dsidev); | 4527 | _dsi_print_reset_status(dsidev); |
4736 | 4528 | ||
4737 | r = dsi_proto_config(dssdev); | 4529 | r = dsi_proto_config(dsidev); |
4738 | if (r) | 4530 | if (r) |
4739 | goto err3; | 4531 | goto err3; |
4740 | 4532 | ||
@@ -4751,20 +4543,16 @@ err3: | |||
4751 | dsi_cio_uninit(dsidev); | 4543 | dsi_cio_uninit(dsidev); |
4752 | err2: | 4544 | err2: |
4753 | dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); | 4545 | dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); |
4754 | dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); | ||
4755 | |||
4756 | err1: | 4546 | err1: |
4757 | dsi_pll_uninit(dsidev, true); | 4547 | dsi_pll_uninit(dsidev, true); |
4758 | err0: | 4548 | err0: |
4759 | return r; | 4549 | return r; |
4760 | } | 4550 | } |
4761 | 4551 | ||
4762 | static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, | 4552 | static void dsi_display_uninit_dsi(struct platform_device *dsidev, |
4763 | bool disconnect_lanes, bool enter_ulps) | 4553 | bool disconnect_lanes, bool enter_ulps) |
4764 | { | 4554 | { |
4765 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | ||
4766 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4555 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4767 | struct omap_overlay_manager *mgr = dssdev->output->manager; | ||
4768 | 4556 | ||
4769 | if (enter_ulps && !dsi->ulps_enabled) | 4557 | if (enter_ulps && !dsi->ulps_enabled) |
4770 | dsi_enter_ulps(dsidev); | 4558 | dsi_enter_ulps(dsidev); |
@@ -4777,7 +4565,6 @@ static void dsi_display_uninit_dsi(struct omap_dss_device *dssdev, | |||
4777 | dsi_vc_enable(dsidev, 3, 0); | 4565 | dsi_vc_enable(dsidev, 3, 0); |
4778 | 4566 | ||
4779 | dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); | 4567 | dss_select_dsi_clk_source(dsi->module_id, OMAP_DSS_CLK_SRC_FCK); |
4780 | dss_select_lcd_clk_source(mgr->id, OMAP_DSS_CLK_SRC_FCK); | ||
4781 | dsi_cio_uninit(dsidev); | 4568 | dsi_cio_uninit(dsidev); |
4782 | dsi_pll_uninit(dsidev, disconnect_lanes); | 4569 | dsi_pll_uninit(dsidev, disconnect_lanes); |
4783 | } | 4570 | } |
@@ -4786,7 +4573,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
4786 | { | 4573 | { |
4787 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4574 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
4788 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4575 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
4789 | struct omap_dss_output *out = dssdev->output; | ||
4790 | int r = 0; | 4576 | int r = 0; |
4791 | 4577 | ||
4792 | DSSDBG("dsi_display_enable\n"); | 4578 | DSSDBG("dsi_display_enable\n"); |
@@ -4795,12 +4581,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
4795 | 4581 | ||
4796 | mutex_lock(&dsi->lock); | 4582 | mutex_lock(&dsi->lock); |
4797 | 4583 | ||
4798 | if (out == NULL || out->manager == NULL) { | ||
4799 | DSSERR("failed to enable display: no output/manager\n"); | ||
4800 | r = -ENODEV; | ||
4801 | goto err_start_dev; | ||
4802 | } | ||
4803 | |||
4804 | r = omap_dss_start_device(dssdev); | 4584 | r = omap_dss_start_device(dssdev); |
4805 | if (r) { | 4585 | if (r) { |
4806 | DSSERR("failed to start device\n"); | 4586 | DSSERR("failed to start device\n"); |
@@ -4815,11 +4595,7 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
4815 | 4595 | ||
4816 | _dsi_initialize_irq(dsidev); | 4596 | _dsi_initialize_irq(dsidev); |
4817 | 4597 | ||
4818 | r = dsi_display_init_dispc(dssdev); | 4598 | r = dsi_display_init_dsi(dsidev); |
4819 | if (r) | ||
4820 | goto err_init_dispc; | ||
4821 | |||
4822 | r = dsi_display_init_dsi(dssdev); | ||
4823 | if (r) | 4599 | if (r) |
4824 | goto err_init_dsi; | 4600 | goto err_init_dsi; |
4825 | 4601 | ||
@@ -4828,8 +4604,6 @@ int omapdss_dsi_display_enable(struct omap_dss_device *dssdev) | |||
4828 | return 0; | 4604 | return 0; |
4829 | 4605 | ||
4830 | err_init_dsi: | 4606 | err_init_dsi: |
4831 | dsi_display_uninit_dispc(dssdev); | ||
4832 | err_init_dispc: | ||
4833 | dsi_enable_pll_clock(dsidev, 0); | 4607 | dsi_enable_pll_clock(dsidev, 0); |
4834 | dsi_runtime_put(dsidev); | 4608 | dsi_runtime_put(dsidev); |
4835 | err_get_dsi: | 4609 | err_get_dsi: |
@@ -4858,9 +4632,7 @@ void omapdss_dsi_display_disable(struct omap_dss_device *dssdev, | |||
4858 | dsi_sync_vc(dsidev, 2); | 4632 | dsi_sync_vc(dsidev, 2); |
4859 | dsi_sync_vc(dsidev, 3); | 4633 | dsi_sync_vc(dsidev, 3); |
4860 | 4634 | ||
4861 | dsi_display_uninit_dispc(dssdev); | 4635 | dsi_display_uninit_dsi(dsidev, disconnect_lanes, enter_ulps); |
4862 | |||
4863 | dsi_display_uninit_dsi(dssdev, disconnect_lanes, enter_ulps); | ||
4864 | 4636 | ||
4865 | dsi_runtime_put(dsidev); | 4637 | dsi_runtime_put(dsidev); |
4866 | dsi_enable_pll_clock(dsidev, 0); | 4638 | dsi_enable_pll_clock(dsidev, 0); |
@@ -4881,77 +4653,579 @@ int omapdss_dsi_enable_te(struct omap_dss_device *dssdev, bool enable) | |||
4881 | } | 4653 | } |
4882 | EXPORT_SYMBOL(omapdss_dsi_enable_te); | 4654 | EXPORT_SYMBOL(omapdss_dsi_enable_te); |
4883 | 4655 | ||
4884 | void omapdss_dsi_set_timings(struct omap_dss_device *dssdev, | 4656 | #ifdef PRINT_VERBOSE_VM_TIMINGS |
4885 | struct omap_video_timings *timings) | 4657 | static void print_dsi_vm(const char *str, |
4658 | const struct omap_dss_dsi_videomode_timings *t) | ||
4659 | { | ||
4660 | unsigned long byteclk = t->hsclk / 4; | ||
4661 | int bl, wc, pps, tot; | ||
4662 | |||
4663 | wc = DIV_ROUND_UP(t->hact * t->bitspp, 8); | ||
4664 | pps = DIV_ROUND_UP(wc + 6, t->ndl); /* pixel packet size */ | ||
4665 | bl = t->hss + t->hsa + t->hse + t->hbp + t->hfp; | ||
4666 | tot = bl + pps; | ||
4667 | |||
4668 | #define TO_DSI_T(x) ((u32)div64_u64((u64)x * 1000000000llu, byteclk)) | ||
4669 | |||
4670 | pr_debug("%s bck %lu, %u/%u/%u/%u/%u/%u = %u+%u = %u, " | ||
4671 | "%u/%u/%u/%u/%u/%u = %u + %u = %u\n", | ||
4672 | str, | ||
4673 | byteclk, | ||
4674 | t->hss, t->hsa, t->hse, t->hbp, pps, t->hfp, | ||
4675 | bl, pps, tot, | ||
4676 | TO_DSI_T(t->hss), | ||
4677 | TO_DSI_T(t->hsa), | ||
4678 | TO_DSI_T(t->hse), | ||
4679 | TO_DSI_T(t->hbp), | ||
4680 | TO_DSI_T(pps), | ||
4681 | TO_DSI_T(t->hfp), | ||
4682 | |||
4683 | TO_DSI_T(bl), | ||
4684 | TO_DSI_T(pps), | ||
4685 | |||
4686 | TO_DSI_T(tot)); | ||
4687 | #undef TO_DSI_T | ||
4688 | } | ||
4689 | |||
4690 | static void print_dispc_vm(const char *str, const struct omap_video_timings *t) | ||
4691 | { | ||
4692 | unsigned long pck = t->pixel_clock * 1000; | ||
4693 | int hact, bl, tot; | ||
4694 | |||
4695 | hact = t->x_res; | ||
4696 | bl = t->hsw + t->hbp + t->hfp; | ||
4697 | tot = hact + bl; | ||
4698 | |||
4699 | #define TO_DISPC_T(x) ((u32)div64_u64((u64)x * 1000000000llu, pck)) | ||
4700 | |||
4701 | pr_debug("%s pck %lu, %u/%u/%u/%u = %u+%u = %u, " | ||
4702 | "%u/%u/%u/%u = %u + %u = %u\n", | ||
4703 | str, | ||
4704 | pck, | ||
4705 | t->hsw, t->hbp, hact, t->hfp, | ||
4706 | bl, hact, tot, | ||
4707 | TO_DISPC_T(t->hsw), | ||
4708 | TO_DISPC_T(t->hbp), | ||
4709 | TO_DISPC_T(hact), | ||
4710 | TO_DISPC_T(t->hfp), | ||
4711 | TO_DISPC_T(bl), | ||
4712 | TO_DISPC_T(hact), | ||
4713 | TO_DISPC_T(tot)); | ||
4714 | #undef TO_DISPC_T | ||
4715 | } | ||
4716 | |||
4717 | /* note: this is not quite accurate */ | ||
4718 | static void print_dsi_dispc_vm(const char *str, | ||
4719 | const struct omap_dss_dsi_videomode_timings *t) | ||
4720 | { | ||
4721 | struct omap_video_timings vm = { 0 }; | ||
4722 | unsigned long byteclk = t->hsclk / 4; | ||
4723 | unsigned long pck; | ||
4724 | u64 dsi_tput; | ||
4725 | int dsi_hact, dsi_htot; | ||
4726 | |||
4727 | dsi_tput = (u64)byteclk * t->ndl * 8; | ||
4728 | pck = (u32)div64_u64(dsi_tput, t->bitspp); | ||
4729 | dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(t->hact * t->bitspp, 8) + 6, t->ndl); | ||
4730 | dsi_htot = t->hss + t->hsa + t->hse + t->hbp + dsi_hact + t->hfp; | ||
4731 | |||
4732 | vm.pixel_clock = pck / 1000; | ||
4733 | vm.hsw = div64_u64((u64)(t->hsa + t->hse) * pck, byteclk); | ||
4734 | vm.hbp = div64_u64((u64)t->hbp * pck, byteclk); | ||
4735 | vm.hfp = div64_u64((u64)t->hfp * pck, byteclk); | ||
4736 | vm.x_res = t->hact; | ||
4737 | |||
4738 | print_dispc_vm(str, &vm); | ||
4739 | } | ||
4740 | #endif /* PRINT_VERBOSE_VM_TIMINGS */ | ||
4741 | |||
4742 | static bool dsi_cm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, | ||
4743 | unsigned long pck, void *data) | ||
4886 | { | 4744 | { |
4887 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4745 | struct dsi_clk_calc_ctx *ctx = data; |
4888 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4746 | struct omap_video_timings *t = &ctx->dispc_vm; |
4889 | 4747 | ||
4890 | mutex_lock(&dsi->lock); | 4748 | ctx->dispc_cinfo.lck_div = lckd; |
4749 | ctx->dispc_cinfo.pck_div = pckd; | ||
4750 | ctx->dispc_cinfo.lck = lck; | ||
4751 | ctx->dispc_cinfo.pck = pck; | ||
4891 | 4752 | ||
4892 | dsi->timings = *timings; | 4753 | *t = *ctx->config->timings; |
4754 | t->pixel_clock = pck / 1000; | ||
4755 | t->x_res = ctx->config->timings->x_res; | ||
4756 | t->y_res = ctx->config->timings->y_res; | ||
4757 | t->hsw = t->hfp = t->hbp = t->vsw = 1; | ||
4758 | t->vfp = t->vbp = 0; | ||
4893 | 4759 | ||
4894 | mutex_unlock(&dsi->lock); | 4760 | return true; |
4895 | } | 4761 | } |
4896 | EXPORT_SYMBOL(omapdss_dsi_set_timings); | ||
4897 | 4762 | ||
4898 | void omapdss_dsi_set_size(struct omap_dss_device *dssdev, u16 w, u16 h) | 4763 | static bool dsi_cm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, |
4764 | void *data) | ||
4899 | { | 4765 | { |
4900 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4766 | struct dsi_clk_calc_ctx *ctx = data; |
4901 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
4902 | 4767 | ||
4903 | mutex_lock(&dsi->lock); | 4768 | ctx->dsi_cinfo.regm_dispc = regm_dispc; |
4769 | ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc; | ||
4904 | 4770 | ||
4905 | dsi->timings.x_res = w; | 4771 | return dispc_div_calc(dispc, ctx->req_pck_min, ctx->req_pck_max, |
4906 | dsi->timings.y_res = h; | 4772 | dsi_cm_calc_dispc_cb, ctx); |
4773 | } | ||
4907 | 4774 | ||
4908 | mutex_unlock(&dsi->lock); | 4775 | static bool dsi_cm_calc_pll_cb(int regn, int regm, unsigned long fint, |
4776 | unsigned long pll, void *data) | ||
4777 | { | ||
4778 | struct dsi_clk_calc_ctx *ctx = data; | ||
4779 | |||
4780 | ctx->dsi_cinfo.regn = regn; | ||
4781 | ctx->dsi_cinfo.regm = regm; | ||
4782 | ctx->dsi_cinfo.fint = fint; | ||
4783 | ctx->dsi_cinfo.clkin4ddr = pll; | ||
4784 | |||
4785 | return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min, | ||
4786 | dsi_cm_calc_hsdiv_cb, ctx); | ||
4909 | } | 4787 | } |
4910 | EXPORT_SYMBOL(omapdss_dsi_set_size); | ||
4911 | 4788 | ||
4912 | void omapdss_dsi_set_pixel_format(struct omap_dss_device *dssdev, | 4789 | static bool dsi_cm_calc(struct dsi_data *dsi, |
4913 | enum omap_dss_dsi_pixel_format fmt) | 4790 | const struct omap_dss_dsi_config *cfg, |
4791 | struct dsi_clk_calc_ctx *ctx) | ||
4914 | { | 4792 | { |
4915 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4793 | unsigned long clkin; |
4916 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4794 | int bitspp, ndl; |
4795 | unsigned long pll_min, pll_max; | ||
4796 | unsigned long pck, txbyteclk; | ||
4917 | 4797 | ||
4918 | mutex_lock(&dsi->lock); | 4798 | clkin = clk_get_rate(dsi->sys_clk); |
4799 | bitspp = dsi_get_pixel_size(cfg->pixel_format); | ||
4800 | ndl = dsi->num_lanes_used - 1; | ||
4919 | 4801 | ||
4920 | dsi->pix_fmt = fmt; | 4802 | /* |
4803 | * Here we should calculate minimum txbyteclk to be able to send the | ||
4804 | * frame in time, and also to handle TE. That's not very simple, though, | ||
4805 | * especially as we go to LP between each pixel packet due to HW | ||
4806 | * "feature". So let's just estimate very roughly and multiply by 1.5. | ||
4807 | */ | ||
4808 | pck = cfg->timings->pixel_clock * 1000; | ||
4809 | pck = pck * 3 / 2; | ||
4810 | txbyteclk = pck * bitspp / 8 / ndl; | ||
4921 | 4811 | ||
4922 | mutex_unlock(&dsi->lock); | 4812 | memset(ctx, 0, sizeof(*ctx)); |
4813 | ctx->dsidev = dsi->pdev; | ||
4814 | ctx->config = cfg; | ||
4815 | ctx->req_pck_min = pck; | ||
4816 | ctx->req_pck_nom = pck; | ||
4817 | ctx->req_pck_max = pck * 3 / 2; | ||
4818 | ctx->dsi_cinfo.clkin = clkin; | ||
4819 | |||
4820 | pll_min = max(cfg->hs_clk_min * 4, txbyteclk * 4 * 4); | ||
4821 | pll_max = cfg->hs_clk_max * 4; | ||
4822 | |||
4823 | return dsi_pll_calc(dsi->pdev, clkin, | ||
4824 | pll_min, pll_max, | ||
4825 | dsi_cm_calc_pll_cb, ctx); | ||
4923 | } | 4826 | } |
4924 | EXPORT_SYMBOL(omapdss_dsi_set_pixel_format); | ||
4925 | 4827 | ||
4926 | void omapdss_dsi_set_operation_mode(struct omap_dss_device *dssdev, | 4828 | static bool dsi_vm_calc_blanking(struct dsi_clk_calc_ctx *ctx) |
4927 | enum omap_dss_dsi_mode mode) | ||
4928 | { | 4829 | { |
4929 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 4830 | struct dsi_data *dsi = dsi_get_dsidrv_data(ctx->dsidev); |
4930 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 4831 | const struct omap_dss_dsi_config *cfg = ctx->config; |
4832 | int bitspp = dsi_get_pixel_size(cfg->pixel_format); | ||
4833 | int ndl = dsi->num_lanes_used - 1; | ||
4834 | unsigned long hsclk = ctx->dsi_cinfo.clkin4ddr / 4; | ||
4835 | unsigned long byteclk = hsclk / 4; | ||
4931 | 4836 | ||
4932 | mutex_lock(&dsi->lock); | 4837 | unsigned long dispc_pck, req_pck_min, req_pck_nom, req_pck_max; |
4838 | int xres; | ||
4839 | int panel_htot, panel_hbl; /* pixels */ | ||
4840 | int dispc_htot, dispc_hbl; /* pixels */ | ||
4841 | int dsi_htot, dsi_hact, dsi_hbl, hss, hse; /* byteclks */ | ||
4842 | int hfp, hsa, hbp; | ||
4843 | const struct omap_video_timings *req_vm; | ||
4844 | struct omap_video_timings *dispc_vm; | ||
4845 | struct omap_dss_dsi_videomode_timings *dsi_vm; | ||
4846 | u64 dsi_tput, dispc_tput; | ||
4933 | 4847 | ||
4934 | dsi->mode = mode; | 4848 | dsi_tput = (u64)byteclk * ndl * 8; |
4935 | 4849 | ||
4936 | mutex_unlock(&dsi->lock); | 4850 | req_vm = cfg->timings; |
4851 | req_pck_min = ctx->req_pck_min; | ||
4852 | req_pck_max = ctx->req_pck_max; | ||
4853 | req_pck_nom = ctx->req_pck_nom; | ||
4854 | |||
4855 | dispc_pck = ctx->dispc_cinfo.pck; | ||
4856 | dispc_tput = (u64)dispc_pck * bitspp; | ||
4857 | |||
4858 | xres = req_vm->x_res; | ||
4859 | |||
4860 | panel_hbl = req_vm->hfp + req_vm->hbp + req_vm->hsw; | ||
4861 | panel_htot = xres + panel_hbl; | ||
4862 | |||
4863 | dsi_hact = DIV_ROUND_UP(DIV_ROUND_UP(xres * bitspp, 8) + 6, ndl); | ||
4864 | |||
4865 | /* | ||
4866 | * When there are no line buffers, DISPC and DSI must have the | ||
4867 | * same tput. Otherwise DISPC tput needs to be higher than DSI's. | ||
4868 | */ | ||
4869 | if (dsi->line_buffer_size < xres * bitspp / 8) { | ||
4870 | if (dispc_tput != dsi_tput) | ||
4871 | return false; | ||
4872 | } else { | ||
4873 | if (dispc_tput < dsi_tput) | ||
4874 | return false; | ||
4875 | } | ||
4876 | |||
4877 | /* DSI tput must be over the min requirement */ | ||
4878 | if (dsi_tput < (u64)bitspp * req_pck_min) | ||
4879 | return false; | ||
4880 | |||
4881 | /* When non-burst mode, DSI tput must be below max requirement. */ | ||
4882 | if (cfg->trans_mode != OMAP_DSS_DSI_BURST_MODE) { | ||
4883 | if (dsi_tput > (u64)bitspp * req_pck_max) | ||
4884 | return false; | ||
4885 | } | ||
4886 | |||
4887 | hss = DIV_ROUND_UP(4, ndl); | ||
4888 | |||
4889 | if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) { | ||
4890 | if (ndl == 3 && req_vm->hsw == 0) | ||
4891 | hse = 1; | ||
4892 | else | ||
4893 | hse = DIV_ROUND_UP(4, ndl); | ||
4894 | } else { | ||
4895 | hse = 0; | ||
4896 | } | ||
4897 | |||
4898 | /* DSI htot to match the panel's nominal pck */ | ||
4899 | dsi_htot = div64_u64((u64)panel_htot * byteclk, req_pck_nom); | ||
4900 | |||
4901 | /* fail if there would be no time for blanking */ | ||
4902 | if (dsi_htot < hss + hse + dsi_hact) | ||
4903 | return false; | ||
4904 | |||
4905 | /* total DSI blanking needed to achieve panel's TL */ | ||
4906 | dsi_hbl = dsi_htot - dsi_hact; | ||
4907 | |||
4908 | /* DISPC htot to match the DSI TL */ | ||
4909 | dispc_htot = div64_u64((u64)dsi_htot * dispc_pck, byteclk); | ||
4910 | |||
4911 | /* verify that the DSI and DISPC TLs are the same */ | ||
4912 | if ((u64)dsi_htot * dispc_pck != (u64)dispc_htot * byteclk) | ||
4913 | return false; | ||
4914 | |||
4915 | dispc_hbl = dispc_htot - xres; | ||
4916 | |||
4917 | /* setup DSI videomode */ | ||
4918 | |||
4919 | dsi_vm = &ctx->dsi_vm; | ||
4920 | memset(dsi_vm, 0, sizeof(*dsi_vm)); | ||
4921 | |||
4922 | dsi_vm->hsclk = hsclk; | ||
4923 | |||
4924 | dsi_vm->ndl = ndl; | ||
4925 | dsi_vm->bitspp = bitspp; | ||
4926 | |||
4927 | if (cfg->trans_mode != OMAP_DSS_DSI_PULSE_MODE) { | ||
4928 | hsa = 0; | ||
4929 | } else if (ndl == 3 && req_vm->hsw == 0) { | ||
4930 | hsa = 0; | ||
4931 | } else { | ||
4932 | hsa = div64_u64((u64)req_vm->hsw * byteclk, req_pck_nom); | ||
4933 | hsa = max(hsa - hse, 1); | ||
4934 | } | ||
4935 | |||
4936 | hbp = div64_u64((u64)req_vm->hbp * byteclk, req_pck_nom); | ||
4937 | hbp = max(hbp, 1); | ||
4938 | |||
4939 | hfp = dsi_hbl - (hss + hsa + hse + hbp); | ||
4940 | if (hfp < 1) { | ||
4941 | int t; | ||
4942 | /* we need to take cycles from hbp */ | ||
4943 | |||
4944 | t = 1 - hfp; | ||
4945 | hbp = max(hbp - t, 1); | ||
4946 | hfp = dsi_hbl - (hss + hsa + hse + hbp); | ||
4947 | |||
4948 | if (hfp < 1 && hsa > 0) { | ||
4949 | /* we need to take cycles from hsa */ | ||
4950 | t = 1 - hfp; | ||
4951 | hsa = max(hsa - t, 1); | ||
4952 | hfp = dsi_hbl - (hss + hsa + hse + hbp); | ||
4953 | } | ||
4954 | } | ||
4955 | |||
4956 | if (hfp < 1) | ||
4957 | return false; | ||
4958 | |||
4959 | dsi_vm->hss = hss; | ||
4960 | dsi_vm->hsa = hsa; | ||
4961 | dsi_vm->hse = hse; | ||
4962 | dsi_vm->hbp = hbp; | ||
4963 | dsi_vm->hact = xres; | ||
4964 | dsi_vm->hfp = hfp; | ||
4965 | |||
4966 | dsi_vm->vsa = req_vm->vsw; | ||
4967 | dsi_vm->vbp = req_vm->vbp; | ||
4968 | dsi_vm->vact = req_vm->y_res; | ||
4969 | dsi_vm->vfp = req_vm->vfp; | ||
4970 | |||
4971 | dsi_vm->trans_mode = cfg->trans_mode; | ||
4972 | |||
4973 | dsi_vm->blanking_mode = 0; | ||
4974 | dsi_vm->hsa_blanking_mode = 1; | ||
4975 | dsi_vm->hfp_blanking_mode = 1; | ||
4976 | dsi_vm->hbp_blanking_mode = 1; | ||
4977 | |||
4978 | dsi_vm->ddr_clk_always_on = cfg->ddr_clk_always_on; | ||
4979 | dsi_vm->window_sync = 4; | ||
4980 | |||
4981 | /* setup DISPC videomode */ | ||
4982 | |||
4983 | dispc_vm = &ctx->dispc_vm; | ||
4984 | *dispc_vm = *req_vm; | ||
4985 | dispc_vm->pixel_clock = dispc_pck / 1000; | ||
4986 | |||
4987 | if (cfg->trans_mode == OMAP_DSS_DSI_PULSE_MODE) { | ||
4988 | hsa = div64_u64((u64)req_vm->hsw * dispc_pck, | ||
4989 | req_pck_nom); | ||
4990 | hsa = max(hsa, 1); | ||
4991 | } else { | ||
4992 | hsa = 1; | ||
4993 | } | ||
4994 | |||
4995 | hbp = div64_u64((u64)req_vm->hbp * dispc_pck, req_pck_nom); | ||
4996 | hbp = max(hbp, 1); | ||
4997 | |||
4998 | hfp = dispc_hbl - hsa - hbp; | ||
4999 | if (hfp < 1) { | ||
5000 | int t; | ||
5001 | /* we need to take cycles from hbp */ | ||
5002 | |||
5003 | t = 1 - hfp; | ||
5004 | hbp = max(hbp - t, 1); | ||
5005 | hfp = dispc_hbl - hsa - hbp; | ||
5006 | |||
5007 | if (hfp < 1) { | ||
5008 | /* we need to take cycles from hsa */ | ||
5009 | t = 1 - hfp; | ||
5010 | hsa = max(hsa - t, 1); | ||
5011 | hfp = dispc_hbl - hsa - hbp; | ||
5012 | } | ||
5013 | } | ||
5014 | |||
5015 | if (hfp < 1) | ||
5016 | return false; | ||
5017 | |||
5018 | dispc_vm->hfp = hfp; | ||
5019 | dispc_vm->hsw = hsa; | ||
5020 | dispc_vm->hbp = hbp; | ||
5021 | |||
5022 | return true; | ||
4937 | } | 5023 | } |
4938 | EXPORT_SYMBOL(omapdss_dsi_set_operation_mode); | ||
4939 | 5024 | ||
4940 | void omapdss_dsi_set_videomode_timings(struct omap_dss_device *dssdev, | 5025 | |
4941 | struct omap_dss_dsi_videomode_timings *timings) | 5026 | static bool dsi_vm_calc_dispc_cb(int lckd, int pckd, unsigned long lck, |
5027 | unsigned long pck, void *data) | ||
5028 | { | ||
5029 | struct dsi_clk_calc_ctx *ctx = data; | ||
5030 | |||
5031 | ctx->dispc_cinfo.lck_div = lckd; | ||
5032 | ctx->dispc_cinfo.pck_div = pckd; | ||
5033 | ctx->dispc_cinfo.lck = lck; | ||
5034 | ctx->dispc_cinfo.pck = pck; | ||
5035 | |||
5036 | if (dsi_vm_calc_blanking(ctx) == false) | ||
5037 | return false; | ||
5038 | |||
5039 | #ifdef PRINT_VERBOSE_VM_TIMINGS | ||
5040 | print_dispc_vm("dispc", &ctx->dispc_vm); | ||
5041 | print_dsi_vm("dsi ", &ctx->dsi_vm); | ||
5042 | print_dispc_vm("req ", ctx->config->timings); | ||
5043 | print_dsi_dispc_vm("act ", &ctx->dsi_vm); | ||
5044 | #endif | ||
5045 | |||
5046 | return true; | ||
5047 | } | ||
5048 | |||
5049 | static bool dsi_vm_calc_hsdiv_cb(int regm_dispc, unsigned long dispc, | ||
5050 | void *data) | ||
5051 | { | ||
5052 | struct dsi_clk_calc_ctx *ctx = data; | ||
5053 | unsigned long pck_max; | ||
5054 | |||
5055 | ctx->dsi_cinfo.regm_dispc = regm_dispc; | ||
5056 | ctx->dsi_cinfo.dsi_pll_hsdiv_dispc_clk = dispc; | ||
5057 | |||
5058 | /* | ||
5059 | * In burst mode we can let the dispc pck be arbitrarily high, but it | ||
5060 | * limits our scaling abilities. So for now, don't aim too high. | ||
5061 | */ | ||
5062 | |||
5063 | if (ctx->config->trans_mode == OMAP_DSS_DSI_BURST_MODE) | ||
5064 | pck_max = ctx->req_pck_max + 10000000; | ||
5065 | else | ||
5066 | pck_max = ctx->req_pck_max; | ||
5067 | |||
5068 | return dispc_div_calc(dispc, ctx->req_pck_min, pck_max, | ||
5069 | dsi_vm_calc_dispc_cb, ctx); | ||
5070 | } | ||
5071 | |||
5072 | static bool dsi_vm_calc_pll_cb(int regn, int regm, unsigned long fint, | ||
5073 | unsigned long pll, void *data) | ||
5074 | { | ||
5075 | struct dsi_clk_calc_ctx *ctx = data; | ||
5076 | |||
5077 | ctx->dsi_cinfo.regn = regn; | ||
5078 | ctx->dsi_cinfo.regm = regm; | ||
5079 | ctx->dsi_cinfo.fint = fint; | ||
5080 | ctx->dsi_cinfo.clkin4ddr = pll; | ||
5081 | |||
5082 | return dsi_hsdiv_calc(ctx->dsidev, pll, ctx->req_pck_min, | ||
5083 | dsi_vm_calc_hsdiv_cb, ctx); | ||
5084 | } | ||
5085 | |||
5086 | static bool dsi_vm_calc(struct dsi_data *dsi, | ||
5087 | const struct omap_dss_dsi_config *cfg, | ||
5088 | struct dsi_clk_calc_ctx *ctx) | ||
5089 | { | ||
5090 | const struct omap_video_timings *t = cfg->timings; | ||
5091 | unsigned long clkin; | ||
5092 | unsigned long pll_min; | ||
5093 | unsigned long pll_max; | ||
5094 | int ndl = dsi->num_lanes_used - 1; | ||
5095 | int bitspp = dsi_get_pixel_size(cfg->pixel_format); | ||
5096 | unsigned long byteclk_min; | ||
5097 | |||
5098 | clkin = clk_get_rate(dsi->sys_clk); | ||
5099 | |||
5100 | memset(ctx, 0, sizeof(*ctx)); | ||
5101 | ctx->dsidev = dsi->pdev; | ||
5102 | ctx->config = cfg; | ||
5103 | |||
5104 | ctx->dsi_cinfo.clkin = clkin; | ||
5105 | |||
5106 | /* these limits should come from the panel driver */ | ||
5107 | ctx->req_pck_min = t->pixel_clock * 1000 - 1000; | ||
5108 | ctx->req_pck_nom = t->pixel_clock * 1000; | ||
5109 | ctx->req_pck_max = t->pixel_clock * 1000 + 1000; | ||
5110 | |||
5111 | byteclk_min = div64_u64((u64)ctx->req_pck_min * bitspp, ndl * 8); | ||
5112 | pll_min = max(cfg->hs_clk_min * 4, byteclk_min * 4 * 4); | ||
5113 | |||
5114 | if (cfg->trans_mode == OMAP_DSS_DSI_BURST_MODE) { | ||
5115 | pll_max = cfg->hs_clk_max * 4; | ||
5116 | } else { | ||
5117 | unsigned long byteclk_max; | ||
5118 | byteclk_max = div64_u64((u64)ctx->req_pck_max * bitspp, | ||
5119 | ndl * 8); | ||
5120 | |||
5121 | pll_max = byteclk_max * 4 * 4; | ||
5122 | } | ||
5123 | |||
5124 | return dsi_pll_calc(dsi->pdev, clkin, | ||
5125 | pll_min, pll_max, | ||
5126 | dsi_vm_calc_pll_cb, ctx); | ||
5127 | } | ||
5128 | |||
5129 | int omapdss_dsi_set_config(struct omap_dss_device *dssdev, | ||
5130 | const struct omap_dss_dsi_config *config) | ||
4942 | { | 5131 | { |
4943 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); | 5132 | struct platform_device *dsidev = dsi_get_dsidev_from_dssdev(dssdev); |
4944 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 5133 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
5134 | struct dsi_clk_calc_ctx ctx; | ||
5135 | bool ok; | ||
5136 | int r; | ||
4945 | 5137 | ||
4946 | mutex_lock(&dsi->lock); | 5138 | mutex_lock(&dsi->lock); |
4947 | 5139 | ||
4948 | dsi->vm_timings = *timings; | 5140 | dsi->pix_fmt = config->pixel_format; |
5141 | dsi->mode = config->mode; | ||
5142 | |||
5143 | if (config->mode == OMAP_DSS_DSI_VIDEO_MODE) | ||
5144 | ok = dsi_vm_calc(dsi, config, &ctx); | ||
5145 | else | ||
5146 | ok = dsi_cm_calc(dsi, config, &ctx); | ||
5147 | |||
5148 | if (!ok) { | ||
5149 | DSSERR("failed to find suitable DSI clock settings\n"); | ||
5150 | r = -EINVAL; | ||
5151 | goto err; | ||
5152 | } | ||
5153 | |||
5154 | dsi_pll_calc_dsi_fck(&ctx.dsi_cinfo); | ||
5155 | |||
5156 | r = dsi_lp_clock_calc(&ctx.dsi_cinfo, config->lp_clk_min, | ||
5157 | config->lp_clk_max); | ||
5158 | if (r) { | ||
5159 | DSSERR("failed to find suitable DSI LP clock settings\n"); | ||
5160 | goto err; | ||
5161 | } | ||
5162 | |||
5163 | dsi->user_dsi_cinfo = ctx.dsi_cinfo; | ||
5164 | dsi->user_dispc_cinfo = ctx.dispc_cinfo; | ||
5165 | |||
5166 | dsi->timings = ctx.dispc_vm; | ||
5167 | dsi->vm_timings = ctx.dsi_vm; | ||
4949 | 5168 | ||
4950 | mutex_unlock(&dsi->lock); | 5169 | mutex_unlock(&dsi->lock); |
5170 | |||
5171 | return 0; | ||
5172 | err: | ||
5173 | mutex_unlock(&dsi->lock); | ||
5174 | |||
5175 | return r; | ||
4951 | } | 5176 | } |
4952 | EXPORT_SYMBOL(omapdss_dsi_set_videomode_timings); | 5177 | EXPORT_SYMBOL(omapdss_dsi_set_config); |
5178 | |||
5179 | /* | ||
5180 | * Return a hardcoded channel for the DSI output. This should work for | ||
5181 | * current use cases, but this can be later expanded to either resolve | ||
5182 | * the channel in some more dynamic manner, or get the channel as a user | ||
5183 | * parameter. | ||
5184 | */ | ||
5185 | static enum omap_channel dsi_get_channel(int module_id) | ||
5186 | { | ||
5187 | switch (omapdss_get_version()) { | ||
5188 | case OMAPDSS_VER_OMAP24xx: | ||
5189 | DSSWARN("DSI not supported\n"); | ||
5190 | return OMAP_DSS_CHANNEL_LCD; | ||
5191 | |||
5192 | case OMAPDSS_VER_OMAP34xx_ES1: | ||
5193 | case OMAPDSS_VER_OMAP34xx_ES3: | ||
5194 | case OMAPDSS_VER_OMAP3630: | ||
5195 | case OMAPDSS_VER_AM35xx: | ||
5196 | return OMAP_DSS_CHANNEL_LCD; | ||
5197 | |||
5198 | case OMAPDSS_VER_OMAP4430_ES1: | ||
5199 | case OMAPDSS_VER_OMAP4430_ES2: | ||
5200 | case OMAPDSS_VER_OMAP4: | ||
5201 | switch (module_id) { | ||
5202 | case 0: | ||
5203 | return OMAP_DSS_CHANNEL_LCD; | ||
5204 | case 1: | ||
5205 | return OMAP_DSS_CHANNEL_LCD2; | ||
5206 | default: | ||
5207 | DSSWARN("unsupported module id\n"); | ||
5208 | return OMAP_DSS_CHANNEL_LCD; | ||
5209 | } | ||
5210 | |||
5211 | case OMAPDSS_VER_OMAP5: | ||
5212 | switch (module_id) { | ||
5213 | case 0: | ||
5214 | return OMAP_DSS_CHANNEL_LCD; | ||
5215 | case 1: | ||
5216 | return OMAP_DSS_CHANNEL_LCD3; | ||
5217 | default: | ||
5218 | DSSWARN("unsupported module id\n"); | ||
5219 | return OMAP_DSS_CHANNEL_LCD; | ||
5220 | } | ||
4953 | 5221 | ||
4954 | static int __init dsi_init_display(struct omap_dss_device *dssdev) | 5222 | default: |
5223 | DSSWARN("unsupported DSS version\n"); | ||
5224 | return OMAP_DSS_CHANNEL_LCD; | ||
5225 | } | ||
5226 | } | ||
5227 | |||
5228 | static int dsi_init_display(struct omap_dss_device *dssdev) | ||
4955 | { | 5229 | { |
4956 | struct platform_device *dsidev = | 5230 | struct platform_device *dsidev = |
4957 | dsi_get_dsidev_from_id(dssdev->phy.dsi.module); | 5231 | dsi_get_dsidev_from_id(dssdev->phy.dsi.module); |
@@ -5073,7 +5347,7 @@ static int dsi_get_clocks(struct platform_device *dsidev) | |||
5073 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 5347 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
5074 | struct clk *clk; | 5348 | struct clk *clk; |
5075 | 5349 | ||
5076 | clk = clk_get(&dsidev->dev, "fck"); | 5350 | clk = devm_clk_get(&dsidev->dev, "fck"); |
5077 | if (IS_ERR(clk)) { | 5351 | if (IS_ERR(clk)) { |
5078 | DSSERR("can't get fck\n"); | 5352 | DSSERR("can't get fck\n"); |
5079 | return PTR_ERR(clk); | 5353 | return PTR_ERR(clk); |
@@ -5081,11 +5355,9 @@ static int dsi_get_clocks(struct platform_device *dsidev) | |||
5081 | 5355 | ||
5082 | dsi->dss_clk = clk; | 5356 | dsi->dss_clk = clk; |
5083 | 5357 | ||
5084 | clk = clk_get(&dsidev->dev, "sys_clk"); | 5358 | clk = devm_clk_get(&dsidev->dev, "sys_clk"); |
5085 | if (IS_ERR(clk)) { | 5359 | if (IS_ERR(clk)) { |
5086 | DSSERR("can't get sys_clk\n"); | 5360 | DSSERR("can't get sys_clk\n"); |
5087 | clk_put(dsi->dss_clk); | ||
5088 | dsi->dss_clk = NULL; | ||
5089 | return PTR_ERR(clk); | 5361 | return PTR_ERR(clk); |
5090 | } | 5362 | } |
5091 | 5363 | ||
@@ -5094,17 +5366,7 @@ static int dsi_get_clocks(struct platform_device *dsidev) | |||
5094 | return 0; | 5366 | return 0; |
5095 | } | 5367 | } |
5096 | 5368 | ||
5097 | static void dsi_put_clocks(struct platform_device *dsidev) | 5369 | static struct omap_dss_device *dsi_find_dssdev(struct platform_device *pdev) |
5098 | { | ||
5099 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | ||
5100 | |||
5101 | if (dsi->dss_clk) | ||
5102 | clk_put(dsi->dss_clk); | ||
5103 | if (dsi->sys_clk) | ||
5104 | clk_put(dsi->sys_clk); | ||
5105 | } | ||
5106 | |||
5107 | static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *pdev) | ||
5108 | { | 5370 | { |
5109 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 5371 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
5110 | struct dsi_data *dsi = dsi_get_dsidrv_data(pdev); | 5372 | struct dsi_data *dsi = dsi_get_dsidrv_data(pdev); |
@@ -5136,7 +5398,7 @@ static struct omap_dss_device * __init dsi_find_dssdev(struct platform_device *p | |||
5136 | return def_dssdev; | 5398 | return def_dssdev; |
5137 | } | 5399 | } |
5138 | 5400 | ||
5139 | static void __init dsi_probe_pdata(struct platform_device *dsidev) | 5401 | static int dsi_probe_pdata(struct platform_device *dsidev) |
5140 | { | 5402 | { |
5141 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 5403 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
5142 | struct omap_dss_device *plat_dssdev; | 5404 | struct omap_dss_device *plat_dssdev; |
@@ -5146,11 +5408,11 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev) | |||
5146 | plat_dssdev = dsi_find_dssdev(dsidev); | 5408 | plat_dssdev = dsi_find_dssdev(dsidev); |
5147 | 5409 | ||
5148 | if (!plat_dssdev) | 5410 | if (!plat_dssdev) |
5149 | return; | 5411 | return 0; |
5150 | 5412 | ||
5151 | dssdev = dss_alloc_and_init_device(&dsidev->dev); | 5413 | dssdev = dss_alloc_and_init_device(&dsidev->dev); |
5152 | if (!dssdev) | 5414 | if (!dssdev) |
5153 | return; | 5415 | return -ENOMEM; |
5154 | 5416 | ||
5155 | dss_copy_device_pdata(dssdev, plat_dssdev); | 5417 | dss_copy_device_pdata(dssdev, plat_dssdev); |
5156 | 5418 | ||
@@ -5158,7 +5420,7 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev) | |||
5158 | if (r) { | 5420 | if (r) { |
5159 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | 5421 | DSSERR("device %s init failed: %d\n", dssdev->name, r); |
5160 | dss_put_device(dssdev); | 5422 | dss_put_device(dssdev); |
5161 | return; | 5423 | return r; |
5162 | } | 5424 | } |
5163 | 5425 | ||
5164 | r = omapdss_output_set_device(&dsi->output, dssdev); | 5426 | r = omapdss_output_set_device(&dsi->output, dssdev); |
@@ -5166,7 +5428,7 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev) | |||
5166 | DSSERR("failed to connect output to new device: %s\n", | 5428 | DSSERR("failed to connect output to new device: %s\n", |
5167 | dssdev->name); | 5429 | dssdev->name); |
5168 | dss_put_device(dssdev); | 5430 | dss_put_device(dssdev); |
5169 | return; | 5431 | return r; |
5170 | } | 5432 | } |
5171 | 5433 | ||
5172 | r = dss_add_device(dssdev); | 5434 | r = dss_add_device(dssdev); |
@@ -5174,11 +5436,13 @@ static void __init dsi_probe_pdata(struct platform_device *dsidev) | |||
5174 | DSSERR("device %s register failed: %d\n", dssdev->name, r); | 5436 | DSSERR("device %s register failed: %d\n", dssdev->name, r); |
5175 | omapdss_output_unset_device(&dsi->output); | 5437 | omapdss_output_unset_device(&dsi->output); |
5176 | dss_put_device(dssdev); | 5438 | dss_put_device(dssdev); |
5177 | return; | 5439 | return r; |
5178 | } | 5440 | } |
5441 | |||
5442 | return 0; | ||
5179 | } | 5443 | } |
5180 | 5444 | ||
5181 | static void __init dsi_init_output(struct platform_device *dsidev) | 5445 | static void dsi_init_output(struct platform_device *dsidev) |
5182 | { | 5446 | { |
5183 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 5447 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
5184 | struct omap_dss_output *out = &dsi->output; | 5448 | struct omap_dss_output *out = &dsi->output; |
@@ -5188,11 +5452,13 @@ static void __init dsi_init_output(struct platform_device *dsidev) | |||
5188 | OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; | 5452 | OMAP_DSS_OUTPUT_DSI1 : OMAP_DSS_OUTPUT_DSI2; |
5189 | 5453 | ||
5190 | out->type = OMAP_DISPLAY_TYPE_DSI; | 5454 | out->type = OMAP_DISPLAY_TYPE_DSI; |
5455 | out->name = dsi->module_id == 0 ? "dsi.0" : "dsi.1"; | ||
5456 | out->dispc_channel = dsi_get_channel(dsi->module_id); | ||
5191 | 5457 | ||
5192 | dss_register_output(out); | 5458 | dss_register_output(out); |
5193 | } | 5459 | } |
5194 | 5460 | ||
5195 | static void __exit dsi_uninit_output(struct platform_device *dsidev) | 5461 | static void dsi_uninit_output(struct platform_device *dsidev) |
5196 | { | 5462 | { |
5197 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); | 5463 | struct dsi_data *dsi = dsi_get_dsidrv_data(dsidev); |
5198 | struct omap_dss_output *out = &dsi->output; | 5464 | struct omap_dss_output *out = &dsi->output; |
@@ -5201,7 +5467,7 @@ static void __exit dsi_uninit_output(struct platform_device *dsidev) | |||
5201 | } | 5467 | } |
5202 | 5468 | ||
5203 | /* DSI1 HW IP initialisation */ | 5469 | /* DSI1 HW IP initialisation */ |
5204 | static int __init omap_dsihw_probe(struct platform_device *dsidev) | 5470 | static int omap_dsihw_probe(struct platform_device *dsidev) |
5205 | { | 5471 | { |
5206 | u32 rev; | 5472 | u32 rev; |
5207 | int r, i; | 5473 | int r, i; |
@@ -5293,9 +5559,17 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev) | |||
5293 | else | 5559 | else |
5294 | dsi->num_lanes_supported = 3; | 5560 | dsi->num_lanes_supported = 3; |
5295 | 5561 | ||
5562 | dsi->line_buffer_size = dsi_get_line_buf_size(dsidev); | ||
5563 | |||
5296 | dsi_init_output(dsidev); | 5564 | dsi_init_output(dsidev); |
5297 | 5565 | ||
5298 | dsi_probe_pdata(dsidev); | 5566 | r = dsi_probe_pdata(dsidev); |
5567 | if (r) { | ||
5568 | dsi_runtime_put(dsidev); | ||
5569 | dsi_uninit_output(dsidev); | ||
5570 | pm_runtime_disable(&dsidev->dev); | ||
5571 | return r; | ||
5572 | } | ||
5299 | 5573 | ||
5300 | dsi_runtime_put(dsidev); | 5574 | dsi_runtime_put(dsidev); |
5301 | 5575 | ||
@@ -5314,7 +5588,6 @@ static int __init omap_dsihw_probe(struct platform_device *dsidev) | |||
5314 | 5588 | ||
5315 | err_runtime_get: | 5589 | err_runtime_get: |
5316 | pm_runtime_disable(&dsidev->dev); | 5590 | pm_runtime_disable(&dsidev->dev); |
5317 | dsi_put_clocks(dsidev); | ||
5318 | return r; | 5591 | return r; |
5319 | } | 5592 | } |
5320 | 5593 | ||
@@ -5330,8 +5603,6 @@ static int __exit omap_dsihw_remove(struct platform_device *dsidev) | |||
5330 | 5603 | ||
5331 | pm_runtime_disable(&dsidev->dev); | 5604 | pm_runtime_disable(&dsidev->dev); |
5332 | 5605 | ||
5333 | dsi_put_clocks(dsidev); | ||
5334 | |||
5335 | if (dsi->vdds_dsi_reg != NULL) { | 5606 | if (dsi->vdds_dsi_reg != NULL) { |
5336 | if (dsi->vdds_dsi_enabled) { | 5607 | if (dsi->vdds_dsi_enabled) { |
5337 | regulator_disable(dsi->vdds_dsi_reg); | 5608 | regulator_disable(dsi->vdds_dsi_reg); |
@@ -5369,6 +5640,7 @@ static const struct dev_pm_ops dsi_pm_ops = { | |||
5369 | }; | 5640 | }; |
5370 | 5641 | ||
5371 | static struct platform_driver omap_dsihw_driver = { | 5642 | static struct platform_driver omap_dsihw_driver = { |
5643 | .probe = omap_dsihw_probe, | ||
5372 | .remove = __exit_p(omap_dsihw_remove), | 5644 | .remove = __exit_p(omap_dsihw_remove), |
5373 | .driver = { | 5645 | .driver = { |
5374 | .name = "omapdss_dsi", | 5646 | .name = "omapdss_dsi", |
@@ -5379,7 +5651,7 @@ static struct platform_driver omap_dsihw_driver = { | |||
5379 | 5651 | ||
5380 | int __init dsi_init_platform_driver(void) | 5652 | int __init dsi_init_platform_driver(void) |
5381 | { | 5653 | { |
5382 | return platform_driver_probe(&omap_dsihw_driver, omap_dsihw_probe); | 5654 | return platform_driver_register(&omap_dsihw_driver); |
5383 | } | 5655 | } |
5384 | 5656 | ||
5385 | void __exit dsi_uninit_platform_driver(void) | 5657 | void __exit dsi_uninit_platform_driver(void) |
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c index 054c2a22b3f1..94f66f9f10a3 100644 --- a/drivers/video/omap2/dss/dss.c +++ b/drivers/video/omap2/dss/dss.c | |||
@@ -473,6 +473,47 @@ int dss_calc_clock_rates(struct dss_clock_info *cinfo) | |||
473 | return 0; | 473 | return 0; |
474 | } | 474 | } |
475 | 475 | ||
476 | bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data) | ||
477 | { | ||
478 | int fckd, fckd_start, fckd_stop; | ||
479 | unsigned long fck; | ||
480 | unsigned long fck_hw_max; | ||
481 | unsigned long fckd_hw_max; | ||
482 | unsigned long prate; | ||
483 | unsigned m; | ||
484 | |||
485 | if (dss.dpll4_m4_ck == NULL) { | ||
486 | /* | ||
487 | * TODO: dss1_fclk can be changed on OMAP2, but the available | ||
488 | * dividers are not continuous. We just use the pre-set rate for | ||
489 | * now. | ||
490 | */ | ||
491 | fck = clk_get_rate(dss.dss_clk); | ||
492 | fckd = 1; | ||
493 | return func(fckd, fck, data); | ||
494 | } | ||
495 | |||
496 | fck_hw_max = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); | ||
497 | fckd_hw_max = dss.feat->fck_div_max; | ||
498 | |||
499 | m = dss.feat->dss_fck_multiplier; | ||
500 | prate = dss_get_dpll4_rate(); | ||
501 | |||
502 | fck_min = fck_min ? fck_min : 1; | ||
503 | |||
504 | fckd_start = min(prate * m / fck_min, fckd_hw_max); | ||
505 | fckd_stop = max(DIV_ROUND_UP(prate * m, fck_hw_max), 1ul); | ||
506 | |||
507 | for (fckd = fckd_start; fckd >= fckd_stop; --fckd) { | ||
508 | fck = prate / fckd * m; | ||
509 | |||
510 | if (func(fckd, fck, data)) | ||
511 | return true; | ||
512 | } | ||
513 | |||
514 | return false; | ||
515 | } | ||
516 | |||
476 | int dss_set_clock_div(struct dss_clock_info *cinfo) | 517 | int dss_set_clock_div(struct dss_clock_info *cinfo) |
477 | { | 518 | { |
478 | if (dss.dpll4_m4_ck) { | 519 | if (dss.dpll4_m4_ck) { |
@@ -482,7 +523,8 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) | |||
482 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); | 523 | prate = clk_get_rate(clk_get_parent(dss.dpll4_m4_ck)); |
483 | DSSDBG("dpll4_m4 = %ld\n", prate); | 524 | DSSDBG("dpll4_m4 = %ld\n", prate); |
484 | 525 | ||
485 | r = clk_set_rate(dss.dpll4_m4_ck, prate / cinfo->fck_div); | 526 | r = clk_set_rate(dss.dpll4_m4_ck, |
527 | DIV_ROUND_UP(prate, cinfo->fck_div)); | ||
486 | if (r) | 528 | if (r) |
487 | return r; | 529 | return r; |
488 | } else { | 530 | } else { |
@@ -492,7 +534,9 @@ int dss_set_clock_div(struct dss_clock_info *cinfo) | |||
492 | 534 | ||
493 | dss.dss_clk_rate = clk_get_rate(dss.dss_clk); | 535 | dss.dss_clk_rate = clk_get_rate(dss.dss_clk); |
494 | 536 | ||
495 | WARN_ONCE(dss.dss_clk_rate != cinfo->fck, "clk rate mismatch"); | 537 | WARN_ONCE(dss.dss_clk_rate != cinfo->fck, |
538 | "clk rate mismatch: %lu != %lu", dss.dss_clk_rate, | ||
539 | cinfo->fck); | ||
496 | 540 | ||
497 | DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); | 541 | DSSDBG("fck = %ld (%d)\n", cinfo->fck, cinfo->fck_div); |
498 | 542 | ||
@@ -542,121 +586,6 @@ static int dss_setup_default_clock(void) | |||
542 | return 0; | 586 | return 0; |
543 | } | 587 | } |
544 | 588 | ||
545 | int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, | ||
546 | struct dispc_clock_info *dispc_cinfo) | ||
547 | { | ||
548 | unsigned long prate; | ||
549 | struct dss_clock_info best_dss; | ||
550 | struct dispc_clock_info best_dispc; | ||
551 | |||
552 | unsigned long fck, max_dss_fck; | ||
553 | |||
554 | u16 fck_div; | ||
555 | |||
556 | int match = 0; | ||
557 | int min_fck_per_pck; | ||
558 | |||
559 | prate = dss_get_dpll4_rate(); | ||
560 | |||
561 | max_dss_fck = dss_feat_get_param_max(FEAT_PARAM_DSS_FCK); | ||
562 | |||
563 | fck = clk_get_rate(dss.dss_clk); | ||
564 | if (req_pck == dss.cache_req_pck && prate == dss.cache_prate && | ||
565 | dss.cache_dss_cinfo.fck == fck) { | ||
566 | DSSDBG("dispc clock info found from cache.\n"); | ||
567 | *dss_cinfo = dss.cache_dss_cinfo; | ||
568 | *dispc_cinfo = dss.cache_dispc_cinfo; | ||
569 | return 0; | ||
570 | } | ||
571 | |||
572 | min_fck_per_pck = CONFIG_OMAP2_DSS_MIN_FCK_PER_PCK; | ||
573 | |||
574 | if (min_fck_per_pck && | ||
575 | req_pck * min_fck_per_pck > max_dss_fck) { | ||
576 | DSSERR("Requested pixel clock not possible with the current " | ||
577 | "OMAP2_DSS_MIN_FCK_PER_PCK setting. Turning " | ||
578 | "the constraint off.\n"); | ||
579 | min_fck_per_pck = 0; | ||
580 | } | ||
581 | |||
582 | retry: | ||
583 | memset(&best_dss, 0, sizeof(best_dss)); | ||
584 | memset(&best_dispc, 0, sizeof(best_dispc)); | ||
585 | |||
586 | if (dss.dpll4_m4_ck == NULL) { | ||
587 | struct dispc_clock_info cur_dispc; | ||
588 | /* XXX can we change the clock on omap2? */ | ||
589 | fck = clk_get_rate(dss.dss_clk); | ||
590 | fck_div = 1; | ||
591 | |||
592 | dispc_find_clk_divs(req_pck, fck, &cur_dispc); | ||
593 | match = 1; | ||
594 | |||
595 | best_dss.fck = fck; | ||
596 | best_dss.fck_div = fck_div; | ||
597 | |||
598 | best_dispc = cur_dispc; | ||
599 | |||
600 | goto found; | ||
601 | } else { | ||
602 | for (fck_div = dss.feat->fck_div_max; fck_div > 0; --fck_div) { | ||
603 | struct dispc_clock_info cur_dispc; | ||
604 | |||
605 | fck = prate / fck_div * dss.feat->dss_fck_multiplier; | ||
606 | |||
607 | if (fck > max_dss_fck) | ||
608 | continue; | ||
609 | |||
610 | if (min_fck_per_pck && | ||
611 | fck < req_pck * min_fck_per_pck) | ||
612 | continue; | ||
613 | |||
614 | match = 1; | ||
615 | |||
616 | dispc_find_clk_divs(req_pck, fck, &cur_dispc); | ||
617 | |||
618 | if (abs(cur_dispc.pck - req_pck) < | ||
619 | abs(best_dispc.pck - req_pck)) { | ||
620 | |||
621 | best_dss.fck = fck; | ||
622 | best_dss.fck_div = fck_div; | ||
623 | |||
624 | best_dispc = cur_dispc; | ||
625 | |||
626 | if (cur_dispc.pck == req_pck) | ||
627 | goto found; | ||
628 | } | ||
629 | } | ||
630 | } | ||
631 | |||
632 | found: | ||
633 | if (!match) { | ||
634 | if (min_fck_per_pck) { | ||
635 | DSSERR("Could not find suitable clock settings.\n" | ||
636 | "Turning FCK/PCK constraint off and" | ||
637 | "trying again.\n"); | ||
638 | min_fck_per_pck = 0; | ||
639 | goto retry; | ||
640 | } | ||
641 | |||
642 | DSSERR("Could not find suitable clock settings.\n"); | ||
643 | |||
644 | return -EINVAL; | ||
645 | } | ||
646 | |||
647 | if (dss_cinfo) | ||
648 | *dss_cinfo = best_dss; | ||
649 | if (dispc_cinfo) | ||
650 | *dispc_cinfo = best_dispc; | ||
651 | |||
652 | dss.cache_req_pck = req_pck; | ||
653 | dss.cache_prate = prate; | ||
654 | dss.cache_dss_cinfo = best_dss; | ||
655 | dss.cache_dispc_cinfo = best_dispc; | ||
656 | |||
657 | return 0; | ||
658 | } | ||
659 | |||
660 | void dss_set_venc_output(enum omap_dss_venc_type type) | 589 | void dss_set_venc_output(enum omap_dss_venc_type type) |
661 | { | 590 | { |
662 | int l = 0; | 591 | int l = 0; |
@@ -767,13 +696,11 @@ int dss_dpi_select_source(enum omap_channel channel) | |||
767 | static int dss_get_clocks(void) | 696 | static int dss_get_clocks(void) |
768 | { | 697 | { |
769 | struct clk *clk; | 698 | struct clk *clk; |
770 | int r; | ||
771 | 699 | ||
772 | clk = clk_get(&dss.pdev->dev, "fck"); | 700 | clk = devm_clk_get(&dss.pdev->dev, "fck"); |
773 | if (IS_ERR(clk)) { | 701 | if (IS_ERR(clk)) { |
774 | DSSERR("can't get clock fck\n"); | 702 | DSSERR("can't get clock fck\n"); |
775 | r = PTR_ERR(clk); | 703 | return PTR_ERR(clk); |
776 | goto err; | ||
777 | } | 704 | } |
778 | 705 | ||
779 | dss.dss_clk = clk; | 706 | dss.dss_clk = clk; |
@@ -782,8 +709,7 @@ static int dss_get_clocks(void) | |||
782 | clk = clk_get(NULL, dss.feat->clk_name); | 709 | clk = clk_get(NULL, dss.feat->clk_name); |
783 | if (IS_ERR(clk)) { | 710 | if (IS_ERR(clk)) { |
784 | DSSERR("Failed to get %s\n", dss.feat->clk_name); | 711 | DSSERR("Failed to get %s\n", dss.feat->clk_name); |
785 | r = PTR_ERR(clk); | 712 | return PTR_ERR(clk); |
786 | goto err; | ||
787 | } | 713 | } |
788 | } else { | 714 | } else { |
789 | clk = NULL; | 715 | clk = NULL; |
@@ -792,21 +718,12 @@ static int dss_get_clocks(void) | |||
792 | dss.dpll4_m4_ck = clk; | 718 | dss.dpll4_m4_ck = clk; |
793 | 719 | ||
794 | return 0; | 720 | return 0; |
795 | |||
796 | err: | ||
797 | if (dss.dss_clk) | ||
798 | clk_put(dss.dss_clk); | ||
799 | if (dss.dpll4_m4_ck) | ||
800 | clk_put(dss.dpll4_m4_ck); | ||
801 | |||
802 | return r; | ||
803 | } | 721 | } |
804 | 722 | ||
805 | static void dss_put_clocks(void) | 723 | static void dss_put_clocks(void) |
806 | { | 724 | { |
807 | if (dss.dpll4_m4_ck) | 725 | if (dss.dpll4_m4_ck) |
808 | clk_put(dss.dpll4_m4_ck); | 726 | clk_put(dss.dpll4_m4_ck); |
809 | clk_put(dss.dss_clk); | ||
810 | } | 727 | } |
811 | 728 | ||
812 | static int dss_runtime_get(void) | 729 | static int dss_runtime_get(void) |
diff --git a/drivers/video/omap2/dss/dss.h b/drivers/video/omap2/dss/dss.h index 610c8e563daa..84758936429d 100644 --- a/drivers/video/omap2/dss/dss.h +++ b/drivers/video/omap2/dss/dss.h | |||
@@ -268,14 +268,21 @@ void dss_set_dac_pwrdn_bgz(bool enable); | |||
268 | unsigned long dss_get_dpll4_rate(void); | 268 | unsigned long dss_get_dpll4_rate(void); |
269 | int dss_calc_clock_rates(struct dss_clock_info *cinfo); | 269 | int dss_calc_clock_rates(struct dss_clock_info *cinfo); |
270 | int dss_set_clock_div(struct dss_clock_info *cinfo); | 270 | int dss_set_clock_div(struct dss_clock_info *cinfo); |
271 | int dss_calc_clock_div(unsigned long req_pck, struct dss_clock_info *dss_cinfo, | 271 | |
272 | struct dispc_clock_info *dispc_cinfo); | 272 | typedef bool (*dss_div_calc_func)(int fckd, unsigned long fck, void *data); |
273 | bool dss_div_calc(unsigned long fck_min, dss_div_calc_func func, void *data); | ||
273 | 274 | ||
274 | /* SDI */ | 275 | /* SDI */ |
275 | int sdi_init_platform_driver(void) __init; | 276 | int sdi_init_platform_driver(void) __init; |
276 | void sdi_uninit_platform_driver(void) __exit; | 277 | void sdi_uninit_platform_driver(void) __exit; |
277 | 278 | ||
278 | /* DSI */ | 279 | /* DSI */ |
280 | |||
281 | typedef bool (*dsi_pll_calc_func)(int regn, int regm, unsigned long fint, | ||
282 | unsigned long pll, void *data); | ||
283 | typedef bool (*dsi_hsdiv_calc_func)(int regm_dispc, unsigned long dispc, | ||
284 | void *data); | ||
285 | |||
279 | #ifdef CONFIG_OMAP2_DSS_DSI | 286 | #ifdef CONFIG_OMAP2_DSS_DSI |
280 | 287 | ||
281 | struct dentry; | 288 | struct dentry; |
@@ -292,12 +299,17 @@ void dsi_dump_clocks(struct seq_file *s); | |||
292 | void dsi_irq_handler(void); | 299 | void dsi_irq_handler(void); |
293 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); | 300 | u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); |
294 | 301 | ||
302 | unsigned long dsi_get_pll_clkin(struct platform_device *dsidev); | ||
303 | |||
304 | bool dsi_hsdiv_calc(struct platform_device *dsidev, unsigned long pll, | ||
305 | unsigned long out_min, dsi_hsdiv_calc_func func, void *data); | ||
306 | bool dsi_pll_calc(struct platform_device *dsidev, unsigned long clkin, | ||
307 | unsigned long pll_min, unsigned long pll_max, | ||
308 | dsi_pll_calc_func func, void *data); | ||
309 | |||
295 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); | 310 | unsigned long dsi_get_pll_hsdiv_dispc_rate(struct platform_device *dsidev); |
296 | int dsi_pll_set_clock_div(struct platform_device *dsidev, | 311 | int dsi_pll_set_clock_div(struct platform_device *dsidev, |
297 | struct dsi_clock_info *cinfo); | 312 | struct dsi_clock_info *cinfo); |
298 | int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, | ||
299 | unsigned long req_pck, struct dsi_clock_info *cinfo, | ||
300 | struct dispc_clock_info *dispc_cinfo); | ||
301 | int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, | 313 | int dsi_pll_init(struct platform_device *dsidev, bool enable_hsclk, |
302 | bool enable_hsdiv); | 314 | bool enable_hsdiv); |
303 | void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); | 315 | void dsi_pll_uninit(struct platform_device *dsidev, bool disconnect_lanes); |
@@ -328,14 +340,6 @@ static inline int dsi_pll_set_clock_div(struct platform_device *dsidev, | |||
328 | WARN("%s: DSI not compiled in\n", __func__); | 340 | WARN("%s: DSI not compiled in\n", __func__); |
329 | return -ENODEV; | 341 | return -ENODEV; |
330 | } | 342 | } |
331 | static inline int dsi_pll_calc_clock_div_pck(struct platform_device *dsidev, | ||
332 | unsigned long req_pck, | ||
333 | struct dsi_clock_info *dsi_cinfo, | ||
334 | struct dispc_clock_info *dispc_cinfo) | ||
335 | { | ||
336 | WARN("%s: DSI not compiled in\n", __func__); | ||
337 | return -ENODEV; | ||
338 | } | ||
339 | static inline int dsi_pll_init(struct platform_device *dsidev, | 343 | static inline int dsi_pll_init(struct platform_device *dsidev, |
340 | bool enable_hsclk, bool enable_hsdiv) | 344 | bool enable_hsclk, bool enable_hsdiv) |
341 | { | 345 | { |
@@ -356,6 +360,27 @@ static inline struct platform_device *dsi_get_dsidev_from_id(int module) | |||
356 | { | 360 | { |
357 | return NULL; | 361 | return NULL; |
358 | } | 362 | } |
363 | |||
364 | static inline unsigned long dsi_get_pll_clkin(struct platform_device *dsidev) | ||
365 | { | ||
366 | return 0; | ||
367 | } | ||
368 | |||
369 | static inline bool dsi_hsdiv_calc(struct platform_device *dsidev, | ||
370 | unsigned long pll, unsigned long out_min, | ||
371 | dsi_hsdiv_calc_func func, void *data) | ||
372 | { | ||
373 | return false; | ||
374 | } | ||
375 | |||
376 | static inline bool dsi_pll_calc(struct platform_device *dsidev, | ||
377 | unsigned long clkin, | ||
378 | unsigned long pll_min, unsigned long pll_max, | ||
379 | dsi_pll_calc_func func, void *data) | ||
380 | { | ||
381 | return false; | ||
382 | } | ||
383 | |||
359 | #endif | 384 | #endif |
360 | 385 | ||
361 | /* DPI */ | 386 | /* DPI */ |
@@ -376,11 +401,15 @@ void dispc_enable_fifomerge(bool enable); | |||
376 | void dispc_enable_gamma_table(bool enable); | 401 | void dispc_enable_gamma_table(bool enable); |
377 | void dispc_set_loadmode(enum omap_dss_load_mode mode); | 402 | void dispc_set_loadmode(enum omap_dss_load_mode mode); |
378 | 403 | ||
404 | typedef bool (*dispc_div_calc_func)(int lckd, int pckd, unsigned long lck, | ||
405 | unsigned long pck, void *data); | ||
406 | bool dispc_div_calc(unsigned long dispc, | ||
407 | unsigned long pck_min, unsigned long pck_max, | ||
408 | dispc_div_calc_func func, void *data); | ||
409 | |||
379 | bool dispc_mgr_timings_ok(enum omap_channel channel, | 410 | bool dispc_mgr_timings_ok(enum omap_channel channel, |
380 | const struct omap_video_timings *timings); | 411 | const struct omap_video_timings *timings); |
381 | unsigned long dispc_fclk_rate(void); | 412 | unsigned long dispc_fclk_rate(void); |
382 | void dispc_find_clk_divs(unsigned long req_pck, unsigned long fck, | ||
383 | struct dispc_clock_info *cinfo); | ||
384 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, | 413 | int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, |
385 | struct dispc_clock_info *cinfo); | 414 | struct dispc_clock_info *cinfo); |
386 | 415 | ||
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c index 7f791aeda4d2..77dbe0cfb34c 100644 --- a/drivers/video/omap2/dss/dss_features.c +++ b/drivers/video/omap2/dss/dss_features.c | |||
@@ -414,7 +414,7 @@ static const char * const omap5_dss_clk_source_names[] = { | |||
414 | }; | 414 | }; |
415 | 415 | ||
416 | static const struct dss_param_range omap2_dss_param_range[] = { | 416 | static const struct dss_param_range omap2_dss_param_range[] = { |
417 | [FEAT_PARAM_DSS_FCK] = { 0, 173000000 }, | 417 | [FEAT_PARAM_DSS_FCK] = { 0, 133000000 }, |
418 | [FEAT_PARAM_DSS_PCD] = { 2, 255 }, | 418 | [FEAT_PARAM_DSS_PCD] = { 2, 255 }, |
419 | [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, | 419 | [FEAT_PARAM_DSIPLL_REGN] = { 0, 0 }, |
420 | [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, | 420 | [FEAT_PARAM_DSIPLL_REGM] = { 0, 0 }, |
@@ -459,15 +459,15 @@ static const struct dss_param_range omap4_dss_param_range[] = { | |||
459 | }; | 459 | }; |
460 | 460 | ||
461 | static const struct dss_param_range omap5_dss_param_range[] = { | 461 | static const struct dss_param_range omap5_dss_param_range[] = { |
462 | [FEAT_PARAM_DSS_FCK] = { 0, 200000000 }, | 462 | [FEAT_PARAM_DSS_FCK] = { 0, 209250000 }, |
463 | [FEAT_PARAM_DSS_PCD] = { 1, 255 }, | 463 | [FEAT_PARAM_DSS_PCD] = { 1, 255 }, |
464 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, | 464 | [FEAT_PARAM_DSIPLL_REGN] = { 0, (1 << 8) - 1 }, |
465 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, | 465 | [FEAT_PARAM_DSIPLL_REGM] = { 0, (1 << 12) - 1 }, |
466 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, | 466 | [FEAT_PARAM_DSIPLL_REGM_DISPC] = { 0, (1 << 5) - 1 }, |
467 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, | 467 | [FEAT_PARAM_DSIPLL_REGM_DSI] = { 0, (1 << 5) - 1 }, |
468 | [FEAT_PARAM_DSIPLL_FINT] = { 500000, 2500000 }, | 468 | [FEAT_PARAM_DSIPLL_FINT] = { 150000, 52000000 }, |
469 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, | 469 | [FEAT_PARAM_DSIPLL_LPDIV] = { 0, (1 << 13) - 1 }, |
470 | [FEAT_PARAM_DSI_FCK] = { 0, 170000000 }, | 470 | [FEAT_PARAM_DSI_FCK] = { 0, 209250000 }, |
471 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, | 471 | [FEAT_PARAM_DOWNSCALE] = { 1, 4 }, |
472 | [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, | 472 | [FEAT_PARAM_LINEWIDTH] = { 1, 2048 }, |
473 | }; | 473 | }; |
diff --git a/drivers/video/omap2/dss/hdmi.c b/drivers/video/omap2/dss/hdmi.c index 72923645dcce..17f4d55c621c 100644 --- a/drivers/video/omap2/dss/hdmi.c +++ b/drivers/video/omap2/dss/hdmi.c | |||
@@ -328,7 +328,7 @@ static void hdmi_runtime_put(void) | |||
328 | WARN_ON(r < 0 && r != -ENOSYS); | 328 | WARN_ON(r < 0 && r != -ENOSYS); |
329 | } | 329 | } |
330 | 330 | ||
331 | static int __init hdmi_init_display(struct omap_dss_device *dssdev) | 331 | static int hdmi_init_display(struct omap_dss_device *dssdev) |
332 | { | 332 | { |
333 | int r; | 333 | int r; |
334 | 334 | ||
@@ -472,17 +472,12 @@ static void hdmi_compute_pll(struct omap_dss_device *dssdev, int phy, | |||
472 | * Input clock is predivided by N + 1 | 472 | * Input clock is predivided by N + 1 |
473 | * out put of which is reference clk | 473 | * out put of which is reference clk |
474 | */ | 474 | */ |
475 | if (dssdev->clocks.hdmi.regn == 0) | 475 | |
476 | pi->regn = HDMI_DEFAULT_REGN; | 476 | pi->regn = HDMI_DEFAULT_REGN; |
477 | else | ||
478 | pi->regn = dssdev->clocks.hdmi.regn; | ||
479 | 477 | ||
480 | refclk = clkin / pi->regn; | 478 | refclk = clkin / pi->regn; |
481 | 479 | ||
482 | if (dssdev->clocks.hdmi.regm2 == 0) | 480 | pi->regm2 = HDMI_DEFAULT_REGM2; |
483 | pi->regm2 = HDMI_DEFAULT_REGM2; | ||
484 | else | ||
485 | pi->regm2 = dssdev->clocks.hdmi.regm2; | ||
486 | 481 | ||
487 | /* | 482 | /* |
488 | * multiplier is pixel_clk/ref_clk | 483 | * multiplier is pixel_clk/ref_clk |
@@ -804,7 +799,7 @@ static int hdmi_get_clocks(struct platform_device *pdev) | |||
804 | { | 799 | { |
805 | struct clk *clk; | 800 | struct clk *clk; |
806 | 801 | ||
807 | clk = clk_get(&pdev->dev, "sys_clk"); | 802 | clk = devm_clk_get(&pdev->dev, "sys_clk"); |
808 | if (IS_ERR(clk)) { | 803 | if (IS_ERR(clk)) { |
809 | DSSERR("can't get sys_clk\n"); | 804 | DSSERR("can't get sys_clk\n"); |
810 | return PTR_ERR(clk); | 805 | return PTR_ERR(clk); |
@@ -815,12 +810,6 @@ static int hdmi_get_clocks(struct platform_device *pdev) | |||
815 | return 0; | 810 | return 0; |
816 | } | 811 | } |
817 | 812 | ||
818 | static void hdmi_put_clocks(void) | ||
819 | { | ||
820 | if (hdmi.sys_clk) | ||
821 | clk_put(hdmi.sys_clk); | ||
822 | } | ||
823 | |||
824 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) | 813 | #if defined(CONFIG_OMAP4_DSS_HDMI_AUDIO) |
825 | int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts) | 814 | int hdmi_compute_acr(u32 sample_freq, u32 *n, u32 *cts) |
826 | { | 815 | { |
@@ -965,7 +954,7 @@ int hdmi_audio_config(struct omap_dss_audio *audio) | |||
965 | 954 | ||
966 | #endif | 955 | #endif |
967 | 956 | ||
968 | static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device *pdev) | 957 | static struct omap_dss_device *hdmi_find_dssdev(struct platform_device *pdev) |
969 | { | 958 | { |
970 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 959 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
971 | const char *def_disp_name = omapdss_get_default_display_name(); | 960 | const char *def_disp_name = omapdss_get_default_display_name(); |
@@ -993,7 +982,7 @@ static struct omap_dss_device * __init hdmi_find_dssdev(struct platform_device * | |||
993 | return def_dssdev; | 982 | return def_dssdev; |
994 | } | 983 | } |
995 | 984 | ||
996 | static void __init hdmi_probe_pdata(struct platform_device *pdev) | 985 | static int hdmi_probe_pdata(struct platform_device *pdev) |
997 | { | 986 | { |
998 | struct omap_dss_device *plat_dssdev; | 987 | struct omap_dss_device *plat_dssdev; |
999 | struct omap_dss_device *dssdev; | 988 | struct omap_dss_device *dssdev; |
@@ -1003,11 +992,11 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev) | |||
1003 | plat_dssdev = hdmi_find_dssdev(pdev); | 992 | plat_dssdev = hdmi_find_dssdev(pdev); |
1004 | 993 | ||
1005 | if (!plat_dssdev) | 994 | if (!plat_dssdev) |
1006 | return; | 995 | return 0; |
1007 | 996 | ||
1008 | dssdev = dss_alloc_and_init_device(&pdev->dev); | 997 | dssdev = dss_alloc_and_init_device(&pdev->dev); |
1009 | if (!dssdev) | 998 | if (!dssdev) |
1010 | return; | 999 | return -ENOMEM; |
1011 | 1000 | ||
1012 | dss_copy_device_pdata(dssdev, plat_dssdev); | 1001 | dss_copy_device_pdata(dssdev, plat_dssdev); |
1013 | 1002 | ||
@@ -1017,13 +1006,11 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev) | |||
1017 | hdmi.ls_oe_gpio = priv->ls_oe_gpio; | 1006 | hdmi.ls_oe_gpio = priv->ls_oe_gpio; |
1018 | hdmi.hpd_gpio = priv->hpd_gpio; | 1007 | hdmi.hpd_gpio = priv->hpd_gpio; |
1019 | 1008 | ||
1020 | dssdev->channel = OMAP_DSS_CHANNEL_DIGIT; | ||
1021 | |||
1022 | r = hdmi_init_display(dssdev); | 1009 | r = hdmi_init_display(dssdev); |
1023 | if (r) { | 1010 | if (r) { |
1024 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | 1011 | DSSERR("device %s init failed: %d\n", dssdev->name, r); |
1025 | dss_put_device(dssdev); | 1012 | dss_put_device(dssdev); |
1026 | return; | 1013 | return r; |
1027 | } | 1014 | } |
1028 | 1015 | ||
1029 | r = omapdss_output_set_device(&hdmi.output, dssdev); | 1016 | r = omapdss_output_set_device(&hdmi.output, dssdev); |
@@ -1031,7 +1018,7 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev) | |||
1031 | DSSERR("failed to connect output to new device: %s\n", | 1018 | DSSERR("failed to connect output to new device: %s\n", |
1032 | dssdev->name); | 1019 | dssdev->name); |
1033 | dss_put_device(dssdev); | 1020 | dss_put_device(dssdev); |
1034 | return; | 1021 | return r; |
1035 | } | 1022 | } |
1036 | 1023 | ||
1037 | r = dss_add_device(dssdev); | 1024 | r = dss_add_device(dssdev); |
@@ -1040,17 +1027,21 @@ static void __init hdmi_probe_pdata(struct platform_device *pdev) | |||
1040 | omapdss_output_unset_device(&hdmi.output); | 1027 | omapdss_output_unset_device(&hdmi.output); |
1041 | hdmi_uninit_display(dssdev); | 1028 | hdmi_uninit_display(dssdev); |
1042 | dss_put_device(dssdev); | 1029 | dss_put_device(dssdev); |
1043 | return; | 1030 | return r; |
1044 | } | 1031 | } |
1032 | |||
1033 | return 0; | ||
1045 | } | 1034 | } |
1046 | 1035 | ||
1047 | static void __init hdmi_init_output(struct platform_device *pdev) | 1036 | static void hdmi_init_output(struct platform_device *pdev) |
1048 | { | 1037 | { |
1049 | struct omap_dss_output *out = &hdmi.output; | 1038 | struct omap_dss_output *out = &hdmi.output; |
1050 | 1039 | ||
1051 | out->pdev = pdev; | 1040 | out->pdev = pdev; |
1052 | out->id = OMAP_DSS_OUTPUT_HDMI; | 1041 | out->id = OMAP_DSS_OUTPUT_HDMI; |
1053 | out->type = OMAP_DISPLAY_TYPE_HDMI; | 1042 | out->type = OMAP_DISPLAY_TYPE_HDMI; |
1043 | out->name = "hdmi.0"; | ||
1044 | out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; | ||
1054 | 1045 | ||
1055 | dss_register_output(out); | 1046 | dss_register_output(out); |
1056 | } | 1047 | } |
@@ -1063,7 +1054,7 @@ static void __exit hdmi_uninit_output(struct platform_device *pdev) | |||
1063 | } | 1054 | } |
1064 | 1055 | ||
1065 | /* HDMI HW IP initialisation */ | 1056 | /* HDMI HW IP initialisation */ |
1066 | static int __init omapdss_hdmihw_probe(struct platform_device *pdev) | 1057 | static int omapdss_hdmihw_probe(struct platform_device *pdev) |
1067 | { | 1058 | { |
1068 | struct resource *res; | 1059 | struct resource *res; |
1069 | int r; | 1060 | int r; |
@@ -1097,23 +1088,25 @@ static int __init omapdss_hdmihw_probe(struct platform_device *pdev) | |||
1097 | hdmi.ip_data.pll_offset = HDMI_PLLCTRL; | 1088 | hdmi.ip_data.pll_offset = HDMI_PLLCTRL; |
1098 | hdmi.ip_data.phy_offset = HDMI_PHY; | 1089 | hdmi.ip_data.phy_offset = HDMI_PHY; |
1099 | 1090 | ||
1091 | hdmi_init_output(pdev); | ||
1092 | |||
1100 | r = hdmi_panel_init(); | 1093 | r = hdmi_panel_init(); |
1101 | if (r) { | 1094 | if (r) { |
1102 | DSSERR("can't init panel\n"); | 1095 | DSSERR("can't init panel\n"); |
1103 | goto err_panel_init; | 1096 | return r; |
1104 | } | 1097 | } |
1105 | 1098 | ||
1106 | dss_debugfs_create_file("hdmi", hdmi_dump_regs); | 1099 | dss_debugfs_create_file("hdmi", hdmi_dump_regs); |
1107 | 1100 | ||
1108 | hdmi_init_output(pdev); | 1101 | r = hdmi_probe_pdata(pdev); |
1109 | 1102 | if (r) { | |
1110 | hdmi_probe_pdata(pdev); | 1103 | hdmi_panel_exit(); |
1104 | hdmi_uninit_output(pdev); | ||
1105 | pm_runtime_disable(&pdev->dev); | ||
1106 | return r; | ||
1107 | } | ||
1111 | 1108 | ||
1112 | return 0; | 1109 | return 0; |
1113 | |||
1114 | err_panel_init: | ||
1115 | hdmi_put_clocks(); | ||
1116 | return r; | ||
1117 | } | 1110 | } |
1118 | 1111 | ||
1119 | static int __exit hdmi_remove_child(struct device *dev, void *data) | 1112 | static int __exit hdmi_remove_child(struct device *dev, void *data) |
@@ -1135,8 +1128,6 @@ static int __exit omapdss_hdmihw_remove(struct platform_device *pdev) | |||
1135 | 1128 | ||
1136 | pm_runtime_disable(&pdev->dev); | 1129 | pm_runtime_disable(&pdev->dev); |
1137 | 1130 | ||
1138 | hdmi_put_clocks(); | ||
1139 | |||
1140 | return 0; | 1131 | return 0; |
1141 | } | 1132 | } |
1142 | 1133 | ||
@@ -1168,6 +1159,7 @@ static const struct dev_pm_ops hdmi_pm_ops = { | |||
1168 | }; | 1159 | }; |
1169 | 1160 | ||
1170 | static struct platform_driver omapdss_hdmihw_driver = { | 1161 | static struct platform_driver omapdss_hdmihw_driver = { |
1162 | .probe = omapdss_hdmihw_probe, | ||
1171 | .remove = __exit_p(omapdss_hdmihw_remove), | 1163 | .remove = __exit_p(omapdss_hdmihw_remove), |
1172 | .driver = { | 1164 | .driver = { |
1173 | .name = "omapdss_hdmi", | 1165 | .name = "omapdss_hdmi", |
@@ -1178,7 +1170,7 @@ static struct platform_driver omapdss_hdmihw_driver = { | |||
1178 | 1170 | ||
1179 | int __init hdmi_init_platform_driver(void) | 1171 | int __init hdmi_init_platform_driver(void) |
1180 | { | 1172 | { |
1181 | return platform_driver_probe(&omapdss_hdmihw_driver, omapdss_hdmihw_probe); | 1173 | return platform_driver_register(&omapdss_hdmihw_driver); |
1182 | } | 1174 | } |
1183 | 1175 | ||
1184 | void __exit hdmi_uninit_platform_driver(void) | 1176 | void __exit hdmi_uninit_platform_driver(void) |
diff --git a/drivers/video/omap2/dss/output.c b/drivers/video/omap2/dss/output.c index 79dea1a1a732..5214df63e0a9 100644 --- a/drivers/video/omap2/dss/output.c +++ b/drivers/video/omap2/dss/output.c | |||
@@ -113,6 +113,7 @@ struct omap_dss_output *omap_dss_get_output(enum omap_dss_output_id id) | |||
113 | 113 | ||
114 | return NULL; | 114 | return NULL; |
115 | } | 115 | } |
116 | EXPORT_SYMBOL(omap_dss_get_output); | ||
116 | 117 | ||
117 | static const struct dss_mgr_ops *dss_mgr_ops; | 118 | static const struct dss_mgr_ops *dss_mgr_ops; |
118 | 119 | ||
diff --git a/drivers/video/omap2/dss/rfbi.c b/drivers/video/omap2/dss/rfbi.c index e903dd3f54d9..1a17dd1447dc 100644 --- a/drivers/video/omap2/dss/rfbi.c +++ b/drivers/video/omap2/dss/rfbi.c | |||
@@ -943,13 +943,13 @@ void omapdss_rfbi_display_disable(struct omap_dss_device *dssdev) | |||
943 | } | 943 | } |
944 | EXPORT_SYMBOL(omapdss_rfbi_display_disable); | 944 | EXPORT_SYMBOL(omapdss_rfbi_display_disable); |
945 | 945 | ||
946 | static int __init rfbi_init_display(struct omap_dss_device *dssdev) | 946 | static int rfbi_init_display(struct omap_dss_device *dssdev) |
947 | { | 947 | { |
948 | rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; | 948 | rfbi.dssdev[dssdev->phy.rfbi.channel] = dssdev; |
949 | return 0; | 949 | return 0; |
950 | } | 950 | } |
951 | 951 | ||
952 | static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device *pdev) | 952 | static struct omap_dss_device *rfbi_find_dssdev(struct platform_device *pdev) |
953 | { | 953 | { |
954 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 954 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
955 | const char *def_disp_name = omapdss_get_default_display_name(); | 955 | const char *def_disp_name = omapdss_get_default_display_name(); |
@@ -977,7 +977,7 @@ static struct omap_dss_device * __init rfbi_find_dssdev(struct platform_device * | |||
977 | return def_dssdev; | 977 | return def_dssdev; |
978 | } | 978 | } |
979 | 979 | ||
980 | static void __init rfbi_probe_pdata(struct platform_device *rfbidev) | 980 | static int rfbi_probe_pdata(struct platform_device *rfbidev) |
981 | { | 981 | { |
982 | struct omap_dss_device *plat_dssdev; | 982 | struct omap_dss_device *plat_dssdev; |
983 | struct omap_dss_device *dssdev; | 983 | struct omap_dss_device *dssdev; |
@@ -986,11 +986,11 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev) | |||
986 | plat_dssdev = rfbi_find_dssdev(rfbidev); | 986 | plat_dssdev = rfbi_find_dssdev(rfbidev); |
987 | 987 | ||
988 | if (!plat_dssdev) | 988 | if (!plat_dssdev) |
989 | return; | 989 | return 0; |
990 | 990 | ||
991 | dssdev = dss_alloc_and_init_device(&rfbidev->dev); | 991 | dssdev = dss_alloc_and_init_device(&rfbidev->dev); |
992 | if (!dssdev) | 992 | if (!dssdev) |
993 | return; | 993 | return -ENOMEM; |
994 | 994 | ||
995 | dss_copy_device_pdata(dssdev, plat_dssdev); | 995 | dss_copy_device_pdata(dssdev, plat_dssdev); |
996 | 996 | ||
@@ -998,7 +998,7 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev) | |||
998 | if (r) { | 998 | if (r) { |
999 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | 999 | DSSERR("device %s init failed: %d\n", dssdev->name, r); |
1000 | dss_put_device(dssdev); | 1000 | dss_put_device(dssdev); |
1001 | return; | 1001 | return r; |
1002 | } | 1002 | } |
1003 | 1003 | ||
1004 | r = omapdss_output_set_device(&rfbi.output, dssdev); | 1004 | r = omapdss_output_set_device(&rfbi.output, dssdev); |
@@ -1006,7 +1006,7 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev) | |||
1006 | DSSERR("failed to connect output to new device: %s\n", | 1006 | DSSERR("failed to connect output to new device: %s\n", |
1007 | dssdev->name); | 1007 | dssdev->name); |
1008 | dss_put_device(dssdev); | 1008 | dss_put_device(dssdev); |
1009 | return; | 1009 | return r; |
1010 | } | 1010 | } |
1011 | 1011 | ||
1012 | r = dss_add_device(dssdev); | 1012 | r = dss_add_device(dssdev); |
@@ -1014,17 +1014,21 @@ static void __init rfbi_probe_pdata(struct platform_device *rfbidev) | |||
1014 | DSSERR("device %s register failed: %d\n", dssdev->name, r); | 1014 | DSSERR("device %s register failed: %d\n", dssdev->name, r); |
1015 | omapdss_output_unset_device(&rfbi.output); | 1015 | omapdss_output_unset_device(&rfbi.output); |
1016 | dss_put_device(dssdev); | 1016 | dss_put_device(dssdev); |
1017 | return; | 1017 | return r; |
1018 | } | 1018 | } |
1019 | |||
1020 | return 0; | ||
1019 | } | 1021 | } |
1020 | 1022 | ||
1021 | static void __init rfbi_init_output(struct platform_device *pdev) | 1023 | static void rfbi_init_output(struct platform_device *pdev) |
1022 | { | 1024 | { |
1023 | struct omap_dss_output *out = &rfbi.output; | 1025 | struct omap_dss_output *out = &rfbi.output; |
1024 | 1026 | ||
1025 | out->pdev = pdev; | 1027 | out->pdev = pdev; |
1026 | out->id = OMAP_DSS_OUTPUT_DBI; | 1028 | out->id = OMAP_DSS_OUTPUT_DBI; |
1027 | out->type = OMAP_DISPLAY_TYPE_DBI; | 1029 | out->type = OMAP_DISPLAY_TYPE_DBI; |
1030 | out->name = "rfbi.0"; | ||
1031 | out->dispc_channel = OMAP_DSS_CHANNEL_LCD; | ||
1028 | 1032 | ||
1029 | dss_register_output(out); | 1033 | dss_register_output(out); |
1030 | } | 1034 | } |
@@ -1037,7 +1041,7 @@ static void __exit rfbi_uninit_output(struct platform_device *pdev) | |||
1037 | } | 1041 | } |
1038 | 1042 | ||
1039 | /* RFBI HW IP initialisation */ | 1043 | /* RFBI HW IP initialisation */ |
1040 | static int __init omap_rfbihw_probe(struct platform_device *pdev) | 1044 | static int omap_rfbihw_probe(struct platform_device *pdev) |
1041 | { | 1045 | { |
1042 | u32 rev; | 1046 | u32 rev; |
1043 | struct resource *rfbi_mem; | 1047 | struct resource *rfbi_mem; |
@@ -1089,7 +1093,12 @@ static int __init omap_rfbihw_probe(struct platform_device *pdev) | |||
1089 | 1093 | ||
1090 | rfbi_init_output(pdev); | 1094 | rfbi_init_output(pdev); |
1091 | 1095 | ||
1092 | rfbi_probe_pdata(pdev); | 1096 | r = rfbi_probe_pdata(pdev); |
1097 | if (r) { | ||
1098 | rfbi_uninit_output(pdev); | ||
1099 | pm_runtime_disable(&pdev->dev); | ||
1100 | return r; | ||
1101 | } | ||
1093 | 1102 | ||
1094 | return 0; | 1103 | return 0; |
1095 | 1104 | ||
@@ -1133,6 +1142,7 @@ static const struct dev_pm_ops rfbi_pm_ops = { | |||
1133 | }; | 1142 | }; |
1134 | 1143 | ||
1135 | static struct platform_driver omap_rfbihw_driver = { | 1144 | static struct platform_driver omap_rfbihw_driver = { |
1145 | .probe = omap_rfbihw_probe, | ||
1136 | .remove = __exit_p(omap_rfbihw_remove), | 1146 | .remove = __exit_p(omap_rfbihw_remove), |
1137 | .driver = { | 1147 | .driver = { |
1138 | .name = "omapdss_rfbi", | 1148 | .name = "omapdss_rfbi", |
@@ -1143,7 +1153,7 @@ static struct platform_driver omap_rfbihw_driver = { | |||
1143 | 1153 | ||
1144 | int __init rfbi_init_platform_driver(void) | 1154 | int __init rfbi_init_platform_driver(void) |
1145 | { | 1155 | { |
1146 | return platform_driver_probe(&omap_rfbihw_driver, omap_rfbihw_probe); | 1156 | return platform_driver_register(&omap_rfbihw_driver); |
1147 | } | 1157 | } |
1148 | 1158 | ||
1149 | void __exit rfbi_uninit_platform_driver(void) | 1159 | void __exit rfbi_uninit_platform_driver(void) |
diff --git a/drivers/video/omap2/dss/sdi.c b/drivers/video/omap2/dss/sdi.c index 62b5374ce438..0bcd30272f69 100644 --- a/drivers/video/omap2/dss/sdi.c +++ b/drivers/video/omap2/dss/sdi.c | |||
@@ -41,6 +41,72 @@ static struct { | |||
41 | struct omap_dss_output output; | 41 | struct omap_dss_output output; |
42 | } sdi; | 42 | } sdi; |
43 | 43 | ||
44 | struct sdi_clk_calc_ctx { | ||
45 | unsigned long pck_min, pck_max; | ||
46 | |||
47 | struct dss_clock_info dss_cinfo; | ||
48 | struct dispc_clock_info dispc_cinfo; | ||
49 | }; | ||
50 | |||
51 | static bool dpi_calc_dispc_cb(int lckd, int pckd, unsigned long lck, | ||
52 | unsigned long pck, void *data) | ||
53 | { | ||
54 | struct sdi_clk_calc_ctx *ctx = data; | ||
55 | |||
56 | ctx->dispc_cinfo.lck_div = lckd; | ||
57 | ctx->dispc_cinfo.pck_div = pckd; | ||
58 | ctx->dispc_cinfo.lck = lck; | ||
59 | ctx->dispc_cinfo.pck = pck; | ||
60 | |||
61 | return true; | ||
62 | } | ||
63 | |||
64 | static bool dpi_calc_dss_cb(int fckd, unsigned long fck, void *data) | ||
65 | { | ||
66 | struct sdi_clk_calc_ctx *ctx = data; | ||
67 | |||
68 | ctx->dss_cinfo.fck = fck; | ||
69 | ctx->dss_cinfo.fck_div = fckd; | ||
70 | |||
71 | return dispc_div_calc(fck, ctx->pck_min, ctx->pck_max, | ||
72 | dpi_calc_dispc_cb, ctx); | ||
73 | } | ||
74 | |||
75 | static int sdi_calc_clock_div(unsigned long pclk, | ||
76 | struct dss_clock_info *dss_cinfo, | ||
77 | struct dispc_clock_info *dispc_cinfo) | ||
78 | { | ||
79 | int i; | ||
80 | struct sdi_clk_calc_ctx ctx; | ||
81 | |||
82 | /* | ||
83 | * DSS fclk gives us very few possibilities, so finding a good pixel | ||
84 | * clock may not be possible. We try multiple times to find the clock, | ||
85 | * each time widening the pixel clock range we look for, up to | ||
86 | * +/- 1MHz. | ||
87 | */ | ||
88 | |||
89 | for (i = 0; i < 10; ++i) { | ||
90 | bool ok; | ||
91 | |||
92 | memset(&ctx, 0, sizeof(ctx)); | ||
93 | if (pclk > 1000 * i * i * i) | ||
94 | ctx.pck_min = max(pclk - 1000 * i * i * i, 0lu); | ||
95 | else | ||
96 | ctx.pck_min = 0; | ||
97 | ctx.pck_max = pclk + 1000 * i * i * i; | ||
98 | |||
99 | ok = dss_div_calc(ctx.pck_min, dpi_calc_dss_cb, &ctx); | ||
100 | if (ok) { | ||
101 | *dss_cinfo = ctx.dss_cinfo; | ||
102 | *dispc_cinfo = ctx.dispc_cinfo; | ||
103 | return 0; | ||
104 | } | ||
105 | } | ||
106 | |||
107 | return -EINVAL; | ||
108 | } | ||
109 | |||
44 | static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) | 110 | static void sdi_config_lcd_manager(struct omap_dss_device *dssdev) |
45 | { | 111 | { |
46 | struct omap_overlay_manager *mgr = dssdev->output->manager; | 112 | struct omap_overlay_manager *mgr = dssdev->output->manager; |
@@ -88,7 +154,7 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev) | |||
88 | t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; | 154 | t->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; |
89 | t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; | 155 | t->sync_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE; |
90 | 156 | ||
91 | r = dss_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); | 157 | r = sdi_calc_clock_div(t->pixel_clock * 1000, &dss_cinfo, &dispc_cinfo); |
92 | if (r) | 158 | if (r) |
93 | goto err_calc_clock_div; | 159 | goto err_calc_clock_div; |
94 | 160 | ||
@@ -182,7 +248,7 @@ void omapdss_sdi_set_datapairs(struct omap_dss_device *dssdev, int datapairs) | |||
182 | } | 248 | } |
183 | EXPORT_SYMBOL(omapdss_sdi_set_datapairs); | 249 | EXPORT_SYMBOL(omapdss_sdi_set_datapairs); |
184 | 250 | ||
185 | static int __init sdi_init_display(struct omap_dss_device *dssdev) | 251 | static int sdi_init_display(struct omap_dss_device *dssdev) |
186 | { | 252 | { |
187 | DSSDBG("SDI init\n"); | 253 | DSSDBG("SDI init\n"); |
188 | 254 | ||
@@ -202,7 +268,7 @@ static int __init sdi_init_display(struct omap_dss_device *dssdev) | |||
202 | return 0; | 268 | return 0; |
203 | } | 269 | } |
204 | 270 | ||
205 | static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *pdev) | 271 | static struct omap_dss_device *sdi_find_dssdev(struct platform_device *pdev) |
206 | { | 272 | { |
207 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 273 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
208 | const char *def_disp_name = omapdss_get_default_display_name(); | 274 | const char *def_disp_name = omapdss_get_default_display_name(); |
@@ -230,7 +296,7 @@ static struct omap_dss_device * __init sdi_find_dssdev(struct platform_device *p | |||
230 | return def_dssdev; | 296 | return def_dssdev; |
231 | } | 297 | } |
232 | 298 | ||
233 | static void __init sdi_probe_pdata(struct platform_device *sdidev) | 299 | static int sdi_probe_pdata(struct platform_device *sdidev) |
234 | { | 300 | { |
235 | struct omap_dss_device *plat_dssdev; | 301 | struct omap_dss_device *plat_dssdev; |
236 | struct omap_dss_device *dssdev; | 302 | struct omap_dss_device *dssdev; |
@@ -239,11 +305,11 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev) | |||
239 | plat_dssdev = sdi_find_dssdev(sdidev); | 305 | plat_dssdev = sdi_find_dssdev(sdidev); |
240 | 306 | ||
241 | if (!plat_dssdev) | 307 | if (!plat_dssdev) |
242 | return; | 308 | return 0; |
243 | 309 | ||
244 | dssdev = dss_alloc_and_init_device(&sdidev->dev); | 310 | dssdev = dss_alloc_and_init_device(&sdidev->dev); |
245 | if (!dssdev) | 311 | if (!dssdev) |
246 | return; | 312 | return -ENOMEM; |
247 | 313 | ||
248 | dss_copy_device_pdata(dssdev, plat_dssdev); | 314 | dss_copy_device_pdata(dssdev, plat_dssdev); |
249 | 315 | ||
@@ -251,7 +317,7 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev) | |||
251 | if (r) { | 317 | if (r) { |
252 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | 318 | DSSERR("device %s init failed: %d\n", dssdev->name, r); |
253 | dss_put_device(dssdev); | 319 | dss_put_device(dssdev); |
254 | return; | 320 | return r; |
255 | } | 321 | } |
256 | 322 | ||
257 | r = omapdss_output_set_device(&sdi.output, dssdev); | 323 | r = omapdss_output_set_device(&sdi.output, dssdev); |
@@ -259,7 +325,7 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev) | |||
259 | DSSERR("failed to connect output to new device: %s\n", | 325 | DSSERR("failed to connect output to new device: %s\n", |
260 | dssdev->name); | 326 | dssdev->name); |
261 | dss_put_device(dssdev); | 327 | dss_put_device(dssdev); |
262 | return; | 328 | return r; |
263 | } | 329 | } |
264 | 330 | ||
265 | r = dss_add_device(dssdev); | 331 | r = dss_add_device(dssdev); |
@@ -267,17 +333,21 @@ static void __init sdi_probe_pdata(struct platform_device *sdidev) | |||
267 | DSSERR("device %s register failed: %d\n", dssdev->name, r); | 333 | DSSERR("device %s register failed: %d\n", dssdev->name, r); |
268 | omapdss_output_unset_device(&sdi.output); | 334 | omapdss_output_unset_device(&sdi.output); |
269 | dss_put_device(dssdev); | 335 | dss_put_device(dssdev); |
270 | return; | 336 | return r; |
271 | } | 337 | } |
338 | |||
339 | return 0; | ||
272 | } | 340 | } |
273 | 341 | ||
274 | static void __init sdi_init_output(struct platform_device *pdev) | 342 | static void sdi_init_output(struct platform_device *pdev) |
275 | { | 343 | { |
276 | struct omap_dss_output *out = &sdi.output; | 344 | struct omap_dss_output *out = &sdi.output; |
277 | 345 | ||
278 | out->pdev = pdev; | 346 | out->pdev = pdev; |
279 | out->id = OMAP_DSS_OUTPUT_SDI; | 347 | out->id = OMAP_DSS_OUTPUT_SDI; |
280 | out->type = OMAP_DISPLAY_TYPE_SDI; | 348 | out->type = OMAP_DISPLAY_TYPE_SDI; |
349 | out->name = "sdi.0"; | ||
350 | out->dispc_channel = OMAP_DSS_CHANNEL_LCD; | ||
281 | 351 | ||
282 | dss_register_output(out); | 352 | dss_register_output(out); |
283 | } | 353 | } |
@@ -289,11 +359,17 @@ static void __exit sdi_uninit_output(struct platform_device *pdev) | |||
289 | dss_unregister_output(out); | 359 | dss_unregister_output(out); |
290 | } | 360 | } |
291 | 361 | ||
292 | static int __init omap_sdi_probe(struct platform_device *pdev) | 362 | static int omap_sdi_probe(struct platform_device *pdev) |
293 | { | 363 | { |
364 | int r; | ||
365 | |||
294 | sdi_init_output(pdev); | 366 | sdi_init_output(pdev); |
295 | 367 | ||
296 | sdi_probe_pdata(pdev); | 368 | r = sdi_probe_pdata(pdev); |
369 | if (r) { | ||
370 | sdi_uninit_output(pdev); | ||
371 | return r; | ||
372 | } | ||
297 | 373 | ||
298 | return 0; | 374 | return 0; |
299 | } | 375 | } |
@@ -308,6 +384,7 @@ static int __exit omap_sdi_remove(struct platform_device *pdev) | |||
308 | } | 384 | } |
309 | 385 | ||
310 | static struct platform_driver omap_sdi_driver = { | 386 | static struct platform_driver omap_sdi_driver = { |
387 | .probe = omap_sdi_probe, | ||
311 | .remove = __exit_p(omap_sdi_remove), | 388 | .remove = __exit_p(omap_sdi_remove), |
312 | .driver = { | 389 | .driver = { |
313 | .name = "omapdss_sdi", | 390 | .name = "omapdss_sdi", |
@@ -317,7 +394,7 @@ static struct platform_driver omap_sdi_driver = { | |||
317 | 394 | ||
318 | int __init sdi_init_platform_driver(void) | 395 | int __init sdi_init_platform_driver(void) |
319 | { | 396 | { |
320 | return platform_driver_probe(&omap_sdi_driver, omap_sdi_probe); | 397 | return platform_driver_register(&omap_sdi_driver); |
321 | } | 398 | } |
322 | 399 | ||
323 | void __exit sdi_uninit_platform_driver(void) | 400 | void __exit sdi_uninit_platform_driver(void) |
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c index 006caf3cb509..74fdb3ee209e 100644 --- a/drivers/video/omap2/dss/venc.c +++ b/drivers/video/omap2/dss/venc.c | |||
@@ -519,10 +519,6 @@ int omapdss_venc_display_enable(struct omap_dss_device *dssdev) | |||
519 | goto err0; | 519 | goto err0; |
520 | } | 520 | } |
521 | 521 | ||
522 | if (dssdev->platform_enable) | ||
523 | dssdev->platform_enable(dssdev); | ||
524 | |||
525 | |||
526 | r = venc_power_on(dssdev); | 522 | r = venc_power_on(dssdev); |
527 | if (r) | 523 | if (r) |
528 | goto err1; | 524 | goto err1; |
@@ -533,8 +529,6 @@ int omapdss_venc_display_enable(struct omap_dss_device *dssdev) | |||
533 | 529 | ||
534 | return 0; | 530 | return 0; |
535 | err1: | 531 | err1: |
536 | if (dssdev->platform_disable) | ||
537 | dssdev->platform_disable(dssdev); | ||
538 | omap_dss_stop_device(dssdev); | 532 | omap_dss_stop_device(dssdev); |
539 | err0: | 533 | err0: |
540 | mutex_unlock(&venc.venc_lock); | 534 | mutex_unlock(&venc.venc_lock); |
@@ -551,9 +545,6 @@ void omapdss_venc_display_disable(struct omap_dss_device *dssdev) | |||
551 | 545 | ||
552 | omap_dss_stop_device(dssdev); | 546 | omap_dss_stop_device(dssdev); |
553 | 547 | ||
554 | if (dssdev->platform_disable) | ||
555 | dssdev->platform_disable(dssdev); | ||
556 | |||
557 | mutex_unlock(&venc.venc_lock); | 548 | mutex_unlock(&venc.venc_lock); |
558 | } | 549 | } |
559 | 550 | ||
@@ -642,7 +633,7 @@ void omapdss_venc_invert_vid_out_polarity(struct omap_dss_device *dssdev, | |||
642 | mutex_unlock(&venc.venc_lock); | 633 | mutex_unlock(&venc.venc_lock); |
643 | } | 634 | } |
644 | 635 | ||
645 | static int __init venc_init_display(struct omap_dss_device *dssdev) | 636 | static int venc_init_display(struct omap_dss_device *dssdev) |
646 | { | 637 | { |
647 | DSSDBG("init_display\n"); | 638 | DSSDBG("init_display\n"); |
648 | 639 | ||
@@ -721,7 +712,7 @@ static int venc_get_clocks(struct platform_device *pdev) | |||
721 | struct clk *clk; | 712 | struct clk *clk; |
722 | 713 | ||
723 | if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { | 714 | if (dss_has_feature(FEAT_VENC_REQUIRES_TV_DAC_CLK)) { |
724 | clk = clk_get(&pdev->dev, "tv_dac_clk"); | 715 | clk = devm_clk_get(&pdev->dev, "tv_dac_clk"); |
725 | if (IS_ERR(clk)) { | 716 | if (IS_ERR(clk)) { |
726 | DSSERR("can't get tv_dac_clk\n"); | 717 | DSSERR("can't get tv_dac_clk\n"); |
727 | return PTR_ERR(clk); | 718 | return PTR_ERR(clk); |
@@ -735,13 +726,7 @@ static int venc_get_clocks(struct platform_device *pdev) | |||
735 | return 0; | 726 | return 0; |
736 | } | 727 | } |
737 | 728 | ||
738 | static void venc_put_clocks(void) | 729 | static struct omap_dss_device *venc_find_dssdev(struct platform_device *pdev) |
739 | { | ||
740 | if (venc.tv_dac_clk) | ||
741 | clk_put(venc.tv_dac_clk); | ||
742 | } | ||
743 | |||
744 | static struct omap_dss_device * __init venc_find_dssdev(struct platform_device *pdev) | ||
745 | { | 730 | { |
746 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; | 731 | struct omap_dss_board_info *pdata = pdev->dev.platform_data; |
747 | const char *def_disp_name = omapdss_get_default_display_name(); | 732 | const char *def_disp_name = omapdss_get_default_display_name(); |
@@ -769,7 +754,7 @@ static struct omap_dss_device * __init venc_find_dssdev(struct platform_device * | |||
769 | return def_dssdev; | 754 | return def_dssdev; |
770 | } | 755 | } |
771 | 756 | ||
772 | static void __init venc_probe_pdata(struct platform_device *vencdev) | 757 | static int venc_probe_pdata(struct platform_device *vencdev) |
773 | { | 758 | { |
774 | struct omap_dss_device *plat_dssdev; | 759 | struct omap_dss_device *plat_dssdev; |
775 | struct omap_dss_device *dssdev; | 760 | struct omap_dss_device *dssdev; |
@@ -778,21 +763,19 @@ static void __init venc_probe_pdata(struct platform_device *vencdev) | |||
778 | plat_dssdev = venc_find_dssdev(vencdev); | 763 | plat_dssdev = venc_find_dssdev(vencdev); |
779 | 764 | ||
780 | if (!plat_dssdev) | 765 | if (!plat_dssdev) |
781 | return; | 766 | return 0; |
782 | 767 | ||
783 | dssdev = dss_alloc_and_init_device(&vencdev->dev); | 768 | dssdev = dss_alloc_and_init_device(&vencdev->dev); |
784 | if (!dssdev) | 769 | if (!dssdev) |
785 | return; | 770 | return -ENOMEM; |
786 | 771 | ||
787 | dss_copy_device_pdata(dssdev, plat_dssdev); | 772 | dss_copy_device_pdata(dssdev, plat_dssdev); |
788 | 773 | ||
789 | dssdev->channel = OMAP_DSS_CHANNEL_DIGIT; | ||
790 | |||
791 | r = venc_init_display(dssdev); | 774 | r = venc_init_display(dssdev); |
792 | if (r) { | 775 | if (r) { |
793 | DSSERR("device %s init failed: %d\n", dssdev->name, r); | 776 | DSSERR("device %s init failed: %d\n", dssdev->name, r); |
794 | dss_put_device(dssdev); | 777 | dss_put_device(dssdev); |
795 | return; | 778 | return r; |
796 | } | 779 | } |
797 | 780 | ||
798 | r = omapdss_output_set_device(&venc.output, dssdev); | 781 | r = omapdss_output_set_device(&venc.output, dssdev); |
@@ -800,7 +783,7 @@ static void __init venc_probe_pdata(struct platform_device *vencdev) | |||
800 | DSSERR("failed to connect output to new device: %s\n", | 783 | DSSERR("failed to connect output to new device: %s\n", |
801 | dssdev->name); | 784 | dssdev->name); |
802 | dss_put_device(dssdev); | 785 | dss_put_device(dssdev); |
803 | return; | 786 | return r; |
804 | } | 787 | } |
805 | 788 | ||
806 | r = dss_add_device(dssdev); | 789 | r = dss_add_device(dssdev); |
@@ -808,17 +791,21 @@ static void __init venc_probe_pdata(struct platform_device *vencdev) | |||
808 | DSSERR("device %s register failed: %d\n", dssdev->name, r); | 791 | DSSERR("device %s register failed: %d\n", dssdev->name, r); |
809 | omapdss_output_unset_device(&venc.output); | 792 | omapdss_output_unset_device(&venc.output); |
810 | dss_put_device(dssdev); | 793 | dss_put_device(dssdev); |
811 | return; | 794 | return r; |
812 | } | 795 | } |
796 | |||
797 | return 0; | ||
813 | } | 798 | } |
814 | 799 | ||
815 | static void __init venc_init_output(struct platform_device *pdev) | 800 | static void venc_init_output(struct platform_device *pdev) |
816 | { | 801 | { |
817 | struct omap_dss_output *out = &venc.output; | 802 | struct omap_dss_output *out = &venc.output; |
818 | 803 | ||
819 | out->pdev = pdev; | 804 | out->pdev = pdev; |
820 | out->id = OMAP_DSS_OUTPUT_VENC; | 805 | out->id = OMAP_DSS_OUTPUT_VENC; |
821 | out->type = OMAP_DISPLAY_TYPE_VENC; | 806 | out->type = OMAP_DISPLAY_TYPE_VENC; |
807 | out->name = "venc.0"; | ||
808 | out->dispc_channel = OMAP_DSS_CHANNEL_DIGIT; | ||
822 | 809 | ||
823 | dss_register_output(out); | 810 | dss_register_output(out); |
824 | } | 811 | } |
@@ -831,7 +818,7 @@ static void __exit venc_uninit_output(struct platform_device *pdev) | |||
831 | } | 818 | } |
832 | 819 | ||
833 | /* VENC HW IP initialisation */ | 820 | /* VENC HW IP initialisation */ |
834 | static int __init omap_venchw_probe(struct platform_device *pdev) | 821 | static int omap_venchw_probe(struct platform_device *pdev) |
835 | { | 822 | { |
836 | u8 rev_id; | 823 | u8 rev_id; |
837 | struct resource *venc_mem; | 824 | struct resource *venc_mem; |
@@ -879,14 +866,19 @@ static int __init omap_venchw_probe(struct platform_device *pdev) | |||
879 | 866 | ||
880 | venc_init_output(pdev); | 867 | venc_init_output(pdev); |
881 | 868 | ||
882 | venc_probe_pdata(pdev); | 869 | r = venc_probe_pdata(pdev); |
870 | if (r) { | ||
871 | venc_panel_exit(); | ||
872 | venc_uninit_output(pdev); | ||
873 | pm_runtime_disable(&pdev->dev); | ||
874 | return r; | ||
875 | } | ||
883 | 876 | ||
884 | return 0; | 877 | return 0; |
885 | 878 | ||
886 | err_panel_init: | 879 | err_panel_init: |
887 | err_runtime_get: | 880 | err_runtime_get: |
888 | pm_runtime_disable(&pdev->dev); | 881 | pm_runtime_disable(&pdev->dev); |
889 | venc_put_clocks(); | ||
890 | return r; | 882 | return r; |
891 | } | 883 | } |
892 | 884 | ||
@@ -904,7 +896,6 @@ static int __exit omap_venchw_remove(struct platform_device *pdev) | |||
904 | venc_uninit_output(pdev); | 896 | venc_uninit_output(pdev); |
905 | 897 | ||
906 | pm_runtime_disable(&pdev->dev); | 898 | pm_runtime_disable(&pdev->dev); |
907 | venc_put_clocks(); | ||
908 | 899 | ||
909 | return 0; | 900 | return 0; |
910 | } | 901 | } |
@@ -939,6 +930,7 @@ static const struct dev_pm_ops venc_pm_ops = { | |||
939 | }; | 930 | }; |
940 | 931 | ||
941 | static struct platform_driver omap_venchw_driver = { | 932 | static struct platform_driver omap_venchw_driver = { |
933 | .probe = omap_venchw_probe, | ||
942 | .remove = __exit_p(omap_venchw_remove), | 934 | .remove = __exit_p(omap_venchw_remove), |
943 | .driver = { | 935 | .driver = { |
944 | .name = "omapdss_venc", | 936 | .name = "omapdss_venc", |
@@ -949,7 +941,7 @@ static struct platform_driver omap_venchw_driver = { | |||
949 | 941 | ||
950 | int __init venc_init_platform_driver(void) | 942 | int __init venc_init_platform_driver(void) |
951 | { | 943 | { |
952 | return platform_driver_probe(&omap_venchw_driver, omap_venchw_probe); | 944 | return platform_driver_register(&omap_venchw_driver); |
953 | } | 945 | } |
954 | 946 | ||
955 | void __exit venc_uninit_platform_driver(void) | 947 | void __exit venc_uninit_platform_driver(void) |
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c index 717f13a93351..c84bb8a4d0c4 100644 --- a/drivers/video/omap2/omapfb/omapfb-main.c +++ b/drivers/video/omap2/omapfb/omapfb-main.c | |||
@@ -2372,7 +2372,7 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev, | |||
2372 | struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; | 2372 | struct omap_dss_device *dssdev = fbdev->displays[i].dssdev; |
2373 | struct omap_dss_output *out = dssdev->output; | 2373 | struct omap_dss_output *out = dssdev->output; |
2374 | 2374 | ||
2375 | mgr = omap_dss_get_overlay_manager(dssdev->channel); | 2375 | mgr = omap_dss_get_overlay_manager(out->dispc_channel); |
2376 | 2376 | ||
2377 | if (!mgr || !out) | 2377 | if (!mgr || !out) |
2378 | continue; | 2378 | continue; |
@@ -2406,7 +2406,7 @@ static int omapfb_init_connections(struct omapfb2_device *fbdev, | |||
2406 | return 0; | 2406 | return 0; |
2407 | } | 2407 | } |
2408 | 2408 | ||
2409 | static int __init omapfb_probe(struct platform_device *pdev) | 2409 | static int omapfb_probe(struct platform_device *pdev) |
2410 | { | 2410 | { |
2411 | struct omapfb2_device *fbdev = NULL; | 2411 | struct omapfb2_device *fbdev = NULL; |
2412 | int r = 0; | 2412 | int r = 0; |
@@ -2468,7 +2468,7 @@ static int __init omapfb_probe(struct platform_device *pdev) | |||
2468 | 2468 | ||
2469 | if (fbdev->num_displays == 0) { | 2469 | if (fbdev->num_displays == 0) { |
2470 | dev_err(&pdev->dev, "no displays\n"); | 2470 | dev_err(&pdev->dev, "no displays\n"); |
2471 | r = -EINVAL; | 2471 | r = -EPROBE_DEFER; |
2472 | goto cleanup; | 2472 | goto cleanup; |
2473 | } | 2473 | } |
2474 | 2474 | ||
@@ -2579,6 +2579,7 @@ static int __exit omapfb_remove(struct platform_device *pdev) | |||
2579 | } | 2579 | } |
2580 | 2580 | ||
2581 | static struct platform_driver omapfb_driver = { | 2581 | static struct platform_driver omapfb_driver = { |
2582 | .probe = omapfb_probe, | ||
2582 | .remove = __exit_p(omapfb_remove), | 2583 | .remove = __exit_p(omapfb_remove), |
2583 | .driver = { | 2584 | .driver = { |
2584 | .name = "omapfb", | 2585 | .name = "omapfb", |
@@ -2586,36 +2587,13 @@ static struct platform_driver omapfb_driver = { | |||
2586 | }, | 2587 | }, |
2587 | }; | 2588 | }; |
2588 | 2589 | ||
2589 | static int __init omapfb_init(void) | ||
2590 | { | ||
2591 | DBG("omapfb_init\n"); | ||
2592 | |||
2593 | if (platform_driver_probe(&omapfb_driver, omapfb_probe)) { | ||
2594 | printk(KERN_ERR "failed to register omapfb driver\n"); | ||
2595 | return -ENODEV; | ||
2596 | } | ||
2597 | |||
2598 | return 0; | ||
2599 | } | ||
2600 | |||
2601 | static void __exit omapfb_exit(void) | ||
2602 | { | ||
2603 | DBG("omapfb_exit\n"); | ||
2604 | platform_driver_unregister(&omapfb_driver); | ||
2605 | } | ||
2606 | |||
2607 | module_param_named(mode, def_mode, charp, 0); | 2590 | module_param_named(mode, def_mode, charp, 0); |
2608 | module_param_named(vram, def_vram, charp, 0); | 2591 | module_param_named(vram, def_vram, charp, 0); |
2609 | module_param_named(rotate, def_rotate, int, 0); | 2592 | module_param_named(rotate, def_rotate, int, 0); |
2610 | module_param_named(vrfb, def_vrfb, bool, 0); | 2593 | module_param_named(vrfb, def_vrfb, bool, 0); |
2611 | module_param_named(mirror, def_mirror, bool, 0); | 2594 | module_param_named(mirror, def_mirror, bool, 0); |
2612 | 2595 | ||
2613 | /* late_initcall to let panel/ctrl drivers loaded first. | 2596 | module_platform_driver(omapfb_driver); |
2614 | * I guess better option would be a more dynamic approach, | ||
2615 | * so that omapfb reacts to new panels when they are loaded */ | ||
2616 | late_initcall(omapfb_init); | ||
2617 | /*module_init(omapfb_init);*/ | ||
2618 | module_exit(omapfb_exit); | ||
2619 | 2597 | ||
2620 | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); | 2598 | MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@nokia.com>"); |
2621 | MODULE_DESCRIPTION("OMAP2/3 Framebuffer"); | 2599 | MODULE_DESCRIPTION("OMAP2/3 Framebuffer"); |