On Mon, Mar 13, 2017 at 05:10:28PM +0100, Maarten Lankhorst wrote: > As a proof of concept, first try to convert intel_tv, which is a rarely > used connector. It has 5 properties, tv format and 4 margins. > > I'm less certain about the state behavior itself, should we pass a size > parameter to intel_connector_alloc instead, so duplicate_state > can be done globally if it can be blindly copied? > > Can we also have a atomic_check function for connectors, so the > crtc_state->connectors_changed can be set there? It would be cleaner > and more atomic-like. > > To match the legacy behavior, format can be changed by probing just like > in legacy mode. > > Changes since v1: > - Add intel_encoder->swap_state to allow updating connector state. > - Add intel_tv->format for detect_mode and mode_valid, updated on atomic commit. > > Signed-off-by: Maarten Lankhorst <maarten.lankhorst@xxxxxxxxxxxxxxx> > --- > drivers/gpu/drm/i915/intel_display.c | 15 ++ > drivers/gpu/drm/i915/intel_drv.h | 4 + > drivers/gpu/drm/i915/intel_tv.c | 259 +++++++++++++++++++++-------------- > 3 files changed, 176 insertions(+), 102 deletions(-) > > diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c > index ac25c9bc8b81..18b7e7546ee1 100644 > --- a/drivers/gpu/drm/i915/intel_display.c > +++ b/drivers/gpu/drm/i915/intel_display.c <snip> > + > +static int > +intel_tv_atomic_get_property(struct drm_connector *connector, > + const struct drm_connector_state *state, > + struct drm_property *property, > + uint64_t *val) > +{ > + struct drm_device *dev = connector->dev; > + struct intel_tv_connector_state *tv_state = > + to_intel_tv_connector_state(state); > + > + if (property == dev->mode_config.tv_left_margin_property) > + *val = tv_state->margin[TV_MARGIN_LEFT]; > + else if (property == dev->mode_config.tv_right_margin_property) > + *val = tv_state->margin[TV_MARGIN_RIGHT]; > + else if (property == dev->mode_config.tv_top_margin_property) > + *val = tv_state->margin[TV_MARGIN_TOP]; > + else if (property == dev->mode_config.tv_bottom_margin_property) > + *val = tv_state->margin[TV_MARGIN_BOTTOM]; > + else if (property == dev->mode_config.tv_mode_property) { > + *val = tv_state->format; Actually, aren't all of these handled by drm_atomic_connector_set_property() already? And same deal with drm_atomic_connector_get_property() AFAICS. > } else { > - ret = -EINVAL; > - goto out; > + DRM_DEBUG_ATOMIC("Unknown atomic property %s\n", property->name); > + return -EINVAL; > } > > - if (changed && crtc) > - intel_crtc_restore_mode(crtc); > -out: > - return ret; > + return 0; > +} > + > +static struct drm_connector_state * > +intel_tv_duplicate_state(struct drm_connector *connector) > +{ > + struct intel_tv_connector_state *state; > + > + state = kmemdup(&connector->state, sizeof(*state), GFP_KERNEL); > + if (state) > + __drm_atomic_helper_connector_duplicate_state(connector, &state->base); > + > + return &state->base; > } > > static const struct drm_connector_funcs intel_tv_connector_funcs = { > @@ -1520,11 +1570,12 @@ static const struct drm_connector_funcs intel_tv_connector_funcs = { > .late_register = intel_connector_register, > .early_unregister = intel_connector_unregister, > .destroy = intel_tv_destroy, > - .set_property = intel_tv_set_property, > - .atomic_get_property = intel_connector_atomic_get_property, > + .set_property = drm_atomic_helper_connector_set_property, > + .atomic_set_property = intel_tv_atomic_set_property, > + .atomic_get_property = intel_tv_atomic_get_property, > .fill_modes = drm_helper_probe_single_connector_modes, > .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, > - .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, > + .atomic_duplicate_state = intel_tv_duplicate_state, > }; > > static const struct drm_connector_helper_funcs intel_tv_connector_helper_funcs = { > @@ -1547,6 +1598,7 @@ intel_tv_init(struct drm_i915_private *dev_priv) > u32 tv_dac_on, tv_dac_off, save_tv_dac; > const char *tv_format_names[ARRAY_SIZE(tv_modes)]; > int i, initial_mode = 0; > + struct intel_tv_connector_state *state; > > if ((I915_READ(TV_CTL) & TV_FUSE_STATE_MASK) == TV_FUSE_STATE_DISABLED) > return; > @@ -1580,16 +1632,17 @@ intel_tv_init(struct drm_i915_private *dev_priv) > return; > > intel_tv = kzalloc(sizeof(*intel_tv), GFP_KERNEL); > - if (!intel_tv) { > - return; > - } > - > - intel_connector = intel_connector_alloc(); > - if (!intel_connector) { > + intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); > + state = kzalloc(sizeof(*state), GFP_KERNEL); > + if (!intel_tv || !intel_connector || !state) { > + kfree(intel_connector); > + kfree(state); > kfree(intel_tv); > return; > } > > + __drm_atomic_helper_connector_reset(&intel_connector->base, &state->base); > + > intel_encoder = &intel_tv->base; > connector = &intel_connector->base; > > @@ -1617,6 +1670,7 @@ intel_tv_init(struct drm_i915_private *dev_priv) > intel_encoder->disable = intel_disable_tv; > intel_encoder->get_hw_state = intel_tv_get_hw_state; > intel_connector->get_hw_state = intel_connector_get_hw_state; > + intel_connector->swap_state = intel_tv_swap_state; > > intel_connector_attach_encoder(intel_connector, intel_encoder); > > @@ -1629,12 +1683,13 @@ intel_tv_init(struct drm_i915_private *dev_priv) > intel_tv->type = DRM_MODE_CONNECTOR_Unknown; > > /* BIOS margin values */ > - intel_tv->margin[TV_MARGIN_LEFT] = 54; > - intel_tv->margin[TV_MARGIN_TOP] = 36; > - intel_tv->margin[TV_MARGIN_RIGHT] = 46; > - intel_tv->margin[TV_MARGIN_BOTTOM] = 37; > + state->margin[TV_MARGIN_LEFT] = 54; > + state->margin[TV_MARGIN_TOP] = 36; > + state->margin[TV_MARGIN_RIGHT] = 46; > + state->margin[TV_MARGIN_BOTTOM] = 37; > > - intel_tv->tv_format = tv_modes[initial_mode].name; > + state->format = initial_mode; > + intel_tv->format = initial_mode; > > drm_connector_helper_add(connector, &intel_tv_connector_helper_funcs); > connector->interlace_allowed = false; > @@ -1648,17 +1703,17 @@ intel_tv_init(struct drm_i915_private *dev_priv) > tv_format_names); > > drm_object_attach_property(&connector->base, dev->mode_config.tv_mode_property, > - initial_mode); > + state->format); > drm_object_attach_property(&connector->base, > dev->mode_config.tv_left_margin_property, > - intel_tv->margin[TV_MARGIN_LEFT]); > + state->margin[TV_MARGIN_LEFT]); > drm_object_attach_property(&connector->base, > dev->mode_config.tv_top_margin_property, > - intel_tv->margin[TV_MARGIN_TOP]); > + state->margin[TV_MARGIN_TOP]); > drm_object_attach_property(&connector->base, > dev->mode_config.tv_right_margin_property, > - intel_tv->margin[TV_MARGIN_RIGHT]); > + state->margin[TV_MARGIN_RIGHT]); > drm_object_attach_property(&connector->base, > dev->mode_config.tv_bottom_margin_property, > - intel_tv->margin[TV_MARGIN_BOTTOM]); > + state->margin[TV_MARGIN_BOTTOM]); > } > -- > 2.7.4 > -- Ville Syrjälä Intel OTC _______________________________________________ Intel-gfx mailing list Intel-gfx@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/intel-gfx