brintos

brintos / linux-shallow public Read only

0
0
Text · 7.0 KiB · 74c760e Raw
307 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Copyright (c) 2021 Linaro Ltd.3 * Generated with linux-mdss-dsi-panel-driver-generator from vendor device tree:4 *   Copyright (c) 2013-2014, The Linux Foundation. All rights reserved.5 */6 7#include <linux/delay.h>8#include <linux/gpio/consumer.h>9#include <linux/module.h>10#include <linux/of.h>11#include <linux/regulator/consumer.h>12 13#include <video/mipi_display.h>14 15#include <drm/drm_mipi_dsi.h>16#include <drm/drm_modes.h>17#include <drm/drm_panel.h>18 19struct sharp_ls060 {20	struct drm_panel panel;21	struct mipi_dsi_device *dsi;22	struct regulator *vddi_supply;23	struct regulator *vddh_supply;24	struct regulator *avdd_supply;25	struct regulator *avee_supply;26	struct gpio_desc *reset_gpio;27};28 29static inline struct sharp_ls060 *to_sharp_ls060(struct drm_panel *panel)30{31	return container_of(panel, struct sharp_ls060, panel);32}33 34static void sharp_ls060_reset(struct sharp_ls060 *ctx)35{36	gpiod_set_value_cansleep(ctx->reset_gpio, 0);37	usleep_range(10000, 11000);38	gpiod_set_value_cansleep(ctx->reset_gpio, 1);39	usleep_range(10000, 11000);40	gpiod_set_value_cansleep(ctx->reset_gpio, 0);41	usleep_range(10000, 11000);42}43 44static int sharp_ls060_on(struct sharp_ls060 *ctx)45{46	struct mipi_dsi_device *dsi = ctx->dsi;47	struct device *dev = &dsi->dev;48	int ret;49 50	dsi->mode_flags |= MIPI_DSI_MODE_LPM;51 52	mipi_dsi_dcs_write_seq(dsi, 0xbb, 0x13);53	mipi_dsi_dcs_write_seq(dsi, MIPI_DCS_WRITE_MEMORY_START);54 55	ret = mipi_dsi_dcs_exit_sleep_mode(dsi);56	if (ret < 0) {57		dev_err(dev, "Failed to exit sleep mode: %d\n", ret);58		return ret;59	}60	msleep(120);61 62	ret = mipi_dsi_dcs_set_display_on(dsi);63	if (ret < 0) {64		dev_err(dev, "Failed to set display on: %d\n", ret);65		return ret;66	}67	msleep(50);68 69	return 0;70}71 72static int sharp_ls060_off(struct sharp_ls060 *ctx)73{74	struct mipi_dsi_device *dsi = ctx->dsi;75	struct device *dev = &dsi->dev;76	int ret;77 78	dsi->mode_flags &= ~MIPI_DSI_MODE_LPM;79 80	ret = mipi_dsi_dcs_set_display_off(dsi);81	if (ret < 0) {82		dev_err(dev, "Failed to set display off: %d\n", ret);83		return ret;84	}85	usleep_range(2000, 3000);86 87	ret = mipi_dsi_dcs_enter_sleep_mode(dsi);88	if (ret < 0) {89		dev_err(dev, "Failed to enter sleep mode: %d\n", ret);90		return ret;91	}92	msleep(121);93 94	return 0;95}96 97static int sharp_ls060_prepare(struct drm_panel *panel)98{99	struct sharp_ls060 *ctx = to_sharp_ls060(panel);100	struct device *dev = &ctx->dsi->dev;101	int ret;102 103	ret = regulator_enable(ctx->vddi_supply);104	if (ret < 0)105		return ret;106 107	ret = regulator_enable(ctx->avdd_supply);108	if (ret < 0)109		goto err_avdd;110 111	usleep_range(1000, 2000);112 113	ret = regulator_enable(ctx->avee_supply);114	if (ret < 0)115		goto err_avee;116 117	usleep_range(10000, 11000);118 119	ret = regulator_enable(ctx->vddh_supply);120	if (ret < 0)121		goto err_vddh;122 123	usleep_range(10000, 11000);124 125	sharp_ls060_reset(ctx);126 127	ret = sharp_ls060_on(ctx);128	if (ret < 0) {129		dev_err(dev, "Failed to initialize panel: %d\n", ret);130		goto err_on;131	}132 133	return 0;134 135err_on:136	regulator_disable(ctx->vddh_supply);137 138	usleep_range(10000, 11000);139 140err_vddh:141	regulator_disable(ctx->avee_supply);142 143err_avee:144	regulator_disable(ctx->avdd_supply);145 146	gpiod_set_value_cansleep(ctx->reset_gpio, 1);147 148err_avdd:149	regulator_disable(ctx->vddi_supply);150 151	return ret;152}153 154static int sharp_ls060_unprepare(struct drm_panel *panel)155{156	struct sharp_ls060 *ctx = to_sharp_ls060(panel);157	struct device *dev = &ctx->dsi->dev;158	int ret;159 160	ret = sharp_ls060_off(ctx);161	if (ret < 0)162		dev_err(dev, "Failed to un-initialize panel: %d\n", ret);163 164	regulator_disable(ctx->vddh_supply);165 166	usleep_range(10000, 11000);167 168	regulator_disable(ctx->avee_supply);169	regulator_disable(ctx->avdd_supply);170 171	gpiod_set_value_cansleep(ctx->reset_gpio, 1);172 173	regulator_disable(ctx->vddi_supply);174 175	return 0;176}177 178static const struct drm_display_mode sharp_ls060_mode = {179	.clock = (1080 + 96 + 16 + 64) * (1920 + 4 + 1 + 16) * 60 / 1000,180	.hdisplay = 1080,181	.hsync_start = 1080 + 96,182	.hsync_end = 1080 + 96 + 16,183	.htotal = 1080 + 96 + 16 + 64,184	.vdisplay = 1920,185	.vsync_start = 1920 + 4,186	.vsync_end = 1920 + 4 + 1,187	.vtotal = 1920 + 4 + 1 + 16,188	.width_mm = 75,189	.height_mm = 132,190};191 192static int sharp_ls060_get_modes(struct drm_panel *panel,193				 struct drm_connector *connector)194{195	struct drm_display_mode *mode;196 197	mode = drm_mode_duplicate(connector->dev, &sharp_ls060_mode);198	if (!mode)199		return -ENOMEM;200 201	drm_mode_set_name(mode);202 203	mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;204	connector->display_info.width_mm = mode->width_mm;205	connector->display_info.height_mm = mode->height_mm;206	drm_mode_probed_add(connector, mode);207 208	return 1;209}210 211static const struct drm_panel_funcs sharp_ls060_panel_funcs = {212	.prepare = sharp_ls060_prepare,213	.unprepare = sharp_ls060_unprepare,214	.get_modes = sharp_ls060_get_modes,215};216 217static int sharp_ls060_probe(struct mipi_dsi_device *dsi)218{219	struct device *dev = &dsi->dev;220	struct sharp_ls060 *ctx;221	int ret;222 223	ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);224	if (!ctx)225		return -ENOMEM;226 227	ctx->vddi_supply = devm_regulator_get(dev, "vddi");228	if (IS_ERR(ctx->vddi_supply))229		return PTR_ERR(ctx->vddi_supply);230 231	ctx->vddh_supply = devm_regulator_get(dev, "vddh");232	if (IS_ERR(ctx->vddh_supply))233		return PTR_ERR(ctx->vddh_supply);234 235	ctx->avdd_supply = devm_regulator_get(dev, "avdd");236	if (IS_ERR(ctx->avdd_supply))237		return PTR_ERR(ctx->avdd_supply);238 239	ctx->avee_supply = devm_regulator_get(dev, "avee");240	if (IS_ERR(ctx->avee_supply))241		return PTR_ERR(ctx->avee_supply);242 243	ctx->reset_gpio = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);244	if (IS_ERR(ctx->reset_gpio))245		return dev_err_probe(dev, PTR_ERR(ctx->reset_gpio),246				     "Failed to get reset-gpios\n");247 248	ctx->dsi = dsi;249	mipi_dsi_set_drvdata(dsi, ctx);250 251	dsi->lanes = 4;252	dsi->format = MIPI_DSI_FMT_RGB888;253	dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST |254			  MIPI_DSI_MODE_NO_EOT_PACKET |255			  MIPI_DSI_CLOCK_NON_CONTINUOUS;256 257	drm_panel_init(&ctx->panel, dev, &sharp_ls060_panel_funcs,258		       DRM_MODE_CONNECTOR_DSI);259 260	ret = drm_panel_of_backlight(&ctx->panel);261	if (ret)262		return dev_err_probe(dev, ret, "Failed to get backlight\n");263 264	drm_panel_add(&ctx->panel);265 266	ret = mipi_dsi_attach(dsi);267	if (ret < 0) {268		dev_err(dev, "Failed to attach to DSI host: %d\n", ret);269		drm_panel_remove(&ctx->panel);270		return ret;271	}272 273	return 0;274}275 276static void sharp_ls060_remove(struct mipi_dsi_device *dsi)277{278	struct sharp_ls060 *ctx = mipi_dsi_get_drvdata(dsi);279	int ret;280 281	ret = mipi_dsi_detach(dsi);282	if (ret < 0)283		dev_err(&dsi->dev, "Failed to detach from DSI host: %d\n", ret);284 285	drm_panel_remove(&ctx->panel);286}287 288static const struct of_device_id sharp_ls060t1sx01_of_match[] = {289	{ .compatible = "sharp,ls060t1sx01" },290	{ /* sentinel */ }291};292MODULE_DEVICE_TABLE(of, sharp_ls060t1sx01_of_match);293 294static struct mipi_dsi_driver sharp_ls060_driver = {295	.probe = sharp_ls060_probe,296	.remove = sharp_ls060_remove,297	.driver = {298		.name = "panel-sharp-ls060t1sx01",299		.of_match_table = sharp_ls060t1sx01_of_match,300	},301};302module_mipi_dsi_driver(sharp_ls060_driver);303 304MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>");305MODULE_DESCRIPTION("DRM driver for Sharp LS060T1SX01 1080p video mode dsi panel");306MODULE_LICENSE("GPL v2");307