130 lines · c
1// SPDX-License-Identifier: MIT2 3#include <drm/drm_atomic_state_helper.h>4#include <drm/drm_edid.h>5#include <drm/drm_modeset_helper_vtables.h>6#include <drm/drm_print.h>7#include <drm/drm_probe_helper.h>8 9#include "ast_ddc.h"10#include "ast_drv.h"11 12/*13 * Encoder14 */15 16static const struct drm_encoder_funcs ast_vga_encoder_funcs = {17 .destroy = drm_encoder_cleanup,18};19 20/*21 * Connector22 */23 24static int ast_vga_connector_helper_get_modes(struct drm_connector *connector)25{26 struct ast_connector *ast_connector = to_ast_connector(connector);27 int count;28 29 if (ast_connector->physical_status == connector_status_connected) {30 count = drm_connector_helper_get_modes(connector);31 } else {32 drm_edid_connector_update(connector, NULL);33 34 /*35 * There's no EDID data without a connected monitor. Set BMC-36 * compatible modes in this case. The XGA default resolution37 * should work well for all BMCs.38 */39 count = drm_add_modes_noedid(connector, 4096, 4096);40 if (count)41 drm_set_preferred_mode(connector, 1024, 768);42 }43 44 return count;45}46 47static int ast_vga_connector_helper_detect_ctx(struct drm_connector *connector,48 struct drm_modeset_acquire_ctx *ctx,49 bool force)50{51 struct ast_connector *ast_connector = to_ast_connector(connector);52 enum drm_connector_status status;53 54 status = drm_connector_helper_detect_from_ddc(connector, ctx, force);55 56 if (status != ast_connector->physical_status)57 ++connector->epoch_counter;58 ast_connector->physical_status = status;59 60 return connector_status_connected;61}62 63static const struct drm_connector_helper_funcs ast_vga_connector_helper_funcs = {64 .get_modes = ast_vga_connector_helper_get_modes,65 .detect_ctx = ast_vga_connector_helper_detect_ctx,66};67 68static const struct drm_connector_funcs ast_vga_connector_funcs = {69 .reset = drm_atomic_helper_connector_reset,70 .fill_modes = drm_helper_probe_single_connector_modes,71 .destroy = drm_connector_cleanup,72 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,73 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,74};75 76static int ast_vga_connector_init(struct drm_device *dev, struct drm_connector *connector)77{78 struct ast_device *ast = to_ast_device(dev);79 struct i2c_adapter *ddc;80 int ret;81 82 ddc = ast_ddc_create(ast);83 if (IS_ERR(ddc)) {84 ret = PTR_ERR(ddc);85 drm_err(dev, "failed to add DDC bus for connector; ret=%d\n", ret);86 return ret;87 }88 89 ret = drm_connector_init_with_ddc(dev, connector, &ast_vga_connector_funcs,90 DRM_MODE_CONNECTOR_VGA, ddc);91 if (ret)92 return ret;93 94 drm_connector_helper_add(connector, &ast_vga_connector_helper_funcs);95 96 connector->interlace_allowed = 0;97 connector->doublescan_allowed = 0;98 99 connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;100 101 return 0;102}103 104int ast_vga_output_init(struct ast_device *ast)105{106 struct drm_device *dev = &ast->base;107 struct drm_crtc *crtc = &ast->crtc;108 struct drm_encoder *encoder = &ast->output.vga.encoder;109 struct ast_connector *ast_connector = &ast->output.vga.connector;110 struct drm_connector *connector = &ast_connector->base;111 int ret;112 113 ret = drm_encoder_init(dev, encoder, &ast_vga_encoder_funcs,114 DRM_MODE_ENCODER_DAC, NULL);115 if (ret)116 return ret;117 encoder->possible_crtcs = drm_crtc_mask(crtc);118 119 ret = ast_vga_connector_init(dev, connector);120 if (ret)121 return ret;122 ast_connector->physical_status = connector->status;123 124 ret = drm_connector_attach_encoder(connector, encoder);125 if (ret)126 return ret;127 128 return 0;129}130