Structure des encodeurs, ponts et connecteurs DRM sur Rockchip RK3399

  1. Structure de l'encodeur

1.1 Structure drm_encoder

L'encodeur est représenté par la structure drm_encoder dans le noyau Linux. Il convertit les signaux vidéo du CRTC (Cathode Ray Tube Controller) en signaux numériques adaptés à différents types de connecteurs comme HDMI, DisplayPort ou LVDS.


struct drm_encoder {
    struct drm_device *dev;
    struct list_head head;
    struct drm_mode_object base;
    char *name;
    int encoder_type;
    unsigned index;
    uint32_t possible_crtcs;
    uint32_t possible_clones;
    struct drm_crtc *crtc;
    struct list_head bridge_chain;
    const struct drm_encoder_funcs *funcs;
    const struct drm_encoder_helper_funcs *helper_private;
};

1.2 Fonctions de contrôle

1.2.1 Structure drm_encoder_funcs

Cette structure définit les fonctions de contrôle de l'encodeur.


struct drm_encoder_funcs {
    void (*reset)(struct drm_encoder *encoder);
    void (*destroy)(struct drm_encoder *encoder);
    int (*late_register)(struct drm_encoder *encoder);
    void (*early_unregister)(struct drm_encoder *encoder);
};

1.2.2 Structure drm_encoder_helper_funcs

Cette structure fournit des fnoctions d'aide pour l'encodeur.


struct drm_encoder_helper_funcs {
    void (*dpms)(struct drm_encoder *encoder, int mode);
    enum drm_mode_status (*mode_valid)(struct drm_encoder *encoder, const struct drm_display_mode *mode);
    bool (*mode_fixup)(struct drm_encoder *encoder, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode);
    void (*prepare)(struct drm_encoder *encoder);
    void (*commit)(struct drm_encoder *encoder);
    void (*mode_set)(struct drm_encoder *encoder, struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode);
    void (*atomic_mode_set)(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state);
    void (*atomic_disable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
    void (*atomic_enable)(struct drm_encoder *encoder, struct drm_atomic_state *state);
    int (*atomic_check)(struct drm_encoder *encoder, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state);
};

  1. Structure du pont

2.1 Strcuture drm_bridge

Un pont est représenté par la structure drm_bridge. Il est généralement utilisé pour ajouter des chips de conversion supplémentaires après l'encodeur.


struct drm_bridge {
    struct drm_private_obj base;
    struct drm_device *dev;
    struct drm_encoder *encoder;
    struct list_head chain_node;
    struct device_node *of_node;
    struct list_head list;
    const struct drm_bridge_timings *timings;
    const struct drm_bridge_funcs *funcs;
    void *driver_private;
    enum drm_bridge_ops ops;
    int type;
    bool interlace_allowed;
    bool pre_enable_prev_first;
    struct i2c_adapter *ddc;
    struct mutex hpd_mutex;
    void (*hpd_cb)(void *data, enum drm_connector_status status);
    void *hpd_data;
};

2.2 Structure drm_bridge_funcs

Cette structure définit les fonctions de contrôle du pont.


struct drm_bridge_funcs {
    int (*attach)(struct drm_bridge *bridge, enum drm_bridge_attach_flags flags);
    void (*detach)(struct drm_bridge *bridge);
    enum drm_mode_status (*mode_valid)(struct drm_bridge *bridge, const struct drm_display_info *info, const struct drm_display_mode *mode);
    bool (*mode_fixup)(struct drm_bridge *bridge, const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode);
    void (*disable)(struct drm_bridge *bridge);
    void (*post_disable)(struct drm_bridge *bridge);
    void (*mode_set)(struct drm_bridge *bridge, const struct drm_display_mode *mode, const struct drm_display_mode *adjusted_mode);
    void (*pre_enable)(struct drm_bridge *bridge);
    void (*enable)(struct drm_bridge *bridge);
    void (*atomic_pre_enable)(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state);
    void (*atomic_enable)(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state);
    void (*atomic_disable)(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state);
    void (*atomic_post_disable)(struct drm_bridge *bridge, struct drm_bridge_state *old_bridge_state);
    struct drm_bridge_state *(*atomic_duplicate_state)(struct drm_bridge *bridge);
    void (*atomic_destroy_state)(struct drm_bridge *bridge, struct drm_bridge_state *state);
    u32 *(*atomic_get_output_bus_fmts)(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state, unsigned int *num_output_fmts);
    u32 *(*atomic_get_input_bus_fmts)(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state, u32 output_fmt, unsigned int *num_input_fmts);
    int (*atomic_check)(struct drm_bridge *bridge, struct drm_bridge_state *bridge_state, struct drm_crtc_state *crtc_state, struct drm_connector_state *conn_state);
    struct drm_bridge_state *(*atomic_reset)(struct drm_bridge *bridge);
    enum drm_connector_status (*detect)(struct drm_bridge *bridge);
    int (*get_modes)(struct drm_bridge *bridge, struct drm_connector *connector);
    struct edid *(*get_edid)(struct drm_bridge *bridge, struct drm_connector *connector);
    void (*hpd_notify)(struct drm_bridge *bridge, enum drm_connector_status status);
    void (*hpd_enable)(struct drm_bridge *bridge);
    void (*hpd_disable)(struct drm_bridge *bridge);
    void (*debugfs_init)(struct drm_bridge *bridge, struct dentry *root);
};

2.3 Fonction drm_bridge_attach

Cette fonction relie le pont à la chaîne de l'encodeur.


int drm_bridge_attach(struct drm_encoder *encoder, struct drm_bridge *bridge, struct drm_bridge *previous, enum drm_bridge_attach_flags flags) {
    int ret;

    if (!encoder || !bridge)
        return -EINVAL;

    if (previous && (!previous->dev || previous->encoder != encoder))
        return -EINVAL;

    if (bridge->dev)
        return -EBUSY;

    bridge->dev = encoder->dev;
    bridge->encoder = encoder;

    if (previous)
        list_add(&bridge->chain_node, &previous->chain_node);
    else
        list_add(&bridge->chain_node, &encoder->bridge_chain);

    if (bridge->funcs->attach) {
        ret = bridge->funcs->attach(bridge, flags);
        if (ret < 0)
            goto err_reset_bridge;
    }

    if (bridge->funcs->atomic_reset) {
        struct drm_bridge_state *state;

        state = bridge->funcs->atomic_reset(bridge);
        if (IS_ERR(state)) {
            ret = PTR_ERR(state);
            goto err_detach_bridge;
        }

        drm_atomic_private_obj_init(bridge->dev, &bridge->base, &state->base, &drm_bridge_priv_state_funcs);
    }

    return 0;

err_detach_bridge:
    if (bridge->funcs->detach)
        bridge->funcs->detach(bridge);

err_reset_bridge:
    bridge->dev = NULL;
    bridge->encoder = NULL;
    list_del(&bridge->chain_node);

    DRM_ERROR("Échec de l'attachement du pont à l'encodeur : %d\n", ret);

    return ret;
}

