diff options
author | Dave Airlie <airlied@redhat.com> | 2016-09-28 01:17:26 (GMT) |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2016-09-28 01:17:26 (GMT) |
commit | 662d5c957161802e2f26317bfe02108fdb215706 (patch) | |
tree | 36ff51fd391095f7d33adcedfeea779e68140e83 /drivers/gpu/drm/tilcdc | |
parent | f01ebbdb46a845a756db7c3cd4cf9718d6d4b715 (diff) | |
parent | 7b993855dfd5d87e07ac84285d3d9bb0c743dede (diff) | |
download | linux-662d5c957161802e2f26317bfe02108fdb215706.tar.xz |
Merge tag 'tilcdc-4.9-3.1' of https://github.com/jsarha/linux into drm-next
Second attempt for 3rd drm/tilcdc pull request for v4.9.
* tag 'tilcdc-4.9-3.1' of https://github.com/jsarha/linux:
drm/tilcdc: fix wrong error handling
drm/tilcdc: Return directly after a failed kfree_table_init() in tilcdc_convert_slave_node()
drm/tilcdc: Remove "default" from blue-and-red-wiring property binding
drm/tilcdc: Fix non static symbol warning
drm/tilcdc: mark symbols static where possible
drm/tilcdc: add missing header dependencies
drm/tilcdc: WARN if CRTC is touched without CRTC lock
drm/tilcdc: Take CRTC lock when calling tilcdc_crtc_disable()
drm/tilcdc: Remove unnecessary tilcdc_crtc_disable() from tilcdc_unload()
drm/tilcdc: Flush flip-work workqueue before drm_flip_work_cleanup()
drm/tilcdc: Clean up LCDC functional clock rate setting code
drm/tilcdc: Take crtc modeset lock while updating the crtc clock rate
Diffstat (limited to 'drivers/gpu/drm/tilcdc')
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 91 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_drv.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_panel.c | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c | 8 | ||||
-rw-r--r-- | drivers/gpu/drm/tilcdc/tilcdc_tfp410.c | 1 |
6 files changed, 73 insertions, 51 deletions
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c index cb9df10..52ebe8f 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c @@ -20,6 +20,7 @@ #include <drm/drm_crtc.h> #include <drm/drm_flip_work.h> #include <drm/drm_plane_helper.h> +#include <linux/workqueue.h> #include "tilcdc_drv.h" #include "tilcdc_regs.h" @@ -37,6 +38,8 @@ struct tilcdc_crtc { bool frame_done; spinlock_t irq_lock; + unsigned int lcd_fck_rate; + ktime_t last_vblank; struct drm_framebuffer *curr_fb; @@ -152,6 +155,8 @@ static void tilcdc_crtc_enable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + if (tilcdc_crtc->enabled) return; @@ -176,6 +181,8 @@ void tilcdc_crtc_disable(struct drm_crtc *crtc) struct drm_device *dev = crtc->dev; struct tilcdc_drm_private *priv = dev->dev_private; + WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + if (!tilcdc_crtc->enabled) return; @@ -227,8 +234,13 @@ static bool tilcdc_crtc_is_on(struct drm_crtc *crtc) static void tilcdc_crtc_destroy(struct drm_crtc *crtc) { struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + struct tilcdc_drm_private *priv = crtc->dev->dev_private; + drm_modeset_lock_crtc(crtc, NULL); tilcdc_crtc_disable(crtc); + drm_modeset_unlock_crtc(crtc); + + flush_workqueue(priv->wq); of_node_put(crtc->port); drm_crtc_cleanup(crtc); @@ -243,6 +255,8 @@ int tilcdc_crtc_update_fb(struct drm_crtc *crtc, struct drm_device *dev = crtc->dev; unsigned long flags; + WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + if (tilcdc_crtc->event) { dev_err(dev->dev, "already pending page flip!\n"); return -EBUSY; @@ -306,6 +320,37 @@ static bool tilcdc_crtc_mode_fixup(struct drm_crtc *crtc, return true; } +static void tilcdc_crtc_set_clk(struct drm_crtc *crtc) +{ + struct drm_device *dev = crtc->dev; + struct tilcdc_drm_private *priv = dev->dev_private; + struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + const unsigned clkdiv = 2; /* using a fixed divider of 2 */ + int ret; + + /* mode.clock is in KHz, set_rate wants parameter in Hz */ + ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv); + if (ret < 0) { + dev_err(dev->dev, "failed to set display clock rate to: %d\n", + crtc->mode.clock); + return; + } + + tilcdc_crtc->lcd_fck_rate = clk_get_rate(priv->clk); + + DBG("lcd_clk=%u, mode clock=%d, div=%u", + tilcdc_crtc->lcd_fck_rate, crtc->mode.clock, clkdiv); + + /* Configure the LCD clock divisor. */ + tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(clkdiv) | + LCDC_RASTER_MODE); + + if (priv->rev == 2) + tilcdc_set(dev, LCDC_CLK_ENABLE_REG, + LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | + LCDC_V2_CORE_CLK_EN); +} + static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) { struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); @@ -316,6 +361,8 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) struct drm_display_mode *mode = &crtc->state->adjusted_mode; struct drm_framebuffer *fb = crtc->primary->state->fb; + WARN_ON(!drm_modeset_is_locked(&crtc->mutex)); + if (WARN_ON(!info)) return; @@ -468,7 +515,7 @@ static void tilcdc_crtc_mode_set_nofb(struct drm_crtc *crtc) set_scanout(crtc, fb); - tilcdc_crtc_update_clk(crtc); + tilcdc_crtc_set_clk(crtc); crtc->hwmode = crtc->state->adjusted_mode; } @@ -637,41 +684,21 @@ void tilcdc_crtc_update_clk(struct drm_crtc *crtc) { struct drm_device *dev = crtc->dev; struct tilcdc_drm_private *priv = dev->dev_private; - unsigned long lcd_clk; - const unsigned clkdiv = 2; /* using a fixed divider of 2 */ - int ret; + struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); - pm_runtime_get_sync(dev->dev); + drm_modeset_lock_crtc(crtc, NULL); + if (tilcdc_crtc->lcd_fck_rate != clk_get_rate(priv->clk)) { + if (tilcdc_crtc_is_on(crtc)) { + pm_runtime_get_sync(dev->dev); + tilcdc_crtc_disable(crtc); - tilcdc_crtc_disable(crtc); + tilcdc_crtc_set_clk(crtc); - /* mode.clock is in KHz, set_rate wants parameter in Hz */ - ret = clk_set_rate(priv->clk, crtc->mode.clock * 1000 * clkdiv); - if (ret < 0) { - dev_err(dev->dev, "failed to set display clock rate to: %d\n", - crtc->mode.clock); - goto out; + tilcdc_crtc_enable(crtc); + pm_runtime_put_sync(dev->dev); + } } - - lcd_clk = clk_get_rate(priv->clk); - - DBG("lcd_clk=%lu, mode clock=%d, div=%u", - lcd_clk, crtc->mode.clock, clkdiv); - - /* Configure the LCD clock divisor. */ - tilcdc_write(dev, LCDC_CTRL_REG, LCDC_CLK_DIVISOR(clkdiv) | - LCDC_RASTER_MODE); - - if (priv->rev == 2) - tilcdc_set(dev, LCDC_CLK_ENABLE_REG, - LCDC_V2_DMA_CLK_EN | LCDC_V2_LIDD_CLK_EN | - LCDC_V2_CORE_CLK_EN); - - if (tilcdc_crtc_is_on(crtc)) - tilcdc_crtc_enable(crtc); - -out: - pm_runtime_put_sync(dev->dev); + drm_modeset_unlock_crtc(crtc); } #define SYNC_LOST_COUNT_LIMIT 50 diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c index f8892e9..a694977 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c @@ -75,8 +75,8 @@ static void tilcdc_fb_output_poll_changed(struct drm_device *dev) drm_fbdev_cma_hotplug_event(priv->fbdev); } -int tilcdc_atomic_check(struct drm_device *dev, - struct drm_atomic_state *state) +static int tilcdc_atomic_check(struct drm_device *dev, + struct drm_atomic_state *state) { int ret; @@ -184,12 +184,9 @@ static int cpufreq_transition(struct notifier_block *nb, { struct tilcdc_drm_private *priv = container_of(nb, struct tilcdc_drm_private, freq_transition); - if (val == CPUFREQ_POSTCHANGE) { - if (priv->lcd_fck_rate != clk_get_rate(priv->clk)) { - priv->lcd_fck_rate = clk_get_rate(priv->clk); - tilcdc_crtc_update_clk(priv->crtc); - } - } + + if (val == CPUFREQ_POSTCHANGE) + tilcdc_crtc_update_clk(priv->crtc); return 0; } @@ -203,8 +200,6 @@ static int tilcdc_unload(struct drm_device *dev) { struct tilcdc_drm_private *priv = dev->dev_private; - tilcdc_crtc_disable(priv->crtc); - tilcdc_remove_external_encoders(dev); drm_fbdev_cma_fini(priv->fbdev); @@ -283,7 +278,6 @@ static int tilcdc_load(struct drm_device *dev, unsigned long flags) } #ifdef CONFIG_CPU_FREQ - priv->lcd_fck_rate = clk_get_rate(priv->clk); priv->freq_transition.notifier_call = cpufreq_transition; ret = cpufreq_register_notifier(&priv->freq_transition, CPUFREQ_TRANSITION_NOTIFIER); @@ -418,13 +412,13 @@ fail_irq_uninstall: fail_vblank_cleanup: drm_vblank_cleanup(dev); -fail_mode_config_cleanup: - drm_mode_config_cleanup(dev); - fail_component_cleanup: if (priv->is_componentized) component_unbind_all(dev->dev, dev); +fail_mode_config_cleanup: + drm_mode_config_cleanup(dev); + fail_external_cleanup: tilcdc_remove_external_encoders(dev); diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h index a6e5e6d..9780c37 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h +++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h @@ -74,7 +74,6 @@ struct tilcdc_drm_private { #ifdef CONFIG_CPU_FREQ struct notifier_block freq_transition; - unsigned int lcd_fck_rate; #endif struct workqueue_struct *wq; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c index 7b36509..2134bb20 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c @@ -25,6 +25,7 @@ #include <drm/drm_atomic_helper.h> #include "tilcdc_drv.h" +#include "tilcdc_panel.h" struct panel_module { struct tilcdc_module base; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c index f9c79da..623a914 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave_compat.c @@ -139,7 +139,7 @@ static void __init tilcdc_node_disable(struct device_node *node) of_update_property(node, prop); } -struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) +static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) { const int size = __dtb_tilcdc_slave_compat_end - __dtb_tilcdc_slave_compat_begin; @@ -195,7 +195,7 @@ static const char * const tilcdc_slave_props[] __initconst = { NULL }; -void __init tilcdc_convert_slave_node(void) +static void __init tilcdc_convert_slave_node(void) { struct device_node *slave = NULL, *lcdc = NULL; struct device_node *i2c = NULL, *fragment = NULL; @@ -207,7 +207,7 @@ void __init tilcdc_convert_slave_node(void) int ret; if (kfree_table_init(&kft)) - goto out; + return; lcdc = of_find_matching_node(NULL, tilcdc_of_match); slave = of_find_matching_node(NULL, tilcdc_slave_of_match); @@ -261,7 +261,7 @@ out: of_node_put(fragment); } -int __init tilcdc_slave_compat_init(void) +static int __init tilcdc_slave_compat_init(void) { tilcdc_convert_slave_node(); return 0; diff --git a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c index c6a70da..458043a 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_tfp410.c @@ -23,6 +23,7 @@ #include <drm/drm_atomic_helper.h> #include "tilcdc_drv.h" +#include "tilcdc_tfp410.h" struct tfp410_module { struct tilcdc_module base; |