382 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2014 NVIDIA Corporation4 */5 6#include <linux/delay.h>7#include <linux/gpio/consumer.h>8#include <linux/module.h>9#include <linux/of.h>10#include <linux/regulator/consumer.h>11 12#include <video/mipi_display.h>13 14#include <drm/drm_crtc.h>15#include <drm/drm_device.h>16#include <drm/drm_mipi_dsi.h>17#include <drm/drm_panel.h>18 19struct sharp_panel {20 struct drm_panel base;21 /* the datasheet refers to them as DSI-LINK1 and DSI-LINK2 */22 struct mipi_dsi_device *link1;23 struct mipi_dsi_device *link2;24 25 struct regulator *supply;26 27 const struct drm_display_mode *mode;28};29 30static inline struct sharp_panel *to_sharp_panel(struct drm_panel *panel)31{32 return container_of(panel, struct sharp_panel, base);33}34 35static void sharp_wait_frames(struct sharp_panel *sharp, unsigned int frames)36{37 unsigned int refresh = drm_mode_vrefresh(sharp->mode);38 39 if (WARN_ON(frames > refresh))40 return;41 42 msleep(1000 / (refresh / frames));43}44 45static int sharp_panel_write(struct sharp_panel *sharp, u16 offset, u8 value)46{47 u8 payload[3] = { offset >> 8, offset & 0xff, value };48 struct mipi_dsi_device *dsi = sharp->link1;49 ssize_t err;50 51 err = mipi_dsi_generic_write(dsi, payload, sizeof(payload));52 if (err < 0) {53 dev_err(&dsi->dev, "failed to write %02x to %04x: %zd\n",54 value, offset, err);55 return err;56 }57 58 err = mipi_dsi_dcs_nop(dsi);59 if (err < 0) {60 dev_err(&dsi->dev, "failed to send DCS nop: %zd\n", err);61 return err;62 }63 64 usleep_range(10, 20);65 66 return 0;67}68 69static __maybe_unused int sharp_panel_read(struct sharp_panel *sharp,70 u16 offset, u8 *value)71{72 ssize_t err;73 74 cpu_to_be16s(&offset);75 76 err = mipi_dsi_generic_read(sharp->link1, &offset, sizeof(offset),77 value, sizeof(*value));78 if (err < 0)79 dev_err(&sharp->link1->dev, "failed to read from %04x: %zd\n",80 offset, err);81 82 return err;83}84 85static int sharp_panel_unprepare(struct drm_panel *panel)86{87 struct sharp_panel *sharp = to_sharp_panel(panel);88 int err;89 90 sharp_wait_frames(sharp, 4);91 92 err = mipi_dsi_dcs_set_display_off(sharp->link1);93 if (err < 0)94 dev_err(panel->dev, "failed to set display off: %d\n", err);95 96 err = mipi_dsi_dcs_enter_sleep_mode(sharp->link1);97 if (err < 0)98 dev_err(panel->dev, "failed to enter sleep mode: %d\n", err);99 100 msleep(120);101 102 regulator_disable(sharp->supply);103 104 return 0;105}106 107static int sharp_setup_symmetrical_split(struct mipi_dsi_device *left,108 struct mipi_dsi_device *right,109 const struct drm_display_mode *mode)110{111 int err;112 113 err = mipi_dsi_dcs_set_column_address(left, 0, mode->hdisplay / 2 - 1);114 if (err < 0) {115 dev_err(&left->dev, "failed to set column address: %d\n", err);116 return err;117 }118 119 err = mipi_dsi_dcs_set_page_address(left, 0, mode->vdisplay - 1);120 if (err < 0) {121 dev_err(&left->dev, "failed to set page address: %d\n", err);122 return err;123 }124 125 err = mipi_dsi_dcs_set_column_address(right, mode->hdisplay / 2,126 mode->hdisplay - 1);127 if (err < 0) {128 dev_err(&right->dev, "failed to set column address: %d\n", err);129 return err;130 }131 132 err = mipi_dsi_dcs_set_page_address(right, 0, mode->vdisplay - 1);133 if (err < 0) {134 dev_err(&right->dev, "failed to set page address: %d\n", err);135 return err;136 }137 138 return 0;139}140 141static int sharp_panel_prepare(struct drm_panel *panel)142{143 struct sharp_panel *sharp = to_sharp_panel(panel);144 u8 format = MIPI_DCS_PIXEL_FMT_24BIT;145 int err;146 147 err = regulator_enable(sharp->supply);148 if (err < 0)149 return err;150 151 /*152 * According to the datasheet, the panel needs around 10 ms to fully153 * power up. At least another 120 ms is required before exiting sleep154 * mode to make sure the panel is ready. Throw in another 20 ms for155 * good measure.156 */157 msleep(150);158 159 err = mipi_dsi_dcs_exit_sleep_mode(sharp->link1);160 if (err < 0) {161 dev_err(panel->dev, "failed to exit sleep mode: %d\n", err);162 goto poweroff;163 }164 165 /*166 * The MIPI DCS specification mandates this delay only between the167 * exit_sleep_mode and enter_sleep_mode commands, so it isn't strictly168 * necessary here.169 */170 /*171 msleep(120);172 */173 174 /* set left-right mode */175 err = sharp_panel_write(sharp, 0x1000, 0x2a);176 if (err < 0) {177 dev_err(panel->dev, "failed to set left-right mode: %d\n", err);178 goto poweroff;179 }180 181 /* enable command mode */182 err = sharp_panel_write(sharp, 0x1001, 0x01);183 if (err < 0) {184 dev_err(panel->dev, "failed to enable command mode: %d\n", err);185 goto poweroff;186 }187 188 err = mipi_dsi_dcs_set_pixel_format(sharp->link1, format);189 if (err < 0) {190 dev_err(panel->dev, "failed to set pixel format: %d\n", err);191 goto poweroff;192 }193 194 /*195 * TODO: The device supports both left-right and even-odd split196 * configurations, but this driver currently supports only the left-197 * right split. To support a different mode a mechanism needs to be198 * put in place to communicate the configuration back to the DSI host199 * controller.200 */201 err = sharp_setup_symmetrical_split(sharp->link1, sharp->link2,202 sharp->mode);203 if (err < 0) {204 dev_err(panel->dev, "failed to set up symmetrical split: %d\n",205 err);206 goto poweroff;207 }208 209 err = mipi_dsi_dcs_set_display_on(sharp->link1);210 if (err < 0) {211 dev_err(panel->dev, "failed to set display on: %d\n", err);212 goto poweroff;213 }214 215 /* wait for 6 frames before continuing */216 sharp_wait_frames(sharp, 6);217 218 return 0;219 220poweroff:221 regulator_disable(sharp->supply);222 return err;223}224 225static const struct drm_display_mode default_mode = {226 .clock = 278000,227 .hdisplay = 2560,228 .hsync_start = 2560 + 128,229 .hsync_end = 2560 + 128 + 64,230 .htotal = 2560 + 128 + 64 + 64,231 .vdisplay = 1600,232 .vsync_start = 1600 + 4,233 .vsync_end = 1600 + 4 + 8,234 .vtotal = 1600 + 4 + 8 + 32,235};236 237static int sharp_panel_get_modes(struct drm_panel *panel,238 struct drm_connector *connector)239{240 struct drm_display_mode *mode;241 242 mode = drm_mode_duplicate(connector->dev, &default_mode);243 if (!mode) {244 dev_err(panel->dev, "failed to add mode %ux%ux@%u\n",245 default_mode.hdisplay, default_mode.vdisplay,246 drm_mode_vrefresh(&default_mode));247 return -ENOMEM;248 }249 250 drm_mode_set_name(mode);251 252 drm_mode_probed_add(connector, mode);253 254 connector->display_info.width_mm = 217;255 connector->display_info.height_mm = 136;256 257 return 1;258}259 260static const struct drm_panel_funcs sharp_panel_funcs = {261 .unprepare = sharp_panel_unprepare,262 .prepare = sharp_panel_prepare,263 .get_modes = sharp_panel_get_modes,264};265 266static const struct of_device_id sharp_of_match[] = {267 { .compatible = "sharp,lq101r1sx01", },268 { }269};270MODULE_DEVICE_TABLE(of, sharp_of_match);271 272static int sharp_panel_add(struct sharp_panel *sharp)273{274 int ret;275 276 sharp->mode = &default_mode;277 278 sharp->supply = devm_regulator_get(&sharp->link1->dev, "power");279 if (IS_ERR(sharp->supply))280 return PTR_ERR(sharp->supply);281 282 drm_panel_init(&sharp->base, &sharp->link1->dev, &sharp_panel_funcs,283 DRM_MODE_CONNECTOR_DSI);284 285 ret = drm_panel_of_backlight(&sharp->base);286 if (ret)287 return ret;288 289 drm_panel_add(&sharp->base);290 291 return 0;292}293 294static void sharp_panel_del(struct sharp_panel *sharp)295{296 if (sharp->base.dev)297 drm_panel_remove(&sharp->base);298 299 if (sharp->link2)300 put_device(&sharp->link2->dev);301}302 303static int sharp_panel_probe(struct mipi_dsi_device *dsi)304{305 struct mipi_dsi_device *secondary = NULL;306 struct sharp_panel *sharp;307 struct device_node *np;308 int err;309 310 dsi->lanes = 4;311 dsi->format = MIPI_DSI_FMT_RGB888;312 dsi->mode_flags = MIPI_DSI_MODE_LPM;313 314 /* Find DSI-LINK1 */315 np = of_parse_phandle(dsi->dev.of_node, "link2", 0);316 if (np) {317 secondary = of_find_mipi_dsi_device_by_node(np);318 of_node_put(np);319 320 if (!secondary)321 return -EPROBE_DEFER;322 }323 324 /* register a panel for only the DSI-LINK1 interface */325 if (secondary) {326 sharp = devm_kzalloc(&dsi->dev, sizeof(*sharp), GFP_KERNEL);327 if (!sharp) {328 put_device(&secondary->dev);329 return -ENOMEM;330 }331 332 mipi_dsi_set_drvdata(dsi, sharp);333 334 sharp->link2 = secondary;335 sharp->link1 = dsi;336 337 err = sharp_panel_add(sharp);338 if (err < 0) {339 put_device(&secondary->dev);340 return err;341 }342 }343 344 err = mipi_dsi_attach(dsi);345 if (err < 0) {346 if (secondary)347 sharp_panel_del(sharp);348 349 return err;350 }351 352 return 0;353}354 355static void sharp_panel_remove(struct mipi_dsi_device *dsi)356{357 struct sharp_panel *sharp = mipi_dsi_get_drvdata(dsi);358 int err;359 360 err = mipi_dsi_detach(dsi);361 if (err < 0)362 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);363 364 /* only detach from host for the DSI-LINK2 interface */365 if (sharp)366 sharp_panel_del(sharp);367}368 369static struct mipi_dsi_driver sharp_panel_driver = {370 .driver = {371 .name = "panel-sharp-lq101r1sx01",372 .of_match_table = sharp_of_match,373 },374 .probe = sharp_panel_probe,375 .remove = sharp_panel_remove,376};377module_mipi_dsi_driver(sharp_panel_driver);378 379MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");380MODULE_DESCRIPTION("Sharp LQ101R1SX01 panel driver");381MODULE_LICENSE("GPL v2");382