  1. Structure du connecteur

3.1 Structure drm_connector

Le connecteur est représenté par la structure drm_connector. Il transmet les signaux vidéo de l'encodeur à l'écran et établit la connexion.


struct drm_connector {
    struct drm_device *dev;
    struct device *kdev;
    struct device_attribute *attr;
    struct fwnode_handle *fwnode;
    struct list_head head;
    struct list_head global_connector_list_entry;
    struct drm_mode_object base;
    char *name;
    struct mutex mutex;
    unsigned index;
    int connector_type;
    int connector_type_id;
    bool interlace_allowed;
    bool doublescan_allowed;
    bool stereo_allowed;
    bool ycbcr_420_allowed;
    enum drm_connector_registration_state registration_state;
    struct list_head modes;
    enum drm_connector_status status;
    struct list_head probed_modes;
    struct drm_display_info display_info;
    const struct drm_connector_funcs *funcs;
    struct drm_property_blob *edid_blob_ptr;
    struct drm_object_properties properties;
    struct drm_property *scaling_mode_property;
    struct drm_property *vrr_capable_property;
    struct drm_property *colorspace_property;
    struct drm_property_blob *path_blob_ptr;
    struct drm_property *max_bpc_property;
    struct drm_privacy_screen *privacy_screen;
    struct notifier_block privacy_screen_notifier;
    struct drm_property *privacy_screen_sw_state_property;
    struct drm_property *privacy_screen_hw_state_property;
    uint8_t polled;
    int dpms;
    const struct drm_connector_helper_funcs *helper_private;
    struct drm_cmdline_mode cmdline_mode;
    enum drm_connector_force force;
    const struct drm_edid *edid_override;
    struct mutex edid_override_mutex;
    u64 epoch_counter;
    u32 possible_encoders;
    struct drm_encoder *encoder;
    uint8_t eld[MAX_ELD_BYTES];
    bool latency_present[2];
    int video_latency[2];
    int audio_latency[2];
    struct i2c_adapter *ddc;
    int null_edid_counter;
    unsigned bad_edid_counter;
    bool edid_corrupt;
    u8 real_edid_checksum;
    struct dentry *debugfs_entry;
    struct drm_connector_state *state;
    struct drm_property_blob *tile_blob_ptr;
    bool has_tile;
    struct drm_tile_group *tile_group;
    bool tile_is_single_monitor;
    uint8_t num_h_tile, num_v_tile;
    uint8_t tile_h_loc, tile_v_loc;
    uint16_t tile_h_size, tile_v_size;
    struct llist_node free_node;
    struct hdr_sink_metadata hdr_sink_metadata;
};

3.2 Fonctions de contrôle

3.2.1 Structure drm_connector_funcs

Cette structure définit les fonctions de contrôle du connecteur.


struct drm_connector_funcs {
    int (*dpms)(struct drm_connector *connector, int mode);
    void (*reset)(struct drm_connector *connector);
    enum drm_connector_status (*detect)(struct drm_connector *connector, bool force);
    void (*force)(struct drm_connector *connector);
    int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
    int (*set_property)(struct drm_connector *connector, struct drm_property *property, uint64_t val);
    int (*late_register)(struct drm_connector *connector);
    void (*early_unregister)(struct drm_connector *connector);
    void (*destroy)(struct drm_connector *connector);
    struct drm_connector_state *(*atomic_duplicate_state)(struct drm_connector *connector);
    void (*atomic_destroy_state)(struct drm_connector *connector, struct drm_connector_state *state);
    int (*atomic_set_property)(struct drm_connector *connector, struct drm_connector_state *state, struct drm_property *property, uint64_t val);
    int (*atomic_get_property)(struct drm_connector *connector, const struct drm_connector_state *state, struct drm_property *property, uint64_t *val);
    void (*atomic_print_state)(struct drm_printer *p, const struct drm_connector_state *state);
    void (*oob_hotplug_event)(struct drm_connector *connector);
    void (*debugfs_init)(struct drm_connector *connector, struct dentry *root);
};

3.2.2 Structure drm_connector_helper_funcs

Cette structure fournit des fonctions d'aide pour le connecteur.


struct drm_connector_helper_funcs {
    int (*get_modes)(struct drm_connector *connector);
    int (*detect_ctx)(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx, bool force);
    enum drm_mode_status (*mode_valid)(struct drm_connector *connector, struct drm_display_mode *mode);
    int (*mode_valid_ctx)(struct drm_connector *connector, struct drm_display_mode *mode, struct drm_modeset_acquire_ctx *ctx, enum drm_mode_status *status);
    struct drm_encoder *(*best_encoder)(struct drm_connector *connector);
    struct drm_encoder *(*atomic_best_encoder)(struct drm_connector *connector, struct drm_atomic_state *state);
    int (*atomic_check)(struct drm_connector *connector, struct drm_atomic_state *state);
    void (*atomic_commit)(struct drm_connector *connector, struct drm_atomic_state *state);
    int (*prepare_writeback_job)(struct drm_writeback_connector *connector, struct drm_writeback_job *job);
    void (*cleanup_writeback_job)(struct drm_writeback_connector *connector, struct drm_writeback_job *job);
    void (*enable_hpd)(struct drm_connector *connector);
    void (*disable_hpd)(struct drm_connector *connector);
};

