/* Initial gadget tv state if applicable, applied on state reset */ struct drm_tv_connector_state initial_tv_state;
/* * Initial gadget backlight brightness if applicable, applied on state reset. * The value -ENODEV is used to signal no backlight.
*/ int initial_brightness;
};
if (!drm_dev_enter(connector->dev, &idx)) return connector_status_disconnected;
if (force) {
ret = gud_usb_set(gdrm, GUD_REQ_SET_CONNECTOR_FORCE_DETECT,
connector->index, NULL, 0); if (ret) {
ret = connector_status_unknown; gotoexit;
}
}
ret = gud_usb_get_u8(gdrm, GUD_REQ_GET_CONNECTOR_STATUS, connector->index, &status); if (ret) {
ret = connector_status_unknown; gotoexit;
}
switch (status & GUD_CONNECTOR_STATUS_CONNECTED_MASK) { case GUD_CONNECTOR_STATUS_DISCONNECTED:
ret = connector_status_disconnected; break; case GUD_CONNECTOR_STATUS_CONNECTED:
ret = connector_status_connected; break; default:
ret = connector_status_unknown; break;
}
if (status & GUD_CONNECTOR_STATUS_CHANGED)
connector->epoch_counter += 1; exit:
drm_dev_exit(idx);
drm_atomic_helper_connector_reset(connector);
connector->state->tv = gconn->initial_tv_state; /* Set margins from command line */
drm_atomic_helper_connector_tv_margins_reset(connector); if (gconn->initial_brightness >= 0)
connector->state->tv.brightness = gconn->initial_brightness;
}
/* * The tv.mode property is shared among the connectors and its enum names are * driver specific. This means that if more than one connector uses tv.mode, * the enum names has to be the same.
*/ staticint gud_connector_add_tv_mode(struct gud_device *gdrm, struct drm_connector *connector)
{
size_t buf_len = GUD_CONNECTOR_TV_MODE_MAX_NUM * GUD_CONNECTOR_TV_MODE_NAME_LEN; constchar *modes[GUD_CONNECTOR_TV_MODE_MAX_NUM]; unsignedint i, num_modes; char *buf; int ret;
buf = kmalloc(buf_len, GFP_KERNEL); if (!buf) return -ENOMEM;
ret = gud_usb_get(gdrm, GUD_REQ_GET_CONNECTOR_TV_MODE_VALUES,
connector->index, buf, buf_len); if (ret < 0) goto free; if (!ret || ret % GUD_CONNECTOR_TV_MODE_NAME_LEN) {
ret = -EIO; goto free;
}
num_modes = ret / GUD_CONNECTOR_TV_MODE_NAME_LEN; for (i = 0; i < num_modes; i++)
modes[i] = &buf[i * GUD_CONNECTOR_TV_MODE_NAME_LEN];
ret = drm_mode_create_tv_properties_legacy(connector->dev, num_modes, modes);
free:
kfree(buf); if (ret < 0)
gud_conn_err(connector, "Failed to add TV modes", ret);
switch (prop) { case GUD_PROPERTY_TV_LEFT_MARGIN: return config->tv_left_margin_property; case GUD_PROPERTY_TV_RIGHT_MARGIN: return config->tv_right_margin_property; case GUD_PROPERTY_TV_TOP_MARGIN: return config->tv_top_margin_property; case GUD_PROPERTY_TV_BOTTOM_MARGIN: return config->tv_bottom_margin_property; case GUD_PROPERTY_TV_MODE: return config->legacy_tv_mode_property; case GUD_PROPERTY_TV_BRIGHTNESS: return config->tv_brightness_property; case GUD_PROPERTY_TV_CONTRAST: return config->tv_contrast_property; case GUD_PROPERTY_TV_FLICKER_REDUCTION: return config->tv_flicker_reduction_property; case GUD_PROPERTY_TV_OVERSCAN: return config->tv_overscan_property; case GUD_PROPERTY_TV_SATURATION: return config->tv_saturation_property; case GUD_PROPERTY_TV_HUE: return config->tv_hue_property; default: return ERR_PTR(-EINVAL);
}
}
staticunsignedint *gud_connector_tv_state_val(u16 prop, struct drm_tv_connector_state *state)
{ switch (prop) { case GUD_PROPERTY_TV_LEFT_MARGIN: return &state->margins.left; case GUD_PROPERTY_TV_RIGHT_MARGIN: return &state->margins.right; case GUD_PROPERTY_TV_TOP_MARGIN: return &state->margins.top; case GUD_PROPERTY_TV_BOTTOM_MARGIN: return &state->margins.bottom; case GUD_PROPERTY_TV_MODE: return &state->legacy_mode; case GUD_PROPERTY_TV_BRIGHTNESS: return &state->brightness; case GUD_PROPERTY_TV_CONTRAST: return &state->contrast; case GUD_PROPERTY_TV_FLICKER_REDUCTION: return &state->flicker_reduction; case GUD_PROPERTY_TV_OVERSCAN: return &state->overscan; case GUD_PROPERTY_TV_SATURATION: return &state->saturation; case GUD_PROPERTY_TV_HUE: return &state->hue; default: return ERR_PTR(-EINVAL);
}
}
switch (prop) { case GUD_PROPERTY_TV_LEFT_MARGIN:
fallthrough; case GUD_PROPERTY_TV_RIGHT_MARGIN:
fallthrough; case GUD_PROPERTY_TV_TOP_MARGIN:
fallthrough; case GUD_PROPERTY_TV_BOTTOM_MARGIN:
ret = drm_mode_create_tv_margin_properties(drm); if (ret) goto out; break; case GUD_PROPERTY_TV_MODE:
ret = gud_connector_add_tv_mode(gdrm, connector); if (ret) goto out; break; case GUD_PROPERTY_TV_BRIGHTNESS:
fallthrough; case GUD_PROPERTY_TV_CONTRAST:
fallthrough; case GUD_PROPERTY_TV_FLICKER_REDUCTION:
fallthrough; case GUD_PROPERTY_TV_OVERSCAN:
fallthrough; case GUD_PROPERTY_TV_SATURATION:
fallthrough; case GUD_PROPERTY_TV_HUE: /* This is a no-op if already added. */
ret = drm_mode_create_tv_properties_legacy(drm, 0, NULL); if (ret) goto out; break; case GUD_PROPERTY_BACKLIGHT_BRIGHTNESS: if (val > 100) {
ret = -EINVAL; goto out;
}
gconn->initial_brightness = val; break; default: /* New ones might show up in future devices, skip those we don't know. */
drm_dbg(drm, "Ignoring unknown property: %u\n", prop); continue;
}
switch (desc->connector_type) { case GUD_CONNECTOR_TYPE_PANEL:
connector_type = DRM_MODE_CONNECTOR_USB; break; case GUD_CONNECTOR_TYPE_VGA:
connector_type = DRM_MODE_CONNECTOR_VGA; break; case GUD_CONNECTOR_TYPE_DVI:
connector_type = DRM_MODE_CONNECTOR_DVID; break; case GUD_CONNECTOR_TYPE_COMPOSITE:
connector_type = DRM_MODE_CONNECTOR_Composite; break; case GUD_CONNECTOR_TYPE_SVIDEO:
connector_type = DRM_MODE_CONNECTOR_SVIDEO; break; case GUD_CONNECTOR_TYPE_COMPONENT:
connector_type = DRM_MODE_CONNECTOR_Component; break; case GUD_CONNECTOR_TYPE_DISPLAYPORT:
connector_type = DRM_MODE_CONNECTOR_DisplayPort; break; case GUD_CONNECTOR_TYPE_HDMI:
connector_type = DRM_MODE_CONNECTOR_HDMIA; break; default: /* future types */
connector_type = DRM_MODE_CONNECTOR_USB; break;
}
drm_connector_helper_add(connector, &gud_connector_helper_funcs);
ret = drm_connector_init(drm, connector, &gud_connector_funcs, connector_type); if (ret) {
kfree(connector); return ret;
}
if (WARN_ON(connector->index != index)) return -EINVAL;
if (flags & GUD_CONNECTOR_FLAGS_POLL_STATUS)
connector->polled = (DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT); if (flags & GUD_CONNECTOR_FLAGS_INTERLACE)
connector->interlace_allowed = true; if (flags & GUD_CONNECTOR_FLAGS_DOUBLESCAN)
connector->doublescan_allowed = true;
ret = gud_connector_add_properties(gdrm, gconn); if (ret) {
gud_conn_err(connector, "Failed to add properties", ret); return ret;
}
/* The first connector is attached to the existing simple pipe encoder */ if (!connector->index) {
encoder = &gdrm->pipe.encoder;
} else {
encoder = &gconn->encoder;
ret = drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_NONE); if (ret) return ret;
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.