aboutsummaryrefslogtreecommitdiff
path: root/drivers/gpu/drm/atmel-hlcdc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/atmel-hlcdc')
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c33
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c43
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h8
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c73
4 files changed, 43 insertions, 114 deletions
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
index 6b50fb706c0e..53bfa56ca47a 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_crtc.c
@@ -55,14 +55,12 @@ drm_crtc_state_to_atmel_hlcdc_crtc_state(struct drm_crtc_state *state)
* @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device
* @event: pointer to the current page flip event
* @id: CRTC id (returned by drm_crtc_index)
- * @enabled: CRTC state
*/
struct atmel_hlcdc_crtc {
struct drm_crtc base;
struct atmel_hlcdc_dc *dc;
struct drm_pending_vblank_event *event;
int id;
- bool enabled;
};
static inline struct atmel_hlcdc_crtc *
@@ -158,9 +156,6 @@ static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
struct regmap *regmap = crtc->dc->hlcdc->regmap;
unsigned int status;
- if (!crtc->enabled)
- return;
-
drm_crtc_vblank_off(c);
pm_runtime_get_sync(dev->dev);
@@ -186,8 +181,6 @@ static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
pm_runtime_allow(dev->dev);
pm_runtime_put_sync(dev->dev);
-
- crtc->enabled = false;
}
static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
@@ -197,9 +190,6 @@ static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
struct regmap *regmap = crtc->dc->hlcdc->regmap;
unsigned int status;
- if (crtc->enabled)
- return;
-
pm_runtime_get_sync(dev->dev);
pm_runtime_forbid(dev->dev);
@@ -226,29 +216,6 @@ static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
pm_runtime_put_sync(dev->dev);
drm_crtc_vblank_on(c);
-
- crtc->enabled = true;
-}
-
-void atmel_hlcdc_crtc_suspend(struct drm_crtc *c)
-{
- struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
-
- if (crtc->enabled) {
- atmel_hlcdc_crtc_disable(c);
- /* save enable state for resume */
- crtc->enabled = true;
- }
-}
-
-void atmel_hlcdc_crtc_resume(struct drm_crtc *c)
-{
- struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
-
- if (crtc->enabled) {
- crtc->enabled = false;
- atmel_hlcdc_crtc_enable(c);
- }
}
#define ATMEL_HLCDC_RGB444_OUTPUT BIT(0)
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 970bd87d7cce..f4a3065f7f51 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -724,17 +724,7 @@ static void atmel_hlcdc_dc_irq_uninstall(struct drm_device *dev)
regmap_read(dc->hlcdc->regmap, ATMEL_HLCDC_ISR, &isr);
}
-static const struct file_operations fops = {
- .owner = THIS_MODULE,
- .open = drm_open,
- .release = drm_release,
- .unlocked_ioctl = drm_ioctl,
- .compat_ioctl = drm_compat_ioctl,
- .poll = drm_poll,
- .read = drm_read,
- .llseek = no_llseek,
- .mmap = drm_gem_cma_mmap,
-};
+DEFINE_DRM_GEM_CMA_FOPS(fops);
static struct drm_driver atmel_hlcdc_dc_driver = {
.driver_features = DRIVER_HAVE_IRQ | DRIVER_GEM |
@@ -810,31 +800,32 @@ static int atmel_hlcdc_dc_drm_remove(struct platform_device *pdev)
static int atmel_hlcdc_dc_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
- struct drm_crtc *crtc;
+ struct atmel_hlcdc_dc *dc = drm_dev->dev_private;
+ struct regmap *regmap = dc->hlcdc->regmap;
+ struct drm_atomic_state *state;
+
+ state = drm_atomic_helper_suspend(drm_dev);
+ if (IS_ERR(state))
+ return PTR_ERR(state);
- if (pm_runtime_suspended(dev))
- return 0;
+ dc->suspend.state = state;
+
+ regmap_read(regmap, ATMEL_HLCDC_IMR, &dc->suspend.imr);
+ regmap_write(regmap, ATMEL_HLCDC_IDR, dc->suspend.imr);
+ clk_disable_unprepare(dc->hlcdc->periph_clk);
- drm_modeset_lock_all(drm_dev);
- list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head)
- atmel_hlcdc_crtc_suspend(crtc);
- drm_modeset_unlock_all(drm_dev);
return 0;
}
static int atmel_hlcdc_dc_drm_resume(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
- struct drm_crtc *crtc;
+ struct atmel_hlcdc_dc *dc = drm_dev->dev_private;
- if (pm_runtime_suspended(dev))
- return 0;
+ clk_prepare_enable(dc->hlcdc->periph_clk);
+ regmap_write(dc->hlcdc->regmap, ATMEL_HLCDC_IER, dc->suspend.imr);
- drm_modeset_lock_all(drm_dev);
- list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head)
- atmel_hlcdc_crtc_resume(crtc);
- drm_modeset_unlock_all(drm_dev);
- return 0;
+ return drm_atomic_helper_resume(drm_dev, dc->suspend.state);
}
#endif
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
index da7f25a59be5..433641b6e23b 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.h
@@ -358,6 +358,7 @@ struct atmel_hlcdc_plane_properties {
* @planes: instantiated planes
* @layers: active HLCDC layers
* @wq: display controller workqueue
+ * @suspend: used to store the HLCDC state when entering suspend
* @commit: used for async commit handling
*/
struct atmel_hlcdc_dc {
@@ -369,6 +370,10 @@ struct atmel_hlcdc_dc {
struct atmel_hlcdc_layer *layers[ATMEL_HLCDC_MAX_LAYERS];
struct workqueue_struct *wq;
struct {
+ u32 imr;
+ struct drm_atomic_state *state;
+ } suspend;
+ struct {
wait_queue_head_t wait;
bool pending;
} commit;
@@ -428,9 +433,6 @@ int atmel_hlcdc_plane_prepare_ahb_routing(struct drm_crtc_state *c_state);
void atmel_hlcdc_crtc_irq(struct drm_crtc *c);
-void atmel_hlcdc_crtc_suspend(struct drm_crtc *crtc);
-void atmel_hlcdc_crtc_resume(struct drm_crtc *crtc);
-
int atmel_hlcdc_crtc_create(struct drm_device *dev);
int atmel_hlcdc_create_outputs(struct drm_device *dev);
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
index e7799b6ee829..f987b4572d4a 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_output.c
@@ -22,7 +22,7 @@
#include <linux/of_graph.h>
#include <drm/drmP.h>
-#include <drm/drm_panel.h>
+#include <drm/drm_of.h>
#include "atmel_hlcdc_dc.h"
@@ -152,29 +152,11 @@ static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
-static int atmel_hlcdc_check_endpoint(struct drm_device *dev,
- const struct of_endpoint *ep)
-{
- struct device_node *np;
- void *obj;
-
- np = of_graph_get_remote_port_parent(ep->local_node);
-
- obj = of_drm_find_panel(np);
- if (!obj)
- obj = of_drm_find_bridge(np);
-
- of_node_put(np);
-
- return obj ? 0 : -EPROBE_DEFER;
-}
-
static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
- const struct of_endpoint *ep)
+ const struct device_node *np)
{
struct atmel_hlcdc_dc *dc = dev->dev_private;
struct atmel_hlcdc_rgb_output *output;
- struct device_node *np;
struct drm_panel *panel;
struct drm_bridge *bridge;
int ret;
@@ -195,13 +177,11 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
output->encoder.possible_crtcs = 0x1;
- np = of_graph_get_remote_port_parent(ep->local_node);
-
- ret = -EPROBE_DEFER;
+ ret = drm_of_find_panel_or_bridge(np, 0, 0, &panel, &bridge);
+ if (ret)
+ return ret;
- panel = of_drm_find_panel(np);
if (panel) {
- of_node_put(np);
output->connector.dpms = DRM_MODE_DPMS_OFF;
output->connector.polled = DRM_CONNECTOR_POLL_CONNECT;
drm_connector_helper_add(&output->connector,
@@ -226,9 +206,6 @@ static int atmel_hlcdc_attach_endpoint(struct drm_device *dev,
return 0;
}
- bridge = of_drm_find_bridge(np);
- of_node_put(np);
-
if (bridge) {
ret = drm_bridge_attach(&output->encoder, bridge, NULL);
if (!ret)
@@ -243,31 +220,23 @@ err_encoder_cleanup:
int atmel_hlcdc_create_outputs(struct drm_device *dev)
{
- struct device_node *ep_np = NULL;
- struct of_endpoint ep;
- int ret;
-
- for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
- ret = of_graph_parse_endpoint(ep_np, &ep);
- if (!ret)
- ret = atmel_hlcdc_check_endpoint(dev, &ep);
-
- if (ret) {
- of_node_put(ep_np);
- return ret;
- }
- }
-
- for_each_endpoint_of_node(dev->dev->of_node, ep_np) {
- ret = of_graph_parse_endpoint(ep_np, &ep);
- if (!ret)
- ret = atmel_hlcdc_attach_endpoint(dev, &ep);
-
- if (ret) {
- of_node_put(ep_np);
+ struct device_node *remote;
+ int ret, endpoint = 0;
+
+ while (true) {
+ /* Loop thru possible multiple connections to the output */
+ remote = of_graph_get_remote_node(dev->dev->of_node, 0,
+ endpoint++);
+ if (!remote)
+ break;
+
+ ret = atmel_hlcdc_attach_endpoint(dev, remote);
+ of_node_put(remote);
+ if (ret)
return ret;
- }
}
- return 0;
+ if (!endpoint)
+ return -ENODEV;
+ return ret;
}