Skip to content

Commit

Permalink
Merge branch 'drm-rockchip-next-2015-12-28' of https://github.com/mar…
Browse files Browse the repository at this point in the history
…kyzq/kernel-drm-rockchip into drm-next

These patches convert drm/rockchip to atomic API and add rk3036 vop support.

* 'drm-rockchip-next-2015-12-28' of https://github.com/markyzq/kernel-drm-rockchip:
  dt-bindings: add document for rk3036-vop
  drm/rockchip: vop: add rk3036 vop support
  drm/rockchip: vop: spilt scale regsters
  drm/rockchip: vop: spilt register related into rockchip_reg_vop.c
  drm/rockchip: vop: move interrupt registers into vop_data
  drm/rockchip: vop: merge vop cfg_done into vop_data
  drm/rockchip: dw_hdmi: use encoder enable function
  drm: bridge/dw_hdmi: add atomic API support
  drm/rockchip: direct config connecter gate and out_mode
  drm/rockchip: support atomic asynchronous commit
  drm/rockchip: Optimization vop mode set
  drm/rockchip: Convert to support atomic API
  drm/rockchip: vop: replace dpms with enable/disable
  drm/rockchip: Use new vblank api drm_crtc_vblank_*
  • Loading branch information
Dave Airlie committed Dec 29, 2015
2 parents 20f8e03 + d4d3c6c commit df83690
Show file tree
Hide file tree
Showing 11 changed files with 1,191 additions and 922 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ buffer to an external LCD interface.
Required properties:
- compatible: value should be one of the following
"rockchip,rk3288-vop";
"rockchip,rk3036-vop";

- interrupts: should contain a list of all VOP IP block interrupts in the
order: VSYNC, LCD_SYSTEM. The interrupt specifier
Expand Down
23 changes: 21 additions & 2 deletions drivers/gpu/drm/bridge/dw-hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

#include <drm/drm_of.h>
#include <drm/drmP.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_crtc_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_encoder_slave.h>
Expand Down Expand Up @@ -1522,6 +1523,17 @@ static const struct drm_connector_funcs dw_hdmi_connector_funcs = {
.force = dw_hdmi_connector_force,
};

static const struct drm_connector_funcs dw_hdmi_atomic_connector_funcs = {
.dpms = drm_atomic_helper_connector_dpms,
.fill_modes = drm_helper_probe_single_connector_modes,
.detect = dw_hdmi_connector_detect,
.destroy = dw_hdmi_connector_destroy,
.force = dw_hdmi_connector_force,
.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 const struct drm_connector_helper_funcs dw_hdmi_connector_helper_funcs = {
.get_modes = dw_hdmi_connector_get_modes,
.mode_valid = dw_hdmi_connector_mode_valid,
Expand Down Expand Up @@ -1645,8 +1657,15 @@ static int dw_hdmi_register(struct drm_device *drm, struct dw_hdmi *hdmi)

drm_connector_helper_add(&hdmi->connector,
&dw_hdmi_connector_helper_funcs);
drm_connector_init(drm, &hdmi->connector, &dw_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);

if (drm_core_check_feature(drm, DRIVER_ATOMIC))
drm_connector_init(drm, &hdmi->connector,
&dw_hdmi_atomic_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);
else
drm_connector_init(drm, &hdmi->connector,
&dw_hdmi_connector_funcs,
DRM_MODE_CONNECTOR_HDMIA);

hdmi->connector.encoder = encoder;

Expand Down
3 changes: 2 additions & 1 deletion drivers/gpu/drm/rockchip/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ rockchipdrm-y := rockchip_drm_drv.o rockchip_drm_fb.o rockchip_drm_fbdev.o \

obj-$(CONFIG_ROCKCHIP_DW_HDMI) += dw_hdmi-rockchip.o

obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o
obj-$(CONFIG_DRM_ROCKCHIP) += rockchipdrm.o rockchip_drm_vop.o \
rockchip_vop_reg.o
14 changes: 5 additions & 9 deletions drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
Original file line number Diff line number Diff line change
Expand Up @@ -195,12 +195,15 @@ static void dw_hdmi_rockchip_encoder_mode_set(struct drm_encoder *encoder,
{
}

static void dw_hdmi_rockchip_encoder_commit(struct drm_encoder *encoder)
static void dw_hdmi_rockchip_encoder_enable(struct drm_encoder *encoder)
{
struct rockchip_hdmi *hdmi = to_rockchip_hdmi(encoder);
u32 val;
int mux;

rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
ROCKCHIP_OUT_MODE_AAAA);

mux = rockchip_drm_encoder_get_mux_id(hdmi->dev->of_node, encoder);
if (mux)
val = HDMI_SEL_VOP_LIT | (HDMI_SEL_VOP_LIT << 16);
Expand All @@ -212,17 +215,10 @@ static void dw_hdmi_rockchip_encoder_commit(struct drm_encoder *encoder)
(mux) ? "LIT" : "BIG");
}

static void dw_hdmi_rockchip_encoder_prepare(struct drm_encoder *encoder)
{
rockchip_drm_crtc_mode_config(encoder->crtc, DRM_MODE_CONNECTOR_HDMIA,
ROCKCHIP_OUT_MODE_AAAA);
}

static const struct drm_encoder_helper_funcs dw_hdmi_rockchip_encoder_helper_funcs = {
.mode_fixup = dw_hdmi_rockchip_encoder_mode_fixup,
.mode_set = dw_hdmi_rockchip_encoder_mode_set,
.prepare = dw_hdmi_rockchip_encoder_prepare,
.commit = dw_hdmi_rockchip_encoder_commit,
.enable = dw_hdmi_rockchip_encoder_enable,
.disable = dw_hdmi_rockchip_encoder_disable,
};

Expand Down
21 changes: 14 additions & 7 deletions drivers/gpu/drm/rockchip/rockchip_drm_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
}
EXPORT_SYMBOL_GPL(rockchip_drm_dma_detach_device);

