1 #include "vigs_output.h"
2 #include "vigs_device.h"
3 #include "drm_crtc_helper.h"
4 #include <linux/init.h>
6 #define DPI_DEF_VALUE 316
7 #define DPI_MIN_VALUE 100
8 #define DPI_MAX_VALUE 600
11 static int vigs_atoi(const char *str)
18 val = (10 * val) + (*str - '0');
30 * 'connector' is the owner of the 'vigs_output', i.e.
31 * when 'connector' is destroyed whole structure is destroyed.
33 struct drm_connector connector;
34 struct drm_encoder encoder;
37 static inline struct vigs_output *connector_to_vigs_output(struct drm_connector *connector)
39 return container_of(connector, struct vigs_output, connector);
42 static inline struct vigs_output *encoder_to_vigs_output(struct drm_encoder *encoder)
44 return container_of(encoder, struct vigs_output, encoder);
47 static void vigs_connector_save(struct drm_connector *connector)
49 DRM_DEBUG_KMS("enter\n");
52 static void vigs_connector_restore(struct drm_connector *connector)
54 DRM_DEBUG_KMS("enter\n");
57 static enum drm_connector_status vigs_connector_detect(
58 struct drm_connector *connector,
61 DRM_DEBUG_KMS("enter: force = %d\n", force);
63 return connector_status_connected;
66 static int vigs_connector_set_property(struct drm_connector *connector,
67 struct drm_property *property,
70 DRM_DEBUG_KMS("enter: %s = %llu\n", property->name, value);
75 static void vigs_connector_destroy(struct drm_connector *connector)
77 struct vigs_output *vigs_output = connector_to_vigs_output(connector);
79 DRM_DEBUG_KMS("enter\n");
81 drm_connector_unregister(connector);
82 drm_connector_cleanup(connector);
87 static int vigs_connector_get_modes(struct drm_connector *connector)
89 struct vigs_output *vigs_output = connector_to_vigs_output(connector);
90 struct drm_device *drm_dev = vigs_output->connector.dev;
93 DRM_DEBUG_KMS("enter\n");
95 if (fb_get_options(connector->name, &option) == 0) {
96 struct drm_cmdline_mode cmdline_mode;
98 if (drm_mode_parse_command_line_for_connector(option,
101 struct drm_display_mode *preferred_mode =
102 drm_mode_create_from_cmdline_mode(drm_dev,
105 /* qHD workaround (540x960) */
106 if (cmdline_mode.xres == 540 && cmdline_mode.yres == 960) {
107 preferred_mode->hdisplay = cmdline_mode.xres;
108 preferred_mode->hsync_start = preferred_mode->hsync_start - 1;
109 preferred_mode->hsync_end = preferred_mode->hsync_end - 1;
112 preferred_mode->type = DRM_MODE_TYPE_PREFERRED | DRM_MODE_TYPE_DRIVER;
113 drm_mode_set_crtcinfo(preferred_mode, CRTC_INTERLACE_HALVE_V);
114 drm_mode_probed_add(connector, preferred_mode);
124 static int vigs_connector_mode_valid(struct drm_connector *connector,
125 struct drm_display_mode *mode)
127 DRM_DEBUG_KMS("enter\n");
132 struct drm_encoder *vigs_connector_best_encoder(struct drm_connector *connector)
134 struct vigs_output *vigs_output = connector_to_vigs_output(connector);
136 DRM_DEBUG_KMS("enter\n");
138 return &vigs_output->encoder;
141 static void vigs_encoder_destroy(struct drm_encoder *encoder)
143 DRM_DEBUG_KMS("enter\n");
145 drm_encoder_cleanup(encoder);
148 static void vigs_encoder_dpms(struct drm_encoder *encoder, int mode)
150 DRM_DEBUG_KMS("enter: mode = %d\n", mode);
153 static bool vigs_encoder_mode_fixup(struct drm_encoder *encoder,
154 const struct drm_display_mode *mode,
155 struct drm_display_mode *adjusted_mode)
157 DRM_DEBUG_KMS("enter\n");
162 static void vigs_encoder_prepare(struct drm_encoder *encoder)
164 DRM_DEBUG_KMS("enter\n");
167 static void vigs_encoder_mode_set(struct drm_encoder *encoder,
168 struct drm_display_mode *mode,
169 struct drm_display_mode *adjusted_mode)
171 DRM_DEBUG_KMS("enter\n");
174 static void vigs_encoder_commit(struct drm_encoder *encoder)
176 DRM_DEBUG_KMS("enter\n");
179 static const struct drm_connector_funcs vigs_connector_funcs =
181 .dpms = drm_helper_connector_dpms,
182 .save = vigs_connector_save,
183 .restore = vigs_connector_restore,
184 .detect = vigs_connector_detect,
185 .fill_modes = drm_helper_probe_single_connector_modes,
186 .set_property = vigs_connector_set_property,
187 .destroy = vigs_connector_destroy,
190 static const struct drm_connector_helper_funcs vigs_connector_helper_funcs =
192 .get_modes = vigs_connector_get_modes,
193 .mode_valid = vigs_connector_mode_valid,
194 .best_encoder = vigs_connector_best_encoder,
197 static const struct drm_encoder_funcs vigs_encoder_funcs =
199 .destroy = vigs_encoder_destroy,
202 static const struct drm_encoder_helper_funcs vigs_encoder_helper_funcs =
204 .dpms = vigs_encoder_dpms,
205 .mode_fixup = vigs_encoder_mode_fixup,
206 .prepare = vigs_encoder_prepare,
207 .mode_set = vigs_encoder_mode_set,
208 .commit = vigs_encoder_commit,
211 int vigs_output_init(struct vigs_device *vigs_dev)
213 struct vigs_output *vigs_output;
216 DRM_DEBUG_KMS("enter\n");
218 vigs_output = kzalloc(sizeof(*vigs_output), GFP_KERNEL);
224 ret = drm_connector_init(vigs_dev->drm_dev,
225 &vigs_output->connector,
226 &vigs_connector_funcs,
227 DRM_MODE_CONNECTOR_LVDS);
234 ret = drm_encoder_init(vigs_dev->drm_dev,
235 &vigs_output->encoder,
237 DRM_MODE_ENCODER_LVDS);
241 * KMS subsystem will delete 'vigs_output'
248 * We only have a single CRTC.
250 vigs_output->encoder.possible_crtcs = (1 << 0);
252 ret = drm_mode_connector_attach_encoder(&vigs_output->connector,
253 &vigs_output->encoder);
259 drm_encoder_helper_add(&vigs_output->encoder, &vigs_encoder_helper_funcs);
261 drm_connector_helper_add(&vigs_output->connector, &vigs_connector_helper_funcs);
263 ret = drm_connector_register(&vigs_output->connector);
272 int vigs_output_get_dpi(void)
274 int dpi = DPI_DEF_VALUE;
278 str = strstr(saved_command_line, "dpi=");
282 dpi = vigs_atoi(str);
283 if ((dpi < DPI_MIN_VALUE) || (dpi > DPI_MAX_VALUE)) {
291 int vigs_output_get_phys_width(int dpi, u32 width)
293 return ((width * 254 / dpi) + 5) / 10;
296 int vigs_output_get_phys_height(int dpi, u32 height)
298 return ((height * 254 / dpi) + 5) / 10;