blob: fdd40a74aa315b5eb59289eb22e0bcb7d985b854 [file] [log] [blame]
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -07001/*
Narender Ankam1afbd172020-03-16 17:27:44 +05302 * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -07003 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 */
14
15#define pr_fmt(fmt) "[drm-dp]: %s: " fmt, __func__
16
17#include <drm/drm_atomic_helper.h>
18#include <drm/drm_atomic.h>
19#include <drm/drm_crtc.h>
20
21#include "msm_drv.h"
22#include "msm_kms.h"
23#include "sde_connector.h"
24#include "dp_drm.h"
Samantha Tran2d1ed732017-07-31 17:30:14 -070025#include "dp_debug.h"
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -070026
27#define to_dp_bridge(x) container_of((x), struct dp_bridge, base)
28
Narender Ankam1afbd172020-03-16 17:27:44 +053029enum dp_connector_hdr_state {
30 HDR_DISABLE,
31 HDR_ENABLE
32};
33
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -070034static void convert_to_dp_mode(const struct drm_display_mode *drm_mode,
Padmanabhan Komandurud0ed9c42017-05-23 02:56:08 -070035 struct dp_display_mode *dp_mode, struct dp_display *dp)
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -070036{
37 memset(dp_mode, 0, sizeof(*dp_mode));
38
39 dp_mode->timing.h_active = drm_mode->hdisplay;
40 dp_mode->timing.h_back_porch = drm_mode->htotal - drm_mode->hsync_end;
41 dp_mode->timing.h_sync_width = drm_mode->htotal -
42 (drm_mode->hsync_start + dp_mode->timing.h_back_porch);
43 dp_mode->timing.h_front_porch = drm_mode->hsync_start -
44 drm_mode->hdisplay;
45 dp_mode->timing.h_skew = drm_mode->hskew;
46
47 dp_mode->timing.v_active = drm_mode->vdisplay;
48 dp_mode->timing.v_back_porch = drm_mode->vtotal - drm_mode->vsync_end;
49 dp_mode->timing.v_sync_width = drm_mode->vtotal -
50 (drm_mode->vsync_start + dp_mode->timing.v_back_porch);
51
52 dp_mode->timing.v_front_porch = drm_mode->vsync_start -
53 drm_mode->vdisplay;
Padmanabhan Komandurufdafc412017-09-11 13:13:38 +053054
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -070055 dp_mode->timing.refresh_rate = drm_mode->vrefresh;
56
57 dp_mode->timing.pixel_clk_khz = drm_mode->clock;
58
59 dp_mode->timing.v_active_low =
60 !!(drm_mode->flags & DRM_MODE_FLAG_NVSYNC);
61
62 dp_mode->timing.h_active_low =
63 !!(drm_mode->flags & DRM_MODE_FLAG_NHSYNC);
64}
65
66static void convert_to_drm_mode(const struct dp_display_mode *dp_mode,
67 struct drm_display_mode *drm_mode)
68{
69 u32 flags = 0;
70
71 memset(drm_mode, 0, sizeof(*drm_mode));
72
73 drm_mode->hdisplay = dp_mode->timing.h_active;
74 drm_mode->hsync_start = drm_mode->hdisplay +
75 dp_mode->timing.h_front_porch;
76 drm_mode->hsync_end = drm_mode->hsync_start +
77 dp_mode->timing.h_sync_width;
78 drm_mode->htotal = drm_mode->hsync_end + dp_mode->timing.h_back_porch;
79 drm_mode->hskew = dp_mode->timing.h_skew;
80
81 drm_mode->vdisplay = dp_mode->timing.v_active;
82 drm_mode->vsync_start = drm_mode->vdisplay +
83 dp_mode->timing.v_front_porch;
84 drm_mode->vsync_end = drm_mode->vsync_start +
85 dp_mode->timing.v_sync_width;
86 drm_mode->vtotal = drm_mode->vsync_end + dp_mode->timing.v_back_porch;
87
88 drm_mode->vrefresh = dp_mode->timing.refresh_rate;
89 drm_mode->clock = dp_mode->timing.pixel_clk_khz;
90
91 if (dp_mode->timing.h_active_low)
92 flags |= DRM_MODE_FLAG_NHSYNC;
93 else
94 flags |= DRM_MODE_FLAG_PHSYNC;
95
96 if (dp_mode->timing.v_active_low)
97 flags |= DRM_MODE_FLAG_NVSYNC;
98 else
99 flags |= DRM_MODE_FLAG_PVSYNC;
100
101 drm_mode->flags = flags;
102
103 drm_mode->type = 0x48;
104 drm_mode_set_name(drm_mode);
105}
106
107static int dp_bridge_attach(struct drm_bridge *dp_bridge)
108{
109 struct dp_bridge *bridge = to_dp_bridge(dp_bridge);
110
111 if (!dp_bridge) {
112 pr_err("Invalid params\n");
113 return -EINVAL;
114 }
115
116 pr_debug("[%d] attached\n", bridge->id);
117
118 return 0;
119}
120
121static void dp_bridge_pre_enable(struct drm_bridge *drm_bridge)
122{
123 int rc = 0;
124 struct dp_bridge *bridge;
125 struct dp_display *dp;
126
127 if (!drm_bridge) {
128 pr_err("Invalid params\n");
129 return;
130 }
131
132 bridge = to_dp_bridge(drm_bridge);
133 dp = bridge->display;
134
135 /* By this point mode should have been validated through mode_fixup */
136 rc = dp->set_mode(dp, &bridge->dp_mode);
137 if (rc) {
138 pr_err("[%d] failed to perform a mode set, rc=%d\n",
139 bridge->id, rc);
140 return;
141 }
142
143 rc = dp->prepare(dp);
144 if (rc) {
145 pr_err("[%d] DP display prepare failed, rc=%d\n",
146 bridge->id, rc);
147 return;
148 }
149
150 rc = dp->enable(dp);
151 if (rc) {
152 pr_err("[%d] DP display enable failed, rc=%d\n",
153 bridge->id, rc);
154 dp->unprepare(dp);
155 }
156}
157
158static void dp_bridge_enable(struct drm_bridge *drm_bridge)
159{
160 int rc = 0;
161 struct dp_bridge *bridge;
162 struct dp_display *dp;
163
164 if (!drm_bridge) {
165 pr_err("Invalid params\n");
166 return;
167 }
168
169 bridge = to_dp_bridge(drm_bridge);
170 dp = bridge->display;
171
172 rc = dp->post_enable(dp);
173 if (rc)
174 pr_err("[%d] DP display post enable failed, rc=%d\n",
175 bridge->id, rc);
176}
177
178static void dp_bridge_disable(struct drm_bridge *drm_bridge)
179{
180 int rc = 0;
181 struct dp_bridge *bridge;
182 struct dp_display *dp;
183
184 if (!drm_bridge) {
185 pr_err("Invalid params\n");
186 return;
187 }
188
189 bridge = to_dp_bridge(drm_bridge);
190 dp = bridge->display;
191
Jayant Shekhar67ad2a92018-03-01 11:32:23 +0530192 if (!dp) {
193 pr_err("dp is null\n");
194 return;
195 }
196
197 if (dp->connector)
Clarence Ip458a5d02017-11-27 18:15:16 -0500198 sde_connector_helper_bridge_disable(dp->connector);
199
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700200 rc = dp->pre_disable(dp);
201 if (rc) {
202 pr_err("[%d] DP display pre disable failed, rc=%d\n",
203 bridge->id, rc);
204 }
205}
206
207static void dp_bridge_post_disable(struct drm_bridge *drm_bridge)
208{
209 int rc = 0;
210 struct dp_bridge *bridge;
211 struct dp_display *dp;
212
213 if (!drm_bridge) {
214 pr_err("Invalid params\n");
215 return;
216 }
217
218 bridge = to_dp_bridge(drm_bridge);
219 dp = bridge->display;
220
221 rc = dp->disable(dp);
222 if (rc) {
223 pr_err("[%d] DP display disable failed, rc=%d\n",
224 bridge->id, rc);
225 return;
226 }
227
228 rc = dp->unprepare(dp);
229 if (rc) {
230 pr_err("[%d] DP display unprepare failed, rc=%d\n",
231 bridge->id, rc);
232 return;
233 }
234}
235
236static void dp_bridge_mode_set(struct drm_bridge *drm_bridge,
237 struct drm_display_mode *mode,
238 struct drm_display_mode *adjusted_mode)
239{
240 struct dp_bridge *bridge;
241 struct dp_display *dp;
242
243 if (!drm_bridge || !mode || !adjusted_mode) {
244 pr_err("Invalid params\n");
245 return;
246 }
247
248 bridge = to_dp_bridge(drm_bridge);
249 dp = bridge->display;
250
251 memset(&bridge->dp_mode, 0x0, sizeof(struct dp_display_mode));
Padmanabhan Komandurud0ed9c42017-05-23 02:56:08 -0700252 convert_to_dp_mode(adjusted_mode, &bridge->dp_mode, dp);
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700253}
254
255static bool dp_bridge_mode_fixup(struct drm_bridge *drm_bridge,
256 const struct drm_display_mode *mode,
257 struct drm_display_mode *adjusted_mode)
258{
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700259 bool ret = true;
260 struct dp_display_mode dp_mode;
261 struct dp_bridge *bridge;
262 struct dp_display *dp;
263
264 if (!drm_bridge || !mode || !adjusted_mode) {
265 pr_err("Invalid params\n");
266 ret = false;
267 goto end;
268 }
269
270 bridge = to_dp_bridge(drm_bridge);
271 dp = bridge->display;
272
Padmanabhan Komandurud0ed9c42017-05-23 02:56:08 -0700273 convert_to_dp_mode(mode, &dp_mode, dp);
Tatenda Chipeperekwa8a44bd92017-10-05 16:32:06 -0700274 convert_to_drm_mode(&dp_mode, adjusted_mode);
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700275end:
276 return ret;
277}
278
279static const struct drm_bridge_funcs dp_bridge_ops = {
280 .attach = dp_bridge_attach,
281 .mode_fixup = dp_bridge_mode_fixup,
282 .pre_enable = dp_bridge_pre_enable,
283 .enable = dp_bridge_enable,
284 .disable = dp_bridge_disable,
285 .post_disable = dp_bridge_post_disable,
286 .mode_set = dp_bridge_mode_set,
287};
288
Ajay Singh Parmar87af50b2017-12-22 22:22:55 -0800289int dp_connector_config_hdr(void *display,
290 struct sde_connector_state *c_state)
Ajay Singh Parmar9c842d42017-09-21 13:02:05 -0700291{
292 struct dp_display *dp = display;
293
Ajay Singh Parmar87af50b2017-12-22 22:22:55 -0800294 if (!display || !c_state) {
Ajay Singh Parmar9c842d42017-09-21 13:02:05 -0700295 pr_err("invalid params\n");
296 return -EINVAL;
297 }
298
Ajay Singh Parmar87af50b2017-12-22 22:22:55 -0800299 return dp->config_hdr(dp, &c_state->hdr_meta);
Ajay Singh Parmar9c842d42017-09-21 13:02:05 -0700300}
301
Alan Kwong769fba92017-11-13 16:50:36 -0500302int dp_connector_post_init(struct drm_connector *connector, void *display)
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700303{
304 struct dp_display *dp_display = display;
305
Alan Kwong769fba92017-11-13 16:50:36 -0500306 if (!dp_display)
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700307 return -EINVAL;
308
Padmanabhan Komandurud84b38b2017-05-24 04:24:57 -0700309 dp_display->connector = connector;
Ajay Singh Parmar315e5852017-11-23 21:47:32 -0800310
311 if (dp_display->post_init)
312 dp_display->post_init(dp_display);
313
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700314 return 0;
315}
316
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -0700317int dp_connector_get_mode_info(const struct drm_display_mode *drm_mode,
Alan Kwongb1bca602017-09-18 17:28:45 -0400318 struct msm_mode_info *mode_info, u32 max_mixer_width, void *display)
Tatenda Chipeperekwa9f2abe12017-05-25 12:06:22 -0700319{
320 const u32 dual_lm = 2;
321 const u32 single_lm = 1;
322 const u32 single_intf = 1;
323 const u32 no_enc = 0;
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -0700324 struct msm_display_topology *topology;
Tatenda Chipeperekwa9f2abe12017-05-25 12:06:22 -0700325
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -0700326 if (!drm_mode || !mode_info || !max_mixer_width) {
Tatenda Chipeperekwa9f2abe12017-05-25 12:06:22 -0700327 pr_err("invalid params\n");
328 return -EINVAL;
329 }
330
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -0700331 topology = &mode_info->topology;
Tatenda Chipeperekwa9f2abe12017-05-25 12:06:22 -0700332 topology->num_lm = (max_mixer_width <= drm_mode->hdisplay) ?
333 dual_lm : single_lm;
334 topology->num_enc = no_enc;
335 topology->num_intf = single_intf;
336
Jeykumar Sankaran446a5f12017-05-09 20:30:39 -0700337 mode_info->frame_rate = drm_mode->vrefresh;
338 mode_info->vtotal = drm_mode->vtotal;
339 mode_info->comp_info.comp_type = MSM_DISPLAY_COMPRESSION_NONE;
340
Tatenda Chipeperekwa9f2abe12017-05-25 12:06:22 -0700341 return 0;
342}
343
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700344int dp_connector_get_info(struct msm_display_info *info, void *data)
345{
Padmanabhan Komandurud84b38b2017-05-24 04:24:57 -0700346 struct dp_display *display = data;
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700347
348 if (!info || !display) {
349 pr_err("invalid params\n");
350 return -EINVAL;
351 }
352
353 info->intf_type = DRM_MODE_CONNECTOR_DisplayPort;
354
355 info->num_of_h_tiles = 1;
356 info->h_tile_instance[0] = 0;
Padmanabhan Komandurud84b38b2017-05-24 04:24:57 -0700357 info->is_connected = display->is_connected;
Padmanabhan Komandurud84b38b2017-05-24 04:24:57 -0700358 info->capabilities = MSM_DISPLAY_CAP_VID_MODE | MSM_DISPLAY_CAP_EDID |
359 MSM_DISPLAY_CAP_HOT_PLUG;
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700360
361 return 0;
362}
363
Chirag Khuranace2aa512019-11-20 18:27:03 +0530364bool dp_connector_mode_needs_full_range(void *data)
365{
366 struct dp_display *display = data;
367 struct dp_bridge *bridge;
368 struct dp_display_mode *mode;
369 struct dp_panel_info *timing;
370
371 if (!display) {
372 pr_err("invalid input\n");
373 return false;
374 }
375
376 bridge = display->bridge;
377 if (!bridge) {
378 pr_err("invalid bridge data\n");
379 return false;
380 }
381
382 mode = &bridge->dp_mode;
383 timing = &mode->timing;
384
385 if (timing->h_active == 640 &&
386 timing->v_active == 480)
387 return true;
388
389 return false;
390}
391
Narender Ankam1afbd172020-03-16 17:27:44 +0530392enum sde_csc_type dp_connector_get_csc_type(struct drm_connector *conn,
393 void *data)
394{
395 struct dp_display *display = data;
396 struct sde_connector_state *c_state;
397 struct drm_msm_ext_hdr_metadata *hdr_meta;
398
399 if (!display || !conn) {
400 pr_err("invalid input\n");
401 goto error;
402 }
403
404 c_state = to_sde_connector_state(conn->state);
405
406 if (!c_state) {
407 pr_err("invalid input\n");
408 goto error;
409 }
410
411 hdr_meta = &c_state->hdr_meta;
412
413 if ((hdr_meta->hdr_state == HDR_ENABLE)
414 && (hdr_meta->eotf != 0))
415 return SDE_CSC_RGB2YUV_2020L;
416 else if (dp_connector_mode_needs_full_range(data)
417 || conn->yuv_qs)
418 return SDE_CSC_RGB2YUV_601FR;
419
420error:
421 return SDE_CSC_RGB2YUV_601L;
422}
423
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700424enum drm_connector_status dp_connector_detect(struct drm_connector *conn,
425 bool force,
426 void *display)
427{
428 enum drm_connector_status status = connector_status_unknown;
429 struct msm_display_info info;
430 int rc;
431
432 if (!conn || !display)
433 return status;
434
435 /* get display dp_info */
436 memset(&info, 0x0, sizeof(info));
437 rc = dp_connector_get_info(&info, display);
438 if (rc) {
439 pr_err("failed to get display info, rc=%d\n", rc);
440 return connector_status_disconnected;
441 }
442
443 if (info.capabilities & MSM_DISPLAY_CAP_HOT_PLUG)
444 status = (info.is_connected ? connector_status_connected :
445 connector_status_disconnected);
446 else
447 status = connector_status_connected;
448
449 conn->display_info.width_mm = info.width_mm;
450 conn->display_info.height_mm = info.height_mm;
451
452 return status;
453}
454
Ajay Singh Parmar315e5852017-11-23 21:47:32 -0800455void dp_connector_post_open(void *display)
Padmanabhan Komanduru71aec2d2017-08-30 20:07:59 +0530456{
457 struct dp_display *dp;
458
459 if (!display) {
460 pr_err("invalid input\n");
461 return;
462 }
463
464 dp = display;
465
Ajay Singh Parmar315e5852017-11-23 21:47:32 -0800466 if (dp->post_open)
467 dp->post_open(dp);
Padmanabhan Komanduru71aec2d2017-08-30 20:07:59 +0530468}
469
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700470int dp_connector_get_modes(struct drm_connector *connector,
471 void *display)
472{
Padmanabhan Komandurud84b38b2017-05-24 04:24:57 -0700473 int rc = 0;
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700474 struct dp_display *dp;
Padmanabhan Komandurufdafc412017-09-11 13:13:38 +0530475 struct dp_display_mode *dp_mode = NULL;
476 struct drm_display_mode *m, drm_mode;
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700477
Padmanabhan Komandurud84b38b2017-05-24 04:24:57 -0700478 if (!connector || !display)
Padmanabhan Komandurufdafc412017-09-11 13:13:38 +0530479 return 0;
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700480
481 dp = display;
Padmanabhan Komandurufdafc412017-09-11 13:13:38 +0530482
483 dp_mode = kzalloc(sizeof(*dp_mode), GFP_KERNEL);
484 if (!dp_mode)
485 return 0;
486
Padmanabhan Komandurud84b38b2017-05-24 04:24:57 -0700487 /* pluggable case assumes EDID is read when HPD */
488 if (dp->is_connected) {
Padmanabhan Komandurufdafc412017-09-11 13:13:38 +0530489 rc = dp->get_modes(dp, dp_mode);
Padmanabhan Komandurud84b38b2017-05-24 04:24:57 -0700490 if (!rc)
491 pr_err("failed to get DP sink modes, rc=%d\n", rc);
Padmanabhan Komandurufdafc412017-09-11 13:13:38 +0530492
493 if (dp_mode->timing.pixel_clk_khz) { /* valid DP mode */
494 memset(&drm_mode, 0x0, sizeof(drm_mode));
495 convert_to_drm_mode(dp_mode, &drm_mode);
496 m = drm_mode_duplicate(connector->dev, &drm_mode);
497 if (!m) {
498 pr_err("failed to add mode %ux%u\n",
499 drm_mode.hdisplay,
500 drm_mode.vdisplay);
501 kfree(dp_mode);
502 return 0;
503 }
504 m->width_mm = connector->display_info.width_mm;
505 m->height_mm = connector->display_info.height_mm;
506 drm_mode_probed_add(connector, m);
507 }
Padmanabhan Komandurud84b38b2017-05-24 04:24:57 -0700508 } else {
509 pr_err("No sink connected\n");
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700510 }
Padmanabhan Komandurufdafc412017-09-11 13:13:38 +0530511 kfree(dp_mode);
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700512
Padmanabhan Komandurufdafc412017-09-11 13:13:38 +0530513 return rc;
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700514}
515
516int dp_drm_bridge_init(void *data, struct drm_encoder *encoder)
517{
518 int rc = 0;
519 struct dp_bridge *bridge;
520 struct drm_device *dev;
521 struct dp_display *display = data;
522 struct msm_drm_private *priv = NULL;
523
524 bridge = kzalloc(sizeof(*bridge), GFP_KERNEL);
525 if (!bridge) {
526 rc = -ENOMEM;
527 goto error;
528 }
529
530 dev = display->drm_dev;
531 bridge->display = display;
532 bridge->base.funcs = &dp_bridge_ops;
533 bridge->base.encoder = encoder;
534
535 priv = dev->dev_private;
536
537 rc = drm_bridge_attach(dev, &bridge->base);
538 if (rc) {
539 pr_err("failed to attach bridge, rc=%d\n", rc);
540 goto error_free_bridge;
541 }
542
Padmanabhan Komanduru15e757d2017-05-24 04:07:31 -0700543 rc = display->request_irq(display);
544 if (rc) {
545 pr_err("request_irq failed, rc=%d\n", rc);
546 goto error_free_bridge;
547 }
548
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700549 encoder->bridge = &bridge->base;
550 priv->bridges[priv->num_bridges++] = &bridge->base;
551 display->bridge = bridge;
552
553 return 0;
554error_free_bridge:
555 kfree(bridge);
556error:
557 return rc;
558}
559
560void dp_drm_bridge_deinit(void *data)
561{
562 struct dp_display *display = data;
563 struct dp_bridge *bridge = display->bridge;
564
565 if (bridge && bridge->base.encoder)
566 bridge->base.encoder->bridge = NULL;
567
568 kfree(bridge);
569}
570
571enum drm_mode_status dp_connector_mode_valid(struct drm_connector *connector,
572 struct drm_display_mode *mode,
573 void *display)
574{
Padmanabhan Komandurud5eae9d2017-06-22 19:23:36 +0530575 struct dp_display *dp_disp;
Samantha Tran2d1ed732017-07-31 17:30:14 -0700576 struct dp_debug *debug;
Padmanabhan Komandurud5eae9d2017-06-22 19:23:36 +0530577
578 if (!mode || !display) {
579 pr_err("invalid params\n");
580 return MODE_ERROR;
581 }
582
583 dp_disp = display;
Samantha Tran2d1ed732017-07-31 17:30:14 -0700584 debug = dp_disp->get_debug(dp_disp);
Padmanabhan Komandurud5eae9d2017-06-22 19:23:36 +0530585
Tatenda Chipeperekwa59510402017-09-28 12:50:58 -0700586 mode->vrefresh = drm_mode_vrefresh(mode);
Padmanabhan Komandurufdafc412017-09-11 13:13:38 +0530587
Tatenda Chipeperekwa59510402017-09-28 12:50:58 -0700588 if (mode->clock > dp_disp->max_pclk_khz)
589 return MODE_BAD;
590
591 if (debug->debug_en && (mode->hdisplay != debug->hdisplay ||
592 mode->vdisplay != debug->vdisplay ||
593 mode->vrefresh != debug->vrefresh ||
594 mode->picture_aspect_ratio != debug->aspect_ratio))
595 return MODE_BAD;
596
Tatenda Chipeperekwa8a44bd92017-10-05 16:32:06 -0700597 return dp_disp->validate_mode(dp_disp, mode->clock);
Ajay Singh Parmar0d6250b2017-04-02 14:08:51 -0700598}