blob: 58222f341c2d56fb33b1c90a532586343f695761 [file] [log] [blame]
Lloyd Atkinsonab3dd302017-02-13 10:44:55 -08001/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
Clarence Ipdd8021c2016-07-20 16:39:47 -04002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
Clarence Ip90b282d2017-05-04 10:00:32 -070013#define pr_fmt(fmt) "[drm:%s:%d] " fmt, __func__, __LINE__
Clarence Ipdd8021c2016-07-20 16:39:47 -040014#include "msm_drv.h"
15
16#include "sde_kms.h"
17#include "sde_connector.h"
Dhaval Patel7cdd6662017-03-08 13:10:37 -080018#include <linux/backlight.h>
19#include "dsi_drm.h"
Ping Li898b1bf2017-02-09 18:03:28 -080020#include "dsi_display.h"
Dhaval Patel7cdd6662017-03-08 13:10:37 -080021
22#define BL_NODE_NAME_SIZE 32
Clarence Ipdd8021c2016-07-20 16:39:47 -040023
Lloyd Atkinson77382202017-02-01 14:59:43 -050024/* Autorefresh will occur after FRAME_CNT frames. Large values are unlikely */
25#define AUTOREFRESH_MAX_FRAME_CNT 6
26
Lloyd Atkinson8ba47032017-03-22 17:13:32 -040027#define SDE_DEBUG_CONN(c, fmt, ...) SDE_DEBUG("conn%d " fmt,\
28 (c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
29
30#define SDE_ERROR_CONN(c, fmt, ...) SDE_ERROR("conn%d " fmt,\
31 (c) ? (c)->base.base.id : -1, ##__VA_ARGS__)
32
Lloyd Atkinsonb6191972016-08-10 18:31:46 -040033static const struct drm_prop_enum_list e_topology_name[] = {
34 {SDE_RM_TOPOLOGY_UNKNOWN, "sde_unknown"},
35 {SDE_RM_TOPOLOGY_SINGLEPIPE, "sde_singlepipe"},
36 {SDE_RM_TOPOLOGY_DUALPIPE, "sde_dualpipe"},
37 {SDE_RM_TOPOLOGY_PPSPLIT, "sde_ppsplit"},
38 {SDE_RM_TOPOLOGY_DUALPIPEMERGE, "sde_dualpipemerge"}
39};
40static const struct drm_prop_enum_list e_topology_control[] = {
41 {SDE_RM_TOPCTL_RESERVE_LOCK, "reserve_lock"},
42 {SDE_RM_TOPCTL_RESERVE_CLEAR, "reserve_clear"},
43 {SDE_RM_TOPCTL_DSPP, "dspp"},
44 {SDE_RM_TOPCTL_FORCE_TILING, "force_tiling"},
45 {SDE_RM_TOPCTL_PPSPLIT, "ppsplit"}
46};
Clarence Ip90b282d2017-05-04 10:00:32 -070047static const struct drm_prop_enum_list e_power_mode[] = {
48 {SDE_MODE_DPMS_ON, "ON"},
49 {SDE_MODE_DPMS_LP1, "LP1"},
50 {SDE_MODE_DPMS_LP2, "LP2"},
51 {SDE_MODE_DPMS_OFF, "OFF"},
52};
Lloyd Atkinsonb6191972016-08-10 18:31:46 -040053
Dhaval Patel7cdd6662017-03-08 13:10:37 -080054static int sde_backlight_device_update_status(struct backlight_device *bd)
55{
56 int brightness;
57 struct dsi_display *display;
58 struct sde_connector *c_conn;
59 int bl_lvl;
60
61 brightness = bd->props.brightness;
62
63 if ((bd->props.power != FB_BLANK_UNBLANK) ||
64 (bd->props.state & BL_CORE_FBBLANK) ||
65 (bd->props.state & BL_CORE_SUSPENDED))
66 brightness = 0;
67
68 c_conn = bl_get_data(bd);
69 display = (struct dsi_display *) c_conn->display;
70 if (brightness > display->panel->bl_config.bl_max_level)
71 brightness = display->panel->bl_config.bl_max_level;
72
73 /* map UI brightness into driver backlight level with rounding */
74 bl_lvl = mult_frac(brightness, display->panel->bl_config.bl_max_level,
75 display->panel->bl_config.brightness_max_level);
76
77 if (!bl_lvl && brightness)
78 bl_lvl = 1;
79
80 if (c_conn->ops.set_backlight)
81 c_conn->ops.set_backlight(c_conn->display, bl_lvl);
82
83 return 0;
84}
85
86static int sde_backlight_device_get_brightness(struct backlight_device *bd)
87{
88 return 0;
89}
90
91static const struct backlight_ops sde_backlight_device_ops = {
92 .update_status = sde_backlight_device_update_status,
93 .get_brightness = sde_backlight_device_get_brightness,
94};
95
Shashank Babu Chinta Venkata06c428e2017-04-17 13:52:28 -070096static int sde_backlight_setup(struct sde_connector *c_conn,
97 struct drm_device *dev)
Dhaval Patel7cdd6662017-03-08 13:10:37 -080098{
99 struct backlight_device *bl_device;
100 struct backlight_properties props;
101 struct dsi_display *display;
102 struct dsi_backlight_config *bl_config;
103 static int display_count;
104 char bl_node_name[BL_NODE_NAME_SIZE];
105
Shashank Babu Chinta Venkata06c428e2017-04-17 13:52:28 -0700106 if (!c_conn || !dev || !dev->dev) {
Dhaval Patel7cdd6662017-03-08 13:10:37 -0800107 SDE_ERROR("invalid param\n");
108 return -EINVAL;
109 } else if (c_conn->connector_type != DRM_MODE_CONNECTOR_DSI) {
110 return 0;
111 }
112
113 memset(&props, 0, sizeof(props));
114 props.type = BACKLIGHT_RAW;
115 props.power = FB_BLANK_UNBLANK;
116
117 display = (struct dsi_display *) c_conn->display;
118 bl_config = &display->panel->bl_config;
119 props.max_brightness = bl_config->brightness_max_level;
120 props.brightness = bl_config->brightness_max_level;
121 snprintf(bl_node_name, BL_NODE_NAME_SIZE, "panel%u-backlight",
122 display_count);
Shashank Babu Chinta Venkata06c428e2017-04-17 13:52:28 -0700123 bl_device = backlight_device_register(bl_node_name, dev->dev,
Dhaval Patel7cdd6662017-03-08 13:10:37 -0800124 c_conn, &sde_backlight_device_ops, &props);
125 if (IS_ERR_OR_NULL(bl_device)) {
126 SDE_ERROR("Failed to register backlight: %ld\n",
127 PTR_ERR(bl_device));
128 return -ENODEV;
129 }
130 display_count++;
131
132 return 0;
133}
134
Clarence Ipa18d4832017-03-13 12:35:44 -0700135int sde_connector_trigger_event(void *drm_connector,
136 uint32_t event_idx, uint32_t instance_idx,
137 uint32_t data0, uint32_t data1,
138 uint32_t data2, uint32_t data3)
139{
140 struct sde_connector *c_conn;
141 unsigned long irq_flags;
142 void (*cb_func)(uint32_t event_idx,
143 uint32_t instance_idx, void *usr,
144 uint32_t data0, uint32_t data1,
145 uint32_t data2, uint32_t data3);
146 void *usr;
147 int rc = 0;
148
149 /*
150 * This function may potentially be called from an ISR context, so
151 * avoid excessive logging/etc.
152 */
153 if (!drm_connector)
154 return -EINVAL;
155 else if (event_idx >= SDE_CONN_EVENT_COUNT)
156 return -EINVAL;
157 c_conn = to_sde_connector(drm_connector);
158
159 spin_lock_irqsave(&c_conn->event_lock, irq_flags);
160 cb_func = c_conn->event_table[event_idx].cb_func;
161 usr = c_conn->event_table[event_idx].usr;
162 spin_unlock_irqrestore(&c_conn->event_lock, irq_flags);
163
164 if (cb_func)
165 cb_func(event_idx, instance_idx, usr,
166 data0, data1, data2, data3);
167 else
168 rc = -EAGAIN;
169
170 return rc;
171}
172
173int sde_connector_register_event(struct drm_connector *connector,
174 uint32_t event_idx,
175 void (*cb_func)(uint32_t event_idx,
176 uint32_t instance_idx, void *usr,
177 uint32_t data0, uint32_t data1,
178 uint32_t data2, uint32_t data3),
179 void *usr)
180{
181 struct sde_connector *c_conn;
182 unsigned long irq_flags;
183
184 if (!connector) {
185 SDE_ERROR("invalid connector\n");
186 return -EINVAL;
187 } else if (event_idx >= SDE_CONN_EVENT_COUNT) {
188 SDE_ERROR("conn%d, invalid event %d\n",
189 connector->base.id, event_idx);
190 return -EINVAL;
191 }
192 c_conn = to_sde_connector(connector);
193
194 spin_lock_irqsave(&c_conn->event_lock, irq_flags);
195 c_conn->event_table[event_idx].cb_func = cb_func;
196 c_conn->event_table[event_idx].usr = usr;
197 spin_unlock_irqrestore(&c_conn->event_lock, irq_flags);
198
199 /* optionally notify display of event registration */
200 if (c_conn->ops.enable_event && c_conn->display)
201 c_conn->ops.enable_event(connector, event_idx,
202 cb_func != NULL, c_conn->display);
203 return 0;
204}
205
206void sde_connector_unregister_event(struct drm_connector *connector,
207 uint32_t event_idx)
208{
209 (void)sde_connector_register_event(connector, event_idx, 0, 0);
210}
211
Clarence Ipcb3afd42016-07-15 16:25:34 -0400212int sde_connector_get_info(struct drm_connector *connector,
213 struct msm_display_info *info)
214{
215 struct sde_connector *c_conn;
216
217 if (!connector || !info) {
218 SDE_ERROR("invalid argument(s), conn %pK, info %pK\n",
219 connector, info);
220 return -EINVAL;
221 }
222
223 c_conn = to_sde_connector(connector);
224
225 if (!c_conn->display || !c_conn->ops.get_info) {
226 SDE_ERROR("display info not supported for %pK\n",
227 c_conn->display);
228 return -EINVAL;
229 }
230
231 return c_conn->ops.get_info(info, c_conn->display);
232}
233
Lloyd Atkinson05d75512017-01-17 14:45:51 -0500234int sde_connector_pre_kickoff(struct drm_connector *connector)
235{
236 struct sde_connector *c_conn;
237 struct sde_connector_state *c_state;
238 struct msm_display_kickoff_params params;
239 int rc;
240
241 if (!connector) {
242 SDE_ERROR("invalid argument\n");
243 return -EINVAL;
244 }
245
246 c_conn = to_sde_connector(connector);
247 c_state = to_sde_connector_state(connector->state);
248
249 if (!c_conn->display) {
250 SDE_ERROR("invalid argument\n");
251 return -EINVAL;
252 }
253
254 if (!c_conn->ops.pre_kickoff)
255 return 0;
256
257 params.rois = &c_state->rois;
258
259 SDE_EVT32_VERBOSE(connector->base.id);
260
261 rc = c_conn->ops.pre_kickoff(connector, c_conn->display, &params);
262
263 return rc;
264}
265
Veera Sundaram Sankaranbb2bf9a2017-03-29 18:56:47 -0700266void sde_connector_clk_ctrl(struct drm_connector *connector, bool enable)
267{
268 struct sde_connector *c_conn;
269 struct dsi_display *display;
270 u32 state = enable ? DSI_CLK_ON : DSI_CLK_OFF;
271
272 if (!connector) {
273 SDE_ERROR("invalid connector\n");
274 return;
275 }
276
277 c_conn = to_sde_connector(connector);
278 display = (struct dsi_display *) c_conn->display;
279
280 if (display && c_conn->ops.clk_ctrl)
281 c_conn->ops.clk_ctrl(display->mdp_clk_handle,
282 DSI_ALL_CLKS, state);
283}
284
Clarence Ipdd8021c2016-07-20 16:39:47 -0400285static void sde_connector_destroy(struct drm_connector *connector)
286{
287 struct sde_connector *c_conn;
288
289 if (!connector) {
290 SDE_ERROR("invalid connector\n");
291 return;
292 }
293
294 c_conn = to_sde_connector(connector);
295
Dhaval Patel4e574842016-08-23 15:11:37 -0700296 if (c_conn->blob_caps)
297 drm_property_unreference_blob(c_conn->blob_caps);
Ping Li898b1bf2017-02-09 18:03:28 -0800298 if (c_conn->blob_hdr)
299 drm_property_unreference_blob(c_conn->blob_hdr);
Clarence Ipdd8021c2016-07-20 16:39:47 -0400300 msm_property_destroy(&c_conn->property_info);
301
302 drm_connector_unregister(connector);
Clarence Ip90b282d2017-05-04 10:00:32 -0700303 mutex_destroy(&c_conn->lock);
Clarence Ipe59fb3f2016-07-26 13:39:59 -0400304 sde_fence_deinit(&c_conn->retire_fence);
Clarence Ipdd8021c2016-07-20 16:39:47 -0400305 drm_connector_cleanup(connector);
306 kfree(c_conn);
307}
308
309/**
310 * _sde_connector_destroy_fb - clean up connector state's out_fb buffer
311 * @c_conn: Pointer to sde connector structure
312 * @c_state: Pointer to sde connector state structure
313 */
314static void _sde_connector_destroy_fb(struct sde_connector *c_conn,
315 struct sde_connector_state *c_state)
316{
317 if (!c_state || !c_state->out_fb) {
318 SDE_ERROR("invalid state %pK\n", c_state);
319 return;
320 }
321
322 msm_framebuffer_cleanup(c_state->out_fb,
323 c_state->mmu_id);
324 drm_framebuffer_unreference(c_state->out_fb);
325 c_state->out_fb = NULL;
326
327 if (c_conn) {
328 c_state->property_values[CONNECTOR_PROP_OUT_FB] =
329 msm_property_get_default(&c_conn->property_info,
330 CONNECTOR_PROP_OUT_FB);
331 } else {
332 c_state->property_values[CONNECTOR_PROP_OUT_FB] = ~0;
333 }
334}
335
336static void sde_connector_atomic_destroy_state(struct drm_connector *connector,
337 struct drm_connector_state *state)
338{
339 struct sde_connector *c_conn = NULL;
340 struct sde_connector_state *c_state = NULL;
341
342 if (!state) {
343 SDE_ERROR("invalid state\n");
344 return;
345 }
346
347 /*
348 * The base DRM framework currently always passes in a NULL
349 * connector pointer. This is not correct, but attempt to
350 * handle that case as much as possible.
351 */
352 if (connector)
353 c_conn = to_sde_connector(connector);
354 c_state = to_sde_connector_state(state);
355
356 if (c_state->out_fb)
357 _sde_connector_destroy_fb(c_conn, c_state);
358
359 if (!c_conn) {
360 kfree(c_state);
361 } else {
362 /* destroy value helper */
363 msm_property_destroy_state(&c_conn->property_info, c_state,
364 c_state->property_values, 0);
365 }
366}
367
368static void sde_connector_atomic_reset(struct drm_connector *connector)
369{
370 struct sde_connector *c_conn;
371 struct sde_connector_state *c_state;
372
373 if (!connector) {
374 SDE_ERROR("invalid connector\n");
375 return;
376 }
377
378 c_conn = to_sde_connector(connector);
379
380 if (connector->state) {
381 sde_connector_atomic_destroy_state(connector, connector->state);
382 connector->state = 0;
383 }
384
385 c_state = msm_property_alloc_state(&c_conn->property_info);
386 if (!c_state) {
387 SDE_ERROR("state alloc failed\n");
388 return;
389 }
390
391 /* reset value helper, zero out state structure and reset properties */
392 msm_property_reset_state(&c_conn->property_info, c_state,
393 c_state->property_values, 0);
394
395 c_state->base.connector = connector;
396 connector->state = &c_state->base;
397}
398
399static struct drm_connector_state *
400sde_connector_atomic_duplicate_state(struct drm_connector *connector)
401{
402 struct sde_connector *c_conn;
403 struct sde_connector_state *c_state, *c_oldstate;
404 int rc;
405
406 if (!connector || !connector->state) {
407 SDE_ERROR("invalid connector %pK\n", connector);
408 return NULL;
409 }
410
411 c_conn = to_sde_connector(connector);
412 c_oldstate = to_sde_connector_state(connector->state);
413 c_state = msm_property_alloc_state(&c_conn->property_info);
414 if (!c_state) {
415 SDE_ERROR("state alloc failed\n");
416 return NULL;
417 }
418
419 /* duplicate value helper */
420 msm_property_duplicate_state(&c_conn->property_info,
421 c_oldstate, c_state, c_state->property_values, 0);
422
423 /* additional handling for drm framebuffer objects */
424 if (c_state->out_fb) {
425 drm_framebuffer_reference(c_state->out_fb);
426 rc = msm_framebuffer_prepare(c_state->out_fb,
427 c_state->mmu_id);
428 if (rc)
429 SDE_ERROR("failed to prepare fb, %d\n", rc);
430 }
431
432 return &c_state->base;
433}
434
Lloyd Atkinson8ba47032017-03-22 17:13:32 -0400435static int _sde_connector_roi_v1_check_roi(
436 struct sde_connector *c_conn,
437 struct drm_clip_rect *roi_conn,
438 const struct msm_roi_caps *caps)
439{
440 const struct msm_roi_alignment *align = &caps->align;
441 int w = roi_conn->x2 - roi_conn->x1;
442 int h = roi_conn->y2 - roi_conn->y1;
443
444 if (w <= 0 || h <= 0) {
445 SDE_ERROR_CONN(c_conn, "invalid conn roi w %d h %d\n", w, h);
446 return -EINVAL;
447 }
448
449 if (w < align->min_width || w % align->width_pix_align) {
450 SDE_ERROR_CONN(c_conn,
451 "invalid conn roi width %d min %d align %d\n",
452 w, align->min_width, align->width_pix_align);
453 return -EINVAL;
454 }
455
456 if (h < align->min_height || h % align->height_pix_align) {
457 SDE_ERROR_CONN(c_conn,
458 "invalid conn roi height %d min %d align %d\n",
459 h, align->min_height, align->height_pix_align);
460 return -EINVAL;
461 }
462
463 if (roi_conn->x1 % align->xstart_pix_align) {
464 SDE_ERROR_CONN(c_conn, "invalid conn roi x1 %d align %d\n",
465 roi_conn->x1, align->xstart_pix_align);
466 return -EINVAL;
467 }
468
469 if (roi_conn->y1 % align->ystart_pix_align) {
470 SDE_ERROR_CONN(c_conn, "invalid conn roi y1 %d align %d\n",
471 roi_conn->y1, align->ystart_pix_align);
472 return -EINVAL;
473 }
474
475 return 0;
476}
477
478static int _sde_connector_set_roi_v1(
479 struct sde_connector *c_conn,
480 struct sde_connector_state *c_state,
481 void *usr_ptr)
482{
483 struct sde_drm_roi_v1 roi_v1;
484 struct msm_display_info display_info;
485 struct msm_roi_caps *caps;
486 int i, rc;
487
488 if (!c_conn || !c_state) {
489 SDE_ERROR("invalid args\n");
490 return -EINVAL;
491 }
492
493 rc = sde_connector_get_info(&c_conn->base, &display_info);
494 if (rc) {
495 SDE_ERROR_CONN(c_conn, "display get info error: %d\n", rc);
496 return rc;
497 }
498
499 caps = &display_info.roi_caps;
500 if (!caps->enabled) {
501 SDE_ERROR_CONN(c_conn, "display roi capability is disabled\n");
502 return -ENOTSUPP;
503 }
504
505 memset(&c_state->rois, 0, sizeof(c_state->rois));
506
507 if (!usr_ptr) {
508 SDE_DEBUG_CONN(c_conn, "rois cleared\n");
509 return 0;
510 }
511
512 if (copy_from_user(&roi_v1, usr_ptr, sizeof(roi_v1))) {
513 SDE_ERROR_CONN(c_conn, "failed to copy roi_v1 data\n");
514 return -EINVAL;
515 }
516
517 SDE_DEBUG_CONN(c_conn, "num_rects %d\n", roi_v1.num_rects);
518
519 if (roi_v1.num_rects == 0) {
520 SDE_DEBUG_CONN(c_conn, "rois cleared\n");
521 return 0;
522 }
523
524 if (roi_v1.num_rects > SDE_MAX_ROI_V1 ||
525 roi_v1.num_rects > caps->num_roi) {
526 SDE_ERROR_CONN(c_conn, "too many rects specified: %d\n",
527 roi_v1.num_rects);
528 return -EINVAL;
529 }
530
531 c_state->rois.num_rects = roi_v1.num_rects;
532 for (i = 0; i < roi_v1.num_rects; ++i) {
533 int rc;
534
535 rc = _sde_connector_roi_v1_check_roi(c_conn, &roi_v1.roi[i],
536 caps);
537 if (rc)
538 return rc;
539
540 c_state->rois.roi[i] = roi_v1.roi[i];
541 SDE_DEBUG_CONN(c_conn, "roi%d: roi 0x%x 0x%x 0x%x 0x%x\n", i,
542 c_state->rois.roi[i].x1,
543 c_state->rois.roi[i].y1,
544 c_state->rois.roi[i].x2,
545 c_state->rois.roi[i].y2);
546 }
547
548 return 0;
549}
550
Clarence Ip90b282d2017-05-04 10:00:32 -0700551static int _sde_connector_update_power_locked(struct sde_connector *c_conn)
552{
553 struct drm_connector *connector;
554 void *display;
555 int (*set_power)(struct drm_connector *, int, void *);
556 int mode, rc = 0;
557
558 if (!c_conn)
559 return -EINVAL;
560 connector = &c_conn->base;
561
562 mode = c_conn->lp_mode;
563 if (c_conn->dpms_mode != DRM_MODE_DPMS_ON)
564 mode = SDE_MODE_DPMS_OFF;
565 switch (c_conn->dpms_mode) {
566 case DRM_MODE_DPMS_ON:
567 mode = c_conn->lp_mode;
568 break;
569 case DRM_MODE_DPMS_STANDBY:
570 mode = SDE_MODE_DPMS_STANDBY;
571 break;
572 case DRM_MODE_DPMS_SUSPEND:
573 mode = SDE_MODE_DPMS_SUSPEND;
574 break;
575 case DRM_MODE_DPMS_OFF:
576 mode = SDE_MODE_DPMS_OFF;
577 break;
578 default:
579 mode = c_conn->lp_mode;
580 SDE_ERROR("conn %d dpms set to unrecognized mode %d\n",
581 connector->base.id, mode);
582 break;
583 }
584
585 SDE_DEBUG("conn %d - dpms %d, lp %d, panel %d\n", connector->base.id,
586 c_conn->dpms_mode, c_conn->lp_mode, mode);
587
588 if (mode != c_conn->last_panel_power_mode && c_conn->ops.set_power) {
589 display = c_conn->display;
590 set_power = c_conn->ops.set_power;
591
592 mutex_unlock(&c_conn->lock);
593 rc = set_power(connector, mode, display);
594 mutex_lock(&c_conn->lock);
595 }
596 c_conn->last_panel_power_mode = mode;
597
598 return rc;
599}
600
Clarence Ipdd8021c2016-07-20 16:39:47 -0400601static int sde_connector_atomic_set_property(struct drm_connector *connector,
602 struct drm_connector_state *state,
603 struct drm_property *property,
604 uint64_t val)
605{
606 struct sde_connector *c_conn;
607 struct sde_connector_state *c_state;
608 int idx, rc;
609
610 if (!connector || !state || !property) {
611 SDE_ERROR("invalid argument(s), conn %pK, state %pK, prp %pK\n",
612 connector, state, property);
613 return -EINVAL;
614 }
615
616 c_conn = to_sde_connector(connector);
617 c_state = to_sde_connector_state(state);
618
619 /* generic property handling */
620 rc = msm_property_atomic_set(&c_conn->property_info,
621 c_state->property_values, 0, property, val);
622 if (rc)
623 goto end;
624
625 /* connector-specific property handling */
626 idx = msm_property_index(&c_conn->property_info, property);
Clarence Ip90b282d2017-05-04 10:00:32 -0700627 switch (idx) {
628 case CONNECTOR_PROP_OUT_FB:
Clarence Ipdd8021c2016-07-20 16:39:47 -0400629 /* clear old fb, if present */
630 if (c_state->out_fb)
631 _sde_connector_destroy_fb(c_conn, c_state);
632
633 /* convert fb val to drm framebuffer and prepare it */
634 c_state->out_fb =
635 drm_framebuffer_lookup(connector->dev, val);
Alan Kwongae1b1142017-03-05 16:07:10 -0800636 if (!c_state->out_fb && val) {
Clarence Ipdd8021c2016-07-20 16:39:47 -0400637 SDE_ERROR("failed to look up fb %lld\n", val);
638 rc = -EFAULT;
Alan Kwongae1b1142017-03-05 16:07:10 -0800639 } else if (!c_state->out_fb && !val) {
640 SDE_DEBUG("cleared fb_id\n");
641 rc = 0;
Clarence Ipdd8021c2016-07-20 16:39:47 -0400642 } else {
Alan Kwong578cdaf2017-01-28 17:25:43 -0800643 msm_framebuffer_set_kmap(c_state->out_fb,
644 c_conn->fb_kmap);
645
Alan Kwongdfa8c082016-07-29 04:10:00 -0400646 if (c_state->out_fb->flags & DRM_MODE_FB_SECURE)
647 c_state->mmu_id =
648 c_conn->mmu_id[SDE_IOMMU_DOMAIN_SECURE];
649 else
650 c_state->mmu_id =
651 c_conn->mmu_id[SDE_IOMMU_DOMAIN_UNSECURE];
Clarence Ipdd8021c2016-07-20 16:39:47 -0400652
653 rc = msm_framebuffer_prepare(c_state->out_fb,
654 c_state->mmu_id);
655 if (rc)
656 SDE_ERROR("prep fb failed, %d\n", rc);
657 }
Clarence Ip90b282d2017-05-04 10:00:32 -0700658 break;
659 case CONNECTOR_PROP_TOPOLOGY_CONTROL:
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400660 rc = sde_rm_check_property_topctl(val);
661 if (rc)
662 SDE_ERROR("invalid topology_control: 0x%llX\n", val);
Clarence Ip90b282d2017-05-04 10:00:32 -0700663 break;
664 case CONNECTOR_PROP_LP:
665 mutex_lock(&c_conn->lock);
666 c_conn->lp_mode = val;
667 _sde_connector_update_power_locked(c_conn);
668 mutex_unlock(&c_conn->lock);
669 break;
670 default:
671 break;
Lloyd Atkinson11f34442016-08-11 11:19:52 -0400672 }
673
Lloyd Atkinson8ba47032017-03-22 17:13:32 -0400674 if (idx == CONNECTOR_PROP_ROI_V1) {
675 rc = _sde_connector_set_roi_v1(c_conn, c_state, (void *)val);
676 if (rc)
677 SDE_ERROR_CONN(c_conn, "invalid roi_v1, rc: %d\n", rc);
678 }
679
Clarence Ipdd8021c2016-07-20 16:39:47 -0400680 /* check for custom property handling */
681 if (!rc && c_conn->ops.set_property) {
682 rc = c_conn->ops.set_property(connector,
683 state,
684 idx,
685 val,
686 c_conn->display);
687
688 /* potentially clean up out_fb if rc != 0 */
689 if ((idx == CONNECTOR_PROP_OUT_FB) && rc)
690 _sde_connector_destroy_fb(c_conn, c_state);
691 }
692end:
693 return rc;
694}
695
696static int sde_connector_set_property(struct drm_connector *connector,
697 struct drm_property *property,
698 uint64_t val)
699{
700 if (!connector) {
701 SDE_ERROR("invalid connector\n");
702 return -EINVAL;
703 }
704
705 return sde_connector_atomic_set_property(connector,
706 connector->state, property, val);
707}
708
709static int sde_connector_atomic_get_property(struct drm_connector *connector,
710 const struct drm_connector_state *state,
711 struct drm_property *property,
712 uint64_t *val)
713{
714 struct sde_connector *c_conn;
715 struct sde_connector_state *c_state;
716 int idx, rc = -EINVAL;
717
718 if (!connector || !state) {
719 SDE_ERROR("invalid argument(s), conn %pK, state %pK\n",
720 connector, state);
721 return -EINVAL;
722 }
723
724 c_conn = to_sde_connector(connector);
725 c_state = to_sde_connector_state(state);
726
727 idx = msm_property_index(&c_conn->property_info, property);
Clarence Ipe59fb3f2016-07-26 13:39:59 -0400728 if (idx == CONNECTOR_PROP_RETIRE_FENCE)
Dhaval Patel5cb59be2017-04-20 20:00:56 -0700729 rc = sde_fence_create(&c_conn->retire_fence, val, 0);
Clarence Ipe59fb3f2016-07-26 13:39:59 -0400730 else
731 /* get cached property value */
732 rc = msm_property_atomic_get(&c_conn->property_info,
733 c_state->property_values, 0, property, val);
Clarence Ipdd8021c2016-07-20 16:39:47 -0400734
735 /* allow for custom override */
736 if (c_conn->ops.get_property)
737 rc = c_conn->ops.get_property(connector,
738 (struct drm_connector_state *)state,
739 idx,
740 val,
741 c_conn->display);
742 return rc;
743}
744
Clarence Ipe59fb3f2016-07-26 13:39:59 -0400745void sde_connector_prepare_fence(struct drm_connector *connector)
746{
747 if (!connector) {
748 SDE_ERROR("invalid connector\n");
749 return;
750 }
751
752 sde_fence_prepare(&to_sde_connector(connector)->retire_fence);
753}
754
755void sde_connector_complete_commit(struct drm_connector *connector)
756{
757 if (!connector) {
758 SDE_ERROR("invalid connector\n");
759 return;
760 }
761
762 /* signal connector's retire fence */
763 sde_fence_signal(&to_sde_connector(connector)->retire_fence, 0);
764}
765
Clarence Ipdd8021c2016-07-20 16:39:47 -0400766static enum drm_connector_status
767sde_connector_detect(struct drm_connector *connector, bool force)
768{
769 enum drm_connector_status status = connector_status_unknown;
770 struct sde_connector *c_conn;
771
772 if (!connector) {
773 SDE_ERROR("invalid connector\n");
774 return status;
775 }
776
777 c_conn = to_sde_connector(connector);
778
779 if (c_conn->ops.detect)
780 status = c_conn->ops.detect(connector,
781 force,
782 c_conn->display);
783
784 return status;
785}
786
Clarence Ip90b282d2017-05-04 10:00:32 -0700787static int sde_connector_dpms(struct drm_connector *connector,
788 int mode)
789{
790 struct sde_connector *c_conn;
791
792 if (!connector) {
793 SDE_ERROR("invalid connector\n");
794 return -EINVAL;
795 }
796 c_conn = to_sde_connector(connector);
797
798 /* validate incoming dpms request */
799 switch (mode) {
800 case DRM_MODE_DPMS_ON:
801 case DRM_MODE_DPMS_STANDBY:
802 case DRM_MODE_DPMS_SUSPEND:
803 case DRM_MODE_DPMS_OFF:
804 SDE_DEBUG("conn %d dpms set to %d\n", connector->base.id, mode);
805 break;
806 default:
807 SDE_ERROR("conn %d dpms set to unrecognized mode %d\n",
808 connector->base.id, mode);
809 break;
810 }
811
812 mutex_lock(&c_conn->lock);
813 c_conn->dpms_mode = mode;
814 _sde_connector_update_power_locked(c_conn);
815 mutex_unlock(&c_conn->lock);
816
817 /* use helper for boilerplate handling */
818 return drm_atomic_helper_connector_dpms(connector, mode);
819}
820
821int sde_connector_get_dpms(struct drm_connector *connector)
822{
823 struct sde_connector *c_conn;
824 int rc;
825
826 if (!connector) {
827 SDE_DEBUG("invalid connector\n");
828 return DRM_MODE_DPMS_OFF;
829 }
830
831 c_conn = to_sde_connector(connector);
832
833 mutex_lock(&c_conn->lock);
834 rc = c_conn->dpms_mode;
835 mutex_unlock(&c_conn->lock);
836
837 return rc;
838}
839
Alan Kwong578cdaf2017-01-28 17:25:43 -0800840#ifdef CONFIG_DEBUG_FS
841/**
842 * sde_connector_init_debugfs - initialize connector debugfs
843 * @connector: Pointer to drm connector
844 */
845static int sde_connector_init_debugfs(struct drm_connector *connector)
846{
847 struct sde_connector *sde_connector;
848
849 if (!connector || !connector->debugfs_entry) {
850 SDE_ERROR("invalid connector\n");
851 return -EINVAL;
852 }
853
854 sde_connector = to_sde_connector(connector);
855
856 if (!debugfs_create_bool("fb_kmap", 0644, connector->debugfs_entry,
857 &sde_connector->fb_kmap)) {
858 SDE_ERROR("failed to create connector fb_kmap\n");
859 return -ENOMEM;
860 }
861
862 return 0;
863}
864#else
865static int sde_connector_init_debugfs(struct drm_connector *connector)
866{
867 return 0;
868}
869#endif
870
871static int sde_connector_late_register(struct drm_connector *connector)
872{
873 return sde_connector_init_debugfs(connector);
874}
875
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -0700876static void sde_connector_early_unregister(struct drm_connector *connector)
877{
878 /* debugfs under connector->debugfs are deleted by drm_debugfs */
879}
880
Clarence Ipdd8021c2016-07-20 16:39:47 -0400881static const struct drm_connector_funcs sde_connector_ops = {
Clarence Ip90b282d2017-05-04 10:00:32 -0700882 .dpms = sde_connector_dpms,
Clarence Ipdd8021c2016-07-20 16:39:47 -0400883 .reset = sde_connector_atomic_reset,
884 .detect = sde_connector_detect,
885 .destroy = sde_connector_destroy,
886 .fill_modes = drm_helper_probe_single_connector_modes,
887 .atomic_duplicate_state = sde_connector_atomic_duplicate_state,
888 .atomic_destroy_state = sde_connector_atomic_destroy_state,
889 .atomic_set_property = sde_connector_atomic_set_property,
890 .atomic_get_property = sde_connector_atomic_get_property,
891 .set_property = sde_connector_set_property,
Alan Kwong578cdaf2017-01-28 17:25:43 -0800892 .late_register = sde_connector_late_register,
Lloyd Atkinsonb020e0f2017-03-14 08:05:18 -0700893 .early_unregister = sde_connector_early_unregister,
Clarence Ipdd8021c2016-07-20 16:39:47 -0400894};
895
896static int sde_connector_get_modes(struct drm_connector *connector)
897{
898 struct sde_connector *c_conn;
899
900 if (!connector) {
901 SDE_ERROR("invalid connector\n");
902 return 0;
903 }
904
905 c_conn = to_sde_connector(connector);
906 if (!c_conn->ops.get_modes) {
907 SDE_DEBUG("missing get_modes callback\n");
908 return 0;
909 }
910
911 return c_conn->ops.get_modes(connector, c_conn->display);
912}
913
914static enum drm_mode_status
915sde_connector_mode_valid(struct drm_connector *connector,
916 struct drm_display_mode *mode)
917{
918 struct sde_connector *c_conn;
919
920 if (!connector || !mode) {
921 SDE_ERROR("invalid argument(s), conn %pK, mode %pK\n",
922 connector, mode);
923 return MODE_ERROR;
924 }
925
926 c_conn = to_sde_connector(connector);
927
928 if (c_conn->ops.mode_valid)
929 return c_conn->ops.mode_valid(connector, mode, c_conn->display);
930
931 /* assume all modes okay by default */
932 return MODE_OK;
933}
934
935static struct drm_encoder *
936sde_connector_best_encoder(struct drm_connector *connector)
937{
938 struct sde_connector *c_conn = to_sde_connector(connector);
939
940 if (!connector) {
941 SDE_ERROR("invalid connector\n");
942 return NULL;
943 }
944
945 /*
946 * This is true for now, revisit this code when multiple encoders are
947 * supported.
948 */
949 return c_conn->encoder;
950}
951
952static const struct drm_connector_helper_funcs sde_connector_helper_ops = {
953 .get_modes = sde_connector_get_modes,
954 .mode_valid = sde_connector_mode_valid,
955 .best_encoder = sde_connector_best_encoder,
956};
957
958struct drm_connector *sde_connector_init(struct drm_device *dev,
959 struct drm_encoder *encoder,
960 struct drm_panel *panel,
961 void *display,
962 const struct sde_connector_ops *ops,
963 int connector_poll,
964 int connector_type)
965{
966 struct msm_drm_private *priv;
967 struct sde_kms *sde_kms;
968 struct sde_kms_info *info;
969 struct sde_connector *c_conn = NULL;
Ping Li898b1bf2017-02-09 18:03:28 -0800970 struct dsi_display *dsi_display;
Lloyd Atkinson8ba47032017-03-22 17:13:32 -0400971 struct msm_display_info display_info;
Clarence Ipdd8021c2016-07-20 16:39:47 -0400972 int rc;
973
974 if (!dev || !dev->dev_private || !encoder) {
975 SDE_ERROR("invalid argument(s), dev %pK, enc %pK\n",
976 dev, encoder);
977 return ERR_PTR(-EINVAL);
978 }
979
980 priv = dev->dev_private;
981 if (!priv->kms) {
982 SDE_ERROR("invalid kms reference\n");
983 return ERR_PTR(-EINVAL);
984 }
985
986 c_conn = kzalloc(sizeof(*c_conn), GFP_KERNEL);
987 if (!c_conn) {
988 SDE_ERROR("failed to alloc sde connector\n");
989 return ERR_PTR(-ENOMEM);
990 }
991
992 rc = drm_connector_init(dev,
993 &c_conn->base,
994 &sde_connector_ops,
995 connector_type);
996 if (rc)
997 goto error_free_conn;
998
Clarence Ipa18d4832017-03-13 12:35:44 -0700999 spin_lock_init(&c_conn->event_lock);
1000
Clarence Ipdd8021c2016-07-20 16:39:47 -04001001 c_conn->connector_type = connector_type;
1002 c_conn->encoder = encoder;
1003 c_conn->panel = panel;
1004 c_conn->display = display;
1005
Clarence Ip90b282d2017-05-04 10:00:32 -07001006 c_conn->dpms_mode = DRM_MODE_DPMS_ON;
1007 c_conn->lp_mode = 0;
1008 c_conn->last_panel_power_mode = SDE_MODE_DPMS_ON;
1009
Alan Kwongdfa8c082016-07-29 04:10:00 -04001010 /* cache mmu_id's for later */
Clarence Ipdd8021c2016-07-20 16:39:47 -04001011 sde_kms = to_sde_kms(priv->kms);
Alan Kwongdfa8c082016-07-29 04:10:00 -04001012 if (sde_kms->vbif[VBIF_NRT]) {
1013 c_conn->mmu_id[SDE_IOMMU_DOMAIN_UNSECURE] =
1014 sde_kms->mmu_id[MSM_SMMU_DOMAIN_NRT_UNSECURE];
1015 c_conn->mmu_id[SDE_IOMMU_DOMAIN_SECURE] =
1016 sde_kms->mmu_id[MSM_SMMU_DOMAIN_NRT_SECURE];
1017 } else {
1018 c_conn->mmu_id[SDE_IOMMU_DOMAIN_UNSECURE] =
1019 sde_kms->mmu_id[MSM_SMMU_DOMAIN_UNSECURE];
1020 c_conn->mmu_id[SDE_IOMMU_DOMAIN_SECURE] =
1021 sde_kms->mmu_id[MSM_SMMU_DOMAIN_SECURE];
1022 }
Clarence Ipdd8021c2016-07-20 16:39:47 -04001023
1024 if (ops)
1025 c_conn->ops = *ops;
1026
1027 c_conn->base.helper_private = &sde_connector_helper_ops;
1028 c_conn->base.polled = connector_poll;
1029 c_conn->base.interlace_allowed = 0;
1030 c_conn->base.doublescan_allowed = 0;
1031
1032 snprintf(c_conn->name,
1033 SDE_CONNECTOR_NAME_SIZE,
1034 "conn%u",
1035 c_conn->base.base.id);
1036
Lloyd Atkinson5d40d312016-09-06 08:34:13 -04001037 rc = sde_fence_init(&c_conn->retire_fence, c_conn->name,
1038 c_conn->base.base.id);
Clarence Ipe59fb3f2016-07-26 13:39:59 -04001039 if (rc) {
1040 SDE_ERROR("failed to init fence, %d\n", rc);
1041 goto error_cleanup_conn;
1042 }
1043
Clarence Ip90b282d2017-05-04 10:00:32 -07001044 mutex_init(&c_conn->lock);
1045
Clarence Ipdd8021c2016-07-20 16:39:47 -04001046 rc = drm_mode_connector_attach_encoder(&c_conn->base, encoder);
1047 if (rc) {
1048 SDE_ERROR("failed to attach encoder to connector, %d\n", rc);
Lloyd Atkinsonab3dd302017-02-13 10:44:55 -08001049 goto error_cleanup_fence;
Clarence Ipdd8021c2016-07-20 16:39:47 -04001050 }
1051
Shashank Babu Chinta Venkata06c428e2017-04-17 13:52:28 -07001052 rc = sde_backlight_setup(c_conn, dev);
Dhaval Patel7cdd6662017-03-08 13:10:37 -08001053 if (rc) {
1054 SDE_ERROR("failed to setup backlight, rc=%d\n", rc);
1055 goto error_cleanup_fence;
Vishnuvardhan Prodduturi75b96802016-10-17 18:45:55 +05301056 }
1057
Clarence Ipdd8021c2016-07-20 16:39:47 -04001058 /* create properties */
1059 msm_property_init(&c_conn->property_info, &c_conn->base.base, dev,
1060 priv->conn_property, c_conn->property_data,
1061 CONNECTOR_PROP_COUNT, CONNECTOR_PROP_BLOBCOUNT,
1062 sizeof(struct sde_connector_state));
1063
1064 if (c_conn->ops.post_init) {
1065 info = kmalloc(sizeof(*info), GFP_KERNEL);
1066 if (!info) {
1067 SDE_ERROR("failed to allocate info buffer\n");
1068 rc = -ENOMEM;
Lloyd Atkinsonab3dd302017-02-13 10:44:55 -08001069 goto error_cleanup_fence;
Clarence Ipdd8021c2016-07-20 16:39:47 -04001070 }
1071
1072 sde_kms_info_reset(info);
1073 rc = c_conn->ops.post_init(&c_conn->base, info, display);
1074 if (rc) {
1075 SDE_ERROR("post-init failed, %d\n", rc);
1076 kfree(info);
Lloyd Atkinsonab3dd302017-02-13 10:44:55 -08001077 goto error_cleanup_fence;
Clarence Ipdd8021c2016-07-20 16:39:47 -04001078 }
1079
1080 msm_property_install_blob(&c_conn->property_info,
Dhaval Patel4e574842016-08-23 15:11:37 -07001081 "capabilities",
Clarence Ipdd8021c2016-07-20 16:39:47 -04001082 DRM_MODE_PROP_IMMUTABLE,
1083 CONNECTOR_PROP_SDE_INFO);
1084
1085 msm_property_set_blob(&c_conn->property_info,
Dhaval Patel4e574842016-08-23 15:11:37 -07001086 &c_conn->blob_caps,
Clarence Ipdd8021c2016-07-20 16:39:47 -04001087 SDE_KMS_INFO_DATA(info),
1088 SDE_KMS_INFO_DATALEN(info),
1089 CONNECTOR_PROP_SDE_INFO);
1090 kfree(info);
1091 }
1092
Ping Li898b1bf2017-02-09 18:03:28 -08001093 if (connector_type == DRM_MODE_CONNECTOR_DSI) {
1094 dsi_display = (struct dsi_display *)(display);
1095 if (dsi_display && dsi_display->panel &&
1096 dsi_display->panel->hdr_props.hdr_enabled == true) {
1097 msm_property_install_blob(&c_conn->property_info,
1098 "hdr_properties",
1099 DRM_MODE_PROP_IMMUTABLE,
1100 CONNECTOR_PROP_HDR_INFO);
1101
1102 msm_property_set_blob(&c_conn->property_info,
1103 &c_conn->blob_hdr,
1104 &dsi_display->panel->hdr_props,
1105 sizeof(dsi_display->panel->hdr_props),
1106 CONNECTOR_PROP_HDR_INFO);
1107 }
1108 }
1109
Lloyd Atkinson8ba47032017-03-22 17:13:32 -04001110 rc = sde_connector_get_info(&c_conn->base, &display_info);
1111 if (!rc && display_info.roi_caps.enabled) {
1112 msm_property_install_volatile_range(
1113 &c_conn->property_info, "sde_drm_roi_v1", 0x0,
1114 0, ~0, 0, CONNECTOR_PROP_ROI_V1);
1115 }
1116
Clarence Ipe59fb3f2016-07-26 13:39:59 -04001117 msm_property_install_range(&c_conn->property_info, "RETIRE_FENCE",
Dhaval Patel4e574842016-08-23 15:11:37 -07001118 0x0, 0, INR_OPEN_MAX, 0, CONNECTOR_PROP_RETIRE_FENCE);
Clarence Ipe59fb3f2016-07-26 13:39:59 -04001119
Lloyd Atkinson77382202017-02-01 14:59:43 -05001120 msm_property_install_range(&c_conn->property_info, "autorefresh",
1121 0x0, 0, AUTOREFRESH_MAX_FRAME_CNT, 0,
1122 CONNECTOR_PROP_AUTOREFRESH);
1123
Lloyd Atkinsonb6191972016-08-10 18:31:46 -04001124 /* enum/bitmask properties */
1125 msm_property_install_enum(&c_conn->property_info, "topology_name",
1126 DRM_MODE_PROP_IMMUTABLE, 0, e_topology_name,
1127 ARRAY_SIZE(e_topology_name),
1128 CONNECTOR_PROP_TOPOLOGY_NAME);
1129 msm_property_install_enum(&c_conn->property_info, "topology_control",
1130 0, 1, e_topology_control,
1131 ARRAY_SIZE(e_topology_control),
1132 CONNECTOR_PROP_TOPOLOGY_CONTROL);
Clarence Ip90b282d2017-05-04 10:00:32 -07001133 msm_property_install_enum(&c_conn->property_info, "LP",
1134 0, 0, e_power_mode,
1135 ARRAY_SIZE(e_power_mode),
1136 CONNECTOR_PROP_LP);
Lloyd Atkinsonb6191972016-08-10 18:31:46 -04001137
Clarence Ipdd8021c2016-07-20 16:39:47 -04001138 rc = msm_property_install_get_status(&c_conn->property_info);
1139 if (rc) {
1140 SDE_ERROR("failed to create one or more properties\n");
1141 goto error_destroy_property;
1142 }
1143
Lloyd Atkinsonb6191972016-08-10 18:31:46 -04001144 SDE_DEBUG("connector %d attach encoder %d\n",
1145 c_conn->base.base.id, encoder->base.id);
1146
Clarence Ipdd8021c2016-07-20 16:39:47 -04001147 priv->connectors[priv->num_connectors++] = &c_conn->base;
1148
1149 return &c_conn->base;
1150
1151error_destroy_property:
Dhaval Patel4e574842016-08-23 15:11:37 -07001152 if (c_conn->blob_caps)
1153 drm_property_unreference_blob(c_conn->blob_caps);
Ping Li898b1bf2017-02-09 18:03:28 -08001154 if (c_conn->blob_hdr)
1155 drm_property_unreference_blob(c_conn->blob_hdr);
Clarence Ipdd8021c2016-07-20 16:39:47 -04001156 msm_property_destroy(&c_conn->property_info);
Clarence Ipe59fb3f2016-07-26 13:39:59 -04001157error_cleanup_fence:
Clarence Ip90b282d2017-05-04 10:00:32 -07001158 mutex_destroy(&c_conn->lock);
Clarence Ipe59fb3f2016-07-26 13:39:59 -04001159 sde_fence_deinit(&c_conn->retire_fence);
Clarence Ipdd8021c2016-07-20 16:39:47 -04001160error_cleanup_conn:
1161 drm_connector_cleanup(&c_conn->base);
1162error_free_conn:
1163 kfree(c_conn);
1164
1165 return ERR_PTR(rc);
1166}
Gopikrishnaiah Anandande2c81b2017-03-15 12:41:29 -07001167
1168int sde_connector_register_custom_event(struct sde_kms *kms,
1169 struct drm_connector *conn_drm, u32 event, bool val)
1170{
1171 return -EINVAL;
1172}