- 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);
};
- 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;
}
- 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);
};
- 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;
}
- 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;
}