+
+ ret = drm_atomic_helper_check_plane_state(new_plane_state, new_crtc_state,
+ DRM_PLANE_NO_SCALING,
+ DRM_PLANE_NO_SCALING,
+ false, true);
+ if (ret)
+ return ret;
+ else if (!new_plane_state->visible)
+ return 0;
+
+ if (plane->state)
+ fb = plane->state->fb;
+
+ if (!fb || (fb->format != new_fb->format))
+ new_crtc_state->mode_changed = true; /* update PLL settings */
+
+ new_mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+ new_mgag200_crtc_state->format = new_fb->format;
+
+ return 0;
+}
+
+static void mgag200_primary_plane_helper_atomic_update(struct drm_plane *plane,
+ struct drm_atomic_state *old_state)
+{
+ struct drm_device *dev = plane->dev;
+ struct mga_device *mdev = to_mga_device(dev);
+ struct drm_plane_state *plane_state = plane->state;
+ struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(old_state, plane);
+ struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
+ struct drm_framebuffer *fb = plane_state->fb;
+ struct drm_atomic_helper_damage_iter iter;
+ struct drm_rect damage;
+
+ if (!fb)
+ return;
+
+ drm_atomic_helper_damage_iter_init(&iter, old_plane_state, plane_state);
+ drm_atomic_for_each_plane_damage(&iter, &damage) {
+ mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage);
+ }
+
+ /* Always scanout image at VRAM offset 0 */
+ mgag200_set_startadd(mdev, (u32)0);
+ mgag200_set_offset(mdev, fb);
+}
+
+static void mgag200_primary_plane_helper_atomic_disable(struct drm_plane *plane,
+ struct drm_atomic_state *old_state)
+{ }
+
+static const struct drm_plane_helper_funcs mgag200_primary_plane_helper_funcs = {
+ DRM_GEM_SHADOW_PLANE_HELPER_FUNCS,
+ .atomic_check = mgag200_primary_plane_helper_atomic_check,
+ .atomic_update = mgag200_primary_plane_helper_atomic_update,
+ .atomic_disable = mgag200_primary_plane_helper_atomic_disable,
+};
+
+static const struct drm_plane_funcs mgag200_primary_plane_funcs = {
+ .update_plane = drm_atomic_helper_update_plane,
+ .disable_plane = drm_atomic_helper_disable_plane,
+ .destroy = drm_plane_cleanup,
+ DRM_GEM_SHADOW_PLANE_FUNCS,
+};
+
+/*
+ * CRTC
+ */
+
+static enum drm_mode_status mgag200_crtc_helper_mode_valid(struct drm_crtc *crtc,
+ const struct drm_display_mode *mode)
+{
+ struct mga_device *mdev = to_mga_device(crtc->dev);
const struct mgag200_device_info *info = mdev->info;
/*
@@ -659,26 +739,69 @@ mgag200_simple_display_pipe_mode_valid(struct drm_simple_display_pipe *pipe,
return MODE_OK;
}
-static void
-mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state,
- struct drm_plane_state *plane_state)
+static int mgag200_crtc_helper_atomic_check(struct drm_crtc *crtc,
+ struct drm_atomic_state *new_state)
{
- struct drm_crtc *crtc = &pipe->crtc;
struct drm_device *dev = crtc->dev;
struct mga_device *mdev = to_mga_device(dev);
+ struct drm_crtc_state *new_crtc_state = drm_atomic_get_new_crtc_state(new_state, crtc);
struct mgag200_pll *pixpll = &mdev->pixpll;
+ struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(new_crtc_state);
+ struct drm_property_blob *new_gamma_lut = new_crtc_state->gamma_lut;
+ int ret;
+
+ ret = drm_atomic_helper_check_crtc_state(new_crtc_state, false);
+ if (ret)
+ return ret;
+
+ if (!new_crtc_state->enable)
+ return 0;
+
+ if (new_crtc_state->mode_changed) {
+ ret = pixpll->funcs->compute(pixpll, new_crtc_state->mode.clock,
+ &mgag200_crtc_state->pixpllc);
+ if (ret)
+ return ret;
+ }
+
+ if (new_crtc_state->color_mgmt_changed && new_gamma_lut) {
+ if (new_gamma_lut->length != MGAG200_LUT_SIZE * sizeof(struct drm_color_lut)) {
+ drm_dbg(dev, "Wrong size for gamma_lut %zu\n", new_gamma_lut->length);
+ return -EINVAL;
+ }
+ }
+
+ return drm_atomic_add_affected_planes(new_state, crtc);
+}
+
+static void mgag200_crtc_helper_atomic_flush(struct drm_crtc *crtc,
+ struct drm_atomic_state *old_state)
+{
+ struct drm_crtc_state *crtc_state = crtc->state;
+ struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
+ struct drm_device *dev = crtc->dev;
+ struct mga_device *mdev = to_mga_device(dev);
+
+ if (crtc_state->enable && crtc_state->color_mgmt_changed) {
+ const struct drm_format_info *format = mgag200_crtc_state->format;
+
+ if (crtc_state->gamma_lut)
+ mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data);
+ else
+ mgag200_crtc_set_gamma_linear(mdev, format);
+ }
+}
+
+static void mgag200_crtc_helper_atomic_enable(struct drm_crtc *crtc,
+ struct drm_atomic_state *old_state)
+{
+ struct drm_device *dev = crtc->dev;
+ struct mga_device *mdev = to_mga_device(dev);
+ struct drm_crtc_state *crtc_state = crtc->state;
struct drm_display_mode *adjusted_mode = &crtc_state->adjusted_mode;
struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
- struct drm_framebuffer *fb = plane_state->fb;
const struct drm_format_info *format = mgag200_crtc_state->format;
- struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(plane_state);
- struct drm_rect fullscreen = {
- .x1 = 0,
- .x2 = fb->width,
- .y1 = 0,
- .y2 = fb->height,
- };
+ struct mgag200_pll *pixpll = &mdev->pixpll;
if (mdev->type == G200_WB || mdev->type == G200_EW3)
mgag200_g200wb_hold_bmc(mdev);
@@ -696,108 +819,50 @@ mgag200_simple_display_pipe_enable(struct drm_simple_display_pipe *pipe,
else if (mdev->type == G200_EV)
mgag200_g200ev_set_hiprilvl(mdev);
- if (mdev->type == G200_WB || mdev->type == G200_EW3)
- mgag200_g200wb_release_bmc(mdev);
-
- if (crtc_state->gamma_lut)
- mgag200_crtc_set_gamma(mdev, format, crtc_state->gamma_lut->data);
- else
- mgag200_crtc_set_gamma_linear(mdev, format);
-
mgag200_enable_display(mdev);
- mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &fullscreen);
-
- /* Always scanout image at VRAM offset 0 */
- mgag200_set_startadd(mdev, (u32)0);
- mgag200_set_offset(mdev, fb);
+ if (mdev->type == G200_WB || mdev->type == G200_EW3)
+ mgag200_g200wb_release_bmc(mdev);
}
-static void
-mgag200_simple_display_pipe_disable(struct drm_simple_display_pipe *pipe)
+static void mgag200_crtc_helper_atomic_disable(struct drm_crtc *crtc,
+ struct drm_atomic_state *old_state)
{
- struct drm_crtc *crtc = &pipe->crtc;
struct mga_device *mdev = to_mga_device(crtc->dev);
- mgag200_disable_display(mdev);
-}
-
-static int
-mgag200_simple_display_pipe_check(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *plane_state,
- struct drm_crtc_state *crtc_state)
-{
- struct drm_plane *plane = plane_state->plane;
- struct drm_device *dev = plane->dev;
- struct mga_device *mdev = to_mga_device(dev);
- struct mgag200_pll *pixpll = &mdev->pixpll;
- struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
- struct drm_framebuffer *new_fb = plane_state->fb;
- struct drm_framebuffer *fb = NULL;
- int ret;
-
- if (!new_fb)
- return 0;
-
- if (plane->state)
- fb = plane->state->fb;
-
- if (!fb || (fb->format != new_fb->format))
- crtc_state->mode_changed = true; /* update PLL settings */
-
- mgag200_crtc_state->format = new_fb->format;
+ if (mdev->type == G200_WB || mdev->type == G200_EW3)
+ mgag200_g200wb_hold_bmc(mdev);
- if (crtc_state->mode_changed) {
- ret = pixpll->funcs->compute(pixpll, crtc_state->mode.clock,
- &mgag200_crtc_state->pixpllc);
- if (ret)
- return ret;
- }
+ mgag200_disable_display(mdev);
- if (crtc_state->color_mgmt_changed && crtc_state->gamma_lut) {
- if (crtc_state->gamma_lut->length !=
- MGAG200_LUT_SIZE * sizeof(struct drm_color_lut)) {
- drm_err(dev, "Wrong size for gamma_lut %zu\n",
- crtc_state->gamma_lut->length);
- return -EINVAL;
- }
- }
- return 0;
+ if (mdev->type == G200_WB || mdev->type == G200_EW3)
+ mgag200_g200wb_release_bmc(mdev);
}
-static void
-mgag200_simple_display_pipe_update(struct drm_simple_display_pipe *pipe,
- struct drm_plane_state *old_state)
-{
- struct drm_plane *plane = &pipe->plane;
- struct drm_crtc *crtc = &pipe->crtc;
- struct drm_device *dev = plane->dev;
- struct mga_device *mdev = to_mga_device(dev);
- struct drm_plane_state *state = plane->state;
- struct drm_shadow_plane_state *shadow_plane_state = to_drm_shadow_plane_state(state);
- struct drm_framebuffer *fb = state->fb;
- struct drm_rect damage;
- struct drm_atomic_helper_damage_iter iter;
+static const struct drm_crtc_helper_funcs mgag200_crtc_helper_funcs = {
+ .mode_valid = mgag200_crtc_helper_mode_valid,
+ .atomic_check = mgag200_crtc_helper_atomic_check,
+ .atomic_flush = mgag200_crtc_helper_atomic_flush,
+ .atomic_enable = mgag200_crtc_helper_atomic_enable,
+ .atomic_disable = mgag200_crtc_helper_atomic_disable,
+};
- if (!fb)
- return;
+static void mgag200_crtc_reset(struct drm_crtc *crtc)
+{
+ struct mgag200_crtc_state *mgag200_crtc_state;
- if (crtc->state->color_mgmt_changed && crtc->state->gamma_lut)
- mgag200_crtc_set_gamma(mdev, fb->format, crtc->state->gamma_lut->data);
+ if (crtc->state)
+ crtc->funcs->atomic_destroy_state(crtc, crtc->state);
- drm_atomic_helper_damage_iter_init(&iter, old_state, state);
- drm_atomic_for_each_plane_damage(&iter, &damage) {
- mgag200_handle_damage(mdev, shadow_plane_state->data, fb, &damage);
- }
- /* Always scanout image at VRAM offset 0 */
- mgag200_set_startadd(mdev, (u32)0);
- mgag200_set_offset(mdev, fb);
+ mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL);
+ if (mgag200_crtc_state)
+ __drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base);
+ else
+ __drm_atomic_helper_crtc_reset(crtc, NULL);
}
-static struct drm_crtc_state *
-mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe *pipe)
+static struct drm_crtc_state *mgag200_crtc_atomic_duplicate_state(struct drm_crtc *crtc)
{
- struct drm_crtc *crtc = &pipe->crtc;
struct drm_crtc_state *crtc_state = crtc->state;
struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
struct mgag200_crtc_state *new_mgag200_crtc_state;
@@ -817,8 +882,8 @@ mgag200_simple_display_pipe_duplicate_crtc_state(struct drm_simple_display_pipe
return &new_mgag200_crtc_state->base;
}
-static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_display_pipe *pipe,
- struct drm_crtc_state *crtc_state)
+static void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc,
+ struct drm_crtc_state *crtc_state)
{
struct mgag200_crtc_state *mgag200_crtc_state = to_mgag200_crtc_state(crtc_state);
@@ -826,33 +891,21 @@ static void mgag200_simple_display_pipe_destroy_crtc_state(struct drm_simple_dis
kfree(mgag200_crtc_state);
}
-static void mgag200_simple_display_pipe_reset_crtc(struct drm_simple_display_pipe *pipe)
-{
- struct drm_crtc *crtc = &pipe->crtc;
- struct mgag200_crtc_state *mgag200_crtc_state;
-
- if (crtc->state) {
- mgag200_simple_display_pipe_destroy_crtc_state(pipe, crtc->state);
- crtc->state = NULL; /* must be set to NULL here */
- }
+static const struct drm_crtc_funcs mgag200_crtc_funcs = {
+ .reset = mgag200_crtc_reset,
+ .destroy = drm_crtc_cleanup,
+ .set_config = drm_atomic_helper_set_config,
+ .page_flip = drm_atomic_helper_page_flip,
+ .atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state,
+ .atomic_destroy_state = mgag200_crtc_atomic_destroy_state,
+};
- mgag200_crtc_state = kzalloc(sizeof(*mgag200_crtc_state), GFP_KERNEL);
- if (!mgag200_crtc_state)
- return;
- __drm_atomic_helper_crtc_reset(crtc, &mgag200_crtc_state->base);
-}
+/*
+ * Encoder
+ */
-static const struct drm_simple_display_pipe_funcs
-mgag200_simple_display_pipe_funcs = {
- .mode_valid = mgag200_simple_display_pipe_mode_valid,
- .enable = mgag200_simple_display_pipe_enable,
- .disable = mgag200_simple_display_pipe_disable,
- .check = mgag200_simple_display_pipe_check,
- .update = mgag200_simple_display_pipe_update,
- .reset_crtc = mgag200_simple_display_pipe_reset_crtc,
- .duplicate_crtc_state = mgag200_simple_display_pipe_duplicate_crtc_state,
- .destroy_crtc_state = mgag200_simple_display_pipe_destroy_crtc_state,
- DRM_GEM_SIMPLE_DISPLAY_PIPE_SHADOW_PLANE_FUNCS,
+static const struct drm_encoder_funcs mgag200_dac_encoder_funcs = {
+ .destroy = drm_encoder_cleanup,
};
/*
@@ -999,12 +1052,49 @@ static int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vra
static int mgag200_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
+ struct drm_plane *primary_plane = &mdev->primary_plane;
+ struct drm_crtc *crtc = &mdev->crtc;
+ struct drm_encoder *encoder = &mdev->encoder;
struct mga_i2c_chan *i2c = &mdev->i2c;
struct drm_connector *connector = &mdev->connector;
- struct drm_simple_display_pipe *pipe = &mdev->display_pipe;
- size_t format_count = ARRAY_SIZE(mgag200_simple_display_pipe_formats);
int ret;
+ ret = mgag200_pixpll_init(&mdev->pixpll, mdev);
+ if (ret)
+ return ret;
+
+ ret = drm_universal_plane_init(dev, primary_plane, 0,
+ &mgag200_primary_plane_funcs,
+ mgag200_primary_plane_formats,
+ ARRAY_SIZE(mgag200_primary_plane_formats),
+ mgag200_primary_plane_fmtmods,
+ DRM_PLANE_TYPE_PRIMARY, NULL);
+ if (ret) {
+ drm_err(dev, "drm_universal_plane_init() failed: %d\n", ret);
+ return ret;
+ }
+ drm_plane_helper_add(primary_plane, &mgag200_primary_plane_helper_funcs);
+ drm_plane_enable_fb_damage_clips(primary_plane);
+
+ ret = drm_crtc_init_with_planes(dev, crtc, primary_plane, NULL, &mgag200_crtc_funcs, NULL);
+ if (ret) {
+ drm_err(dev, "drm_crtc_init_with_planes() failed: %d\n", ret);
+ return ret;
+ }
+ drm_crtc_helper_add(crtc, &mgag200_crtc_helper_funcs);
+
+ /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
+ drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
+ drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
+
+ encoder->possible_crtcs = drm_crtc_mask(crtc);
+ ret = drm_encoder_init(dev, encoder, &mgag200_dac_encoder_funcs,
+ DRM_MODE_ENCODER_DAC, NULL);
+ if (ret) {
+ drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
+ return ret;
+ }
+
ret = mgag200_i2c_init(mdev, i2c);
if (ret) {
drm_err(dev, "failed to add DDC bus: %d\n", ret);
@@ -1021,30 +1111,12 @@ static int mgag200_pipeline_init(struct mga_device *mdev)
}
drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
- ret = mgag200_pixpll_init(&mdev->pixpll, mdev);
- if (ret)
- return ret;
-
- ret = drm_simple_display_pipe_init(dev, pipe,
- &mgag200_simple_display_pipe_funcs,
- mgag200_simple_display_pipe_formats,
- format_count,
- mgag200_simple_display_pipe_fmtmods,
- connector);
+ ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
- drm_err(dev,
- "drm_simple_display_pipe_init() failed, error %d\n",
- ret);
+ drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
return ret;
}
- drm_plane_enable_fb_damage_clips(&pipe->plane);
-
- /* FIXME: legacy gamma tables, but atomic gamma doesn't work without */
- drm_mode_crtc_set_gamma_size(&pipe->crtc, MGAG200_LUT_SIZE);
-
- drm_crtc_enable_color_mgmt(&pipe->crtc, 0, false, MGAG200_LUT_SIZE);
-
return 0;
}