diff options
Diffstat (limited to 'drivers/gpu/drm/omapdrm')
32 files changed, 858 insertions, 746 deletions
diff --git a/drivers/gpu/drm/omapdrm/Kconfig b/drivers/gpu/drm/omapdrm/Kconfig index 556f81f6b2c7..b3d08c5f41d4 100644 --- a/drivers/gpu/drm/omapdrm/Kconfig +++ b/drivers/gpu/drm/omapdrm/Kconfig @@ -10,15 +10,6 @@ config DRM_OMAP if DRM_OMAP -config DRM_OMAP_NUM_CRTCS - int "Number of CRTCs" - range 1 10 - default 1 if ARCH_OMAP2 || ARCH_OMAP3 - default 2 if ARCH_OMAP4 - help - Select the number of video overlays which can be used as framebuffers. - The remaining overlays are reserved for video. - source "drivers/gpu/drm/omapdrm/dss/Kconfig" source "drivers/gpu/drm/omapdrm/displays/Kconfig" diff --git a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c index 38003208d9ca..04ce8c5f2954 100644 --- a/drivers/gpu/drm/omapdrm/displays/panel-dpi.c +++ b/drivers/gpu/drm/omapdrm/displays/panel-dpi.c @@ -16,6 +16,7 @@ #include <linux/of.h> #include <linux/of_gpio.h> #include <linux/regulator/consumer.h> +#include <linux/backlight.h> #include <video/omap-panel-data.h> #include <video/of_display_timing.h> @@ -30,6 +31,8 @@ struct panel_drv_data { struct videomode vm; + struct backlight_device *backlight; + /* used for non-DT boot, to be removed */ int backlight_gpio; @@ -97,6 +100,11 @@ static int panel_dpi_enable(struct omap_dss_device *dssdev) if (gpio_is_valid(ddata->backlight_gpio)) gpio_set_value_cansleep(ddata->backlight_gpio, 1); + if (ddata->backlight) { + ddata->backlight->props.power = FB_BLANK_UNBLANK; + backlight_update_status(ddata->backlight); + } + dssdev->state = OMAP_DSS_DISPLAY_ACTIVE; return 0; @@ -113,6 +121,11 @@ static void panel_dpi_disable(struct omap_dss_device *dssdev) if (gpio_is_valid(ddata->backlight_gpio)) gpio_set_value_cansleep(ddata->backlight_gpio, 0); + if (ddata->backlight) { + ddata->backlight->props.power = FB_BLANK_POWERDOWN; + backlight_update_status(ddata->backlight); + } + gpiod_set_value_cansleep(ddata->enable_gpio, 0); regulator_disable(ddata->vcc_supply); @@ -209,6 +222,7 @@ static int panel_dpi_probe_of(struct platform_device *pdev) { struct panel_drv_data *ddata = platform_get_drvdata(pdev); struct device_node *node = pdev->dev.of_node; + struct device_node *bl_node; struct omap_dss_device *in; int r; struct display_timing timing; @@ -236,10 +250,19 @@ static int panel_dpi_probe_of(struct platform_device *pdev) ddata->backlight_gpio = -ENOENT; + bl_node = of_parse_phandle(node, "backlight", 0); + if (bl_node) { + ddata->backlight = of_find_backlight_by_node(bl_node); + of_node_put(bl_node); + + if (!ddata->backlight) + return -EPROBE_DEFER; + } + r = of_get_display_timing(node, "panel-timing", &timing); if (r) { dev_err(&pdev->dev, "failed to get video timing\n"); - return r; + goto error_free_backlight; } videomode_from_timing(&timing, &ddata->vm); @@ -247,12 +270,19 @@ static int panel_dpi_probe_of(struct platform_device *pdev) in = omapdss_of_find_source_for_first_ep(node); if (IS_ERR(in)) { dev_err(&pdev->dev, "failed to find video source\n"); - return PTR_ERR(in); + r = PTR_ERR(in); + goto error_free_backlight; } ddata->in = in; return 0; + +error_free_backlight: + if (ddata->backlight) + put_device(&ddata->backlight->dev); + + return r; } static int panel_dpi_probe(struct platform_device *pdev) @@ -321,6 +351,9 @@ static int __exit panel_dpi_remove(struct platform_device *pdev) omap_dss_put_device(in); + if (ddata->backlight) + put_device(&ddata->backlight->dev); + return 0; } diff --git a/drivers/gpu/drm/omapdrm/dss/Kconfig b/drivers/gpu/drm/omapdrm/dss/Kconfig index d1fa730c7d54..f53adb944a0d 100644 --- a/drivers/gpu/drm/omapdrm/dss/Kconfig +++ b/drivers/gpu/drm/omapdrm/dss/Kconfig @@ -1,8 +1,12 @@ config OMAP2_DSS_INIT bool +config OMAP_DSS_BASE + tristate + menuconfig OMAP2_DSS tristate "OMAP2+ Display Subsystem support" + select OMAP_DSS_BASE select VIDEOMODE_HELPERS select OMAP2_DSS_INIT select HDMI diff --git a/drivers/gpu/drm/omapdrm/dss/Makefile b/drivers/gpu/drm/omapdrm/dss/Makefile index b651ec9751e6..75ec30f231c7 100644 --- a/drivers/gpu/drm/omapdrm/dss/Makefile +++ b/drivers/gpu/drm/omapdrm/dss/Makefile @@ -1,8 +1,12 @@ obj-$(CONFIG_OMAP2_DSS_INIT) += omapdss-boot-init.o + +obj-$(CONFIG_OMAP_DSS_BASE) += omapdss-base.o +omapdss-base-y := base.o display.o dss-of.o output.o + obj-$(CONFIG_OMAP2_DSS) += omapdss.o # Core DSS files -omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o display.o \ - output.o dss-of.o pll.o video-pll.o +omapdss-y := core.o dss.o dss_features.o dispc.o dispc_coefs.o \ + pll.o video-pll.o omapdss-$(CONFIG_OMAP2_DSS_DPI) += dpi.o omapdss-$(CONFIG_OMAP2_DSS_RFBI) += rfbi.o omapdss-$(CONFIG_OMAP2_DSS_VENC) += venc.o diff --git a/drivers/gpu/drm/omapdrm/dss/base.c b/drivers/gpu/drm/omapdrm/dss/base.c new file mode 100644 index 000000000000..13e91faaf7a6 --- /dev/null +++ b/drivers/gpu/drm/omapdrm/dss/base.c @@ -0,0 +1,140 @@ +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_graph.h> +#include <linux/list.h> +#include "omapdss.h" + +static bool dss_initialized; +static const struct dispc_ops *ops; + +static struct list_head omapdss_comp_list; + +struct omapdss_comp_node { + struct list_head list; + struct device_node *node; + bool dss_core_component; +}; + +void omapdss_set_is_initialized(bool set) +{ + dss_initialized = set; +} +EXPORT_SYMBOL(omapdss_set_is_initialized); + +bool omapdss_is_initialized(void) +{ + return dss_initialized; +} +EXPORT_SYMBOL(omapdss_is_initialized); + +void dispc_set_ops(const struct dispc_ops *o) +{ + ops = o; +} +EXPORT_SYMBOL(dispc_set_ops); + +const struct dispc_ops *dispc_get_ops(void) +{ + return ops; +} +EXPORT_SYMBOL(dispc_get_ops); + +static bool omapdss_list_contains(const struct device_node *node) +{ + struct omapdss_comp_node *comp; + + list_for_each_entry(comp, &omapdss_comp_list, list) { + if (comp->node == node) + return true; + } + + return false; +} + +static void omapdss_walk_device(struct device *dev, struct device_node *node, + bool dss_core) +{ + struct device_node *n; + struct omapdss_comp_node *comp = devm_kzalloc(dev, sizeof(*comp), + GFP_KERNEL); + + if (comp) { + comp->node = node; + comp->dss_core_component = dss_core; + list_add(&comp->list, &omapdss_comp_list); + } + + /* + * of_graph_get_remote_port_parent() prints an error if there is no + * port/ports node. To avoid that, check first that there's the node. + */ + n = of_get_child_by_name(node, "ports"); + if (!n) + n = of_get_child_by_name(node, "port"); + if (!n) + return; + + of_node_put(n); + + n = NULL; + while ((n = of_graph_get_next_endpoint(node, n)) != NULL) { + struct device_node *pn = of_graph_get_remote_port_parent(n); + + if (!pn) + continue; + + if (!of_device_is_available(pn) || omapdss_list_contains(pn)) { + of_node_put(pn); + continue; + } + + omapdss_walk_device(dev, pn, false); + } +} + +void omapdss_gather_components(struct device *dev) +{ + struct device_node *child; + + INIT_LIST_HEAD(&omapdss_comp_list); + + omapdss_walk_device(dev, dev->of_node, true); + + for_each_available_child_of_node(dev->of_node, child) { + if (!of_find_property(child, "compatible", NULL)) + continue; + + omapdss_walk_device(dev, child, true); + } +} +EXPORT_SYMBOL(omapdss_gather_components); + +static bool omapdss_component_is_loaded(struct omapdss_comp_node *comp) +{ + if (comp->dss_core_component) + return true; + if (omapdss_component_is_display(comp->node)) + return true; + if (omapdss_component_is_output(comp->node)) + return true; + + return false; +} + +bool omapdss_stack_is_ready(void) +{ + struct omapdss_comp_node *comp; + + list_for_each_entry(comp, &omapdss_comp_list, list) { + if (!omapdss_component_is_loaded(comp)) + return false; + } + + return true; +} +EXPORT_SYMBOL(omapdss_stack_is_ready); + +MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>"); +MODULE_DESCRIPTION("OMAP Display Subsystem Base"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c index d956e6266368..5ac0145fbae6 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.c +++ b/drivers/gpu/drm/omapdrm/dss/dispc.c @@ -303,8 +303,12 @@ static unsigned long dispc_core_clk_rate(void); static unsigned long dispc_mgr_lclk_rate(enum omap_channel channel); static unsigned long dispc_mgr_pclk_rate(enum omap_channel channel); -static unsigned long dispc_plane_pclk_rate(enum omap_plane plane); -static unsigned long dispc_plane_lclk_rate(enum omap_plane plane); +static unsigned long dispc_plane_pclk_rate(enum omap_plane_id plane); +static unsigned long dispc_plane_lclk_rate(enum omap_plane_id plane); + +static void dispc_clear_irqstatus(u32 mask); +static bool dispc_mgr_is_enabled(enum omap_channel channel); +static void dispc_clear_irqstatus(u32 mask); static inline void dispc_write_reg(const u16 idx, u32 val) { @@ -581,7 +585,6 @@ int dispc_runtime_get(void) WARN_ON(r < 0); return r < 0 ? r : 0; } -EXPORT_SYMBOL(dispc_runtime_get); void dispc_runtime_put(void) { @@ -592,54 +595,48 @@ void dispc_runtime_put(void) r = pm_runtime_put_sync(&dispc.pdev->dev); WARN_ON(r < 0 && r != -ENOSYS); } -EXPORT_SYMBOL(dispc_runtime_put); -u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) +static u32 dispc_mgr_get_vsync_irq(enum omap_channel channel) { return mgr_desc[channel].vsync_irq; } -EXPORT_SYMBOL(dispc_mgr_get_vsync_irq); -u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) +static u32 dispc_mgr_get_framedone_irq(enum omap_channel channel) { if (channel == OMAP_DSS_CHANNEL_DIGIT && dispc.feat->no_framedone_tv) return 0; return mgr_desc[channel].framedone_irq; } -EXPORT_SYMBOL(dispc_mgr_get_framedone_irq); -u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel) +static u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel) { return mgr_desc[channel].sync_lost_irq; } -EXPORT_SYMBOL(dispc_mgr_get_sync_lost_irq); u32 dispc_wb_get_framedone_irq(void) { return DISPC_IRQ_FRAMEDONEWB; } -void dispc_mgr_enable(enum omap_channel channel, bool enable) +static void dispc_mgr_enable(enum omap_channel channel, bool enable) { mgr_fld_write(channel, DISPC_MGR_FLD_ENABLE, enable); /* flush posted write */ mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); } -EXPORT_SYMBOL(dispc_mgr_enable); static bool dispc_mgr_is_enabled(enum omap_channel channel) { return !!mgr_fld_read(channel, DISPC_MGR_FLD_ENABLE); } -bool dispc_mgr_go_busy(enum omap_channel channel) +static bool dispc_mgr_go_busy(enum omap_channel channel) { return mgr_fld_read(channel, DISPC_MGR_FLD_GO) == 1; } -EXPORT_SYMBOL(dispc_mgr_go_busy); -void dispc_mgr_go(enum omap_channel channel) +static void dispc_mgr_go(enum omap_channel channel) { WARN_ON(!dispc_mgr_is_enabled(channel)); WARN_ON(dispc_mgr_go_busy(channel)); @@ -648,7 +645,6 @@ void dispc_mgr_go(enum omap_channel channel) mgr_fld_write(channel, DISPC_MGR_FLD_GO, 1); } -EXPORT_SYMBOL(dispc_mgr_go); bool dispc_wb_go_busy(void) { @@ -657,7 +653,7 @@ bool dispc_wb_go_busy(void) void dispc_wb_go(void) { - enum omap_plane plane = OMAP_DSS_WB; + enum omap_plane_id plane = OMAP_DSS_WB; bool enable, go; enable = REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0) == 1; @@ -674,29 +670,33 @@ void dispc_wb_go(void) REG_FLD_MOD(DISPC_CONTROL2, 1, 6, 6); } -static void dispc_ovl_write_firh_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firh_reg(enum omap_plane_id plane, int reg, + u32 value) { dispc_write_reg(DISPC_OVL_FIR_COEF_H(plane, reg), value); } -static void dispc_ovl_write_firhv_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firhv_reg(enum omap_plane_id plane, int reg, + u32 value) { dispc_write_reg(DISPC_OVL_FIR_COEF_HV(plane, reg), value); } -static void dispc_ovl_write_firv_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firv_reg(enum omap_plane_id plane, int reg, + u32 value) { dispc_write_reg(DISPC_OVL_FIR_COEF_V(plane, reg), value); } -static void dispc_ovl_write_firh2_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firh2_reg(enum omap_plane_id plane, int reg, + u32 value) { BUG_ON(plane == OMAP_DSS_GFX); dispc_write_reg(DISPC_OVL_FIR_COEF_H2(plane, reg), value); } -static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg, +static void dispc_ovl_write_firhv2_reg(enum omap_plane_id plane, int reg, u32 value) { BUG_ON(plane == OMAP_DSS_GFX); @@ -704,14 +704,15 @@ static void dispc_ovl_write_firhv2_reg(enum omap_plane plane, int reg, dispc_write_reg(DISPC_OVL_FIR_COEF_HV2(plane, reg), value); } -static void dispc_ovl_write_firv2_reg(enum omap_plane plane, int reg, u32 value) +static void dispc_ovl_write_firv2_reg(enum omap_plane_id plane, int reg, + u32 value) { BUG_ON(plane == OMAP_DSS_GFX); dispc_write_reg(DISPC_OVL_FIR_COEF_V2(plane, reg), value); } -static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc, +static void dispc_ovl_set_scale_coef(enum omap_plane_id plane, int fir_hinc, int fir_vinc, int five_taps, enum omap_color_component color_comp) { @@ -757,7 +758,7 @@ static void dispc_ovl_set_scale_coef(enum omap_plane plane, int fir_hinc, } -static void dispc_ovl_write_color_conv_coef(enum omap_plane plane, +static void dispc_ovl_write_color_conv_coef(enum omap_plane_id plane, const struct color_conv_coef *ct) { #define CVAL(x, y) (FLD_VAL(x, 26, 16) | FLD_VAL(y, 10, 0)) @@ -793,27 +794,27 @@ static void dispc_setup_color_conv_coef(void) dispc_ovl_write_color_conv_coef(OMAP_DSS_WB, &ctbl_bt601_5_wb); } -static void dispc_ovl_set_ba0(enum omap_plane plane, u32 paddr) +static void dispc_ovl_set_ba0(enum omap_plane_id plane, u32 paddr) { dispc_write_reg(DISPC_OVL_BA0(plane), paddr); } -static void dispc_ovl_set_ba1(enum omap_plane plane, u32 paddr) +static void dispc_ovl_set_ba1(enum omap_plane_id plane, u32 paddr) { dispc_write_reg(DISPC_OVL_BA1(plane), paddr); } -static void dispc_ovl_set_ba0_uv(enum omap_plane plane, u32 paddr) +static void dispc_ovl_set_ba0_uv(enum omap_plane_id plane, u32 paddr) { dispc_write_reg(DISPC_OVL_BA0_UV(plane), paddr); } -static void dispc_ovl_set_ba1_uv(enum omap_plane plane, u32 paddr) +static void dispc_ovl_set_ba1_uv(enum omap_plane_id plane, u32 paddr) { dispc_write_reg(DISPC_OVL_BA1_UV(plane), paddr); } -static void dispc_ovl_set_pos(enum omap_plane plane, +static void dispc_ovl_set_pos(enum omap_plane_id plane, enum omap_overlay_caps caps, int x, int y) { u32 val; @@ -826,7 +827,7 @@ static void dispc_ovl_set_pos(enum omap_plane plane, dispc_write_reg(DISPC_OVL_POSITION(plane), val); } -static void dispc_ovl_set_input_size(enum omap_plane plane, int width, +static void dispc_ovl_set_input_size(enum omap_plane_id plane, int width, int height) { u32 val = FLD_VAL(height - 1, 26, 16) | FLD_VAL(width - 1, 10, 0); @@ -837,7 +838,7 @@ static void dispc_ovl_set_input_size(enum omap_plane plane, int width, dispc_write_reg(DISPC_OVL_PICTURE_SIZE(plane), val); } -static void dispc_ovl_set_output_size(enum omap_plane plane, int width, +static void dispc_ovl_set_output_size(enum omap_plane_id plane, int width, int height) { u32 val; @@ -852,7 +853,7 @@ static void dispc_ovl_set_output_size(enum omap_plane plane, int width, dispc_write_reg(DISPC_OVL_SIZE(plane), val); } -static void dispc_ovl_set_zorder(enum omap_plane plane, +static void dispc_ovl_set_zorder(enum omap_plane_id plane, enum omap_overlay_caps caps, u8 zorder) { if ((caps & OMAP_DSS_OVL_CAP_ZORDER) == 0) @@ -872,7 +873,7 @@ static void dispc_ovl_enable_zorder_planes(void) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(i), 1, 25, 25); } -static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, +static void dispc_ovl_set_pre_mult_alpha(enum omap_plane_id plane, enum omap_overlay_caps caps, bool enable) { if ((caps & OMAP_DSS_OVL_CAP_PRE_MULT_ALPHA) == 0) @@ -881,7 +882,7 @@ static void dispc_ovl_set_pre_mult_alpha(enum omap_plane plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable ? 1 : 0, 28, 28); } -static void dispc_ovl_setup_global_alpha(enum omap_plane plane, +static void dispc_ovl_setup_global_alpha(enum omap_plane_id plane, enum omap_overlay_caps caps, u8 global_alpha) { static const unsigned shifts[] = { 0, 8, 16, 24, }; @@ -894,17 +895,17 @@ static void dispc_ovl_setup_global_alpha(enum omap_plane plane, REG_FLD_MOD(DISPC_GLOBAL_ALPHA, global_alpha, shift + 7, shift); } -static void dispc_ovl_set_pix_inc(enum omap_plane plane, s32 inc) +static void dispc_ovl_set_pix_inc(enum omap_plane_id plane, s32 inc) { dispc_write_reg(DISPC_OVL_PIXEL_INC(plane), inc); } -static void dispc_ovl_set_row_inc(enum omap_plane plane, s32 inc) +static void dispc_ovl_set_row_inc(enum omap_plane_id plane, s32 inc) { dispc_write_reg(DISPC_OVL_ROW_INC(plane), inc); } -static void dispc_ovl_set_color_mode(enum omap_plane plane, +static void dispc_ovl_set_color_mode(enum omap_plane_id plane, enum omap_color_mode color_mode) { u32 m = 0; @@ -985,7 +986,7 @@ static void dispc_ovl_set_color_mode(enum omap_plane plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), m, 4, 1); } -static void dispc_ovl_configure_burst_type(enum omap_plane plane, +static void dispc_ovl_configure_burst_type(enum omap_plane_id plane, enum omap_dss_rotation_type rotation_type) { if (dss_has_feature(FEAT_BURST_2D) == 0) @@ -997,7 +998,8 @@ static void dispc_ovl_configure_burst_type(enum omap_plane plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), 0, 29, 29); } -void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) +static void dispc_ovl_set_channel_out(enum omap_plane_id plane, + enum omap_channel channel) { int shift; u32 val; @@ -1057,9 +1059,8 @@ void dispc_ovl_set_channel_out(enum omap_plane plane, enum omap_channel channel) } dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); } -EXPORT_SYMBOL(dispc_ovl_set_channel_out); -static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) +static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane_id plane) { int shift; u32 val; @@ -1101,12 +1102,12 @@ static enum omap_channel dispc_ovl_get_channel_out(enum omap_plane plane) void dispc_wb_set_channel_in(enum dss_writeback_channel channel) { - enum omap_plane plane = OMAP_DSS_WB; + enum omap_plane_id plane = OMAP_DSS_WB; REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), channel, 18, 16); } -static void dispc_ovl_set_burst_size(enum omap_plane plane, +static void dispc_ovl_set_burst_size(enum omap_plane_id plane, enum omap_burst_size burst_size) { static const unsigned shifts[] = { 6, 14, 14, 14, 14, }; @@ -1128,13 +1129,23 @@ static void dispc_configure_burst_sizes(void) dispc_ovl_set_burst_size(OMAP_DSS_WB, burst_size); } -static u32 dispc_ovl_get_burst_size(enum omap_plane plane) +static u32 dispc_ovl_get_burst_size(enum omap_plane_id plane) { unsigned unit = dss_feat_get_burst_size_unit(); /* burst multiplier is always x8 (see dispc_configure_burst_sizes()) */ return unit * 8; } +static enum omap_color_mode dispc_ovl_get_color_modes(enum omap_plane_id plane) +{ + return dss_feat_get_supported_color_modes(plane); +} + +static int dispc_get_num_ovls(void) +{ + return dss_feat_get_num_ovls(); +} + static void dispc_mgr_enable_cpr(enum omap_channel channel, bool enable) { if (channel == OMAP_DSS_CHANNEL_DIGIT) @@ -1163,7 +1174,8 @@ static void dispc_mgr_set_cpr_coef(enum omap_channel channel, dispc_write_reg(DISPC_CPR_COEF_B(channel), coef_b); } -static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable) +static void dispc_ovl_set_vid_color_conv(enum omap_plane_id plane, + bool enable) { u32 val; @@ -1174,7 +1186,7 @@ static void dispc_ovl_set_vid_color_conv(enum omap_plane plane, bool enable) dispc_write_reg(DISPC_OVL_ATTRIBUTES(plane), val); } -static void dispc_ovl_enable_replication(enum omap_plane plane, +static void dispc_ovl_enable_replication(enum omap_plane_id plane, enum omap_overlay_caps caps, bool enable) { static const unsigned shifts[] = { 5, 10, 10, 10 }; @@ -1271,7 +1283,7 @@ static void dispc_init_fifos(void) } } -static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) +static u32 dispc_ovl_get_fifo_size(enum omap_plane_id plane) { int fifo; u32 size = 0; @@ -1284,7 +1296,8 @@ static u32 dispc_ovl_get_fifo_size(enum omap_plane plane) return size; } -void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high) +void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, + u32 high) { u8 hi_start, hi_end, lo_start, lo_end; u32 unit; @@ -1333,7 +1346,7 @@ void dispc_enable_fifomerge(bool enable) REG_FLD_MOD(DISPC_CONFIG, enable ? 1 : 0, 14, 14); } -void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, +void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, bool manual_update) { @@ -1380,7 +1393,7 @@ void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, } } -static void dispc_ovl_set_mflag(enum omap_plane plane, bool enable) +static void dispc_ovl_set_mflag(enum omap_plane_id plane, bool enable) { int bit; @@ -1392,7 +1405,7 @@ static void dispc_ovl_set_mflag(enum omap_plane plane, bool enable) REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), enable, bit, bit); } -static void dispc_ovl_set_mflag_threshold(enum omap_plane plane, +static void dispc_ovl_set_mflag_threshold(enum omap_plane_id plane, int low, int high) { dispc_write_reg(DISPC_OVL_MFLAG_THRESHOLD(plane), @@ -1456,7 +1469,7 @@ static void dispc_init_mflag(void) } } -static void dispc_ovl_set_fir(enum omap_plane plane, +static void dispc_ovl_set_fir(enum omap_plane_id plane, int hinc, int vinc, enum omap_color_component color_comp) { @@ -1479,7 +1492,8 @@ static void dispc_ovl_set_fir(enum omap_plane plane, } } -static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) +static void dispc_ovl_set_vid_accu0(enum omap_plane_id plane, int haccu, + int vaccu) { u32 val; u8 hor_start, hor_end, vert_start, vert_end; @@ -1493,7 +1507,8 @@ static void dispc_ovl_set_vid_accu0(enum omap_plane plane, int haccu, int vaccu) dispc_write_reg(DISPC_OVL_ACCU0(plane), val); } -static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) +static void dispc_ovl_set_vid_accu1(enum omap_plane_id plane, int haccu, + int vaccu) { u32 val; u8 hor_start, hor_end, vert_start, vert_end; @@ -1507,7 +1522,7 @@ static void dispc_ovl_set_vid_accu1(enum omap_plane plane, int haccu, int vaccu) dispc_write_reg(DISPC_OVL_ACCU1(plane), val); } -static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu, +static void dispc_ovl_set_vid_accu2_0(enum omap_plane_id plane, int haccu, int vaccu) { u32 val; @@ -1516,7 +1531,7 @@ static void dispc_ovl_set_vid_accu2_0(enum omap_plane plane, int haccu, dispc_write_reg(DISPC_OVL_ACCU2_0(plane), val); } -static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu, +static void dispc_ovl_set_vid_accu2_1(enum omap_plane_id plane, int haccu, int vaccu) { u32 val; @@ -1525,7 +1540,7 @@ static void dispc_ovl_set_vid_accu2_1(enum omap_plane plane, int haccu, dispc_write_reg(DISPC_OVL_ACCU2_1(plane), val); } -static void dispc_ovl_set_scale_param(enum omap_plane plane, +static void dispc_ovl_set_scale_param(enum omap_plane_id plane, u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, bool five_taps, u8 rotation, @@ -1541,7 +1556,7 @@ static void dispc_ovl_set_scale_param(enum omap_plane plane, dispc_ovl_set_fir(plane, fir_hinc, fir_vinc, color_comp); } -static void dispc_ovl_set_accu_uv(enum omap_plane plane, +static void dispc_ovl_set_accu_uv(enum omap_plane_id plane, u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, bool ilace, enum omap_color_mode color_mode, u8 rotation) { @@ -1629,7 +1644,7 @@ static void dispc_ovl_set_accu_uv(enum omap_plane plane, dispc_ovl_set_vid_accu2_1(plane, h_accu2_1, v_accu2_1); } -static void dispc_ovl_set_scaling_common(enum omap_plane plane, +static void dispc_ovl_set_scaling_common(enum omap_plane_id plane, u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, bool ilace, bool five_taps, @@ -1683,7 +1698,7 @@ static void dispc_ovl_set_scaling_common(enum omap_plane plane, dispc_ovl_set_vid_accu1(plane, 0, accu1); } -static void dispc_ovl_set_scaling_uv(enum omap_plane plane, +static void dispc_ovl_set_scaling_uv(enum omap_plane_id plane, u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, bool ilace, bool five_taps, @@ -1763,7 +1778,7 @@ static void dispc_ovl_set_scaling_uv(enum omap_plane plane, REG_FLD_MOD(DISPC_OVL_ATTRIBUTES(plane), scale_y ? 1 : 0, 6, 6); } -static void dispc_ovl_set_scaling(enum omap_plane plane, +static void dispc_ovl_set_scaling(enum omap_plane_id plane, u16 orig_width, u16 orig_height, u16 out_width, u16 out_height, bool ilace, bool five_taps, @@ -1787,7 +1802,7 @@ static void dispc_ovl_set_scaling(enum omap_plane plane, rotation); } -static void dispc_ovl_set_rotation_attrs(enum omap_plane plane, u8 rotation, +static void dispc_ovl_set_rotation_attrs(enum omap_plane_id plane, u8 rotation, enum omap_dss_rotation_type rotation_type, bool mirroring, enum omap_color_mode color_mode) { @@ -2619,7 +2634,7 @@ static int dispc_ovl_calc_scaling(unsigned long pclk, unsigned long lclk, return 0; } -static int dispc_ovl_setup_common(enum omap_plane plane, +static int dispc_ovl_setup_common(enum omap_plane_id plane, enum omap_overlay_caps caps, u32 paddr, u32 p_uv_addr, u16 screen_width, int pos_x, int pos_y, u16 width, u16 height, u16 out_width, u16 out_height, enum omap_color_mode color_mode, @@ -2817,13 +2832,14 @@ static int dispc_ovl_setup_common(enum omap_plane plane, return 0; } -int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, - bool replication, const struct videomode *vm, - bool mem_to_mem) +static int dispc_ovl_setup(enum omap_plane_id plane, + const struct omap_overlay_info *oi, + const struct videomode *vm, bool mem_to_mem) { int r; enum omap_overlay_caps caps = dss_feat_get_overlay_caps(plane); enum omap_channel channel; + const bool replication = true; channel = dispc_ovl_get_channel_out(plane); @@ -2841,17 +2857,16 @@ int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, return r; } -EXPORT_SYMBOL(dispc_ovl_setup); int dispc_wb_setup(const struct omap_dss_writeback_info *wi, bool mem_to_mem, const struct videomode *vm) { int r; u32 l; - enum omap_plane plane = OMAP_DSS_WB; + enum omap_plane_id plane = OMAP_DSS_WB; const int pos_x = 0, pos_y = 0; const u8 zorder = 0, global_alpha = 0; - const bool replication = false; + const bool replication = true; bool truncation; int in_width = vm->hactive; int in_height = vm->vactive; @@ -2911,7 +2926,7 @@ int dispc_wb_setup(const struct omap_dss_writeback_info *wi, return r; } -int dispc_ovl_enable(enum omap_plane plane, bool enable) +static int dispc_ovl_enable(enum omap_plane_id plane, bool enable) { DSSDBG("dispc_enable_plane %d, %d\n", plane, enable); @@ -2919,29 +2934,16 @@ int dispc_ovl_enable(enum omap_plane plane, bool enable) return 0; } -EXPORT_SYMBOL(dispc_ovl_enable); -bool dispc_ovl_enabled(enum omap_plane plane) +static bool dispc_ovl_enabled(enum omap_plane_id plane) { return REG_GET(DISPC_OVL_ATTRIBUTES(plane), 0, 0); } -EXPORT_SYMBOL(dispc_ovl_enabled); -enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel) +static enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel) { return dss_feat_get_supported_outputs(channel); } -EXPORT_SYMBOL(dispc_mgr_get_supported_outputs); - -void dispc_wb_enable(bool enable) -{ - dispc_ovl_enable(OMAP_DSS_WB, enable); -} - -bool dispc_wb_is_enabled(void) -{ - return dispc_ovl_enabled(OMAP_DSS_WB); -} static void dispc_lcd_enable_signal_polarity(bool act_high) { @@ -2967,6 +2969,11 @@ void dispc_pck_free_enable(bool enable) REG_FLD_MOD(DISPC_CONTROL, enable ? 1 : 0, 27, 27); } +static int dispc_get_num_mgrs(void) +{ + return dss_feat_get_num_mgrs(); +} + static void dispc_mgr_enable_fifohandcheck(enum omap_channel channel, bool enable) { mgr_fld_write(channel, DISPC_MGR_FLD_FIFOHANDCHECK, enable); @@ -3015,7 +3022,7 @@ static void dispc_mgr_enable_alpha_fixed_zorder(enum omap_channel ch, REG_FLD_MOD(DISPC_CONFIG, enable, 19, 19); } -void dispc_mgr_setup(enum omap_channel channel, +static void dispc_mgr_setup(enum omap_channel channel, const struct omap_overlay_manager_info *info) { dispc_mgr_set_default_color(channel, info->default_color); @@ -3028,7 +3035,6 @@ void dispc_mgr_setup(enum omap_channel channel, dispc_mgr_set_cpr_coef(channel, &info->cpr_coefs); } } -EXPORT_SYMBOL(dispc_mgr_setup); static void dispc_mgr_set_tft_data_lines(enum omap_channel channel, u8 data_lines) { @@ -3089,7 +3095,7 @@ static void dispc_mgr_enable_stallmode(enum omap_channel channel, bool enable) mgr_fld_write(channel, DISPC_MGR_FLD_STALLMODE, enable); } -void dispc_mgr_set_lcd_config(enum omap_channel channel, +static void dispc_mgr_set_lcd_config(enum omap_channel channel, const struct dss_lcd_mgr_config *config) { dispc_mgr_set_io_pad_mode(config->io_pad_mode); @@ -3105,7 +3111,6 @@ void dispc_mgr_set_lcd_config(enum omap_channel channel, dispc_mgr_set_lcd_type_tft(channel); } -EXPORT_SYMBOL(dispc_mgr_set_lcd_config); static bool _dispc_mgr_size_ok(u16 width, u16 height) { @@ -3235,8 +3240,18 @@ static void _dispc_mgr_set_lcd_timings(enum omap_channel channel, } } +static int vm_flag_to_int(enum display_flags flags, enum display_flags high, + enum display_flags low) +{ + if (flags & high) + return 1; + if (flags & low) + return -1; + return 0; +} + /* change name to mode? */ -void dispc_mgr_set_timings(enum omap_channel channel, +static void dispc_mgr_set_timings(enum omap_channel channel, const struct videomode *vm) { unsigned xtot, ytot; @@ -3264,11 +3279,11 @@ void dispc_mgr_set_timings(enum omap_channel channel, t.hsync_len, t.hfront_porch, t.hback_porch, t.vsync_len, t.vfront_porch, t.vback_porch); DSSDBG("vsync_level %d hsync_level %d data_pclk_edge %d de_level %d sync_pclk_edge %d\n", - !!(t.flags & DISPLAY_FLAGS_VSYNC_HIGH), - !!(t.flags & DISPLAY_FLAGS_HSYNC_HIGH), - !!(t.flags & DISPLAY_FLAGS_PIXDATA_POSEDGE), - !!(t.flags & DISPLAY_FLAGS_DE_HIGH), - !!(t.flags & DISPLAY_FLAGS_SYNC_POSEDGE)); + vm_flag_to_int(t.flags, DISPLAY_FLAGS_VSYNC_HIGH, DISPLAY_FLAGS_VSYNC_LOW), + vm_flag_to_int(t.flags, DISPLAY_FLAGS_HSYNC_HIGH, DISPLAY_FLAGS_HSYNC_LOW), + vm_flag_to_int(t.flags, DISPLAY_FLAGS_PIXDATA_POSEDGE, DISPLAY_FLAGS_PIXDATA_NEGEDGE), + vm_flag_to_int(t.flags, DISPLAY_FLAGS_DE_HIGH, DISPLAY_FLAGS_DE_LOW), + vm_flag_to_int(t.flags, DISPLAY_FLAGS_SYNC_POSEDGE, DISPLAY_FLAGS_SYNC_NEGEDGE)); DSSDBG("hsync %luHz, vsync %luHz\n", ht, vt); } else { @@ -3283,7 +3298,6 @@ void dispc_mgr_set_timings(enum omap_channel channel, dispc_mgr_set_size(channel, t.hactive, t.vactive); } -EXPORT_SYMBOL(dispc_mgr_set_timings); static void dispc_mgr_set_lcd_divisor(enum omap_channel channel, u16 lck_div, u16 pck_div) @@ -3389,7 +3403,7 @@ static unsigned long dispc_core_clk_rate(void) return dispc.core_clk_rate; } -static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) +static unsigned long dispc_plane_pclk_rate(enum omap_plane_id plane) { enum omap_channel channel; @@ -3401,7 +3415,7 @@ static unsigned long dispc_plane_pclk_rate(enum omap_plane plane) return dispc_mgr_pclk_rate(channel); } -static unsigned long dispc_plane_lclk_rate(enum omap_plane plane) +static unsigned long dispc_plane_lclk_rate(enum omap_plane_id plane) { enum omap_channel channel; @@ -3763,25 +3777,22 @@ int dispc_mgr_get_clock_div(enum omap_channel channel, return 0; } -u32 dispc_read_irqstatus(void) +static u32 dispc_read_irqstatus(void) { return dispc_read_reg(DISPC_IRQSTATUS); } -EXPORT_SYMBOL(dispc_read_irqstatus); -void dispc_clear_irqstatus(u32 mask) +static void dispc_clear_irqstatus(u32 mask) { dispc_write_reg(DISPC_IRQSTATUS, mask); } -EXPORT_SYMBOL(dispc_clear_irqstatus); -u32 dispc_read_irqenable(void) +static u32 dispc_read_irqenable(void) { return dispc_read_reg(DISPC_IRQENABLE); } -EXPORT_SYMBOL(dispc_read_irqenable); -void dispc_write_irqenable(u32 mask) +static void dispc_write_irqenable(u32 mask) { u32 old_mask = dispc_read_reg(DISPC_IRQENABLE); @@ -3790,7 +3801,6 @@ void dispc_write_irqenable(u32 mask) dispc_write_reg(DISPC_IRQENABLE, mask); } -EXPORT_SYMBOL(dispc_write_irqenable); void dispc_enable_sidle(void) { @@ -3802,7 +3812,7 @@ void dispc_disable_sidle(void) REG_FLD_MOD(DISPC_SYSCONFIG, 1, 4, 3); /* SIDLEMODE: no idle */ } -u32 dispc_mgr_gamma_size(enum omap_channel channel) +static u32 dispc_mgr_gamma_size(enum omap_channel channel) { const struct dispc_gamma_desc *gdesc = &mgr_desc[channel].gamma; @@ -3811,7 +3821,6 @@ u32 dispc_mgr_gamma_size(enum omap_channel channel) return gdesc->len; } -EXPORT_SYMBOL(dispc_mgr_gamma_size); static void dispc_mgr_write_gamma_table(enum omap_channel channel) { @@ -3856,7 +3865,7 @@ static const struct drm_color_lut dispc_mgr_gamma_default_lut[] = { { .red = U16_MAX, .green = U16_MAX, .blue = U16_MAX, }, }; -void dispc_mgr_set_gamma(enum omap_channel channel, +static void dispc_mgr_set_gamma(enum omap_channel channel, const struct drm_color_lut *lut, unsigned int length) { @@ -3902,7 +3911,6 @@ void dispc_mgr_set_gamma(enum omap_channel channel, if (dispc.is_enabled) dispc_mgr_write_gamma_table(channel); } -EXPORT_SYMBOL(dispc_mgr_set_gamma); static int dispc_init_gamma_tables(void) { @@ -4149,7 +4157,7 @@ static irqreturn_t dispc_irq_handler(int irq, void *arg) return dispc.user_handler(irq, dispc.user_data); } -int dispc_request_irq(irq_handler_t handler, void *dev_id) +static int dispc_request_irq(irq_handler_t handler, void *dev_id) { int r; @@ -4171,16 +4179,14 @@ int dispc_request_irq(irq_handler_t handler, void *dev_id) return r; } -EXPORT_SYMBOL(dispc_request_irq); -void dispc_free_irq(void *dev_id) +static void dispc_free_irq(void *dev_id) { devm_free_irq(&dispc.pdev->dev, dispc.irq, &dispc); dispc.user_handler = NULL; dispc.user_data = NULL; } -EXPORT_SYMBOL(dispc_free_irq); /* * Workaround for errata i734 in DSS dispc @@ -4304,7 +4310,7 @@ static void dispc_errata_i734_wa(void) /* Setup and enable GFX plane */ dispc_ovl_set_channel_out(OMAP_DSS_GFX, OMAP_DSS_CHANNEL_LCD); - dispc_ovl_setup(OMAP_DSS_GFX, &ovli, false, &i734.vm, false); + dispc_ovl_setup(OMAP_DSS_GFX, &ovli, &i734.vm, false); dispc_ovl_enable(OMAP_DSS_GFX, true); /* Set up and enable display manager for LCD1 */ @@ -4341,6 +4347,42 @@ static void dispc_errata_i734_wa(void) REG_FLD_MOD(DISPC_CONFIG, gatestate, 8, 4); } +static const struct dispc_ops dispc_ops = { + .read_irqstatus = dispc_read_irqstatus, + .clear_irqstatus = dispc_clear_irqstatus, + .read_irqenable = dispc_read_irqenable, + .write_irqenable = dispc_write_irqenable, + + .request_irq = dispc_request_irq, + .free_irq = dispc_free_irq, + + .runtime_get = dispc_runtime_get, + .runtime_put = dispc_runtime_put, + + .get_num_ovls = dispc_get_num_ovls, + .get_num_mgrs = dispc_get_num_mgrs, + + .mgr_enable = dispc_mgr_enable, + .mgr_is_enabled = dispc_mgr_is_enabled, + .mgr_get_vsync_irq = dispc_mgr_get_vsync_irq, + .mgr_get_framedone_irq = dispc_mgr_get_framedone_irq, + .mgr_get_sync_lost_irq = dispc_mgr_get_sync_lost_irq, + .mgr_go_busy = dispc_mgr_go_busy, + .mgr_go = dispc_mgr_go, + .mgr_set_lcd_config = dispc_mgr_set_lcd_config, + .mgr_set_timings = dispc_mgr_set_timings, + .mgr_setup = dispc_mgr_setup, + .mgr_get_supported_outputs = dispc_mgr_get_supported_outputs, + .mgr_gamma_size = dispc_mgr_gamma_size, + .mgr_set_gamma = dispc_mgr_set_gamma, + + .ovl_enable = dispc_ovl_enable, + .ovl_enabled = dispc_ovl_enabled, + .ovl_set_channel_out = dispc_ovl_set_channel_out, + .ovl_setup = dispc_ovl_setup, + .ovl_get_color_modes = dispc_ovl_get_color_modes, +}; + /* DISPC HW IP initialisation */ static int dispc_bind(struct device *dev, struct device *master, void *data) { @@ -4413,6 +4455,8 @@ static int dispc_bind(struct device *dev, struct device *master, void *data) dispc_runtime_put(); + dispc_set_ops(&dispc_ops); + dss_debugfs_create_file("dispc", dispc_dump_regs); return 0; @@ -4425,6 +4469,8 @@ err_runtime_get: static void dispc_unbind(struct device *dev, struct device *master, void *data) { + dispc_set_ops(NULL); + pm_runtime_disable(dev); dispc_errata_i734_wa_fini(); diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.h b/drivers/gpu/drm/omapdrm/dss/dispc.h index bc1d8126ee87..003adce532f4 100644 --- a/drivers/gpu/drm/omapdrm/dss/dispc.h +++ b/drivers/gpu/drm/omapdrm/dss/dispc.h @@ -353,7 +353,7 @@ static inline u16 DISPC_CPR_COEF_B(enum omap_channel channel) } /* DISPC overlay register base addresses */ -static inline u16 DISPC_OVL_BASE(enum omap_plane plane) +static inline u16 DISPC_OVL_BASE(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -373,7 +373,7 @@ static inline u16 DISPC_OVL_BASE(enum omap_plane plane) } /* DISPC overlay register offsets */ -static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane) +static inline u16 DISPC_BA0_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -389,7 +389,7 @@ static inline u16 DISPC_BA0_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane) +static inline u16 DISPC_BA1_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -405,7 +405,7 @@ static inline u16 DISPC_BA1_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane) +static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -425,7 +425,7 @@ static inline u16 DISPC_BA0_UV_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane) +static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -445,7 +445,7 @@ static inline u16 DISPC_BA1_UV_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_POS_OFFSET(enum omap_plane plane) +static inline u16 DISPC_POS_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -460,7 +460,7 @@ static inline u16 DISPC_POS_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane) +static inline u16 DISPC_SIZE_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -476,7 +476,7 @@ static inline u16 DISPC_SIZE_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane) +static inline u16 DISPC_ATTR_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -493,7 +493,7 @@ static inline u16 DISPC_ATTR_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane) +static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -513,7 +513,7 @@ static inline u16 DISPC_ATTR2_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane) +static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -530,7 +530,7 @@ static inline u16 DISPC_FIFO_THRESH_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane) +static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -547,7 +547,7 @@ static inline u16 DISPC_FIFO_SIZE_STATUS_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane) +static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -564,7 +564,7 @@ static inline u16 DISPC_ROW_INC_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane) +static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -581,7 +581,7 @@ static inline u16 DISPC_PIX_INC_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane) +static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -597,7 +597,7 @@ static inline u16 DISPC_WINDOW_SKIP_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane) +static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -613,7 +613,7 @@ static inline u16 DISPC_TABLE_BA_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane) +static inline u16 DISPC_FIR_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -631,7 +631,7 @@ static inline u16 DISPC_FIR_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane) +static inline u16 DISPC_FIR2_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -651,7 +651,7 @@ static inline u16 DISPC_FIR2_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane) +static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -670,7 +670,7 @@ static inline u16 DISPC_PIC_SIZE_OFFSET(enum omap_plane plane) } -static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane) +static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -688,7 +688,7 @@ static inline u16 DISPC_ACCU0_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane) +static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -708,7 +708,7 @@ static inline u16 DISPC_ACCU2_0_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane) +static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -726,7 +726,7 @@ static inline u16 DISPC_ACCU1_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane) +static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -747,7 +747,7 @@ static inline u16 DISPC_ACCU2_1_OFFSET(enum omap_plane plane) } /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ -static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i) +static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane_id plane, u16 i) { switch (plane) { case OMAP_DSS_GFX: @@ -766,7 +766,7 @@ static inline u16 DISPC_FIR_COEF_H_OFFSET(enum omap_plane plane, u16 i) } /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ -static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i) +static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane_id plane, u16 i) { switch (plane) { case OMAP_DSS_GFX: @@ -787,7 +787,7 @@ static inline u16 DISPC_FIR_COEF_H2_OFFSET(enum omap_plane plane, u16 i) } /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ -static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i) +static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane_id plane, u16 i) { switch (plane) { case OMAP_DSS_GFX: @@ -806,7 +806,7 @@ static inline u16 DISPC_FIR_COEF_HV_OFFSET(enum omap_plane plane, u16 i) } /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ -static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i) +static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane_id plane, u16 i) { switch (plane) { case OMAP_DSS_GFX: @@ -827,7 +827,7 @@ static inline u16 DISPC_FIR_COEF_HV2_OFFSET(enum omap_plane plane, u16 i) } /* coef index i = {0, 1, 2, 3, 4,} */ -static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i) +static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane_id plane, u16 i) { switch (plane) { case OMAP_DSS_GFX: @@ -845,7 +845,7 @@ static inline u16 DISPC_CONV_COEF_OFFSET(enum omap_plane plane, u16 i) } /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ -static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i) +static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane_id plane, u16 i) { switch (plane) { case OMAP_DSS_GFX: @@ -865,7 +865,7 @@ static inline u16 DISPC_FIR_COEF_V_OFFSET(enum omap_plane plane, u16 i) } /* coef index i = {0, 1, 2, 3, 4, 5, 6, 7} */ -static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i) +static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane_id plane, u16 i) { switch (plane) { case OMAP_DSS_GFX: @@ -885,7 +885,7 @@ static inline u16 DISPC_FIR_COEF_V2_OFFSET(enum omap_plane plane, u16 i) } } -static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane) +static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: @@ -902,7 +902,7 @@ static inline u16 DISPC_PRELOAD_OFFSET(enum omap_plane plane) } } -static inline u16 DISPC_MFLAG_THRESHOLD_OFFSET(enum omap_plane plane) +static inline u16 DISPC_MFLAG_THRESHOLD_OFFSET(enum omap_plane_id plane) { switch (plane) { case OMAP_DSS_GFX: diff --git a/drivers/gpu/drm/omapdrm/dss/display.c b/drivers/gpu/drm/omapdrm/dss/display.c index 425a5a8dff8b..26cb59be045e 100644 --- a/drivers/gpu/drm/omapdrm/dss/display.c +++ b/drivers/gpu/drm/omapdrm/dss/display.c @@ -29,8 +29,6 @@ #include <linux/of.h> #include "omapdss.h" -#include "dss.h" -#include "dss_features.h" void omapdss_default_get_resolution(struct omap_dss_device *dssdev, u16 *xres, u16 *yres) @@ -55,10 +53,10 @@ int omapdss_default_get_recommended_bpp(struct omap_dss_device *dssdev) else return 16; case OMAP_DISPLAY_TYPE_DSI: - if (dsi_get_pixel_size(dssdev->panel.dsi_pix_fmt) > 16) - return 24; - else + if (dssdev->panel.dsi_pix_fmt == OMAP_DSS_DSI_FMT_RGB565) return 16; + else + return 24; case OMAP_DISPLAY_TYPE_VENC: case OMAP_DISPLAY_TYPE_SDI: case OMAP_DISPLAY_TYPE_HDMI: @@ -85,6 +83,7 @@ static int disp_num_counter; int omapdss_register_display(struct omap_dss_device *dssdev) { struct omap_dss_driver *drv = dssdev->driver; + struct list_head *cur; int id; /* @@ -120,7 +119,14 @@ int omapdss_register_display(struct omap_dss_device *dssdev) drv->get_timings = omapdss_default_get_timings; mutex_lock(&panel_list_mutex); - list_add_tail(&dssdev->panel_list, &panel_list); + list_for_each(cur, &panel_list) { + struct omap_dss_device *ldev = list_entry(cur, + struct omap_dss_device, + panel_list); + if (strcmp(ldev->alias, dssdev->alias) > 0) + break; + } + list_add_tail(&dssdev->panel_list, cur); mutex_unlock(&panel_list_mutex); return 0; } @@ -134,6 +140,24 @@ void omapdss_unregister_display(struct omap_dss_device *dssdev) } EXPORT_SYMBOL(omapdss_unregister_display); +bool omapdss_component_is_display(struct device_node *node) +{ + struct omap_dss_device *dssdev; + bool found = false; + + mutex_lock(&panel_list_mutex); + list_for_each_entry(dssdev, &panel_list, panel_list) { + if (dssdev->dev->of_node == node) { + found = true; + goto out; + } + } +out: + mutex_unlock(&panel_list_mutex); + return found; +} +EXPORT_SYMBOL(omapdss_component_is_display); + struct omap_dss_device *omap_dss_get_device(struct omap_dss_device *dssdev) { if (!try_module_get(dssdev->owner)) diff --git a/drivers/gpu/drm/omapdrm/dss/dpi.c b/drivers/gpu/drm/omapdrm/dss/dpi.c index e75162d26ac0..8a730a7afe76 100644 --- a/drivers/gpu/drm/omapdrm/dss/dpi.c +++ b/drivers/gpu/drm/omapdrm/dss/dpi.c @@ -67,6 +67,45 @@ static struct dpi_data *dpi_get_data_from_pdev(struct platform_device *pdev) return dev_get_drvdata(&pdev->dev); } +static enum dss_clk_source dpi_get_clk_src_dra7xx(enum omap_channel channel) +{ + /* + * Possible clock sources: + * LCD1: FCK/PLL1_1/HDMI_PLL + * LCD2: FCK/PLL1_3/HDMI_PLL (DRA74x: PLL2_3) + * LCD3: FCK/PLL1_3/HDMI_PLL (DRA74x: PLL2_1) + */ + + switch (channel) { + case OMAP_DSS_CHANNEL_LCD: + { + if (dss_pll_find_by_src(DSS_CLK_SRC_PLL1_1)) + return DSS_CLK_SRC_PLL1_1; + break; + } + case OMAP_DSS_CHANNEL_LCD2: + { + if (dss_pll_find_by_src(DSS_CLK_SRC_PLL1_3)) + return DSS_CLK_SRC_PLL1_3; + if (dss_pll_find_by_src(DSS_CLK_SRC_PLL2_3)) + return DSS_CLK_SRC_PLL2_3; + break; + } + case OMAP_DSS_CHANNEL_LCD3: + { + if (dss_pll_find_by_src(DSS_CLK_SRC_PLL2_1)) + return DSS_CLK_SRC_PLL2_1; + if (dss_pll_find_by_src(DSS_CLK_SRC_PLL1_3)) + return DSS_CLK_SRC_PLL1_3; + break; + } + default: + break; + } + + return DSS_CLK_SRC_FCK; +} + static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel) { /* @@ -107,16 +146,7 @@ static enum dss_clk_source dpi_get_clk_src(enum omap_channel channel) } case OMAPDSS_VER_DRA7xx: - switch (channel) { - case OMAP_DSS_CHANNEL_LCD: - return DSS_CLK_SRC_PLL1_1; - case OMAP_DSS_CHANNEL_LCD2: - return DSS_CLK_SRC_PLL1_3; - case OMAP_DSS_CHANNEL_LCD3: - return DSS_CLK_SRC_PLL2_1; - default: - return DSS_CLK_SRC_FCK; - } + return dpi_get_clk_src_dra7xx(channel); default: return DSS_CLK_SRC_FCK; @@ -170,14 +200,6 @@ static bool dpi_calc_hsdiv_cb(int m_dispc, unsigned long dispc, { struct dpi_clk_calc_ctx *ctx = data; - /* - * Odd dividers give us uneven duty cycle, causing problem when level - * shifted. So skip all odd dividers when the pixel clock is on the - * higher side. - */ - if (m_dispc > 1 && m_dispc % 2 != 0 && ctx->pck_min >= 100000000) - return false; - ctx->pll_cinfo.mX[ctx->clkout_idx] = m_dispc; ctx->pll_cinfo.clkout[ctx->clkout_idx] = dispc; @@ -855,7 +877,7 @@ int dpi_init_port(struct platform_device *pdev, struct device_node *port) if (!dpi) return -ENOMEM; - ep = omapdss_of_get_next_endpoint(port, NULL); + ep = of_get_next_child(port, NULL); if (!ep) return 0; diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c index f74615d005a8..910754bf8cf9 100644 --- a/drivers/gpu/drm/omapdrm/dss/dsi.c +++ b/drivers/gpu/drm/omapdrm/dss/dsi.c @@ -39,6 +39,7 @@ #include <linux/debugfs.h> #include <linux/pm_runtime.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/of_platform.h> #include <linux/component.h> @@ -527,7 +528,7 @@ static inline int wait_for_bit_change(struct platform_device *dsidev, return !value; } -u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) +static u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) { switch (fmt) { case OMAP_DSS_DSI_FMT_RGB888: @@ -582,15 +583,14 @@ static void dsi_perf_show(struct platform_device *dsidev, const char *name) total_bytes = dsi->update_bytes; - printk(KERN_INFO "DSI(%s): %u us + %u us = %u us (%uHz), " - "%u bytes, %u kbytes/sec\n", - name, - setup_us, - trans_us, - total_us, - 1000*1000 / total_us, - total_bytes, - total_bytes * 1000 / total_us); + pr_info("DSI(%s): %u us + %u us = %u us (%uHz), %u bytes, %u kbytes/sec\n", + name, + setup_us, + trans_us, + total_us, + 1000 * 1000 / total_us, + total_bytes, + total_bytes * 1000 / total_us); } #else static inline void dsi_perf_mark_setup(struct platform_device *dsidev) @@ -5091,7 +5091,7 @@ static int dsi_probe_of(struct platform_device *pdev) struct device_node *ep; struct omap_dsi_pin_config pin_cfg; - ep = omapdss_of_get_first_endpoint(node); + ep = of_graph_get_endpoint_by_regs(node, 0, 0); if (!ep) return 0; diff --git a/drivers/gpu/drm/omapdrm/dss/dss-of.c b/drivers/gpu/drm/omapdrm/dss/dss-of.c index dfd4e9621e3b..c6b86f348a5c 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss-of.c +++ b/drivers/gpu/drm/omapdrm/dss/dss-of.c @@ -16,76 +16,10 @@ #include <linux/err.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/seq_file.h> #include "omapdss.h" -#include "dss.h" - -struct device_node * -omapdss_of_get_next_port(const struct device_node *parent, - struct device_node *prev) -{ - struct device_node *port = NULL; - - if (!parent) - return NULL; - - if (!prev) { - struct device_node *ports; - /* - * It's the first call, we have to find a port subnode - * within this node or within an optional 'ports' node. - */ - ports = of_get_child_by_name(parent, "ports"); - if (ports) - parent = ports; - - port = of_get_child_by_name(parent, "port"); - - /* release the 'ports' node */ - of_node_put(ports); - } else { - struct device_node *ports; - - ports = of_get_parent(prev); - if (!ports) - return NULL; - - do { - port = of_get_next_child(ports, prev); - if (!port) { - of_node_put(ports); - return NULL; - } - prev = port; - } while (of_node_cmp(port->name, "port") != 0); - - of_node_put(ports); - } - - return port; -} -EXPORT_SYMBOL_GPL(omapdss_of_get_next_port); - -struct device_node * -omapdss_of_get_next_endpoint(const struct device_node *parent, - struct device_node *prev) -{ - struct device_node *ep = NULL; - - if (!parent) - return NULL; - - do { - ep = of_get_next_child(parent, prev); - if (!ep) - return NULL; - prev = ep; - } while (of_node_cmp(ep->name, "endpoint") != 0); - - return ep; -} -EXPORT_SYMBOL_GPL(omapdss_of_get_next_endpoint); struct device_node *dss_of_port_get_parent_device(struct device_node *port) { @@ -110,6 +44,7 @@ struct device_node *dss_of_port_get_parent_device(struct device_node *port) return NULL; } +EXPORT_SYMBOL_GPL(dss_of_port_get_parent_device); u32 dss_of_port_get_port_number(struct device_node *port) { @@ -122,37 +57,7 @@ u32 dss_of_port_get_port_number(struct device_node *port) return reg; } - -static struct device_node *omapdss_of_get_remote_port(const struct device_node *node) -{ - struct device_node *np; - - np = of_parse_phandle(node, "remote-endpoint", 0); - if (!np) - return NULL; - - np = of_get_next_parent(np); - - return np; -} - -struct device_node * -omapdss_of_get_first_endpoint(const struct device_node *parent) -{ - struct device_node *port, *ep; - - port = omapdss_of_get_next_port(parent, NULL); - - if (!port) - return NULL; - - ep = omapdss_of_get_next_endpoint(port, NULL); - - of_node_put(port); - - return ep; -} -EXPORT_SYMBOL_GPL(omapdss_of_get_first_endpoint); +EXPORT_SYMBOL_GPL(dss_of_port_get_port_number); struct omap_dss_device * omapdss_of_find_source_for_first_ep(struct device_node *node) @@ -161,11 +66,11 @@ omapdss_of_find_source_for_first_ep(struct device_node *node) struct device_node *src_port; struct omap_dss_device *src; - ep = omapdss_of_get_first_endpoint(node); + ep = of_graph_get_endpoint_by_regs(node, 0, 0); if (!ep) return ERR_PTR(-EINVAL); - src_port = omapdss_of_get_remote_port(ep); + src_port = of_graph_get_remote_port(ep); if (!src_port) { of_node_put(ep); return ERR_PTR(-EINVAL); diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c index 14887d5b02e5..fa99ec72d832 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.c +++ b/drivers/gpu/drm/omapdrm/dss/dss.c @@ -38,6 +38,7 @@ #include <linux/mfd/syscon.h> #include <linux/regmap.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/regulator/consumer.h> #include <linux/suspend.h> #include <linux/component.h> @@ -117,14 +118,6 @@ static const char * const dss_generic_clk_source_names[] = { [DSS_CLK_SRC_HDMI_PLL] = "HDMI PLL", }; -static bool dss_initialized; - -bool omapdss_is_initialized(void) -{ - return dss_initialized; -} -EXPORT_SYMBOL(omapdss_is_initialized); - static inline void dss_write_reg(const struct dss_reg idx, u32 val) { __raw_writel(val, dss.base + idx.idx); @@ -1043,32 +1036,14 @@ static int dss_init_ports(struct platform_device *pdev) { struct device_node *parent = pdev->dev.of_node; struct device_node *port; - int r; - - if (parent == NULL) - return 0; - - port = omapdss_of_get_next_port(parent, NULL); - if (!port) - return 0; - - if (dss.feat->num_ports == 0) - return 0; - - do { - enum omap_display_type port_type; - u32 reg; - - r = of_property_read_u32(port, "reg", ®); - if (r) - reg = 0; + int i; - if (reg >= dss.feat->num_ports) + for (i = 0; i < dss.feat->num_ports; i++) { + port = of_graph_get_port_by_id(parent, i); + if (!port) continue; - port_type = dss.feat->ports[reg]; - - switch (port_type) { + switch (dss.feat->ports[i]) { case OMAP_DISPLAY_TYPE_DPI: dpi_init_port(pdev, port); break; @@ -1078,7 +1053,7 @@ static int dss_init_ports(struct platform_device *pdev) default: break; } - } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); + } return 0; } @@ -1087,32 +1062,14 @@ static void dss_uninit_ports(struct platform_device *pdev) { struct device_node *parent = pdev->dev.of_node; struct device_node *port; + int i; - if (parent == NULL) - return; - - port = omapdss_of_get_next_port(parent, NULL); - if (!port) - return; - - if (dss.feat->num_ports == 0) - return; - - do { - enum omap_display_type port_type; - u32 reg; - int r; - - r = of_property_read_u32(port, "reg", ®); - if (r) - reg = 0; - - if (reg >= dss.feat->num_ports) + for (i = 0; i < dss.feat->num_ports; i++) { + port = of_graph_get_port_by_id(parent, i); + if (!port) continue; - port_type = dss.feat->ports[reg]; - - switch (port_type) { + switch (dss.feat->ports[i]) { case OMAP_DISPLAY_TYPE_DPI: dpi_uninit_port(port); break; @@ -1122,7 +1079,7 @@ static void dss_uninit_ports(struct platform_device *pdev) default: break; } - } while ((port = omapdss_of_get_next_port(parent, port)) != NULL); + } } static int dss_video_pll_probe(struct platform_device *pdev) @@ -1254,8 +1211,7 @@ static int dss_bind(struct device *dev) dss.lcd_clk_source[1] = DSS_CLK_SRC_FCK; rev = dss_read_reg(DSS_REVISION); - printk(KERN_INFO "OMAP DSS rev %d.%d\n", - FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); + pr_info("OMAP DSS rev %d.%d\n", FLD_GET(rev, 7, 4), FLD_GET(rev, 3, 0)); dss_runtime_put(); @@ -1267,7 +1223,8 @@ static int dss_bind(struct device *dev) pm_set_vt_switch(0); - dss_initialized = true; + omapdss_gather_components(dev); + omapdss_set_is_initialized(true); return 0; @@ -1291,7 +1248,7 @@ static void dss_unbind(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); - dss_initialized = false; + omapdss_set_is_initialized(false); component_unbind_all(&pdev->dev, NULL); diff --git a/drivers/gpu/drm/omapdrm/dss/dss.h b/drivers/gpu/drm/omapdrm/dss/dss.h index 56493b290731..5dd29c98143a 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss.h +++ b/drivers/gpu/drm/omapdrm/dss/dss.h @@ -42,29 +42,26 @@ #ifdef DSS_SUBSYS_NAME #define DSSERR(format, ...) \ - printk(KERN_ERR "omapdss " DSS_SUBSYS_NAME " error: " format, \ - ## __VA_ARGS__) + pr_err("omapdss " DSS_SUBSYS_NAME " error: " format, ##__VA_ARGS__) #else #define DSSERR(format, ...) \ - printk(KERN_ERR "omapdss error: " format, ## __VA_ARGS__) + pr_err("omapdss error: " format, ##__VA_ARGS__) #endif #ifdef DSS_SUBSYS_NAME #define DSSINFO(format, ...) \ - printk(KERN_INFO "omapdss " DSS_SUBSYS_NAME ": " format, \ - ## __VA_ARGS__) + pr_info("omapdss " DSS_SUBSYS_NAME ": " format, ##__VA_ARGS__) #else #define DSSINFO(format, ...) \ - printk(KERN_INFO "omapdss: " format, ## __VA_ARGS__) + pr_info("omapdss: " format, ## __VA_ARGS__) #endif #ifdef DSS_SUBSYS_NAME #define DSSWARN(format, ...) \ - printk(KERN_WARNING "omapdss " DSS_SUBSYS_NAME ": " format, \ - ## __VA_ARGS__) + pr_warn("omapdss " DSS_SUBSYS_NAME ": " format, ##__VA_ARGS__) #else #define DSSWARN(format, ...) \ - printk(KERN_WARNING "omapdss: " format, ## __VA_ARGS__) + pr_warn("omapdss: " format, ##__VA_ARGS__) #endif /* OMAP TRM gives bitfields as start:end, where start is the higher bit @@ -256,10 +253,6 @@ struct dss_pll *dss_video_pll_init(struct platform_device *pdev, int id, struct regulator *regulator); void dss_video_pll_uninit(struct dss_pll *pll); -/* dss-of */ -struct device_node *dss_of_port_get_parent_device(struct device_node *port); -u32 dss_of_port_get_port_number(struct device_node *port); - #if defined(CONFIG_OMAP2_DSS_DEBUGFS) void dss_debug_dump_clocks(struct seq_file *s); #endif @@ -318,15 +311,7 @@ void dsi_uninit_platform_driver(void); void dsi_dump_clocks(struct seq_file *s); void dsi_irq_handler(void); -u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt); -#else -static inline u8 dsi_get_pixel_size(enum omap_dss_dsi_pixel_format fmt) -{ - WARN(1, "%s: DSI not compiled in, returning pixel_size as 0\n", - __func__); - return 0; -} #endif /* DPI */ @@ -352,6 +337,9 @@ int dispc_init_platform_driver(void) __init; void dispc_uninit_platform_driver(void); void dispc_dump_clocks(struct seq_file *s); +int dispc_runtime_get(void); +void dispc_runtime_put(void); + void dispc_enable_sidle(void); void dispc_disable_sidle(void); @@ -371,8 +359,9 @@ int dispc_calc_clock_rates(unsigned long dispc_fclk_rate, struct dispc_clock_info *cinfo); -void dispc_ovl_set_fifo_threshold(enum omap_plane plane, u32 low, u32 high); -void dispc_ovl_compute_fifo_thresholds(enum omap_plane plane, +void dispc_ovl_set_fifo_threshold(enum omap_plane_id plane, u32 low, + u32 high); +void dispc_ovl_compute_fifo_thresholds(enum omap_plane_id plane, u32 *fifo_low, u32 *fifo_high, bool use_fifomerge, bool manual_update); @@ -385,8 +374,6 @@ void dispc_set_tv_pclk(unsigned long pclk); u32 dispc_wb_get_framedone_irq(void); bool dispc_wb_go_busy(void); void dispc_wb_go(void); -void dispc_wb_enable(bool enable); -bool dispc_wb_is_enabled(void); void dispc_wb_set_channel_in(enum dss_writeback_channel channel); int dispc_wb_setup(const struct omap_dss_writeback_info *wi, bool mem_to_mem, const struct videomode *vm); diff --git a/drivers/gpu/drm/omapdrm/dss/dss_features.c b/drivers/gpu/drm/omapdrm/dss/dss_features.c index ee5b93ce2763..80c6440a0e08 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss_features.c +++ b/drivers/gpu/drm/omapdrm/dss/dss_features.c @@ -774,13 +774,11 @@ int dss_feat_get_num_mgrs(void) { return omap_current_dss_features->num_mgrs; } -EXPORT_SYMBOL(dss_feat_get_num_mgrs); int dss_feat_get_num_ovls(void) { return omap_current_dss_features->num_ovls; } -EXPORT_SYMBOL(dss_feat_get_num_ovls); unsigned long dss_feat_get_param_min(enum dss_range_param param) { @@ -802,18 +800,17 @@ enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel return omap_current_dss_features->supported_outputs[channel]; } -enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane) +enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane_id plane) { return omap_current_dss_features->supported_color_modes[plane]; } -EXPORT_SYMBOL(dss_feat_get_supported_color_modes); -enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane) +enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane_id plane) { return omap_current_dss_features->overlay_caps[plane]; } -bool dss_feat_color_mode_supported(enum omap_plane plane, +bool dss_feat_color_mode_supported(enum omap_plane_id plane, enum omap_color_mode color_mode) { return omap_current_dss_features->supported_color_modes[plane] & diff --git a/drivers/gpu/drm/omapdrm/dss/dss_features.h b/drivers/gpu/drm/omapdrm/dss/dss_features.h index bb4b7f0e642b..27fbe64935e8 100644 --- a/drivers/gpu/drm/omapdrm/dss/dss_features.h +++ b/drivers/gpu/drm/omapdrm/dss/dss_features.h @@ -88,8 +88,8 @@ enum dss_range_param { /* DSS Feature Functions */ unsigned long dss_feat_get_param_min(enum dss_range_param param); unsigned long dss_feat_get_param_max(enum dss_range_param param); -enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane plane); -bool dss_feat_color_mode_supported(enum omap_plane plane, +enum omap_overlay_caps dss_feat_get_overlay_caps(enum omap_plane_id plane); +bool dss_feat_color_mode_supported(enum omap_plane_id plane, enum omap_color_mode color_mode); u32 dss_feat_get_buffer_size_unit(void); /* in bytes */ @@ -104,4 +104,8 @@ void dss_features_init(enum omapdss_version version); enum omap_display_type dss_feat_get_supported_displays(enum omap_channel channel); enum omap_dss_output_id dss_feat_get_supported_outputs(enum omap_channel channel); +int dss_feat_get_num_mgrs(void); +int dss_feat_get_num_ovls(void); +enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane_id plane); + #endif diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c index e7162c16de2e..87c53034c634 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c @@ -34,6 +34,7 @@ #include <linux/regulator/consumer.h> #include <linux/component.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <sound/omap-hdmi-audio.h> #include "omapdss.h" @@ -546,7 +547,7 @@ static int hdmi_probe_of(struct platform_device *pdev) struct device_node *ep; int r; - ep = omapdss_of_get_first_endpoint(node); + ep = of_graph_get_endpoint_by_regs(node, 0, 0); if (!ep) return 0; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c index 678dfb02764a..d13dce7e8079 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c @@ -39,6 +39,7 @@ #include <linux/regulator/consumer.h> #include <linux/component.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <sound/omap-hdmi-audio.h> #include "omapdss.h" @@ -572,7 +573,7 @@ static int hdmi_probe_of(struct platform_device *pdev) struct device_node *ep; int r; - ep = omapdss_of_get_first_endpoint(node); + ep = of_graph_get_endpoint_by_regs(node, 0, 0); if (!ep) return 0; diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c index b783d5a0750e..597ec9d87d1d 100644 --- a/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c +++ b/drivers/gpu/drm/omapdrm/dss/hdmi_wp.c @@ -147,15 +147,17 @@ void hdmi_wp_video_config_interface(struct hdmi_wp_data *wp, struct videomode *vm) { u32 r; - bool vsync_pol, hsync_pol; + bool vsync_inv, hsync_inv; DSSDBG("Enter hdmi_wp_video_config_interface\n"); - vsync_pol = !!(vm->flags & DISPLAY_FLAGS_VSYNC_HIGH); - hsync_pol = !!(vm->flags & DISPLAY_FLAGS_HSYNC_HIGH); + vsync_inv = !!(vm->flags & DISPLAY_FLAGS_VSYNC_LOW); + hsync_inv = !!(vm->flags & DISPLAY_FLAGS_HSYNC_LOW); r = hdmi_read_reg(wp->base, HDMI_WP_VIDEO_CFG); - r = FLD_MOD(r, vsync_pol, 7, 7); - r = FLD_MOD(r, hsync_pol, 6, 6); + r = FLD_MOD(r, 1, 7, 7); /* VSYNC_POL to dispc active high */ + r = FLD_MOD(r, 1, 6, 6); /* HSYNC_POL to dispc active high */ + r = FLD_MOD(r, vsync_inv, 5, 5); /* CORE_VSYNC_INV */ + r = FLD_MOD(r, hsync_inv, 4, 4); /* CORE_HSYNC_INV */ r = FLD_MOD(r, !!(vm->flags & DISPLAY_FLAGS_INTERLACED), 3, 3); r = FLD_MOD(r, 1, 1, 0); /* HDMI_TIMING_MASTER_24BIT */ hdmi_write_reg(wp->base, HDMI_WP_VIDEO_CFG, r); diff --git a/drivers/gpu/drm/omapdrm/dss/omapdss.h b/drivers/gpu/drm/omapdrm/dss/omapdss.h index 5b3b961127bd..b19dae1fd6c5 100644 --- a/drivers/gpu/drm/omapdrm/dss/omapdss.h +++ b/drivers/gpu/drm/omapdrm/dss/omapdss.h @@ -76,7 +76,7 @@ enum omap_display_type { OMAP_DISPLAY_TYPE_DVI = 1 << 6, }; -enum omap_plane { +enum omap_plane_id { OMAP_DSS_GFX = 0, OMAP_DSS_VIDEO1 = 1, OMAP_DSS_VIDEO2 = 2, @@ -338,7 +338,7 @@ struct omap_overlay { /* static fields */ const char *name; - enum omap_plane id; + enum omap_plane_id id; enum omap_color_mode supported_modes; enum omap_overlay_caps caps; @@ -785,7 +785,7 @@ const char *omapdss_get_default_display_name(void); int dss_feat_get_num_mgrs(void); int dss_feat_get_num_ovls(void); -enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane plane); +enum omap_color_mode dss_feat_get_supported_color_modes(enum omap_plane_id plane); @@ -830,56 +830,13 @@ static inline bool omapdss_device_is_enabled(struct omap_dss_device *dssdev) return dssdev->state == OMAP_DSS_DISPLAY_ACTIVE; } -struct device_node * -omapdss_of_get_next_port(const struct device_node *parent, - struct device_node *prev); - -struct device_node * -omapdss_of_get_next_endpoint(const struct device_node *parent, - struct device_node *prev); - -struct device_node * -omapdss_of_get_first_endpoint(const struct device_node *parent); - struct omap_dss_device * omapdss_of_find_source_for_first_ep(struct device_node *node); -u32 dispc_read_irqstatus(void); -void dispc_clear_irqstatus(u32 mask); -u32 dispc_read_irqenable(void); -void dispc_write_irqenable(u32 mask); +void omapdss_set_is_initialized(bool set); -int dispc_request_irq(irq_handler_t handler, void *dev_id); -void dispc_free_irq(void *dev_id); - -int dispc_runtime_get(void); -void dispc_runtime_put(void); - -void dispc_mgr_enable(enum omap_channel channel, bool enable); -u32 dispc_mgr_get_vsync_irq(enum omap_channel channel); -u32 dispc_mgr_get_framedone_irq(enum omap_channel channel); -u32 dispc_mgr_get_sync_lost_irq(enum omap_channel channel); -bool dispc_mgr_go_busy(enum omap_channel channel); -void dispc_mgr_go(enum omap_channel channel); -void dispc_mgr_set_lcd_config(enum omap_channel channel, - const struct dss_lcd_mgr_config *config); -void dispc_mgr_set_timings(enum omap_channel channel, - const struct videomode *vm); -void dispc_mgr_setup(enum omap_channel channel, - const struct omap_overlay_manager_info *info); -u32 dispc_mgr_gamma_size(enum omap_channel channel); -void dispc_mgr_set_gamma(enum omap_channel channel, - const struct drm_color_lut *lut, - unsigned int length); - -int dispc_ovl_enable(enum omap_plane plane, bool enable); -bool dispc_ovl_enabled(enum omap_plane plane); -void dispc_ovl_set_channel_out(enum omap_plane plane, - enum omap_channel channel); -int dispc_ovl_setup(enum omap_plane plane, const struct omap_overlay_info *oi, - bool replication, const struct videomode *vm, bool mem_to_mem); - -enum omap_dss_output_id dispc_mgr_get_supported_outputs(enum omap_channel channel); +struct device_node *dss_of_port_get_parent_device(struct device_node *port); +u32 dss_of_port_get_port_number(struct device_node *port); struct dss_mgr_ops { int (*connect)(enum omap_channel channel, @@ -919,4 +876,60 @@ int dss_mgr_register_framedone_handler(enum omap_channel channel, void dss_mgr_unregister_framedone_handler(enum omap_channel channel, void (*handler)(void *), void *data); +/* dispc ops */ + +struct dispc_ops { + u32 (*read_irqstatus)(void); + void (*clear_irqstatus)(u32 mask); + u32 (*read_irqenable)(void); + void (*write_irqenable)(u32 mask); + + int (*request_irq)(irq_handler_t handler, void *dev_id); + void (*free_irq)(void *dev_id); + + int (*runtime_get)(void); + void (*runtime_put)(void); + + int (*get_num_ovls)(void); + int (*get_num_mgrs)(void); + + void (*mgr_enable)(enum omap_channel channel, bool enable); + bool (*mgr_is_enabled)(enum omap_channel channel); + u32 (*mgr_get_vsync_irq)(enum omap_channel channel); + u32 (*mgr_get_framedone_irq)(enum omap_channel channel); + u32 (*mgr_get_sync_lost_irq)(enum omap_channel channel); + bool (*mgr_go_busy)(enum omap_channel channel); + void (*mgr_go)(enum omap_channel channel); + void (*mgr_set_lcd_config)(enum omap_channel channel, + const struct dss_lcd_mgr_config *config); + void (*mgr_set_timings)(enum omap_channel channel, + const struct videomode *vm); + void (*mgr_setup)(enum omap_channel channel, + const struct omap_overlay_manager_info *info); + enum omap_dss_output_id (*mgr_get_supported_outputs)(enum omap_channel channel); + u32 (*mgr_gamma_size)(enum omap_channel channel); + void (*mgr_set_gamma)(enum omap_channel channel, + const struct drm_color_lut *lut, + unsigned int length); + + int (*ovl_enable)(enum omap_plane_id plane, bool enable); + bool (*ovl_enabled)(enum omap_plane_id plane); + void (*ovl_set_channel_out)(enum omap_plane_id plane, + enum omap_channel channel); + int (*ovl_setup)(enum omap_plane_id plane, + const struct omap_overlay_info *oi, + const struct videomode *vm, bool mem_to_mem); + + enum omap_color_mode (*ovl_get_color_modes)(enum omap_plane_id plane); +}; + +void dispc_set_ops(const struct dispc_ops *o); +const struct dispc_ops *dispc_get_ops(void); + +bool omapdss_component_is_display(struct device_node *node); +bool omapdss_component_is_output(struct device_node *node); + +bool omapdss_stack_is_ready(void); +void omapdss_gather_components(struct device *dev); + #endif /* __OMAP_DRM_DSS_H */ diff --git a/drivers/gpu/drm/omapdrm/dss/output.c b/drivers/gpu/drm/omapdrm/dss/output.c index a901af5a9bc3..655c5d73eac9 100644 --- a/drivers/gpu/drm/omapdrm/dss/output.c +++ b/drivers/gpu/drm/omapdrm/dss/output.c @@ -22,7 +22,6 @@ #include <linux/of.h> #include "omapdss.h" -#include "dss.h" static LIST_HEAD(output_list); static DEFINE_MUTEX(output_lock); @@ -35,14 +34,15 @@ int omapdss_output_set_device(struct omap_dss_device *out, mutex_lock(&output_lock); if (out->dst) { - DSSERR("output already has device %s connected to it\n", + dev_err(out->dev, + "output already has device %s connected to it\n", out->dst->name); r = -EINVAL; goto err; } if (out->output_type != dssdev->type) { - DSSERR("output type and display type don't match\n"); + dev_err(out->dev, "output type and display type don't match\n"); r = -EINVAL; goto err; } @@ -67,14 +67,16 @@ int omapdss_output_unset_device(struct omap_dss_device *out) mutex_lock(&output_lock); if (!out->dst) { - DSSERR("output doesn't have a device connected to it\n"); + dev_err(out->dev, + "output doesn't have a device connected to it\n"); r = -EINVAL; goto err; } if (out->dst->state != OMAP_DSS_DISPLAY_DISABLED) { - DSSERR("device %s is not disabled, cannot unset device\n", - out->dst->name); + dev_err(out->dev, + "device %s is not disabled, cannot unset device\n", + out->dst->name); r = -EINVAL; goto err; } @@ -105,6 +107,19 @@ void omapdss_unregister_output(struct omap_dss_device *out) } EXPORT_SYMBOL(omapdss_unregister_output); +bool omapdss_component_is_output(struct device_node *node) +{ + struct omap_dss_device *out; + + list_for_each_entry(out, &output_list, list) { + if (out->dev->of_node == node) + return true; + } + + return false; +} +EXPORT_SYMBOL(omapdss_component_is_output); + struct omap_dss_device *omap_dss_get_output(enum omap_dss_output_id id) { struct omap_dss_device *out; diff --git a/drivers/gpu/drm/omapdrm/dss/pll.c b/drivers/gpu/drm/omapdrm/dss/pll.c index 0a76c89cdc2e..5e221302768b 100644 --- a/drivers/gpu/drm/omapdrm/dss/pll.c +++ b/drivers/gpu/drm/omapdrm/dss/pll.c @@ -215,8 +215,8 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin, dss_pll_calc_func func, void *data) { const struct dss_pll_hw *hw = pll->hw; - int n, n_start, n_stop; - int m, m_start, m_stop; + int n, n_min, n_max; + int m, m_min, m_max; unsigned long fint, clkdco; unsigned long pll_hw_max; unsigned long fint_hw_min, fint_hw_max; @@ -226,21 +226,22 @@ bool dss_pll_calc_a(const struct dss_pll *pll, unsigned long clkin, fint_hw_min = hw->fint_min; fint_hw_max = hw->fint_max; - n_start = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); - n_stop = min((unsigned)(clkin / fint_hw_min), hw->n_max); + n_min = max(DIV_ROUND_UP(clkin, fint_hw_max), 1ul); + n_max = min((unsigned)(clkin / fint_hw_min), hw->n_max); pll_max = pll_max ? pll_max : ULONG_MAX; - for (n = n_start; n <= n_stop; ++n) { + /* Try to find high N & M to avoid jitter (DRA7 errata i886) */ + for (n = n_max; n >= n_min; --n) { fint = clkin / n; - m_start = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2), + m_min = max(DIV_ROUND_UP(DIV_ROUND_UP(pll_min, fint), 2), 1ul); - m_stop = min3((unsigned)(pll_max / fint / 2), + m_max = min3((unsigned)(pll_max / fint / 2), (unsigned)(pll_hw_max / fint / 2), hw->m_max); - for (m = m_start; m <= m_stop; ++m) { + for (m = m_max; m >= m_min; --m) { clkdco = 2 * m * fint; if (func(n, m, fint, clkdco, data)) diff --git a/drivers/gpu/drm/omapdrm/dss/sdi.c b/drivers/gpu/drm/omapdrm/dss/sdi.c index b3bda2d3c08d..0620b9f8c231 100644 --- a/drivers/gpu/drm/omapdrm/dss/sdi.c +++ b/drivers/gpu/drm/omapdrm/dss/sdi.c @@ -414,7 +414,7 @@ int sdi_init_port(struct platform_device *pdev, struct device_node *port) u32 datapairs; int r; - ep = omapdss_of_get_next_endpoint(port, NULL); + ep = of_get_next_child(port, NULL); if (!ep) return 0; diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c index d74f7fcc2e46..19d14957f566 100644 --- a/drivers/gpu/drm/omapdrm/dss/venc.c +++ b/drivers/gpu/drm/omapdrm/dss/venc.c @@ -35,6 +35,7 @@ #include <linux/regulator/consumer.h> #include <linux/pm_runtime.h> #include <linux/of.h> +#include <linux/of_graph.h> #include <linux/component.h> #include "omapdss.h" @@ -818,7 +819,7 @@ static int venc_probe_of(struct platform_device *pdev) u32 channels; int r; - ep = omapdss_of_get_first_endpoint(node); + ep = of_graph_get_endpoint_by_regs(node, 0, 0); if (!ep) return 0; diff --git a/drivers/gpu/drm/omapdrm/omap_connector.c b/drivers/gpu/drm/omapdrm/omap_connector.c index f90e2d22c5ec..c24b6b783e9a 100644 --- a/drivers/gpu/drm/omapdrm/omap_connector.c +++ b/drivers/gpu/drm/omapdrm/omap_connector.c @@ -146,8 +146,6 @@ static int omap_connector_mode_valid(struct drm_connector *connector, int r, ret = MODE_BAD; drm_display_mode_to_videomode(mode, &vm); - vm.flags |= DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_PIXDATA_POSEDGE | - DISPLAY_FLAGS_SYNC_NEGEDGE; mode->vrefresh = drm_mode_vrefresh(mode); /* @@ -162,6 +160,12 @@ static int omap_connector_mode_valid(struct drm_connector *connector, dssdrv->get_timings(dssdev, &t); + /* + * Ignore the flags, as we don't get them from + * drm_display_mode_to_videomode. + */ + t.flags = 0; + if (memcmp(&vm, &t, sizeof(vm))) r = -EINVAL; else @@ -229,13 +233,11 @@ struct drm_connector *omap_connector_init(struct drm_device *dev, connector_type); drm_connector_helper_add(connector, &omap_connector_helper_funcs); -#if 0 /* enable when dss2 supports hotplug */ - if (dssdev->caps & OMAP_DSS_DISPLAY_CAP_HPD) - connector->polled = 0; - else -#endif + if (dssdev->driver->detect) connector->polled = DRM_CONNECTOR_POLL_CONNECT | - DRM_CONNECTOR_POLL_DISCONNECT; + DRM_CONNECTOR_POLL_DISCONNECT; + else + connector->polled = 0; connector->interlace_allowed = 1; connector->doublescan_allowed = 0; diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c index b68c70eb395f..dccd03726796 100644 --- a/drivers/gpu/drm/omapdrm/omap_crtc.c +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c @@ -107,10 +107,12 @@ static struct omap_dss_device *omap_crtc_output[8]; static int omap_crtc_dss_connect(enum omap_channel channel, struct omap_dss_device *dst) { + const struct dispc_ops *dispc_ops = dispc_get_ops(); + if (omap_crtc_output[channel]) return -EINVAL; - if ((dispc_mgr_get_supported_outputs(channel) & dst->id) == 0) + if ((dispc_ops->mgr_get_supported_outputs(channel) & dst->id) == 0) return -EINVAL; omap_crtc_output[channel] = dst; @@ -134,6 +136,7 @@ static void omap_crtc_dss_start_update(enum omap_channel channel) static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) { struct drm_device *dev = crtc->dev; + struct omap_drm_private *priv = dev->dev_private; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); enum omap_channel channel = omap_crtc->channel; struct omap_irq_wait *wait; @@ -144,7 +147,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) return; if (omap_crtc_output[channel]->output_type == OMAP_DISPLAY_TYPE_HDMI) { - dispc_mgr_enable(channel, enable); + priv->dispc_ops->mgr_enable(channel, enable); omap_crtc->enabled = enable; return; } @@ -157,8 +160,8 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) omap_crtc->ignore_digit_sync_lost = true; } - framedone_irq = dispc_mgr_get_framedone_irq(channel); - vsync_irq = dispc_mgr_get_vsync_irq(channel); + framedone_irq = priv->dispc_ops->mgr_get_framedone_irq(channel); + vsync_irq = priv->dispc_ops->mgr_get_vsync_irq(channel); if (enable) { wait = omap_irq_wait_init(dev, vsync_irq, 1); @@ -178,7 +181,7 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) wait = omap_irq_wait_init(dev, vsync_irq, 2); } - dispc_mgr_enable(channel, enable); + priv->dispc_ops->mgr_enable(channel, enable); omap_crtc->enabled = enable; ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100)); @@ -198,17 +201,9 @@ static void omap_crtc_set_enabled(struct drm_crtc *crtc, bool enable) static int omap_crtc_dss_enable(enum omap_channel channel) { struct omap_crtc *omap_crtc = omap_crtcs[channel]; - struct omap_overlay_manager_info info; + struct omap_drm_private *priv = omap_crtc->base.dev->dev_private; - memset(&info, 0, sizeof(info)); - info.default_color = 0x00000000; - info.trans_key = 0x00000000; - info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST; - info.trans_enabled = false; - - dispc_mgr_setup(omap_crtc->channel, &info); - dispc_mgr_set_timings(omap_crtc->channel, - &omap_crtc->vm); + priv->dispc_ops->mgr_set_timings(omap_crtc->channel, &omap_crtc->vm); omap_crtc_set_enabled(&omap_crtc->base, true); return 0; @@ -233,8 +228,10 @@ static void omap_crtc_dss_set_lcd_config(enum omap_channel channel, const struct dss_lcd_mgr_config *config) { struct omap_crtc *omap_crtc = omap_crtcs[channel]; + struct omap_drm_private *priv = omap_crtc->base.dev->dev_private; + DBG("%s", omap_crtc->name); - dispc_mgr_set_lcd_config(omap_crtc->channel, config); + priv->dispc_ops->mgr_set_lcd_config(omap_crtc->channel, config); } static int omap_crtc_dss_register_framedone( @@ -282,6 +279,8 @@ void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus) void omap_crtc_vblank_irq(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct drm_device *dev = omap_crtc->base.dev; + struct omap_drm_private *priv = dev->dev_private; bool pending; spin_lock(&crtc->dev->event_lock); @@ -289,7 +288,7 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc) * If the dispc is busy we're racing the flush operation. Try again on * the next vblank interrupt. */ - if (dispc_mgr_go_busy(omap_crtc->channel)) { + if (priv->dispc_ops->mgr_go_busy(omap_crtc->channel)) { spin_unlock(&crtc->dev->event_lock); return; } @@ -313,6 +312,22 @@ void omap_crtc_vblank_irq(struct drm_crtc *crtc) DBG("%s: apply done", omap_crtc->name); } +static void omap_crtc_write_crtc_properties(struct drm_crtc *crtc) +{ + struct omap_drm_private *priv = crtc->dev->dev_private; + struct omap_crtc *omap_crtc = to_omap_crtc(crtc); + struct omap_overlay_manager_info info; + + memset(&info, 0, sizeof(info)); + + info.default_color = 0x000000; + info.trans_enabled = false; + info.partial_alpha_enabled = false; + info.cpr_enable = false; + + priv->dispc_ops->mgr_setup(omap_crtc->channel, &info); +} + /* ----------------------------------------------------------------------------- * CRTC Functions */ @@ -358,6 +373,11 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct omap_crtc *omap_crtc = to_omap_crtc(crtc); struct drm_display_mode *mode = &crtc->state->adjusted_mode; + struct omap_drm_private *priv = crtc->dev->dev_private; + const u32 flags_mask = DISPLAY_FLAGS_DE_HIGH | DISPLAY_FLAGS_DE_LOW | + DISPLAY_FLAGS_PIXDATA_POSEDGE | DISPLAY_FLAGS_PIXDATA_NEGEDGE | + DISPLAY_FLAGS_SYNC_POSEDGE | DISPLAY_FLAGS_SYNC_NEGEDGE; + unsigned int i; DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x", omap_crtc->name, mode->base.id, mode->name, @@ -367,9 +387,38 @@ static void omap_crtc_mode_set_nofb(struct drm_crtc *crtc) mode->type, mode->flags); drm_display_mode_to_videomode(mode, &omap_crtc->vm); - omap_crtc->vm.flags |= DISPLAY_FLAGS_DE_HIGH | - DISPLAY_FLAGS_PIXDATA_POSEDGE | - DISPLAY_FLAGS_SYNC_NEGEDGE; + + /* + * HACK: This fixes the vm flags. + * struct drm_display_mode does not contain the VSYNC/HSYNC/DE flags + * and they get lost when converting back and forth between + * struct drm_display_mode and struct videomode. The hack below + * goes and fetches the missing flags from the panel drivers. + * + * Correct solution would be to use DRM's bus-flags, but that's not + * easily possible before the omapdrm's panel/encoder driver model + * has been changed to the DRM model. + */ + + for (i = 0; i < priv->num_encoders; ++i) { + struct drm_encoder *encoder = priv->encoders[i]; + + if (encoder->crtc == crtc) { + struct omap_dss_device *dssdev; + + dssdev = omap_encoder_get_dssdev(encoder); + + if (dssdev) { + struct videomode vm = {0}; + + dssdev->driver->get_timings(dssdev, &vm); + + omap_crtc->vm.flags |= vm.flags & flags_mask; + } + + break; + } + } } static int omap_crtc_atomic_check(struct drm_crtc *crtc, @@ -394,6 +443,7 @@ static void omap_crtc_atomic_begin(struct drm_crtc *crtc, static void omap_crtc_atomic_flush(struct drm_crtc *crtc, struct drm_crtc_state *old_crtc_state) { + struct omap_drm_private *priv = crtc->dev->dev_private; struct omap_crtc *omap_crtc = to_omap_crtc(crtc); int ret; @@ -407,9 +457,11 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, length = crtc->state->gamma_lut->length / sizeof(*lut); } - dispc_mgr_set_gamma(omap_crtc->channel, lut, length); + priv->dispc_ops->mgr_set_gamma(omap_crtc->channel, lut, length); } + omap_crtc_write_crtc_properties(crtc); + /* Only flush the CRTC if it is currently enabled. */ if (!omap_crtc->enabled) return; @@ -420,7 +472,7 @@ static void omap_crtc_atomic_flush(struct drm_crtc *crtc, WARN_ON(ret != 0); spin_lock_irq(&crtc->dev->event_lock); - dispc_mgr_go(omap_crtc->channel); + priv->dispc_ops->mgr_go(omap_crtc->channel); WARN_ON(omap_crtc->pending); omap_crtc->pending = true; @@ -495,6 +547,8 @@ static const struct drm_crtc_funcs omap_crtc_funcs = { .atomic_destroy_state = drm_atomic_helper_crtc_destroy_state, .atomic_set_property = omap_crtc_atomic_set_property, .atomic_get_property = omap_crtc_atomic_get_property, + .enable_vblank = omap_irq_enable_vblank, + .disable_vblank = omap_irq_disable_vblank, }; static const struct drm_crtc_helper_funcs omap_crtc_helper_funcs = { @@ -519,6 +573,8 @@ static const char *channel_names[] = { void omap_crtc_pre_init(void) { + memset(omap_crtcs, 0, sizeof(omap_crtcs)); + dss_install_mgr_ops(&mgr_ops); } @@ -529,17 +585,28 @@ void omap_crtc_pre_uninit(void) /* initialize crtc */ struct drm_crtc *omap_crtc_init(struct drm_device *dev, - struct drm_plane *plane, enum omap_channel channel, int id) + struct drm_plane *plane, struct omap_dss_device *dssdev) { + struct omap_drm_private *priv = dev->dev_private; struct drm_crtc *crtc = NULL; struct omap_crtc *omap_crtc; + enum omap_channel channel; + struct omap_dss_device *out; int ret; + out = omapdss_find_output_from_display(dssdev); + channel = out->dispc_channel; + omap_dss_put_device(out); + DBG("%s", channel_names[channel]); + /* Multiple displays on same channel is not allowed */ + if (WARN_ON(omap_crtcs[channel] != NULL)) + return ERR_PTR(-EINVAL); + omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL); if (!omap_crtc) - return NULL; + return ERR_PTR(-ENOMEM); crtc = &omap_crtc->base; @@ -551,8 +618,10 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, ret = drm_crtc_init_with_planes(dev, crtc, plane, NULL, &omap_crtc_funcs, NULL); if (ret < 0) { + dev_err(dev->dev, "%s(): could not init crtc for: %s\n", + __func__, dssdev->name); kfree(omap_crtc); - return NULL; + return ERR_PTR(ret); } drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs); @@ -564,7 +633,7 @@ struct drm_crtc *omap_crtc_init(struct drm_device *dev, * extracted with dispc_mgr_gamma_size(). If it returns 0 * gamma table is not supprted. */ - if (dispc_mgr_gamma_size(channel)) { + if (priv->dispc_ops->mgr_gamma_size(channel)) { uint gamma_lut_size = 256; drm_crtc_enable_color_mgmt(crtc, 0, false, gamma_lut_size); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c index 3f2554235225..e1f47f0b3ccf 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.c +++ b/drivers/gpu/drm/omapdrm/omap_drv.c @@ -34,11 +34,6 @@ #define DRIVER_MINOR 0 #define DRIVER_PATCHLEVEL 0 -static int num_crtc = CONFIG_DRM_OMAP_NUM_CRTCS; - -MODULE_PARM_DESC(num_crtc, "Number of overlays to use as CRTCs"); -module_param(num_crtc, int, 0600); - /* * mode config funcs */ @@ -93,7 +88,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit) struct drm_atomic_state *old_state = commit->state; /* Apply the atomic update. */ - dispc_runtime_get(); + priv->dispc_ops->runtime_get(); drm_atomic_helper_commit_modeset_disables(dev, old_state); @@ -117,7 +112,7 @@ static void omap_atomic_complete(struct omap_atomic_state_commit *commit) drm_atomic_helper_cleanup_planes(dev, old_state); - dispc_runtime_put(); + priv->dispc_ops->runtime_put(); drm_atomic_state_put(old_state); @@ -224,20 +219,6 @@ static int get_connector_type(struct omap_dss_device *dssdev) } } -static bool channel_used(struct drm_device *dev, enum omap_channel channel) -{ - struct omap_drm_private *priv = dev->dev_private; - int i; - - for (i = 0; i < priv->num_crtcs; i++) { - struct drm_crtc *crtc = priv->crtcs[i]; - - if (omap_crtc_channel(crtc) == channel) - return true; - } - - return false; -} static void omap_disconnect_dssdevs(void) { struct omap_dss_device *dssdev = NULL; @@ -250,7 +231,9 @@ static int omap_connect_dssdevs(void) { int r; struct omap_dss_device *dssdev = NULL; - bool no_displays = true; + + if (!omapdss_stack_is_ready()) + return -EPROBE_DEFER; for_each_dss_dev(dssdev) { r = dssdev->driver->connect(dssdev); @@ -260,14 +243,9 @@ static int omap_connect_dssdevs(void) } else if (r) { dev_warn(dssdev->dev, "could not connect display: %s\n", dssdev->name); - } else { - no_displays = false; } } - if (no_displays) - return -EPROBE_DEFER; - return 0; cleanup: @@ -280,31 +258,6 @@ cleanup: return r; } -static int omap_modeset_create_crtc(struct drm_device *dev, int id, - enum omap_channel channel, - u32 possible_crtcs) -{ - struct omap_drm_private *priv = dev->dev_private; - struct drm_plane *plane; - struct drm_crtc *crtc; - - plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_PRIMARY, - possible_crtcs); - if (IS_ERR(plane)) - return PTR_ERR(plane); - - crtc = omap_crtc_init(dev, plane, channel, id); - - BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs)); - priv->crtcs[id] = crtc; - priv->num_crtcs++; - - priv->planes[id] = plane; - priv->num_planes++; - - return 0; -} - static int omap_modeset_init_properties(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; @@ -320,12 +273,11 @@ static int omap_modeset_init(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; struct omap_dss_device *dssdev = NULL; - int num_ovls = dss_feat_get_num_ovls(); - int num_mgrs = dss_feat_get_num_mgrs(); - int num_crtcs; - int i, id = 0; + int num_ovls = priv->dispc_ops->get_num_ovls(); + int num_mgrs = priv->dispc_ops->get_num_mgrs(); + int num_crtcs, crtc_idx, plane_idx; int ret; - u32 possible_crtcs; + u32 plane_crtc_mask; drm_mode_config_init(dev); @@ -334,162 +286,97 @@ static int omap_modeset_init(struct drm_device *dev) return ret; /* - * We usually don't want to create a CRTC for each manager, at least - * not until we have a way to expose private planes to userspace. - * Otherwise there would not be enough video pipes left for drm planes. - * We use the num_crtc argument to limit the number of crtcs we create. + * This function creates exactly one connector, encoder, crtc, + * and primary plane per each connected dss-device. Each + * connector->encoder->crtc chain is expected to be separate + * and each crtc is connect to a single dss-channel. If the + * configuration does not match the expectations or exceeds + * the available resources, the configuration is rejected. */ - num_crtcs = min3(num_crtc, num_mgrs, num_ovls); - possible_crtcs = (1 << num_crtcs) - 1; + num_crtcs = 0; + for_each_dss_dev(dssdev) + if (omapdss_device_is_connected(dssdev)) + num_crtcs++; + + if (num_crtcs > num_mgrs || num_crtcs > num_ovls || + num_crtcs > ARRAY_SIZE(priv->crtcs) || + num_crtcs > ARRAY_SIZE(priv->planes) || + num_crtcs > ARRAY_SIZE(priv->encoders) || + num_crtcs > ARRAY_SIZE(priv->connectors)) { + dev_err(dev->dev, "%s(): Too many connected displays\n", + __func__); + return -EINVAL; + } + + /* All planes can be put to any CRTC */ + plane_crtc_mask = (1 << num_crtcs) - 1; dssdev = NULL; + crtc_idx = 0; + plane_idx = 0; for_each_dss_dev(dssdev) { struct drm_connector *connector; struct drm_encoder *encoder; - enum omap_channel channel; - struct omap_dss_device *out; + struct drm_plane *plane; + struct drm_crtc *crtc; if (!omapdss_device_is_connected(dssdev)) continue; encoder = omap_encoder_init(dev, dssdev); - - if (!encoder) { - dev_err(dev->dev, "could not create encoder: %s\n", - dssdev->name); + if (!encoder) return -ENOMEM; - } connector = omap_connector_init(dev, get_connector_type(dssdev), dssdev, encoder); - - if (!connector) { - dev_err(dev->dev, "could not create connector: %s\n", - dssdev->name); + if (!connector) return -ENOMEM; - } - BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders)); - BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors)); + plane = omap_plane_init(dev, plane_idx, DRM_PLANE_TYPE_PRIMARY, + plane_crtc_mask); + if (IS_ERR(plane)) + return PTR_ERR(plane); - priv->encoders[priv->num_encoders++] = encoder; - priv->connectors[priv->num_connectors++] = connector; + crtc = omap_crtc_init(dev, plane, dssdev); + if (IS_ERR(crtc)) + return PTR_ERR(crtc); drm_mode_connector_attach_encoder(connector, encoder); + encoder->possible_crtcs = (1 << crtc_idx); - /* - * if we have reached the limit of the crtcs we are allowed to - * create, let's not try to look for a crtc for this - * panel/encoder and onwards, we will, of course, populate the - * the possible_crtcs field for all the encoders with the final - * set of crtcs we create - */ - if (id == num_crtcs) - continue; - - /* - * get the recommended DISPC channel for this encoder. For now, - * we only try to get create a crtc out of the recommended, the - * other possible channels to which the encoder can connect are - * not considered. - */ - - out = omapdss_find_output_from_display(dssdev); - channel = out->dispc_channel; - omap_dss_put_device(out); - - /* - * if this channel hasn't already been taken by a previously - * allocated crtc, we create a new crtc for it - */ - if (!channel_used(dev, channel)) { - ret = omap_modeset_create_crtc(dev, id, channel, - possible_crtcs); - if (ret < 0) { - dev_err(dev->dev, - "could not create CRTC (channel %u)\n", - channel); - return ret; - } - - id++; - } - } - - /* - * we have allocated crtcs according to the need of the panels/encoders, - * adding more crtcs here if needed - */ - for (; id < num_crtcs; id++) { - - /* find a free manager for this crtc */ - for (i = 0; i < num_mgrs; i++) { - if (!channel_used(dev, i)) - break; - } - - if (i == num_mgrs) { - /* this shouldn't really happen */ - dev_err(dev->dev, "no managers left for crtc\n"); - return -ENOMEM; - } + priv->crtcs[priv->num_crtcs++] = crtc; + priv->planes[priv->num_planes++] = plane; + priv->encoders[priv->num_encoders++] = encoder; + priv->connectors[priv->num_connectors++] = connector; - ret = omap_modeset_create_crtc(dev, id, i, - possible_crtcs); - if (ret < 0) { - dev_err(dev->dev, - "could not create CRTC (channel %u)\n", i); - return ret; - } + plane_idx++; + crtc_idx++; } /* * Create normal planes for the remaining overlays: */ - for (; id < num_ovls; id++) { + for (; plane_idx < num_ovls; plane_idx++) { struct drm_plane *plane; - plane = omap_plane_init(dev, id, DRM_PLANE_TYPE_OVERLAY, - possible_crtcs); + if (WARN_ON(priv->num_planes >= ARRAY_SIZE(priv->planes))) + return -EINVAL; + + plane = omap_plane_init(dev, plane_idx, DRM_PLANE_TYPE_OVERLAY, + plane_crtc_mask); if (IS_ERR(plane)) return PTR_ERR(plane); - BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes)); priv->planes[priv->num_planes++] = plane; } - for (i = 0; i < priv->num_encoders; i++) { - struct drm_encoder *encoder = priv->encoders[i]; - struct omap_dss_device *dssdev = - omap_encoder_get_dssdev(encoder); - struct omap_dss_device *output; - - output = omapdss_find_output_from_display(dssdev); - - /* figure out which crtc's we can connect the encoder to: */ - encoder->possible_crtcs = 0; - for (id = 0; id < priv->num_crtcs; id++) { - struct drm_crtc *crtc = priv->crtcs[id]; - enum omap_channel crtc_channel; - - crtc_channel = omap_crtc_channel(crtc); - - if (output->dispc_channel == crtc_channel) { - encoder->possible_crtcs |= (1 << id); - break; - } - } - - omap_dss_put_device(output); - } - DBG("registered %d planes, %d crtcs, %d encoders and %d connectors\n", priv->num_planes, priv->num_crtcs, priv->num_encoders, priv->num_connectors); - dev->mode_config.min_width = 32; - dev->mode_config.min_height = 32; + dev->mode_config.min_width = 8; + dev->mode_config.min_height = 2; /* note: eventually will need some cpu_is_omapXYZ() type stuff here * to fill in these limits properly on different OMAP generations.. @@ -629,12 +516,18 @@ static int ioctl_gem_info(struct drm_device *dev, void *data, } static const struct drm_ioctl_desc ioctls[DRM_COMMAND_END - DRM_COMMAND_BASE] = { - DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, DRM_AUTH), - DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, DRM_AUTH), - DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, ioctl_gem_cpu_prep, DRM_AUTH), - DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, ioctl_gem_cpu_fini, DRM_AUTH), - DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info, DRM_AUTH), + DRM_IOCTL_DEF_DRV(OMAP_GET_PARAM, ioctl_get_param, + DRM_AUTH | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(OMAP_SET_PARAM, ioctl_set_param, + DRM_AUTH | DRM_MASTER | DRM_ROOT_ONLY), + DRM_IOCTL_DEF_DRV(OMAP_GEM_NEW, ioctl_gem_new, + DRM_AUTH | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_PREP, ioctl_gem_cpu_prep, + DRM_AUTH | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(OMAP_GEM_CPU_FINI, ioctl_gem_cpu_fini, + DRM_AUTH | DRM_RENDER_ALLOW), + DRM_IOCTL_DEF_DRV(OMAP_GEM_INFO, ioctl_gem_info, + DRM_AUTH | DRM_RENDER_ALLOW), }; /* @@ -724,12 +617,9 @@ static const struct file_operations omapdriver_fops = { static struct drm_driver omap_drm_driver = { .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME | - DRIVER_ATOMIC, + DRIVER_ATOMIC | DRIVER_RENDER, .open = dev_open, .lastclose = dev_lastclose, - .get_vblank_counter = drm_vblank_no_hw_counter, - .enable_vblank = omap_irq_enable_vblank, - .disable_vblank = omap_irq_disable_vblank, #ifdef CONFIG_DEBUG_FS .debugfs_init = omap_debugfs_init, #endif @@ -779,6 +669,8 @@ static int pdev_probe(struct platform_device *pdev) goto err_disconnect_dssdevs; } + priv->dispc_ops = dispc_get_ops(); + priv->omaprev = pdata->omaprev; priv->wq = alloc_ordered_workqueue("omapdrm", 0); @@ -863,6 +755,8 @@ static int pdev_remove(struct platform_device *pdev) if (priv->fbdev) omap_fbdev_free(ddev); + drm_atomic_helper_shutdown(ddev); + drm_mode_config_cleanup(ddev); omap_drm_irq_uninstall(ddev); diff --git a/drivers/gpu/drm/omapdrm/omap_drv.h b/drivers/gpu/drm/omapdrm/omap_drv.h index 65977982f15f..7a4c57eb6536 100644 --- a/drivers/gpu/drm/omapdrm/omap_drv.h +++ b/drivers/gpu/drm/omapdrm/omap_drv.h @@ -59,6 +59,8 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, struct omap_drm_private { uint32_t omaprev; + const struct dispc_ops *dispc_ops; + unsigned int num_crtcs; struct drm_crtc *crtcs[8]; @@ -112,8 +114,8 @@ void omap_gem_describe_objects(struct list_head *list, struct seq_file *m); int omap_gem_resume(struct device *dev); #endif -int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe); -void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe); +int omap_irq_enable_vblank(struct drm_crtc *crtc); +void omap_irq_disable_vblank(struct drm_crtc *crtc); void omap_drm_irq_uninstall(struct drm_device *dev); int omap_drm_irq_install(struct drm_device *dev); @@ -135,13 +137,13 @@ enum omap_channel omap_crtc_channel(struct drm_crtc *crtc); void omap_crtc_pre_init(void); void omap_crtc_pre_uninit(void); struct drm_crtc *omap_crtc_init(struct drm_device *dev, - struct drm_plane *plane, enum omap_channel channel, int id); + struct drm_plane *plane, struct omap_dss_device *dssdev); int omap_crtc_wait_pending(struct drm_crtc *crtc); void omap_crtc_error_irq(struct drm_crtc *crtc, uint32_t irqstatus); void omap_crtc_vblank_irq(struct drm_crtc *crtc); struct drm_plane *omap_plane_init(struct drm_device *dev, - int id, enum drm_plane_type type, + int idx, enum drm_plane_type type, u32 possible_crtcs); void omap_plane_install_properties(struct drm_plane *plane, struct drm_mode_object *obj); diff --git a/drivers/gpu/drm/omapdrm/omap_fbdev.c b/drivers/gpu/drm/omapdrm/omap_fbdev.c index 942c4d483008..4e89dd537862 100644 --- a/drivers/gpu/drm/omapdrm/omap_fbdev.c +++ b/drivers/gpu/drm/omapdrm/omap_fbdev.c @@ -222,9 +222,6 @@ fail_unlock: fail: if (ret) { - - drm_fb_helper_release_fbi(helper); - if (fb) drm_framebuffer_remove(fb); } @@ -301,7 +298,6 @@ void omap_fbdev_free(struct drm_device *dev) DBG(); drm_fb_helper_unregister_fbi(helper); - drm_fb_helper_release_fbi(helper); drm_fb_helper_fini(helper); diff --git a/drivers/gpu/drm/omapdrm/omap_gem.c b/drivers/gpu/drm/omapdrm/omap_gem.c index 5d5a9f517c30..68a75b829b71 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem.c +++ b/drivers/gpu/drm/omapdrm/omap_gem.c @@ -1107,9 +1107,8 @@ static inline bool is_waiting(struct omap_gem_sync_waiter *waiter) /* macro for sync debug.. */ #define SYNCDBG 0 -#define SYNC(fmt, ...) do { if (SYNCDBG) \ - printk(KERN_ERR "%s:%d: "fmt"\n", \ - __func__, __LINE__, ##__VA_ARGS__); \ +#define SYNC(fmt, ...) do { if (SYNCDBG) \ + pr_err("%s:%d: " fmt "\n", __func__, __LINE__, ##__VA_ARGS__); \ } while (0) diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c index ee5883f59be5..0dbe0306953d 100644 --- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c +++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c @@ -160,10 +160,10 @@ static struct dma_buf_ops omap_dmabuf_ops = { .release = omap_gem_dmabuf_release, .begin_cpu_access = omap_gem_dmabuf_begin_cpu_access, .end_cpu_access = omap_gem_dmabuf_end_cpu_access, - .kmap_atomic = omap_gem_dmabuf_kmap_atomic, - .kunmap_atomic = omap_gem_dmabuf_kunmap_atomic, - .kmap = omap_gem_dmabuf_kmap, - .kunmap = omap_gem_dmabuf_kunmap, + .map_atomic = omap_gem_dmabuf_kmap_atomic, + .unmap_atomic = omap_gem_dmabuf_kunmap_atomic, + .map = omap_gem_dmabuf_kmap, + .unmap = omap_gem_dmabuf_kunmap, .mmap = omap_gem_dmabuf_mmap, }; diff --git a/drivers/gpu/drm/omapdrm/omap_irq.c b/drivers/gpu/drm/omapdrm/omap_irq.c index 9adfa7c99695..115104cdcc59 100644 --- a/drivers/gpu/drm/omapdrm/omap_irq.c +++ b/drivers/gpu/drm/omapdrm/omap_irq.c @@ -40,8 +40,8 @@ static void omap_irq_update(struct drm_device *dev) DBG("irqmask=%08x", irqmask); - dispc_write_irqenable(irqmask); - dispc_read_irqenable(); /* flush posted write */ + priv->dispc_ops->write_irqenable(irqmask); + priv->dispc_ops->read_irqenable(); /* flush posted write */ } static void omap_irq_wait_handler(struct omap_irq_wait *wait) @@ -101,16 +101,17 @@ int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait, * Zero on success, appropriate errno if the given @crtc's vblank * interrupt cannot be enabled. */ -int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe) +int omap_irq_enable_vblank(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; struct omap_drm_private *priv = dev->dev_private; - struct drm_crtc *crtc = priv->crtcs[pipe]; unsigned long flags; + enum omap_channel channel = omap_crtc_channel(crtc); - DBG("dev=%p, crtc=%u", dev, pipe); + DBG("dev=%p, crtc=%u", dev, channel); spin_lock_irqsave(&priv->wait_lock, flags); - priv->irq_mask |= dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc)); + priv->irq_mask |= priv->dispc_ops->mgr_get_vsync_irq(channel); omap_irq_update(dev); spin_unlock_irqrestore(&priv->wait_lock, flags); @@ -126,16 +127,17 @@ int omap_irq_enable_vblank(struct drm_device *dev, unsigned int pipe) * a hardware vblank counter, this routine should be a no-op, since * interrupts will have to stay on to keep the count accurate. */ -void omap_irq_disable_vblank(struct drm_device *dev, unsigned int pipe) +void omap_irq_disable_vblank(struct drm_crtc *crtc) { + struct drm_device *dev = crtc->dev; struct omap_drm_private *priv = dev->dev_private; - struct drm_crtc *crtc = priv->crtcs[pipe]; unsigned long flags; + enum omap_channel channel = omap_crtc_channel(crtc); - DBG("dev=%p, crtc=%u", dev, pipe); + DBG("dev=%p, crtc=%u", dev, channel); spin_lock_irqsave(&priv->wait_lock, flags); - priv->irq_mask &= ~dispc_mgr_get_vsync_irq(omap_crtc_channel(crtc)); + priv->irq_mask &= ~priv->dispc_ops->mgr_get_vsync_irq(channel); omap_irq_update(dev); spin_unlock_irqrestore(&priv->wait_lock, flags); } @@ -198,9 +200,9 @@ static irqreturn_t omap_irq_handler(int irq, void *arg) unsigned int id; u32 irqstatus; - irqstatus = dispc_read_irqstatus(); - dispc_clear_irqstatus(irqstatus); - dispc_read_irqstatus(); /* flush posted write */ + irqstatus = priv->dispc_ops->read_irqstatus(); + priv->dispc_ops->clear_irqstatus(irqstatus); + priv->dispc_ops->read_irqstatus(); /* flush posted write */ VERB("irqs: %08x", irqstatus); @@ -208,12 +210,12 @@ static irqreturn_t omap_irq_handler(int irq, void *arg) struct drm_crtc *crtc = priv->crtcs[id]; enum omap_channel channel = omap_crtc_channel(crtc); - if (irqstatus & dispc_mgr_get_vsync_irq(channel)) { + if (irqstatus & priv->dispc_ops->mgr_get_vsync_irq(channel)) { drm_handle_vblank(dev, id); omap_crtc_vblank_irq(crtc); } - if (irqstatus & dispc_mgr_get_sync_lost_irq(channel)) + if (irqstatus & priv->dispc_ops->mgr_get_sync_lost_irq(channel)) omap_crtc_error_irq(crtc, irqstatus); } @@ -247,7 +249,7 @@ static const u32 omap_underflow_irqs[] = { int omap_drm_irq_install(struct drm_device *dev) { struct omap_drm_private *priv = dev->dev_private; - unsigned int num_mgrs = dss_feat_get_num_mgrs(); + unsigned int num_mgrs = priv->dispc_ops->get_num_mgrs(); unsigned int max_planes; unsigned int i; int ret; @@ -265,13 +267,13 @@ int omap_drm_irq_install(struct drm_device *dev) } for (i = 0; i < num_mgrs; ++i) - priv->irq_mask |= dispc_mgr_get_sync_lost_irq(i); + priv->irq_mask |= priv->dispc_ops->mgr_get_sync_lost_irq(i); - dispc_runtime_get(); - dispc_clear_irqstatus(0xffffffff); - dispc_runtime_put(); + priv->dispc_ops->runtime_get(); + priv->dispc_ops->clear_irqstatus(0xffffffff); + priv->dispc_ops->runtime_put(); - ret = dispc_request_irq(omap_irq_handler, dev); + ret = priv->dispc_ops->request_irq(omap_irq_handler, dev); if (ret < 0) return ret; @@ -282,25 +284,12 @@ int omap_drm_irq_install(struct drm_device *dev) void omap_drm_irq_uninstall(struct drm_device *dev) { - unsigned long irqflags; - int i; + struct omap_drm_private *priv = dev->dev_private; if (!dev->irq_enabled) return; dev->irq_enabled = false; - /* Wake up any waiters so they don't hang. */ - if (dev->num_crtcs) { - spin_lock_irqsave(&dev->vbl_lock, irqflags); - for (i = 0; i < dev->num_crtcs; i++) { - wake_up(&dev->vblank[i].queue); - dev->vblank[i].enabled = false; - dev->vblank[i].last = - dev->driver->get_vblank_counter(dev, i); - } - spin_unlock_irqrestore(&dev->vbl_lock, irqflags); - } - - dispc_free_irq(dev); + priv->dispc_ops->free_irq(dev); } diff --git a/drivers/gpu/drm/omapdrm/omap_plane.c b/drivers/gpu/drm/omapdrm/omap_plane.c index 386d90af70f7..9168154d749e 100644 --- a/drivers/gpu/drm/omapdrm/omap_plane.c +++ b/drivers/gpu/drm/omapdrm/omap_plane.c @@ -24,12 +24,6 @@ #include "omap_dmm_tiler.h" #include "omap_drv.h" -/* some hackery because omapdss has an 'enum omap_plane' (which would be - * better named omap_plane_id).. and compiler seems unhappy about having - * both a 'struct omap_plane' and 'enum omap_plane' - */ -#define omap_plane _omap_plane - /* * plane funcs */ @@ -38,7 +32,7 @@ struct omap_plane { struct drm_plane base; - int id; /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */ + enum omap_plane_id id; const char *name; uint32_t nformats; @@ -76,6 +70,7 @@ static void omap_plane_cleanup_fb(struct drm_plane *plane, static void omap_plane_atomic_update(struct drm_plane *plane, struct drm_plane_state *old_state) { + struct omap_drm_private *priv = plane->dev->dev_private; struct omap_plane *omap_plane = to_omap_plane(plane); struct drm_plane_state *state = plane->state; struct omap_plane_state *omap_state = to_omap_plane_state(state); @@ -123,25 +118,26 @@ static void omap_plane_atomic_update(struct drm_plane *plane, DBG("%d,%d %pad %pad", info.pos_x, info.pos_y, &info.paddr, &info.p_uv_addr); - dispc_ovl_set_channel_out(omap_plane->id, + priv->dispc_ops->ovl_set_channel_out(omap_plane->id, omap_crtc_channel(state->crtc)); /* and finally, update omapdss: */ - ret = dispc_ovl_setup(omap_plane->id, &info, false, + ret = priv->dispc_ops->ovl_setup(omap_plane->id, &info, omap_crtc_timings(state->crtc), false); if (ret) { dev_err(plane->dev->dev, "Failed to setup plane %s\n", omap_plane->name); - dispc_ovl_enable(omap_plane->id, false); + priv->dispc_ops->ovl_enable(omap_plane->id, false); return; } - dispc_ovl_enable(omap_plane->id, true); + priv->dispc_ops->ovl_enable(omap_plane->id, true); } static void omap_plane_atomic_disable(struct drm_plane *plane, struct drm_plane_state *old_state) { + struct omap_drm_private *priv = plane->dev->dev_private; struct omap_plane_state *omap_state = to_omap_plane_state(plane->state); struct omap_plane *omap_plane = to_omap_plane(plane); @@ -149,7 +145,7 @@ static void omap_plane_atomic_disable(struct drm_plane *plane, omap_state->zorder = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : omap_plane->id; - dispc_ovl_enable(omap_plane->id, false); + priv->dispc_ops->ovl_enable(omap_plane->id, false); } static int omap_plane_atomic_check(struct drm_plane *plane, @@ -328,23 +324,37 @@ static const struct drm_plane_funcs omap_plane_funcs = { .atomic_get_property = omap_plane_atomic_get_property, }; -static const char *plane_names[] = { +static const char *plane_id_to_name[] = { [OMAP_DSS_GFX] = "gfx", [OMAP_DSS_VIDEO1] = "vid1", [OMAP_DSS_VIDEO2] = "vid2", [OMAP_DSS_VIDEO3] = "vid3", }; +static const enum omap_plane_id plane_idx_to_id[] = { + OMAP_DSS_GFX, + OMAP_DSS_VIDEO1, + OMAP_DSS_VIDEO2, + OMAP_DSS_VIDEO3, +}; + /* initialize plane */ struct drm_plane *omap_plane_init(struct drm_device *dev, - int id, enum drm_plane_type type, + int idx, enum drm_plane_type type, u32 possible_crtcs) { + struct omap_drm_private *priv = dev->dev_private; struct drm_plane *plane; struct omap_plane *omap_plane; + enum omap_plane_id id; int ret; - DBG("%s: type=%d", plane_names[id], type); + if (WARN_ON(idx >= ARRAY_SIZE(plane_idx_to_id))) + return ERR_PTR(-EINVAL); + + id = plane_idx_to_id[idx]; + + DBG("%s: type=%d", plane_id_to_name[id], type); omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL); if (!omap_plane) @@ -352,9 +362,9 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, omap_plane->nformats = omap_framebuffer_get_formats( omap_plane->formats, ARRAY_SIZE(omap_plane->formats), - dss_feat_get_supported_color_modes(id)); + priv->dispc_ops->ovl_get_color_modes(id)); omap_plane->id = id; - omap_plane->name = plane_names[id]; + omap_plane->name = plane_id_to_name[id]; plane = &omap_plane->base; @@ -371,6 +381,9 @@ struct drm_plane *omap_plane_init(struct drm_device *dev, return plane; error: + dev_err(dev->dev, "%s(): could not create plane: %s\n", + __func__, plane_id_to_name[id]); + kfree(omap_plane); return NULL; } |