int rockchip_register_crtc_funcs(struct drm_device *dev,
const struct rockchip_crtc_funcs *crtc_funcs,
int pipe)
int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
const struct rockchip_crtc_funcs *crtc_funcs)
{
struct rockchip_drm_private *priv = dev->dev_private;
int pipe = drm_crtc_index(crtc);
struct rockchip_drm_private *priv = crtc->dev->dev_private;

if (pipe > ROCKCHIP_MAX_CRTC)
return -EINVAL;
Expand All @@ -79,9 +79,10 @@ int rockchip_register_crtc_funcs(struct drm_device *dev,
}
EXPORT_SYMBOL_GPL(rockchip_register_crtc_funcs);

void rockchip_unregister_crtc_funcs(struct drm_device *dev, int pipe)
void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc)
{
struct rockchip_drm_private *priv = dev->dev_private;
int pipe = drm_crtc_index(crtc);
struct rockchip_drm_private *priv = crtc->dev->dev_private;

if (pipe > ROCKCHIP_MAX_CRTC)
return;
Expand Down Expand Up @@ -139,6 +140,9 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
if (!private)
return -ENOMEM;

mutex_init(&private->commit.lock);
INIT_WORK(&private->commit.work, rockchip_drm_atomic_work);

drm_dev->dev_private = private;

drm_mode_config_init(drm_dev);
Expand Down Expand Up @@ -212,6 +216,8 @@ static int rockchip_drm_load(struct drm_device *drm_dev, unsigned long flags)
*/
drm_dev->vblank_disable_allowed = true;

drm_mode_config_reset(drm_dev);

ret = rockchip_drm_fbdev_init(drm_dev);
if (ret)
goto err_vblank_cleanup;
Expand Down Expand Up @@ -275,7 +281,8 @@ const struct vm_operations_struct rockchip_drm_vm_ops = {
};

static struct drm_driver rockchip_drm_driver = {
.driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_PRIME,
.driver_features = DRIVER_MODESET | DRIVER_GEM |
DRIVER_PRIME | DRIVER_ATOMIC,
.load = rockchip_drm_load,
.unload = rockchip_drm_unload,
.lastclose = rockchip_drm_lastclose,
Expand Down
20 changes: 15 additions & 5 deletions drivers/gpu/drm/rockchip/rockchip_drm_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define _ROCKCHIP_DRM_DRV_H

#include <drm/drm_fb_helper.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_gem.h>

#include <linux/module.h>
Expand All @@ -38,6 +39,14 @@ struct drm_connector;
struct rockchip_crtc_funcs {
int (*enable_vblank)(struct drm_crtc *crtc);
void (*disable_vblank)(struct drm_crtc *crtc);
void (*wait_for_update)(struct drm_crtc *crtc);
};

struct rockchip_atomic_commit {
struct work_struct work;
struct drm_atomic_state *state;
struct drm_device *dev;
struct mutex lock;
};

/*
Expand All @@ -50,12 +59,14 @@ struct rockchip_drm_private {
struct drm_fb_helper fbdev_helper;
struct drm_gem_object *fbdev_bo;
const struct rockchip_crtc_funcs *crtc_funcs[ROCKCHIP_MAX_CRTC];

struct rockchip_atomic_commit commit;
};

int rockchip_register_crtc_funcs(struct drm_device *dev,
const struct rockchip_crtc_funcs *crtc_funcs,
int pipe);
void rockchip_unregister_crtc_funcs(struct drm_device *dev, int pipe);
void rockchip_drm_atomic_work(struct work_struct *work);
int rockchip_register_crtc_funcs(struct drm_crtc *crtc,
const struct rockchip_crtc_funcs *crtc_funcs);
void rockchip_unregister_crtc_funcs(struct drm_crtc *crtc);
int rockchip_drm_encoder_get_mux_id(struct device_node *node,
struct drm_encoder *encoder);
int rockchip_drm_crtc_mode_config(struct drm_crtc *crtc, int connector_type,
Expand All @@ -64,5 +75,4 @@ int rockchip_drm_dma_attach_device(struct drm_device *drm_dev,
struct device *dev);
void rockchip_drm_dma_detach_device(struct drm_device *drm_dev,
struct device *dev);

#endif /* _ROCKCHIP_DRM_DRV_H_ */
123 changes: 123 additions & 0 deletions drivers/gpu/drm/rockchip/rockchip_drm_fb.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <drm/drm.h>
#include <drm/drmP.h>
#include <drm/drm_atomic.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>

Expand Down Expand Up @@ -166,9 +167,131 @@ static void rockchip_drm_output_poll_changed(struct drm_device *dev)
drm_fb_helper_hotplug_event(fb_helper);
}

static void rockchip_crtc_wait_for_update(struct drm_crtc *crtc)
{
struct rockchip_drm_private *priv = crtc->dev->dev_private;
int pipe = drm_crtc_index(crtc);
const struct rockchip_crtc_funcs *crtc_funcs = priv->crtc_funcs[pipe];

if (crtc_funcs && crtc_funcs->wait_for_update)
crtc_funcs->wait_for_update(crtc);
}

static void
rockchip_atomic_wait_for_complete(struct drm_atomic_state *old_state)
{
struct drm_crtc_state *old_crtc_state;
struct drm_crtc *crtc;
int i, ret;

for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
/* No one cares about the old state, so abuse it for tracking
* and store whether we hold a vblank reference (and should do a
* vblank wait) in the ->enable boolean.
*/
old_crtc_state->enable = false;

if (!crtc->state->active)
continue;

ret = drm_crtc_vblank_get(crtc);
if (ret != 0)
continue;

old_crtc_state->enable = true;
}

for_each_crtc_in_state(old_state, crtc, old_crtc_state, i) {
if (!old_crtc_state->enable)
continue;

rockchip_crtc_wait_for_update(crtc);
drm_crtc_vblank_put(crtc);
}
}

