diff options
author | Jani Nikula <jani.nikula@intel.com> | 2015-01-23 08:30:56 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2015-01-29 10:51:13 -0500 |
commit | 593e0622f4e415351f0a5148aaf0ce5abf667c05 (patch) | |
tree | d3697c3a5d0b988c43c83917514f456e7016662c | |
parent | e3d998451090800927f283981319e7d2f8fb7059 (diff) |
drm/i915/dsi: switch to drm_panel interface
Replace intel_dsi_device and intel_dsi_dev_ops with drm_panel and
drm_panel_funcs. They are adequate for what we have now, and if we end
up needing more than this we should improve drm_panel. This will keep us
better aligned with the drm core infrastructure.
The panel driver initialization changes a bit. It still remains hideous,
but fixing that is beyond the scope here.
v2: extend mode config mutex to cover drm_panel_get_modes (Shobhit)
vbt_panel->intel_dsi = intel_dsi in vbt panel init (Shobhit)
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
Reviewed-By: Shobhit Kumar <shobhit.kumar@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/Kconfig | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dsi.c | 68 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dsi.h | 27 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | 180 |
4 files changed, 157 insertions, 119 deletions
diff --git a/drivers/gpu/drm/i915/Kconfig b/drivers/gpu/drm/i915/Kconfig index 4e39ab34eb1c..da196cd07263 100644 --- a/drivers/gpu/drm/i915/Kconfig +++ b/drivers/gpu/drm/i915/Kconfig | |||
@@ -11,6 +11,7 @@ config DRM_I915 | |||
11 | select SHMEM | 11 | select SHMEM |
12 | select TMPFS | 12 | select TMPFS |
13 | select DRM_KMS_HELPER | 13 | select DRM_KMS_HELPER |
14 | select DRM_PANEL | ||
14 | # i915 depends on ACPI_VIDEO when ACPI is enabled | 15 | # i915 depends on ACPI_VIDEO when ACPI is enabled |
15 | # but for select to work, need to select ACPI_VIDEO's dependencies, ick | 16 | # but for select to work, need to select ACPI_VIDEO's dependencies, ick |
16 | select BACKLIGHT_LCD_SUPPORT if ACPI | 17 | select BACKLIGHT_LCD_SUPPORT if ACPI |
diff --git a/drivers/gpu/drm/i915/intel_dsi.c b/drivers/gpu/drm/i915/intel_dsi.c index 317e63396060..1e151e00a614 100644 --- a/drivers/gpu/drm/i915/intel_dsi.c +++ b/drivers/gpu/drm/i915/intel_dsi.c | |||
@@ -28,18 +28,20 @@ | |||
28 | #include <drm/drm_crtc.h> | 28 | #include <drm/drm_crtc.h> |
29 | #include <drm/drm_edid.h> | 29 | #include <drm/drm_edid.h> |
30 | #include <drm/i915_drm.h> | 30 | #include <drm/i915_drm.h> |
31 | #include <drm/drm_panel.h> | ||
31 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
32 | #include "i915_drv.h" | 33 | #include "i915_drv.h" |
33 | #include "intel_drv.h" | 34 | #include "intel_drv.h" |
34 | #include "intel_dsi.h" | 35 | #include "intel_dsi.h" |
35 | #include "intel_dsi_cmd.h" | 36 | #include "intel_dsi_cmd.h" |
36 | 37 | ||
37 | /* the sub-encoders aka panel drivers */ | 38 | static const struct { |
38 | static const struct intel_dsi_device intel_dsi_devices[] = { | 39 | u16 panel_id; |
40 | struct drm_panel * (*init)(struct intel_dsi *intel_dsi, u16 panel_id); | ||
41 | } intel_dsi_drivers[] = { | ||
39 | { | 42 | { |
40 | .panel_id = MIPI_DSI_GENERIC_PANEL_ID, | 43 | .panel_id = MIPI_DSI_GENERIC_PANEL_ID, |
41 | .name = "vbt-generic-dsi-vid-mode-display", | 44 | .init = vbt_panel_init, |
42 | .dev_ops = &vbt_generic_dsi_display_ops, | ||
43 | }, | 45 | }, |
44 | }; | 46 | }; |
45 | 47 | ||
@@ -215,8 +217,7 @@ static void intel_dsi_enable(struct intel_encoder *encoder) | |||
215 | dpi_send_cmd(intel_dsi, TURN_ON, DPI_LP_MODE_EN, port); | 217 | dpi_send_cmd(intel_dsi, TURN_ON, DPI_LP_MODE_EN, port); |
216 | msleep(100); | 218 | msleep(100); |
217 | 219 | ||
218 | if (intel_dsi->dev.dev_ops->enable) | 220 | drm_panel_enable(intel_dsi->panel); |
219 | intel_dsi->dev.dev_ops->enable(&intel_dsi->dev); | ||
220 | 221 | ||
221 | for_each_dsi_port(port, intel_dsi->ports) | 222 | for_each_dsi_port(port, intel_dsi->ports) |
222 | wait_for_dsi_fifo_empty(intel_dsi, port); | 223 | wait_for_dsi_fifo_empty(intel_dsi, port); |
@@ -256,8 +257,7 @@ static void intel_dsi_pre_enable(struct intel_encoder *encoder) | |||
256 | 257 | ||
257 | msleep(intel_dsi->panel_on_delay); | 258 | msleep(intel_dsi->panel_on_delay); |
258 | 259 | ||
259 | if (intel_dsi->dev.dev_ops->panel_reset) | 260 | drm_panel_prepare(intel_dsi->panel); |
260 | intel_dsi->dev.dev_ops->panel_reset(&intel_dsi->dev); | ||
261 | 261 | ||
262 | for_each_dsi_port(port, intel_dsi->ports) | 262 | for_each_dsi_port(port, intel_dsi->ports) |
263 | wait_for_dsi_fifo_empty(intel_dsi, port); | 263 | wait_for_dsi_fifo_empty(intel_dsi, port); |
@@ -330,8 +330,7 @@ static void intel_dsi_disable(struct intel_encoder *encoder) | |||
330 | } | 330 | } |
331 | /* if disable packets are sent before sending shutdown packet then in | 331 | /* if disable packets are sent before sending shutdown packet then in |
332 | * some next enable sequence send turn on packet error is observed */ | 332 | * some next enable sequence send turn on packet error is observed */ |
333 | if (intel_dsi->dev.dev_ops->disable) | 333 | drm_panel_disable(intel_dsi->panel); |
334 | intel_dsi->dev.dev_ops->disable(&intel_dsi->dev); | ||
335 | 334 | ||
336 | for_each_dsi_port(port, intel_dsi->ports) | 335 | for_each_dsi_port(port, intel_dsi->ports) |
337 | wait_for_dsi_fifo_empty(intel_dsi, port); | 336 | wait_for_dsi_fifo_empty(intel_dsi, port); |
@@ -396,8 +395,7 @@ static void intel_dsi_post_disable(struct intel_encoder *encoder) | |||
396 | val &= ~DPOUNIT_CLOCK_GATE_DISABLE; | 395 | val &= ~DPOUNIT_CLOCK_GATE_DISABLE; |
397 | I915_WRITE(DSPCLK_GATE_D, val); | 396 | I915_WRITE(DSPCLK_GATE_D, val); |
398 | 397 | ||
399 | if (intel_dsi->dev.dev_ops->disable_panel_power) | 398 | drm_panel_unprepare(intel_dsi->panel); |
400 | intel_dsi->dev.dev_ops->disable_panel_power(&intel_dsi->dev); | ||
401 | 399 | ||
402 | msleep(intel_dsi->panel_off_delay); | 400 | msleep(intel_dsi->panel_off_delay); |
403 | msleep(intel_dsi->panel_pwr_cycle_delay); | 401 | msleep(intel_dsi->panel_pwr_cycle_delay); |
@@ -761,7 +759,7 @@ static int intel_dsi_get_modes(struct drm_connector *connector) | |||
761 | return 1; | 759 | return 1; |
762 | } | 760 | } |
763 | 761 | ||
764 | static void intel_dsi_destroy(struct drm_connector *connector) | 762 | static void intel_dsi_connector_destroy(struct drm_connector *connector) |
765 | { | 763 | { |
766 | struct intel_connector *intel_connector = to_intel_connector(connector); | 764 | struct intel_connector *intel_connector = to_intel_connector(connector); |
767 | 765 | ||
@@ -771,8 +769,20 @@ static void intel_dsi_destroy(struct drm_connector *connector) | |||
771 | kfree(connector); | 769 | kfree(connector); |
772 | } | 770 | } |
773 | 771 | ||
772 | static void intel_dsi_encoder_destroy(struct drm_encoder *encoder) | ||
773 | { | ||
774 | struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); | ||
775 | |||
776 | if (intel_dsi->panel) { | ||
777 | drm_panel_detach(intel_dsi->panel); | ||
778 | /* XXX: Logically this call belongs in the panel driver. */ | ||
779 | drm_panel_remove(intel_dsi->panel); | ||
780 | } | ||
781 | intel_encoder_destroy(encoder); | ||
782 | } | ||
783 | |||
774 | static const struct drm_encoder_funcs intel_dsi_funcs = { | 784 | static const struct drm_encoder_funcs intel_dsi_funcs = { |
775 | .destroy = intel_encoder_destroy, | 785 | .destroy = intel_dsi_encoder_destroy, |
776 | }; | 786 | }; |
777 | 787 | ||
778 | static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs = { | 788 | static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs = { |
@@ -784,7 +794,7 @@ static const struct drm_connector_helper_funcs intel_dsi_connector_helper_funcs | |||
784 | static const struct drm_connector_funcs intel_dsi_connector_funcs = { | 794 | static const struct drm_connector_funcs intel_dsi_connector_funcs = { |
785 | .dpms = intel_connector_dpms, | 795 | .dpms = intel_connector_dpms, |
786 | .detect = intel_dsi_detect, | 796 | .detect = intel_dsi_detect, |
787 | .destroy = intel_dsi_destroy, | 797 | .destroy = intel_dsi_connector_destroy, |
788 | .fill_modes = drm_helper_probe_single_connector_modes, | 798 | .fill_modes = drm_helper_probe_single_connector_modes, |
789 | .atomic_get_property = intel_connector_atomic_get_property, | 799 | .atomic_get_property = intel_connector_atomic_get_property, |
790 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, | 800 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
@@ -797,9 +807,8 @@ void intel_dsi_init(struct drm_device *dev) | |||
797 | struct drm_encoder *encoder; | 807 | struct drm_encoder *encoder; |
798 | struct intel_connector *intel_connector; | 808 | struct intel_connector *intel_connector; |
799 | struct drm_connector *connector; | 809 | struct drm_connector *connector; |
800 | struct drm_display_mode *fixed_mode = NULL; | 810 | struct drm_display_mode *scan, *fixed_mode = NULL; |
801 | struct drm_i915_private *dev_priv = dev->dev_private; | 811 | struct drm_i915_private *dev_priv = dev->dev_private; |
802 | const struct intel_dsi_device *dsi; | ||
803 | unsigned int i; | 812 | unsigned int i; |
804 | 813 | ||
805 | DRM_DEBUG_KMS("\n"); | 814 | DRM_DEBUG_KMS("\n"); |
@@ -856,15 +865,14 @@ void intel_dsi_init(struct drm_device *dev) | |||
856 | intel_dsi->ports = (1 << PORT_C); | 865 | intel_dsi->ports = (1 << PORT_C); |
857 | } | 866 | } |
858 | 867 | ||
859 | for (i = 0; i < ARRAY_SIZE(intel_dsi_devices); i++) { | 868 | for (i = 0; i < ARRAY_SIZE(intel_dsi_drivers); i++) { |
860 | dsi = &intel_dsi_devices[i]; | 869 | intel_dsi->panel = intel_dsi_drivers[i].init(intel_dsi, |
861 | intel_dsi->dev = *dsi; | 870 | intel_dsi_drivers[i].panel_id); |
862 | 871 | if (intel_dsi->panel) | |
863 | if (dsi->dev_ops->init(&intel_dsi->dev)) | ||
864 | break; | 872 | break; |
865 | } | 873 | } |
866 | 874 | ||
867 | if (i == ARRAY_SIZE(intel_dsi_devices)) { | 875 | if (!intel_dsi->panel) { |
868 | DRM_DEBUG_KMS("no device found\n"); | 876 | DRM_DEBUG_KMS("no device found\n"); |
869 | goto err; | 877 | goto err; |
870 | } | 878 | } |
@@ -884,13 +892,23 @@ void intel_dsi_init(struct drm_device *dev) | |||
884 | 892 | ||
885 | drm_connector_register(connector); | 893 | drm_connector_register(connector); |
886 | 894 | ||
887 | fixed_mode = dsi->dev_ops->get_modes(&intel_dsi->dev); | 895 | drm_panel_attach(intel_dsi->panel, connector); |
896 | |||
897 | mutex_lock(&dev->mode_config.mutex); | ||
898 | drm_panel_get_modes(intel_dsi->panel); | ||
899 | list_for_each_entry(scan, &connector->probed_modes, head) { | ||
900 | if ((scan->type & DRM_MODE_TYPE_PREFERRED)) { | ||
901 | fixed_mode = drm_mode_duplicate(dev, scan); | ||
902 | break; | ||
903 | } | ||
904 | } | ||
905 | mutex_unlock(&dev->mode_config.mutex); | ||
906 | |||
888 | if (!fixed_mode) { | 907 | if (!fixed_mode) { |
889 | DRM_DEBUG_KMS("no fixed mode\n"); | 908 | DRM_DEBUG_KMS("no fixed mode\n"); |
890 | goto err; | 909 | goto err; |
891 | } | 910 | } |
892 | 911 | ||
893 | fixed_mode->type |= DRM_MODE_TYPE_PREFERRED; | ||
894 | intel_panel_init(&intel_connector->panel, fixed_mode, NULL); | 912 | intel_panel_init(&intel_connector->panel, fixed_mode, NULL); |
895 | 913 | ||
896 | return; | 914 | return; |
diff --git a/drivers/gpu/drm/i915/intel_dsi.h b/drivers/gpu/drm/i915/intel_dsi.h index 22f87036a256..fc0b2b8d90f1 100644 --- a/drivers/gpu/drm/i915/intel_dsi.h +++ b/drivers/gpu/drm/i915/intel_dsi.h | |||
@@ -33,33 +33,10 @@ | |||
33 | #define DSI_DUAL_LINK_FRONT_BACK 1 | 33 | #define DSI_DUAL_LINK_FRONT_BACK 1 |
34 | #define DSI_DUAL_LINK_PIXEL_ALT 2 | 34 | #define DSI_DUAL_LINK_PIXEL_ALT 2 |
35 | 35 | ||
36 | struct intel_dsi_device { | ||
37 | unsigned int panel_id; | ||
38 | const char *name; | ||
39 | const struct intel_dsi_dev_ops *dev_ops; | ||
40 | void *dev_priv; | ||
41 | }; | ||
42 | |||
43 | struct intel_dsi_dev_ops { | ||
44 | bool (*init)(struct intel_dsi_device *dsi); | ||
45 | |||
46 | void (*panel_reset)(struct intel_dsi_device *dsi); | ||
47 | |||
48 | void (*disable_panel_power)(struct intel_dsi_device *dsi); | ||
49 | |||
50 | /* This callback must be able to assume DSI commands can be sent */ | ||
51 | void (*enable)(struct intel_dsi_device *dsi); | ||
52 | |||
53 | /* This callback must be able to assume DSI commands can be sent */ | ||
54 | void (*disable)(struct intel_dsi_device *dsi); | ||
55 | |||
56 | struct drm_display_mode *(*get_modes)(struct intel_dsi_device *dsi); | ||
57 | }; | ||
58 | |||
59 | struct intel_dsi { | 36 | struct intel_dsi { |
60 | struct intel_encoder base; | 37 | struct intel_encoder base; |
61 | 38 | ||
62 | struct intel_dsi_device dev; | 39 | struct drm_panel *panel; |
63 | 40 | ||
64 | struct intel_connector *attached_connector; | 41 | struct intel_connector *attached_connector; |
65 | 42 | ||
@@ -130,6 +107,6 @@ extern void vlv_enable_dsi_pll(struct intel_encoder *encoder); | |||
130 | extern void vlv_disable_dsi_pll(struct intel_encoder *encoder); | 107 | extern void vlv_disable_dsi_pll(struct intel_encoder *encoder); |
131 | extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp); | 108 | extern u32 vlv_get_dsi_pclk(struct intel_encoder *encoder, int pipe_bpp); |
132 | 109 | ||
133 | extern struct intel_dsi_dev_ops vbt_generic_dsi_display_ops; | 110 | struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id); |
134 | 111 | ||
135 | #endif /* _INTEL_DSI_H */ | 112 | #endif /* _INTEL_DSI_H */ |
diff --git a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c index 561ec2981dfd..ac7a24dcf7f7 100644 --- a/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c +++ b/drivers/gpu/drm/i915/intel_dsi_panel_vbt.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <drm/drm_crtc.h> | 28 | #include <drm/drm_crtc.h> |
29 | #include <drm/drm_edid.h> | 29 | #include <drm/drm_edid.h> |
30 | #include <drm/i915_drm.h> | 30 | #include <drm/i915_drm.h> |
31 | #include <drm/drm_panel.h> | ||
31 | #include <linux/slab.h> | 32 | #include <linux/slab.h> |
32 | #include <video/mipi_display.h> | 33 | #include <video/mipi_display.h> |
33 | #include <asm/intel-mid.h> | 34 | #include <asm/intel-mid.h> |
@@ -37,6 +38,16 @@ | |||
37 | #include "intel_dsi.h" | 38 | #include "intel_dsi.h" |
38 | #include "intel_dsi_cmd.h" | 39 | #include "intel_dsi_cmd.h" |
39 | 40 | ||
41 | struct vbt_panel { | ||
42 | struct drm_panel panel; | ||
43 | struct intel_dsi *intel_dsi; | ||
44 | }; | ||
45 | |||
46 | static inline struct vbt_panel *to_vbt_panel(struct drm_panel *panel) | ||
47 | { | ||
48 | return container_of(panel, struct vbt_panel, panel); | ||
49 | } | ||
50 | |||
40 | #define MIPI_TRANSFER_MODE_SHIFT 0 | 51 | #define MIPI_TRANSFER_MODE_SHIFT 0 |
41 | #define MIPI_VIRTUAL_CHANNEL_SHIFT 1 | 52 | #define MIPI_VIRTUAL_CHANNEL_SHIFT 1 |
42 | #define MIPI_PORT_SHIFT 3 | 53 | #define MIPI_PORT_SHIFT 3 |
@@ -272,14 +283,103 @@ static void generic_exec_sequence(struct intel_dsi *intel_dsi, const u8 *data) | |||
272 | } | 283 | } |
273 | } | 284 | } |
274 | 285 | ||
275 | static bool generic_init(struct intel_dsi_device *dsi) | 286 | static int vbt_panel_prepare(struct drm_panel *panel) |
287 | { | ||
288 | struct vbt_panel *vbt_panel = to_vbt_panel(panel); | ||
289 | struct intel_dsi *intel_dsi = vbt_panel->intel_dsi; | ||
290 | struct drm_device *dev = intel_dsi->base.base.dev; | ||
291 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
292 | const u8 *sequence; | ||
293 | |||
294 | sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET]; | ||
295 | generic_exec_sequence(intel_dsi, sequence); | ||
296 | |||
297 | sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; | ||
298 | generic_exec_sequence(intel_dsi, sequence); | ||
299 | |||
300 | return 0; | ||
301 | } | ||
302 | |||
303 | static int vbt_panel_unprepare(struct drm_panel *panel) | ||
304 | { | ||
305 | struct vbt_panel *vbt_panel = to_vbt_panel(panel); | ||
306 | struct intel_dsi *intel_dsi = vbt_panel->intel_dsi; | ||
307 | struct drm_device *dev = intel_dsi->base.base.dev; | ||
308 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
309 | const u8 *sequence; | ||
310 | |||
311 | sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]; | ||
312 | generic_exec_sequence(intel_dsi, sequence); | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | static int vbt_panel_enable(struct drm_panel *panel) | ||
318 | { | ||
319 | struct vbt_panel *vbt_panel = to_vbt_panel(panel); | ||
320 | struct intel_dsi *intel_dsi = vbt_panel->intel_dsi; | ||
321 | struct drm_device *dev = intel_dsi->base.base.dev; | ||
322 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
323 | const u8 *sequence; | ||
324 | |||
325 | sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_ON]; | ||
326 | generic_exec_sequence(intel_dsi, sequence); | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static int vbt_panel_disable(struct drm_panel *panel) | ||
332 | { | ||
333 | struct vbt_panel *vbt_panel = to_vbt_panel(panel); | ||
334 | struct intel_dsi *intel_dsi = vbt_panel->intel_dsi; | ||
335 | struct drm_device *dev = intel_dsi->base.base.dev; | ||
336 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
337 | const u8 *sequence; | ||
338 | |||
339 | sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_OFF]; | ||
340 | generic_exec_sequence(intel_dsi, sequence); | ||
341 | |||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static int vbt_panel_get_modes(struct drm_panel *panel) | ||
346 | { | ||
347 | struct vbt_panel *vbt_panel = to_vbt_panel(panel); | ||
348 | struct intel_dsi *intel_dsi = vbt_panel->intel_dsi; | ||
349 | struct drm_device *dev = intel_dsi->base.base.dev; | ||
350 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
351 | struct drm_display_mode *mode; | ||
352 | |||
353 | if (!panel->connector) | ||
354 | return 0; | ||
355 | |||
356 | mode = drm_mode_duplicate(dev, dev_priv->vbt.lfp_lvds_vbt_mode); | ||
357 | if (!mode) | ||
358 | return 0; | ||
359 | |||
360 | mode->type |= DRM_MODE_TYPE_PREFERRED; | ||
361 | |||
362 | drm_mode_probed_add(panel->connector, mode); | ||
363 | |||
364 | return 1; | ||
365 | } | ||
366 | |||
367 | static const struct drm_panel_funcs vbt_panel_funcs = { | ||
368 | .disable = vbt_panel_disable, | ||
369 | .unprepare = vbt_panel_unprepare, | ||
370 | .prepare = vbt_panel_prepare, | ||
371 | .enable = vbt_panel_enable, | ||
372 | .get_modes = vbt_panel_get_modes, | ||
373 | }; | ||
374 | |||
375 | struct drm_panel *vbt_panel_init(struct intel_dsi *intel_dsi, u16 panel_id) | ||
276 | { | 376 | { |
277 | struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev); | ||
278 | struct drm_device *dev = intel_dsi->base.base.dev; | 377 | struct drm_device *dev = intel_dsi->base.base.dev; |
279 | struct drm_i915_private *dev_priv = dev->dev_private; | 378 | struct drm_i915_private *dev_priv = dev->dev_private; |
280 | struct mipi_config *mipi_config = dev_priv->vbt.dsi.config; | 379 | struct mipi_config *mipi_config = dev_priv->vbt.dsi.config; |
281 | struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps; | 380 | struct mipi_pps_data *pps = dev_priv->vbt.dsi.pps; |
282 | struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode; | 381 | struct drm_display_mode *mode = dev_priv->vbt.lfp_lvds_vbt_mode; |
382 | struct vbt_panel *vbt_panel; | ||
283 | u32 bits_per_pixel = 24; | 383 | u32 bits_per_pixel = 24; |
284 | u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui; | 384 | u32 tlpx_ns, extra_byte_count, bitrate, tlpx_ui; |
285 | u32 ui_num, ui_den; | 385 | u32 ui_num, ui_den; |
@@ -346,7 +446,7 @@ static bool generic_init(struct intel_dsi_device *dsi) | |||
346 | if (mipi_config->target_burst_mode_freq < | 446 | if (mipi_config->target_burst_mode_freq < |
347 | computed_ddr) { | 447 | computed_ddr) { |
348 | DRM_ERROR("Burst mode freq is less than computed\n"); | 448 | DRM_ERROR("Burst mode freq is less than computed\n"); |
349 | return false; | 449 | return NULL; |
350 | } | 450 | } |
351 | 451 | ||
352 | burst_mode_ratio = DIV_ROUND_UP( | 452 | burst_mode_ratio = DIV_ROUND_UP( |
@@ -356,7 +456,7 @@ static bool generic_init(struct intel_dsi_device *dsi) | |||
356 | pclk = DIV_ROUND_UP(pclk * burst_mode_ratio, 100); | 456 | pclk = DIV_ROUND_UP(pclk * burst_mode_ratio, 100); |
357 | } else { | 457 | } else { |
358 | DRM_ERROR("Burst mode target is not set\n"); | 458 | DRM_ERROR("Burst mode target is not set\n"); |
359 | return false; | 459 | return NULL; |
360 | } | 460 | } |
361 | } else | 461 | } else |
362 | burst_mode_ratio = 100; | 462 | burst_mode_ratio = 100; |
@@ -557,71 +657,13 @@ static bool generic_init(struct intel_dsi_device *dsi) | |||
557 | intel_dsi->panel_off_delay = pps->panel_off_delay / 10; | 657 | intel_dsi->panel_off_delay = pps->panel_off_delay / 10; |
558 | intel_dsi->panel_pwr_cycle_delay = pps->panel_power_cycle_delay / 10; | 658 | intel_dsi->panel_pwr_cycle_delay = pps->panel_power_cycle_delay / 10; |
559 | 659 | ||
560 | return true; | 660 | /* This is cheating a bit with the cleanup. */ |
561 | } | 661 | vbt_panel = devm_kzalloc(dev->dev, sizeof(*vbt_panel), GFP_KERNEL); |
562 | |||
563 | static void generic_panel_reset(struct intel_dsi_device *dsi) | ||
564 | { | ||
565 | struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev); | ||
566 | struct drm_device *dev = intel_dsi->base.base.dev; | ||
567 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
568 | |||
569 | char *sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_ASSERT_RESET]; | ||
570 | |||
571 | generic_exec_sequence(intel_dsi, sequence); | ||
572 | |||
573 | sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_INIT_OTP]; | ||
574 | generic_exec_sequence(intel_dsi, sequence); | ||
575 | } | ||
576 | |||
577 | static void generic_disable_panel_power(struct intel_dsi_device *dsi) | ||
578 | { | ||
579 | struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev); | ||
580 | struct drm_device *dev = intel_dsi->base.base.dev; | ||
581 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
582 | |||
583 | char *sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DEASSERT_RESET]; | ||
584 | |||
585 | generic_exec_sequence(intel_dsi, sequence); | ||
586 | } | ||
587 | |||
588 | static void generic_enable(struct intel_dsi_device *dsi) | ||
589 | { | ||
590 | struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev); | ||
591 | struct drm_device *dev = intel_dsi->base.base.dev; | ||
592 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
593 | 662 | ||
594 | char *sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_ON]; | 663 | vbt_panel->intel_dsi = intel_dsi; |
664 | drm_panel_init(&vbt_panel->panel); | ||
665 | vbt_panel->panel.funcs = &vbt_panel_funcs; | ||
666 | drm_panel_add(&vbt_panel->panel); | ||
595 | 667 | ||
596 | generic_exec_sequence(intel_dsi, sequence); | 668 | return &vbt_panel->panel; |
597 | } | 669 | } |
598 | |||
599 | static void generic_disable(struct intel_dsi_device *dsi) | ||
600 | { | ||
601 | struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev); | ||
602 | struct drm_device *dev = intel_dsi->base.base.dev; | ||
603 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
604 | |||
605 | char *sequence = dev_priv->vbt.dsi.sequence[MIPI_SEQ_DISPLAY_OFF]; | ||
606 | |||
607 | generic_exec_sequence(intel_dsi, sequence); | ||
608 | } | ||
609 | |||
610 | static struct drm_display_mode *generic_get_modes(struct intel_dsi_device *dsi) | ||
611 | { | ||
612 | struct intel_dsi *intel_dsi = container_of(dsi, struct intel_dsi, dev); | ||
613 | struct drm_device *dev = intel_dsi->base.base.dev; | ||
614 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
615 | |||
616 | dev_priv->vbt.lfp_lvds_vbt_mode->type |= DRM_MODE_TYPE_PREFERRED; | ||
617 | return dev_priv->vbt.lfp_lvds_vbt_mode; | ||
618 | } | ||
619 | |||
620 | struct intel_dsi_dev_ops vbt_generic_dsi_display_ops = { | ||
621 | .init = generic_init, | ||
622 | .panel_reset = generic_panel_reset, | ||
623 | .disable_panel_power = generic_disable_panel_power, | ||
624 | .enable = generic_enable, | ||
625 | .disable = generic_disable, | ||
626 | .get_modes = generic_get_modes, | ||
627 | }; | ||