提交 87dc8b6c 编写于 作者: D Dave Airlie

Merge branch 'drm-atmel-hlcdc-devel' of git://github.com/bbrezillon/linux-at91 into drm-next

This pull request includes:
- support for Atomic mode setting
- the discard area optimization
- implementation of PM primitives

* 'drm-atmel-hlcdc-devel' of git://github.com/bbrezillon/linux-at91:
  drm: atmel-hlcdc: Add pinctrl PM select sleep,default state in CRTC suspend/resume
  drm: atmel-hlcdc: Add PM suspend/resume support
  drm: atmel-hlcdc: add discard area support
  drm: atmel-hlcdc: Atomic mode-setting conversion
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/pm.h> #include <linux/pm.h>
#include <linux/pm_runtime.h> #include <linux/pm_runtime.h>
#include <linux/pinctrl/consumer.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
...@@ -37,14 +38,14 @@ ...@@ -37,14 +38,14 @@
* @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device * @hlcdc: pointer to the atmel_hlcdc structure provided by the MFD device
* @event: pointer to the current page flip event * @event: pointer to the current page flip event
* @id: CRTC id (returned by drm_crtc_index) * @id: CRTC id (returned by drm_crtc_index)
* @dpms: DPMS mode * @enabled: CRTC state
*/ */
struct atmel_hlcdc_crtc { struct atmel_hlcdc_crtc {
struct drm_crtc base; struct drm_crtc base;
struct atmel_hlcdc_dc *dc; struct atmel_hlcdc_dc *dc;
struct drm_pending_vblank_event *event; struct drm_pending_vblank_event *event;
int id; int id;
int dpms; bool enabled;
}; };
static inline struct atmel_hlcdc_crtc * static inline struct atmel_hlcdc_crtc *
...@@ -53,86 +54,17 @@ drm_crtc_to_atmel_hlcdc_crtc(struct drm_crtc *crtc) ...@@ -53,86 +54,17 @@ drm_crtc_to_atmel_hlcdc_crtc(struct drm_crtc *crtc)
return container_of(crtc, struct atmel_hlcdc_crtc, base); return container_of(crtc, struct atmel_hlcdc_crtc, base);
} }
static void atmel_hlcdc_crtc_dpms(struct drm_crtc *c, int mode) static void atmel_hlcdc_crtc_mode_set_nofb(struct drm_crtc *c)
{
struct drm_device *dev = c->dev;
struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
struct regmap *regmap = crtc->dc->hlcdc->regmap;
unsigned int status;
if (mode != DRM_MODE_DPMS_ON)
mode = DRM_MODE_DPMS_OFF;
if (crtc->dpms == mode)
return;
pm_runtime_get_sync(dev->dev);
if (mode != DRM_MODE_DPMS_ON) {
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
(status & ATMEL_HLCDC_DISP))
cpu_relax();
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
(status & ATMEL_HLCDC_SYNC))
cpu_relax();
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
(status & ATMEL_HLCDC_PIXEL_CLK))
cpu_relax();
clk_disable_unprepare(crtc->dc->hlcdc->sys_clk);
pm_runtime_allow(dev->dev);
} else {
pm_runtime_forbid(dev->dev);
clk_prepare_enable(crtc->dc->hlcdc->sys_clk);
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
!(status & ATMEL_HLCDC_PIXEL_CLK))
cpu_relax();
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
!(status & ATMEL_HLCDC_SYNC))
cpu_relax();
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
!(status & ATMEL_HLCDC_DISP))
cpu_relax();
}
pm_runtime_put_sync(dev->dev);
crtc->dpms = mode;
}
static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c,
struct drm_display_mode *mode,
struct drm_display_mode *adj,
int x, int y,
struct drm_framebuffer *old_fb)
{ {
struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c); struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
struct regmap *regmap = crtc->dc->hlcdc->regmap; struct regmap *regmap = crtc->dc->hlcdc->regmap;
struct drm_plane *plane = c->primary; struct drm_display_mode *adj = &c->state->adjusted_mode;
struct drm_framebuffer *fb;
unsigned long mode_rate; unsigned long mode_rate;
struct videomode vm; struct videomode vm;
unsigned long prate; unsigned long prate;
unsigned int cfg; unsigned int cfg;
int div; int div;
if (atmel_hlcdc_dc_mode_valid(crtc->dc, adj) != MODE_OK)
return -EINVAL;
vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay; vm.vfront_porch = adj->crtc_vsync_start - adj->crtc_vdisplay;
vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end; vm.vback_porch = adj->crtc_vtotal - adj->crtc_vsync_end;
vm.vsync_len = adj->crtc_vsync_end - adj->crtc_vsync_start; vm.vsync_len = adj->crtc_vsync_end - adj->crtc_vsync_start;
...@@ -156,7 +88,7 @@ static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c, ...@@ -156,7 +88,7 @@ static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c,
cfg = ATMEL_HLCDC_CLKPOL; cfg = ATMEL_HLCDC_CLKPOL;
prate = clk_get_rate(crtc->dc->hlcdc->sys_clk); prate = clk_get_rate(crtc->dc->hlcdc->sys_clk);
mode_rate = mode->crtc_clock * 1000; mode_rate = adj->crtc_clock * 1000;
if ((prate / 2) < mode_rate) { if ((prate / 2) < mode_rate) {
prate *= 2; prate *= 2;
cfg |= ATMEL_HLCDC_CLKSEL; cfg |= ATMEL_HLCDC_CLKSEL;
...@@ -174,10 +106,10 @@ static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c, ...@@ -174,10 +106,10 @@ static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c,
cfg = 0; cfg = 0;
if (mode->flags & DRM_MODE_FLAG_NVSYNC) if (adj->flags & DRM_MODE_FLAG_NVSYNC)
cfg |= ATMEL_HLCDC_VSPOL; cfg |= ATMEL_HLCDC_VSPOL;
if (mode->flags & DRM_MODE_FLAG_NHSYNC) if (adj->flags & DRM_MODE_FLAG_NHSYNC)
cfg |= ATMEL_HLCDC_HSPOL; cfg |= ATMEL_HLCDC_HSPOL;
regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5), regmap_update_bits(regmap, ATMEL_HLCDC_CFG(5),
...@@ -187,77 +119,134 @@ static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c, ...@@ -187,77 +119,134 @@ static int atmel_hlcdc_crtc_mode_set(struct drm_crtc *c,
ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO | ATMEL_HLCDC_VSPSU | ATMEL_HLCDC_VSPHO |
ATMEL_HLCDC_GUARDTIME_MASK, ATMEL_HLCDC_GUARDTIME_MASK,
cfg); cfg);
fb = plane->fb;
plane->fb = old_fb;
return atmel_hlcdc_plane_update_with_mode(plane, c, fb, 0, 0,
adj->hdisplay, adj->vdisplay,
x << 16, y << 16,
adj->hdisplay << 16,
adj->vdisplay << 16,
adj);
} }
int atmel_hlcdc_crtc_mode_set_base(struct drm_crtc *c, int x, int y, static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *crtc,
struct drm_framebuffer *old_fb) const struct drm_display_mode *mode,
struct drm_display_mode *adjusted_mode)
{ {
struct drm_plane *plane = c->primary; return true;
struct drm_framebuffer *fb = plane->fb;
struct drm_display_mode *mode = &c->hwmode;
plane->fb = old_fb;
return plane->funcs->update_plane(plane, c, fb,
0, 0,
mode->hdisplay,
mode->vdisplay,
x << 16, y << 16,
mode->hdisplay << 16,
mode->vdisplay << 16);
} }
static void atmel_hlcdc_crtc_prepare(struct drm_crtc *crtc) static void atmel_hlcdc_crtc_disable(struct drm_crtc *c)
{ {
atmel_hlcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); struct drm_device *dev = c->dev;
struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_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);
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_DISP);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
(status & ATMEL_HLCDC_DISP))
cpu_relax();
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_SYNC);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
(status & ATMEL_HLCDC_SYNC))
cpu_relax();
regmap_write(regmap, ATMEL_HLCDC_DIS, ATMEL_HLCDC_PIXEL_CLK);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
(status & ATMEL_HLCDC_PIXEL_CLK))
cpu_relax();
clk_disable_unprepare(crtc->dc->hlcdc->sys_clk);
pinctrl_pm_select_sleep_state(dev->dev);
pm_runtime_allow(dev->dev);
pm_runtime_put_sync(dev->dev);
crtc->enabled = false;
} }
static void atmel_hlcdc_crtc_commit(struct drm_crtc *crtc) static void atmel_hlcdc_crtc_enable(struct drm_crtc *c)
{ {
atmel_hlcdc_crtc_dpms(crtc, DRM_MODE_DPMS_ON); struct drm_device *dev = c->dev;
struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_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);
pinctrl_pm_select_default_state(dev->dev);
clk_prepare_enable(crtc->dc->hlcdc->sys_clk);
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_PIXEL_CLK);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
!(status & ATMEL_HLCDC_PIXEL_CLK))
cpu_relax();
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_SYNC);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
!(status & ATMEL_HLCDC_SYNC))
cpu_relax();
regmap_write(regmap, ATMEL_HLCDC_EN, ATMEL_HLCDC_DISP);
while (!regmap_read(regmap, ATMEL_HLCDC_SR, &status) &&
!(status & ATMEL_HLCDC_DISP))
cpu_relax();
pm_runtime_put_sync(dev->dev);
drm_crtc_vblank_on(c);
crtc->enabled = true;
} }
static bool atmel_hlcdc_crtc_mode_fixup(struct drm_crtc *crtc, static int atmel_hlcdc_crtc_atomic_check(struct drm_crtc *c,
const struct drm_display_mode *mode, struct drm_crtc_state *s)
struct drm_display_mode *adjusted_mode)
{ {
return true; struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
if (atmel_hlcdc_dc_mode_valid(crtc->dc, &s->adjusted_mode) != MODE_OK)
return -EINVAL;
return atmel_hlcdc_plane_prepare_disc_area(s);
} }
static void atmel_hlcdc_crtc_disable(struct drm_crtc *crtc) static void atmel_hlcdc_crtc_atomic_begin(struct drm_crtc *c)
{ {
struct drm_plane *plane; struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
atmel_hlcdc_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); if (c->state->event) {
crtc->primary->funcs->disable_plane(crtc->primary); c->state->event->pipe = drm_crtc_index(c);
drm_for_each_legacy_plane(plane, &crtc->dev->mode_config.plane_list) { WARN_ON(drm_crtc_vblank_get(c) != 0);
if (plane->crtc != crtc)
continue;
plane->funcs->disable_plane(crtc->primary); crtc->event = c->state->event;
plane->crtc = NULL; c->state->event = NULL;
} }
} }
static void atmel_hlcdc_crtc_atomic_flush(struct drm_crtc *crtc)
{
/* TODO: write common plane control register if available */
}
static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = { static const struct drm_crtc_helper_funcs lcdc_crtc_helper_funcs = {
.mode_fixup = atmel_hlcdc_crtc_mode_fixup, .mode_fixup = atmel_hlcdc_crtc_mode_fixup,
.dpms = atmel_hlcdc_crtc_dpms, .mode_set = drm_helper_crtc_mode_set,
.mode_set = atmel_hlcdc_crtc_mode_set, .mode_set_nofb = atmel_hlcdc_crtc_mode_set_nofb,
.mode_set_base = atmel_hlcdc_crtc_mode_set_base, .mode_set_base = drm_helper_crtc_mode_set_base,
.prepare = atmel_hlcdc_crtc_prepare,
.commit = atmel_hlcdc_crtc_commit,
.disable = atmel_hlcdc_crtc_disable, .disable = atmel_hlcdc_crtc_disable,
.enable = atmel_hlcdc_crtc_enable,
.atomic_check = atmel_hlcdc_crtc_atomic_check,
.atomic_begin = atmel_hlcdc_crtc_atomic_begin,
.atomic_flush = atmel_hlcdc_crtc_atomic_flush,
}; };
static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c) static void atmel_hlcdc_crtc_destroy(struct drm_crtc *c)
...@@ -306,61 +295,13 @@ void atmel_hlcdc_crtc_irq(struct drm_crtc *c) ...@@ -306,61 +295,13 @@ void atmel_hlcdc_crtc_irq(struct drm_crtc *c)
atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c)); atmel_hlcdc_crtc_finish_page_flip(drm_crtc_to_atmel_hlcdc_crtc(c));
} }
static int atmel_hlcdc_crtc_page_flip(struct drm_crtc *c,
struct drm_framebuffer *fb,
struct drm_pending_vblank_event *event,
uint32_t page_flip_flags)
{
struct atmel_hlcdc_crtc *crtc = drm_crtc_to_atmel_hlcdc_crtc(c);
struct atmel_hlcdc_plane_update_req req;
struct drm_plane *plane = c->primary;
struct drm_device *dev = c->dev;
unsigned long flags;
int ret = 0;
spin_lock_irqsave(&dev->event_lock, flags);
if (crtc->event)
ret = -EBUSY;
spin_unlock_irqrestore(&dev->event_lock, flags);
if (ret)
return ret;
memset(&req, 0, sizeof(req));
req.crtc_x = 0;
req.crtc_y = 0;
req.crtc_h = c->mode.crtc_vdisplay;
req.crtc_w = c->mode.crtc_hdisplay;
req.src_x = c->x << 16;
req.src_y = c->y << 16;
req.src_w = req.crtc_w << 16;
req.src_h = req.crtc_h << 16;
req.fb = fb;
ret = atmel_hlcdc_plane_prepare_update_req(plane, &req, &c->hwmode);
if (ret)
return ret;
if (event) {
drm_vblank_get(c->dev, crtc->id);
spin_lock_irqsave(&dev->event_lock, flags);
crtc->event = event;
spin_unlock_irqrestore(&dev->event_lock, flags);
}
ret = atmel_hlcdc_plane_apply_update_req(plane, &req);
if (ret)
crtc->event = NULL;
else
plane->fb = fb;
return ret;
}
static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = { static const struct drm_crtc_funcs atmel_hlcdc_crtc_funcs = {
.page_flip = atmel_hlcdc_crtc_page_flip, .page_flip = drm_atomic_helper_page_flip,
.set_config = drm_crtc_helper_set_config, .set_config = drm_atomic_helper_set_config,
.destroy = atmel_hlcdc_crtc_destroy, .destroy = atmel_hlcdc_crtc_destroy,
.reset = drm_atomic_helper_crtc_reset,
.atomic_duplicate_state = drm_atomic_helper_crtc_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_crtc_destroy_state,
}; };
int atmel_hlcdc_crtc_create(struct drm_device *dev) int atmel_hlcdc_crtc_create(struct drm_device *dev)
...@@ -375,7 +316,6 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev) ...@@ -375,7 +316,6 @@ int atmel_hlcdc_crtc_create(struct drm_device *dev)
if (!crtc) if (!crtc)
return -ENOMEM; return -ENOMEM;
crtc->dpms = DRM_MODE_DPMS_OFF;
crtc->dc = dc; crtc->dc = dc;
ret = drm_crtc_init_with_planes(dev, &crtc->base, ret = drm_crtc_init_with_planes(dev, &crtc->base,
......
...@@ -222,6 +222,8 @@ static void atmel_hlcdc_fb_output_poll_changed(struct drm_device *dev) ...@@ -222,6 +222,8 @@ static void atmel_hlcdc_fb_output_poll_changed(struct drm_device *dev)
static const struct drm_mode_config_funcs mode_config_funcs = { static const struct drm_mode_config_funcs mode_config_funcs = {
.fb_create = atmel_hlcdc_fb_create, .fb_create = atmel_hlcdc_fb_create,
.output_poll_changed = atmel_hlcdc_fb_output_poll_changed, .output_poll_changed = atmel_hlcdc_fb_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = drm_atomic_helper_commit,
}; };
static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev) static int atmel_hlcdc_dc_modeset_init(struct drm_device *dev)
...@@ -319,6 +321,8 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev) ...@@ -319,6 +321,8 @@ static int atmel_hlcdc_dc_load(struct drm_device *dev)
goto err_periph_clk_disable; goto err_periph_clk_disable;
} }
drm_mode_config_reset(dev);
ret = drm_vblank_init(dev, 1); ret = drm_vblank_init(dev, 1);
if (ret < 0) { if (ret < 0) {
dev_err(dev->dev, "failed to initialize vblank\n"); dev_err(dev->dev, "failed to initialize vblank\n");
...@@ -557,6 +561,52 @@ static int atmel_hlcdc_dc_drm_remove(struct platform_device *pdev) ...@@ -557,6 +561,52 @@ static int atmel_hlcdc_dc_drm_remove(struct platform_device *pdev)
return 0; return 0;
} }
#ifdef CONFIG_PM
static int atmel_hlcdc_dc_drm_suspend(struct device *dev)
{
struct drm_device *drm_dev = dev_get_drvdata(dev);
struct drm_crtc *crtc;
if (pm_runtime_suspended(dev))
return 0;
drm_modeset_lock_all(drm_dev);
list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) {
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
if (crtc->enabled) {
crtc_funcs->disable(crtc);
/* save enable state for resume */
crtc->enabled = true;
}
}
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;
if (pm_runtime_suspended(dev))
return 0;
drm_modeset_lock_all(drm_dev);
list_for_each_entry(crtc, &drm_dev->mode_config.crtc_list, head) {
struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
if (crtc->enabled) {
crtc->enabled = false;
crtc_funcs->enable(crtc);
}
}
drm_modeset_unlock_all(drm_dev);
return 0;
}
#endif
static SIMPLE_DEV_PM_OPS(atmel_hlcdc_dc_drm_pm_ops,
atmel_hlcdc_dc_drm_suspend, atmel_hlcdc_dc_drm_resume);
static const struct of_device_id atmel_hlcdc_dc_of_match[] = { static const struct of_device_id atmel_hlcdc_dc_of_match[] = {
{ .compatible = "atmel,hlcdc-display-controller" }, { .compatible = "atmel,hlcdc-display-controller" },
{ }, { },
...@@ -567,6 +617,7 @@ static struct platform_driver atmel_hlcdc_dc_platform_driver = { ...@@ -567,6 +617,7 @@ static struct platform_driver atmel_hlcdc_dc_platform_driver = {
.remove = atmel_hlcdc_dc_drm_remove, .remove = atmel_hlcdc_dc_drm_remove,
.driver = { .driver = {
.name = "atmel-hlcdc-display-controller", .name = "atmel-hlcdc-display-controller",
.pm = &atmel_hlcdc_dc_drm_pm_ops,
.of_match_table = atmel_hlcdc_dc_of_match, .of_match_table = atmel_hlcdc_dc_of_match,
}, },
}; };
......
...@@ -26,11 +26,14 @@ ...@@ -26,11 +26,14 @@
#include <linux/irqdomain.h> #include <linux/irqdomain.h>
#include <linux/pwm.h> #include <linux/pwm.h>
#include <drm/drm_atomic.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc.h> #include <drm/drm_crtc.h>
#include <drm/drm_crtc_helper.h> #include <drm/drm_crtc_helper.h>
#include <drm/drm_fb_cma_helper.h> #include <drm/drm_fb_cma_helper.h>
#include <drm/drm_gem_cma_helper.h> #include <drm/drm_gem_cma_helper.h>
#include <drm/drm_panel.h> #include <drm/drm_panel.h>
#include <drm/drm_plane_helper.h>
#include <drm/drmP.h> #include <drm/drmP.h>
#include "atmel_hlcdc_layer.h" #include "atmel_hlcdc_layer.h"
...@@ -69,7 +72,6 @@ struct atmel_hlcdc_dc_desc { ...@@ -69,7 +72,6 @@ struct atmel_hlcdc_dc_desc {
*/ */
struct atmel_hlcdc_plane_properties { struct atmel_hlcdc_plane_properties {
struct drm_property *alpha; struct drm_property *alpha;
struct drm_property *rotation;
}; };
/** /**
...@@ -84,7 +86,6 @@ struct atmel_hlcdc_plane { ...@@ -84,7 +86,6 @@ struct atmel_hlcdc_plane {
struct drm_plane base; struct drm_plane base;
struct atmel_hlcdc_layer layer; struct atmel_hlcdc_layer layer;
struct atmel_hlcdc_plane_properties *properties; struct atmel_hlcdc_plane_properties *properties;
unsigned int rotation;
}; };
static inline struct atmel_hlcdc_plane * static inline struct atmel_hlcdc_plane *
...@@ -99,43 +100,6 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *l) ...@@ -99,43 +100,6 @@ atmel_hlcdc_layer_to_plane(struct atmel_hlcdc_layer *l)
return container_of(l, struct atmel_hlcdc_plane, layer); return container_of(l, struct atmel_hlcdc_plane, layer);
} }
/**
* Atmel HLCDC Plane update request structure.
*
* @crtc_x: x position of the plane relative to the CRTC
* @crtc_y: y position of the plane relative to the CRTC
* @crtc_w: visible width of the plane
* @crtc_h: visible height of the plane
* @src_x: x buffer position
* @src_y: y buffer position
* @src_w: buffer width
* @src_h: buffer height
* @fb: framebuffer object object
* @bpp: bytes per pixel deduced from pixel_format
* @offsets: offsets to apply to the GEM buffers
* @xstride: value to add to the pixel pointer between each line
* @pstride: value to add to the pixel pointer between each pixel
* @nplanes: number of planes (deduced from pixel_format)
*/
struct atmel_hlcdc_plane_update_req {
int crtc_x;
int crtc_y;
unsigned int crtc_w;
unsigned int crtc_h;
uint32_t src_x;
uint32_t src_y;
uint32_t src_w;
uint32_t src_h;
struct drm_framebuffer *fb;
/* These fields are private and should not be touched */
int bpp[ATMEL_HLCDC_MAX_PLANES];
unsigned int offsets[ATMEL_HLCDC_MAX_PLANES];
int xstride[ATMEL_HLCDC_MAX_PLANES];
int pstride[ATMEL_HLCDC_MAX_PLANES];
int nplanes;
};
/** /**
* Atmel HLCDC Planes. * Atmel HLCDC Planes.
* *
...@@ -184,22 +148,7 @@ int atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc, ...@@ -184,22 +148,7 @@ int atmel_hlcdc_dc_mode_valid(struct atmel_hlcdc_dc *dc,
struct atmel_hlcdc_planes * struct atmel_hlcdc_planes *
atmel_hlcdc_create_planes(struct drm_device *dev); atmel_hlcdc_create_planes(struct drm_device *dev);
int atmel_hlcdc_plane_prepare_update_req(struct drm_plane *p, int atmel_hlcdc_plane_prepare_disc_area(struct drm_crtc_state *c_state);
struct atmel_hlcdc_plane_update_req *req,
const struct drm_display_mode *mode);
int atmel_hlcdc_plane_apply_update_req(struct drm_plane *p,
struct atmel_hlcdc_plane_update_req *req);
int atmel_hlcdc_plane_update_with_mode(struct drm_plane *p,
struct drm_crtc *crtc,
struct drm_framebuffer *fb,
int crtc_x, int crtc_y,
unsigned int crtc_w,
unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h,
const struct drm_display_mode *mode);
void atmel_hlcdc_crtc_irq(struct drm_crtc *c); void atmel_hlcdc_crtc_irq(struct drm_crtc *c);
......
...@@ -298,7 +298,7 @@ void atmel_hlcdc_layer_irq(struct atmel_hlcdc_layer *layer) ...@@ -298,7 +298,7 @@ void atmel_hlcdc_layer_irq(struct atmel_hlcdc_layer *layer)
spin_unlock_irqrestore(&layer->lock, flags); spin_unlock_irqrestore(&layer->lock, flags);
} }
int atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer) void atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer)
{ {
struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma; struct atmel_hlcdc_layer_dma_channel *dma = &layer->dma;
struct atmel_hlcdc_layer_update *upd = &layer->update; struct atmel_hlcdc_layer_update *upd = &layer->update;
...@@ -340,8 +340,6 @@ int atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer) ...@@ -340,8 +340,6 @@ int atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer)
dma->status = ATMEL_HLCDC_LAYER_DISABLED; dma->status = ATMEL_HLCDC_LAYER_DISABLED;
spin_unlock_irqrestore(&layer->lock, flags); spin_unlock_irqrestore(&layer->lock, flags);
return 0;
} }
int atmel_hlcdc_layer_update_start(struct atmel_hlcdc_layer *layer) int atmel_hlcdc_layer_update_start(struct atmel_hlcdc_layer *layer)
......
...@@ -120,6 +120,7 @@ ...@@ -120,6 +120,7 @@
#define ATMEL_HLCDC_LAYER_DISCEN BIT(11) #define ATMEL_HLCDC_LAYER_DISCEN BIT(11)
#define ATMEL_HLCDC_LAYER_GA_SHIFT 16 #define ATMEL_HLCDC_LAYER_GA_SHIFT 16
#define ATMEL_HLCDC_LAYER_GA_MASK GENMASK(23, ATMEL_HLCDC_LAYER_GA_SHIFT) #define ATMEL_HLCDC_LAYER_GA_MASK GENMASK(23, ATMEL_HLCDC_LAYER_GA_SHIFT)
#define ATMEL_HLCDC_LAYER_GA(x) ((x) << ATMEL_HLCDC_LAYER_GA_SHIFT)
#define ATMEL_HLCDC_LAYER_CSC_CFG(p, o) ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.csc + o) #define ATMEL_HLCDC_LAYER_CSC_CFG(p, o) ATMEL_HLCDC_LAYER_CFG(p, (p)->desc->layout.csc + o)
...@@ -376,7 +377,7 @@ int atmel_hlcdc_layer_init(struct drm_device *dev, ...@@ -376,7 +377,7 @@ int atmel_hlcdc_layer_init(struct drm_device *dev,
void atmel_hlcdc_layer_cleanup(struct drm_device *dev, void atmel_hlcdc_layer_cleanup(struct drm_device *dev,
struct atmel_hlcdc_layer *layer); struct atmel_hlcdc_layer *layer);
int atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer); void atmel_hlcdc_layer_disable(struct atmel_hlcdc_layer *layer);
int atmel_hlcdc_layer_update_start(struct atmel_hlcdc_layer *layer); int atmel_hlcdc_layer_update_start(struct atmel_hlcdc_layer *layer);
......
...@@ -86,25 +86,22 @@ atmel_hlcdc_rgb_output_to_panel(struct atmel_hlcdc_rgb_output *output) ...@@ -86,25 +86,22 @@ atmel_hlcdc_rgb_output_to_panel(struct atmel_hlcdc_rgb_output *output)
return container_of(output, struct atmel_hlcdc_panel, base); return container_of(output, struct atmel_hlcdc_panel, base);
} }
static void atmel_hlcdc_panel_encoder_dpms(struct drm_encoder *encoder, static void atmel_hlcdc_panel_encoder_enable(struct drm_encoder *encoder)
int mode)
{ {
struct atmel_hlcdc_rgb_output *rgb = struct atmel_hlcdc_rgb_output *rgb =
drm_encoder_to_atmel_hlcdc_rgb_output(encoder); drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb); struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
if (mode != DRM_MODE_DPMS_ON) drm_panel_enable(panel->panel);
mode = DRM_MODE_DPMS_OFF; }
if (mode == rgb->dpms)
return;
if (mode != DRM_MODE_DPMS_ON) static void atmel_hlcdc_panel_encoder_disable(struct drm_encoder *encoder)
drm_panel_disable(panel->panel); {
else struct atmel_hlcdc_rgb_output *rgb =
drm_panel_enable(panel->panel); drm_encoder_to_atmel_hlcdc_rgb_output(encoder);
struct atmel_hlcdc_panel *panel = atmel_hlcdc_rgb_output_to_panel(rgb);
rgb->dpms = mode; drm_panel_disable(panel->panel);
} }
static bool static bool
...@@ -115,16 +112,6 @@ atmel_hlcdc_panel_encoder_mode_fixup(struct drm_encoder *encoder, ...@@ -115,16 +112,6 @@ atmel_hlcdc_panel_encoder_mode_fixup(struct drm_encoder *encoder,
return true; return true;
} }
static void atmel_hlcdc_panel_encoder_prepare(struct drm_encoder *encoder)
{
atmel_hlcdc_panel_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
}
static void atmel_hlcdc_panel_encoder_commit(struct drm_encoder *encoder)
{
atmel_hlcdc_panel_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
}
static void static void
atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder, atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder,
struct drm_display_mode *mode, struct drm_display_mode *mode,
...@@ -156,11 +143,10 @@ atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder, ...@@ -156,11 +143,10 @@ atmel_hlcdc_rgb_encoder_mode_set(struct drm_encoder *encoder,
} }
static struct drm_encoder_helper_funcs atmel_hlcdc_panel_encoder_helper_funcs = { static struct drm_encoder_helper_funcs atmel_hlcdc_panel_encoder_helper_funcs = {
.dpms = atmel_hlcdc_panel_encoder_dpms,
.mode_fixup = atmel_hlcdc_panel_encoder_mode_fixup, .mode_fixup = atmel_hlcdc_panel_encoder_mode_fixup,
.prepare = atmel_hlcdc_panel_encoder_prepare,
.commit = atmel_hlcdc_panel_encoder_commit,
.mode_set = atmel_hlcdc_rgb_encoder_mode_set, .mode_set = atmel_hlcdc_rgb_encoder_mode_set,
.disable = atmel_hlcdc_panel_encoder_disable,
.enable = atmel_hlcdc_panel_encoder_enable,
}; };
static void atmel_hlcdc_rgb_encoder_destroy(struct drm_encoder *encoder) static void atmel_hlcdc_rgb_encoder_destroy(struct drm_encoder *encoder)
...@@ -226,10 +212,13 @@ atmel_hlcdc_panel_connector_destroy(struct drm_connector *connector) ...@@ -226,10 +212,13 @@ atmel_hlcdc_panel_connector_destroy(struct drm_connector *connector)
} }
static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = { static const struct drm_connector_funcs atmel_hlcdc_panel_connector_funcs = {
.dpms = drm_helper_connector_dpms, .dpms = drm_atomic_helper_connector_dpms,
.detect = atmel_hlcdc_panel_connector_detect, .detect = atmel_hlcdc_panel_connector_detect,
.fill_modes = drm_helper_probe_single_connector_modes, .fill_modes = drm_helper_probe_single_connector_modes,
.destroy = atmel_hlcdc_panel_connector_destroy, .destroy = atmel_hlcdc_panel_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
}; };
static int atmel_hlcdc_create_panel_output(struct drm_device *dev, static int atmel_hlcdc_create_panel_output(struct drm_device *dev,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册