static void
rockchip_atomic_commit_complete(struct rockchip_atomic_commit *commit)
{
struct drm_atomic_state *state = commit->state;
struct drm_device *dev = commit->dev;

/*
* TODO: do fence wait here.
*/

/*
* Rockchip crtc support runtime PM, can't update display planes
* when crtc is disabled.
*
* drm_atomic_helper_commit comments detail that:
* For drivers supporting runtime PM the recommended sequence is
*
* drm_atomic_helper_commit_modeset_disables(dev, state);
*
* drm_atomic_helper_commit_modeset_enables(dev, state);
*
* drm_atomic_helper_commit_planes(dev, state, true);
*
* See the kerneldoc entries for these three functions for more details.
*/
drm_atomic_helper_commit_modeset_disables(dev, state);

drm_atomic_helper_commit_modeset_enables(dev, state);

drm_atomic_helper_commit_planes(dev, state, true);

rockchip_atomic_wait_for_complete(state);

drm_atomic_helper_cleanup_planes(dev, state);

drm_atomic_state_free(state);
}

void rockchip_drm_atomic_work(struct work_struct *work)
{
struct rockchip_atomic_commit *commit = container_of(work,
struct rockchip_atomic_commit, work);

rockchip_atomic_commit_complete(commit);
}

int rockchip_drm_atomic_commit(struct drm_device *dev,
struct drm_atomic_state *state,
bool async)
{
struct rockchip_drm_private *private = dev->dev_private;
struct rockchip_atomic_commit *commit = &private->commit;
int ret;

ret = drm_atomic_helper_prepare_planes(dev, state);
if (ret)
return ret;

/* serialize outstanding asynchronous commits */
mutex_lock(&commit->lock);
flush_work(&commit->work);

drm_atomic_helper_swap_state(dev, state);

commit->dev = dev;
commit->state = state;

if (async)
schedule_work(&commit->work);
else
rockchip_atomic_commit_complete(commit);

mutex_unlock(&commit->lock);

return 0;
}

static const struct drm_mode_config_funcs rockchip_drm_mode_config_funcs = {
.fb_create = rockchip_user_fb_create,
.output_poll_changed = rockchip_drm_output_poll_changed,
.atomic_check = drm_atomic_helper_check,
.atomic_commit = rockchip_drm_atomic_commit,
};

struct drm_framebuffer *
Expand Down
Loading

0 comments on commit df83690

Please sign in to comment.