1 /* 2 * Copyright (C) 2015 Red Hat 3 * Copyright (C) 2015 Sony Mobile Communications Inc. 4 * Author: Werner Johansson <werner.johansson@sonymobile.com> 5 * 6 * Based on AUO panel driver by Rob Clark <robdclark@gmail.com> 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License version 2 as published by 10 * the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but WITHOUT 13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 * more details. 16 * 17 * You should have received a copy of the GNU General Public License along with 18 * this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 #include <linux/backlight.h> 22 #include <linux/gpio/consumer.h> 23 #include <linux/module.h> 24 #include <linux/of.h> 25 #include <linux/regulator/consumer.h> 26 27 #include <drm/drmP.h> 28 #include <drm/drm_crtc.h> 29 #include <drm/drm_mipi_dsi.h> 30 #include <drm/drm_panel.h> 31 32 #include <video/mipi_display.h> 33 34 struct sharp_nt_panel { 35 struct drm_panel base; 36 struct mipi_dsi_device *dsi; 37 38 struct backlight_device *backlight; 39 struct regulator *supply; 40 struct gpio_desc *reset_gpio; 41 42 bool prepared; 43 bool enabled; 44 45 const struct drm_display_mode *mode; 46 }; 47 48 static inline struct sharp_nt_panel *to_sharp_nt_panel(struct drm_panel *panel) 49 { 50 return container_of(panel, struct sharp_nt_panel, base); 51 } 52 53 static int sharp_nt_panel_init(struct sharp_nt_panel *sharp_nt) 54 { 55 struct mipi_dsi_device *dsi = sharp_nt->dsi; 56 int ret; 57 58 dsi->mode_flags |= MIPI_DSI_MODE_LPM; 59 60 ret = mipi_dsi_dcs_exit_sleep_mode(dsi); 61 if (ret < 0) 62 return ret; 63 64 msleep(120); 65 66 /* Novatek two-lane operation */ 67 ret = mipi_dsi_dcs_write(dsi, 0xae, (u8[]){ 0x03 }, 1); 68 if (ret < 0) 69 return ret; 70 71 /* Set both MCU and RGB I/F to 24bpp */ 72 ret = mipi_dsi_dcs_set_pixel_format(dsi, MIPI_DCS_PIXEL_FMT_24BIT | 73 (MIPI_DCS_PIXEL_FMT_24BIT << 4)); 74 if (ret < 0) 75 return ret; 76 77 return 0; 78 } 79 80 static int sharp_nt_panel_on(struct sharp_nt_panel *sharp_nt) 81 { 82 struct mipi_dsi_device *dsi = sharp_nt->dsi; 83 int ret; 84 85 dsi->mode_flags |= MIPI_DSI_MODE_LPM; 86 87 ret = mipi_dsi_dcs_set_display_on(dsi); 88 if (ret < 0) 89 return ret; 90 91 return 0; 92 } 93 94 static int sharp_nt_panel_off(struct sharp_nt_panel *sharp_nt) 95 { 96 struct mipi_dsi_device *dsi = sharp_nt->dsi; 97 int ret; 98 99 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 100 101 ret = mipi_dsi_dcs_set_display_off(dsi); 102 if (ret < 0) 103 return ret; 104 105 ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 106 if (ret < 0) 107 return ret; 108 109 return 0; 110 } 111 112 113 static int sharp_nt_panel_disable(struct drm_panel *panel) 114 { 115 struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel); 116 117 if (!sharp_nt->enabled) 118 return 0; 119 120 if (sharp_nt->backlight) { 121 sharp_nt->backlight->props.power = FB_BLANK_POWERDOWN; 122 backlight_update_status(sharp_nt->backlight); 123 } 124 125 sharp_nt->enabled = false; 126 127 return 0; 128 } 129 130 static int sharp_nt_panel_unprepare(struct drm_panel *panel) 131 { 132 struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel); 133 int ret; 134 135 if (!sharp_nt->prepared) 136 return 0; 137 138 ret = sharp_nt_panel_off(sharp_nt); 139 if (ret < 0) { 140 dev_err(panel->dev, "failed to set panel off: %d\n", ret); 141 return ret; 142 } 143 144 regulator_disable(sharp_nt->supply); 145 if (sharp_nt->reset_gpio) 146 gpiod_set_value(sharp_nt->reset_gpio, 0); 147 148 sharp_nt->prepared = false; 149 150 return 0; 151 } 152 153 static int sharp_nt_panel_prepare(struct drm_panel *panel) 154 { 155 struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel); 156 int ret; 157 158 if (sharp_nt->prepared) 159 return 0; 160 161 ret = regulator_enable(sharp_nt->supply); 162 if (ret < 0) 163 return ret; 164 165 msleep(20); 166 167 if (sharp_nt->reset_gpio) { 168 gpiod_set_value(sharp_nt->reset_gpio, 1); 169 msleep(1); 170 gpiod_set_value(sharp_nt->reset_gpio, 0); 171 msleep(1); 172 gpiod_set_value(sharp_nt->reset_gpio, 1); 173 msleep(10); 174 } 175 176 ret = sharp_nt_panel_init(sharp_nt); 177 if (ret < 0) { 178 dev_err(panel->dev, "failed to init panel: %d\n", ret); 179 goto poweroff; 180 } 181 182 ret = sharp_nt_panel_on(sharp_nt); 183 if (ret < 0) { 184 dev_err(panel->dev, "failed to set panel on: %d\n", ret); 185 goto poweroff; 186 } 187 188 sharp_nt->prepared = true; 189 190 return 0; 191 192 poweroff: 193 regulator_disable(sharp_nt->supply); 194 if (sharp_nt->reset_gpio) 195 gpiod_set_value(sharp_nt->reset_gpio, 0); 196 return ret; 197 } 198 199 static int sharp_nt_panel_enable(struct drm_panel *panel) 200 { 201 struct sharp_nt_panel *sharp_nt = to_sharp_nt_panel(panel); 202 203 if (sharp_nt->enabled) 204 return 0; 205 206 if (sharp_nt->backlight) { 207 sharp_nt->backlight->props.power = FB_BLANK_UNBLANK; 208 backlight_update_status(sharp_nt->backlight); 209 } 210 211 sharp_nt->enabled = true; 212 213 return 0; 214 } 215 216 static const struct drm_display_mode default_mode = { 217 .clock = 41118, 218 .hdisplay = 540, 219 .hsync_start = 540 + 48, 220 .hsync_end = 540 + 48 + 80, 221 .htotal = 540 + 48 + 80 + 32, 222 .vdisplay = 960, 223 .vsync_start = 960 + 3, 224 .vsync_end = 960 + 3 + 15, 225 .vtotal = 960 + 3 + 15 + 1, 226 .vrefresh = 60, 227 }; 228 229 static int sharp_nt_panel_get_modes(struct drm_panel *panel) 230 { 231 struct drm_display_mode *mode; 232 233 mode = drm_mode_duplicate(panel->drm, &default_mode); 234 if (!mode) { 235 dev_err(panel->drm->dev, "failed to add mode %ux%ux@%u\n", 236 default_mode.hdisplay, default_mode.vdisplay, 237 default_mode.vrefresh); 238 return -ENOMEM; 239 } 240 241 drm_mode_set_name(mode); 242 243 drm_mode_probed_add(panel->connector, mode); 244 245 panel->connector->display_info.width_mm = 54; 246 panel->connector->display_info.height_mm = 95; 247 248 return 1; 249 } 250 251 static const struct drm_panel_funcs sharp_nt_panel_funcs = { 252 .disable = sharp_nt_panel_disable, 253 .unprepare = sharp_nt_panel_unprepare, 254 .prepare = sharp_nt_panel_prepare, 255 .enable = sharp_nt_panel_enable, 256 .get_modes = sharp_nt_panel_get_modes, 257 }; 258 259 static int sharp_nt_panel_add(struct sharp_nt_panel *sharp_nt) 260 { 261 struct device *dev = &sharp_nt->dsi->dev; 262 struct device_node *np; 263 int ret; 264 265 sharp_nt->mode = &default_mode; 266 267 sharp_nt->supply = devm_regulator_get(dev, "avdd"); 268 if (IS_ERR(sharp_nt->supply)) 269 return PTR_ERR(sharp_nt->supply); 270 271 sharp_nt->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW); 272 if (IS_ERR(sharp_nt->reset_gpio)) { 273 dev_err(dev, "cannot get reset-gpios %ld\n", 274 PTR_ERR(sharp_nt->reset_gpio)); 275 sharp_nt->reset_gpio = NULL; 276 } else { 277 gpiod_set_value(sharp_nt->reset_gpio, 0); 278 } 279 280 np = of_parse_phandle(dev->of_node, "backlight", 0); 281 if (np) { 282 sharp_nt->backlight = of_find_backlight_by_node(np); 283 of_node_put(np); 284 285 if (!sharp_nt->backlight) 286 return -EPROBE_DEFER; 287 } 288 289 drm_panel_init(&sharp_nt->base); 290 sharp_nt->base.funcs = &sharp_nt_panel_funcs; 291 sharp_nt->base.dev = &sharp_nt->dsi->dev; 292 293 ret = drm_panel_add(&sharp_nt->base); 294 if (ret < 0) 295 goto put_backlight; 296 297 return 0; 298 299 put_backlight: 300 if (sharp_nt->backlight) 301 put_device(&sharp_nt->backlight->dev); 302 303 return ret; 304 } 305 306 static void sharp_nt_panel_del(struct sharp_nt_panel *sharp_nt) 307 { 308 if (sharp_nt->base.dev) 309 drm_panel_remove(&sharp_nt->base); 310 311 if (sharp_nt->backlight) 312 put_device(&sharp_nt->backlight->dev); 313 } 314 315 static int sharp_nt_panel_probe(struct mipi_dsi_device *dsi) 316 { 317 struct sharp_nt_panel *sharp_nt; 318 int ret; 319 320 dsi->lanes = 2; 321 dsi->format = MIPI_DSI_FMT_RGB888; 322 dsi->mode_flags = MIPI_DSI_MODE_VIDEO | 323 MIPI_DSI_MODE_VIDEO_HSE | 324 MIPI_DSI_CLOCK_NON_CONTINUOUS | 325 MIPI_DSI_MODE_EOT_PACKET; 326 327 sharp_nt = devm_kzalloc(&dsi->dev, sizeof(*sharp_nt), GFP_KERNEL); 328 if (!sharp_nt) 329 return -ENOMEM; 330 331 mipi_dsi_set_drvdata(dsi, sharp_nt); 332 333 sharp_nt->dsi = dsi; 334 335 ret = sharp_nt_panel_add(sharp_nt); 336 if (ret < 0) 337 return ret; 338 339 return mipi_dsi_attach(dsi); 340 } 341 342 static int sharp_nt_panel_remove(struct mipi_dsi_device *dsi) 343 { 344 struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi); 345 int ret; 346 347 ret = sharp_nt_panel_disable(&sharp_nt->base); 348 if (ret < 0) 349 dev_err(&dsi->dev, "failed to disable panel: %d\n", ret); 350 351 ret = mipi_dsi_detach(dsi); 352 if (ret < 0) 353 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); 354 355 drm_panel_detach(&sharp_nt->base); 356 sharp_nt_panel_del(sharp_nt); 357 358 return 0; 359 } 360 361 static void sharp_nt_panel_shutdown(struct mipi_dsi_device *dsi) 362 { 363 struct sharp_nt_panel *sharp_nt = mipi_dsi_get_drvdata(dsi); 364 365 sharp_nt_panel_disable(&sharp_nt->base); 366 } 367 368 static const struct of_device_id sharp_nt_of_match[] = { 369 { .compatible = "sharp,ls043t1le01-qhd", }, 370 { } 371 }; 372 MODULE_DEVICE_TABLE(of, sharp_nt_of_match); 373 374 static struct mipi_dsi_driver sharp_nt_panel_driver = { 375 .driver = { 376 .name = "panel-sharp-ls043t1le01-qhd", 377 .of_match_table = sharp_nt_of_match, 378 }, 379 .probe = sharp_nt_panel_probe, 380 .remove = sharp_nt_panel_remove, 381 .shutdown = sharp_nt_panel_shutdown, 382 }; 383 module_mipi_dsi_driver(sharp_nt_panel_driver); 384 385 MODULE_AUTHOR("Werner Johansson <werner.johansson@sonymobile.com>"); 386 MODULE_DESCRIPTION("Sharp LS043T1LE01 NT35565-based qHD (540x960) video mode panel driver"); 387 MODULE_LICENSE("GPL v2"); 388