|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
| 2 | + |
| 3 | +#include <linux/backlight.h> |
| 4 | +#include <drm/drm_device.h> |
| 5 | +#include <drm/drm_mipi_dsi.h> |
| 6 | +#include <drm/drm_mode.h> |
| 7 | +#include <drm/drm_modes.h> |
| 8 | +#include <drm/drm_panel.h> |
| 9 | +#include <drm/drm_probe_helper.h> |
| 10 | +#include <video/mipi_display.h> |
| 11 | + |
| 12 | +struct summit_data { |
| 13 | + struct mipi_dsi_device *dsi; |
| 14 | + struct backlight_device *bl; |
| 15 | + struct drm_panel panel; |
| 16 | +}; |
| 17 | + |
| 18 | +static int summit_set_brightness(struct device *dev) |
| 19 | +{ |
| 20 | + struct summit_data *s_data = dev_get_drvdata(dev); |
| 21 | + int level = backlight_get_brightness(s_data->bl); |
| 22 | + |
| 23 | + return mipi_dsi_dcs_set_display_brightness(s_data->dsi, level); |
| 24 | +} |
| 25 | + |
| 26 | +static int summit_bl_update_status(struct backlight_device *dev) |
| 27 | +{ |
| 28 | + return summit_set_brightness(&dev->dev); |
| 29 | +} |
| 30 | + |
| 31 | +static const struct backlight_ops summit_bl_ops = { |
| 32 | + .update_status = summit_bl_update_status, |
| 33 | +}; |
| 34 | + |
| 35 | +static struct drm_display_mode summit_mode = { |
| 36 | + .vdisplay = 2008, |
| 37 | + .hdisplay = 60, |
| 38 | + .hsync_start = 60 + 8, |
| 39 | + .hsync_end = 60 + 8 + 80, |
| 40 | + .htotal = 60 + 8 + 80 + 40, |
| 41 | + .vsync_start = 2008 + 1, |
| 42 | + .vsync_end = 2008 + 1 + 15, |
| 43 | + .vtotal = 2008 + 1 + 15 + 6, |
| 44 | + .clock = ((60 + 8 + 80 + 40) * (2008 + 1 + 15 + 6) * 60) / 1000, |
| 45 | + .type = DRM_MODE_TYPE_DRIVER, |
| 46 | + .flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_NVSYNC, |
| 47 | +}; |
| 48 | + |
| 49 | +static int summit_get_modes(struct drm_panel *panel, |
| 50 | + struct drm_connector *connector) |
| 51 | +{ |
| 52 | + connector->display_info.non_desktop = true; |
| 53 | + drm_object_property_set_value(&connector->base, |
| 54 | + connector->dev->mode_config.non_desktop_property, |
| 55 | + connector->display_info.non_desktop); |
| 56 | + |
| 57 | + return drm_connector_helper_get_modes_fixed(connector, &summit_mode); |
| 58 | +} |
| 59 | + |
| 60 | +static const struct drm_panel_funcs summit_panel_funcs = { |
| 61 | + .get_modes = summit_get_modes, |
| 62 | +}; |
| 63 | + |
| 64 | +static int summit_probe(struct mipi_dsi_device *dsi) |
| 65 | +{ |
| 66 | + struct backlight_properties props = { 0 }; |
| 67 | + struct device *dev = &dsi->dev; |
| 68 | + struct summit_data *s_data; |
| 69 | + int ret; |
| 70 | + |
| 71 | + s_data = devm_kzalloc(dev, sizeof(*s_data), GFP_KERNEL); |
| 72 | + if (!s_data) |
| 73 | + return -ENOMEM; |
| 74 | + |
| 75 | + mipi_dsi_set_drvdata(dsi, s_data); |
| 76 | + s_data->dsi = dsi; |
| 77 | + |
| 78 | + ret = device_property_read_u32(dev, "max-brightness", &props.max_brightness); |
| 79 | + if (ret) |
| 80 | + return ret; |
| 81 | + props.type = BACKLIGHT_RAW; |
| 82 | + |
| 83 | + s_data->bl = devm_backlight_device_register(dev, dev_name(dev), |
| 84 | + dev, s_data, &summit_bl_ops, &props); |
| 85 | + if (IS_ERR(s_data->bl)) |
| 86 | + return PTR_ERR(s_data->bl); |
| 87 | + |
| 88 | + drm_panel_init(&s_data->panel, dev, &summit_panel_funcs, |
| 89 | + DRM_MODE_CONNECTOR_DSI); |
| 90 | + drm_panel_add(&s_data->panel); |
| 91 | + |
| 92 | + return mipi_dsi_attach(dsi); |
| 93 | +} |
| 94 | + |
| 95 | +static void summit_remove(struct mipi_dsi_device *dsi) |
| 96 | +{ |
| 97 | + struct summit_data *s_data = mipi_dsi_get_drvdata(dsi); |
| 98 | + |
| 99 | + mipi_dsi_detach(dsi); |
| 100 | + drm_panel_remove(&s_data->panel); |
| 101 | +} |
| 102 | + |
| 103 | +static int summit_suspend(struct device *dev) |
| 104 | +{ |
| 105 | + struct summit_data *s_data = dev_get_drvdata(dev); |
| 106 | + |
| 107 | + return mipi_dsi_dcs_set_display_brightness(s_data->dsi, 0); |
| 108 | +} |
| 109 | + |
| 110 | +static DEFINE_SIMPLE_DEV_PM_OPS(summit_pm_ops, summit_suspend, |
| 111 | + summit_set_brightness); |
| 112 | + |
| 113 | +static const struct of_device_id summit_of_match[] = { |
| 114 | + { .compatible = "apple,summit" }, |
| 115 | + {}, |
| 116 | +}; |
| 117 | + |
| 118 | +MODULE_DEVICE_TABLE(of, summit_of_match); |
| 119 | + |
| 120 | +static struct mipi_dsi_driver summit_driver = { |
| 121 | + .probe = summit_probe, |
| 122 | + .remove = summit_remove, |
| 123 | + .driver = { |
| 124 | + .name = "panel-summit", |
| 125 | + .of_match_table = summit_of_match, |
| 126 | + .pm = pm_sleep_ptr(&summit_pm_ops), |
| 127 | + }, |
| 128 | +}; |
| 129 | +module_mipi_dsi_driver(summit_driver); |
| 130 | + |
| 131 | +MODULE_DESCRIPTION("Summit Display Panel Driver"); |
| 132 | +MODULE_LICENSE("GPL"); |
0 commit comments