  1. API clés de l'encodeur

4.1 Initialisation de l'encodeur

Fonction pour initialiser un objet encodeur préalloué.


int drm_encoder_init(struct drm_device *dev, struct drm_encoder *encoder, const struct drm_encoder_funcs *funcs, int encoder_type, const char *name, ...) {
    va_list ap;
    int ret;

    WARN_ON(!funcs->destroy);

    va_start(ap, name);
    ret = __drm_encoder_init(dev, encoder, funcs, encoder_type, name, ap);
    va_end(ap);

    return ret;
}

4.2 Enregistrement de l'encodeur

Fonction pour enregistrer tous les objets encodeur.


int drm_encoder_register_all(struct drm_device *dev) {
    struct drm_encoder *encoder;
    int ret = 0;

    drm_for_each_encoder(encoder, dev) {
        if (encoder->funcs && encoder->funcs->late_register)
            ret = encoder->funcs->late_register(encoder);
        if (ret)
            return ret;
    }

    return 0;
}

  1. API clés du connecteur

5.1 Initialisation du connecteur

Fonction pour initialiser un objet connecteur préalloué.


int drm_connector_init(struct drm_device *dev, struct drm_connector *connector, const struct drm_connector_funcs *funcs, int connector_type) {
    if (drm_WARN_ON(dev, !(funcs && funcs->destroy)))
        return -EINVAL;

    return __drm_connector_init(dev, connector, funcs, connector_type, NULL);
}

5.2 Enregistrement du connecteur

Fonction pour enregistrer tous les objets connecteur.


int drm_connector_register_all(struct drm_device *dev) {
    struct drm_connector *connector;
    struct drm_connector_list_iter conn_iter;
    int ret = 0;

    drm_connector_list_iter_begin(dev, &conn_iter);
    drm_for_each_connector_iter(connector, &conn_iter) {
        ret = drm_connector_register(connector);
        if (ret)
            break;
    }
    drm_connector_list_iter_end(&conn_iter);

    if (ret)
        drm_connector_unregister_all(dev);
    return ret;
}

Étiquettes: Rockchip RK3399 DRM encoder Bridge

Publié le 5 octobre à 06h05