0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #include <linux/delay.h>
0014 #include <linux/gpio/consumer.h>
0015 #include <linux/module.h>
0016 #include <linux/of.h>
0017 #include <linux/platform_device.h>
0018 #include <linux/regulator/consumer.h>
0019
0020 #include <drm/drm_connector.h>
0021 #include <drm/drm_modes.h>
0022 #include <drm/drm_panel.h>
0023
0024 struct ls037v7dw01_panel {
0025 struct drm_panel panel;
0026 struct platform_device *pdev;
0027
0028 struct regulator *vdd;
0029 struct gpio_desc *resb_gpio;
0030 struct gpio_desc *ini_gpio;
0031 struct gpio_desc *mo_gpio;
0032 struct gpio_desc *lr_gpio;
0033 struct gpio_desc *ud_gpio;
0034 };
0035
0036 #define to_ls037v7dw01_device(p) \
0037 container_of(p, struct ls037v7dw01_panel, panel)
0038
0039 static int ls037v7dw01_disable(struct drm_panel *panel)
0040 {
0041 struct ls037v7dw01_panel *lcd = to_ls037v7dw01_device(panel);
0042
0043 gpiod_set_value_cansleep(lcd->ini_gpio, 0);
0044 gpiod_set_value_cansleep(lcd->resb_gpio, 0);
0045
0046
0047 msleep(100);
0048
0049 return 0;
0050 }
0051
0052 static int ls037v7dw01_unprepare(struct drm_panel *panel)
0053 {
0054 struct ls037v7dw01_panel *lcd = to_ls037v7dw01_device(panel);
0055
0056 regulator_disable(lcd->vdd);
0057 return 0;
0058 }
0059
0060 static int ls037v7dw01_prepare(struct drm_panel *panel)
0061 {
0062 struct ls037v7dw01_panel *lcd = to_ls037v7dw01_device(panel);
0063 int ret;
0064
0065 ret = regulator_enable(lcd->vdd);
0066 if (ret < 0)
0067 dev_err(&lcd->pdev->dev, "%s: failed to enable regulator\n",
0068 __func__);
0069
0070 return ret;
0071 }
0072
0073 static int ls037v7dw01_enable(struct drm_panel *panel)
0074 {
0075 struct ls037v7dw01_panel *lcd = to_ls037v7dw01_device(panel);
0076
0077
0078 msleep(50);
0079
0080 gpiod_set_value_cansleep(lcd->resb_gpio, 1);
0081 gpiod_set_value_cansleep(lcd->ini_gpio, 1);
0082
0083 return 0;
0084 }
0085
0086 static const struct drm_display_mode ls037v7dw01_mode = {
0087 .clock = 19200,
0088 .hdisplay = 480,
0089 .hsync_start = 480 + 1,
0090 .hsync_end = 480 + 1 + 2,
0091 .htotal = 480 + 1 + 2 + 28,
0092 .vdisplay = 640,
0093 .vsync_start = 640 + 1,
0094 .vsync_end = 640 + 1 + 1,
0095 .vtotal = 640 + 1 + 1 + 1,
0096 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
0097 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
0098 .width_mm = 56,
0099 .height_mm = 75,
0100 };
0101
0102 static int ls037v7dw01_get_modes(struct drm_panel *panel,
0103 struct drm_connector *connector)
0104 {
0105 struct drm_display_mode *mode;
0106
0107 mode = drm_mode_duplicate(connector->dev, &ls037v7dw01_mode);
0108 if (!mode)
0109 return -ENOMEM;
0110
0111 drm_mode_set_name(mode);
0112 drm_mode_probed_add(connector, mode);
0113
0114 connector->display_info.width_mm = ls037v7dw01_mode.width_mm;
0115 connector->display_info.height_mm = ls037v7dw01_mode.height_mm;
0116
0117
0118
0119
0120
0121
0122 connector->display_info.bus_flags = DRM_BUS_FLAG_DE_HIGH
0123 | DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE
0124 | DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE;
0125
0126 return 1;
0127 }
0128
0129 static const struct drm_panel_funcs ls037v7dw01_funcs = {
0130 .disable = ls037v7dw01_disable,
0131 .unprepare = ls037v7dw01_unprepare,
0132 .prepare = ls037v7dw01_prepare,
0133 .enable = ls037v7dw01_enable,
0134 .get_modes = ls037v7dw01_get_modes,
0135 };
0136
0137 static int ls037v7dw01_probe(struct platform_device *pdev)
0138 {
0139 struct ls037v7dw01_panel *lcd;
0140
0141 lcd = devm_kzalloc(&pdev->dev, sizeof(*lcd), GFP_KERNEL);
0142 if (!lcd)
0143 return -ENOMEM;
0144
0145 platform_set_drvdata(pdev, lcd);
0146 lcd->pdev = pdev;
0147
0148 lcd->vdd = devm_regulator_get(&pdev->dev, "envdd");
0149 if (IS_ERR(lcd->vdd))
0150 return dev_err_probe(&pdev->dev, PTR_ERR(lcd->vdd),
0151 "failed to get regulator\n");
0152
0153 lcd->ini_gpio = devm_gpiod_get(&pdev->dev, "enable", GPIOD_OUT_LOW);
0154 if (IS_ERR(lcd->ini_gpio))
0155 return dev_err_probe(&pdev->dev, PTR_ERR(lcd->ini_gpio),
0156 "failed to get enable gpio\n");
0157
0158 lcd->resb_gpio = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_LOW);
0159 if (IS_ERR(lcd->resb_gpio))
0160 return dev_err_probe(&pdev->dev, PTR_ERR(lcd->resb_gpio),
0161 "failed to get reset gpio\n");
0162
0163 lcd->mo_gpio = devm_gpiod_get_index(&pdev->dev, "mode", 0,
0164 GPIOD_OUT_LOW);
0165 if (IS_ERR(lcd->mo_gpio)) {
0166 dev_err(&pdev->dev, "failed to get mode[0] gpio\n");
0167 return PTR_ERR(lcd->mo_gpio);
0168 }
0169
0170 lcd->lr_gpio = devm_gpiod_get_index(&pdev->dev, "mode", 1,
0171 GPIOD_OUT_LOW);
0172 if (IS_ERR(lcd->lr_gpio)) {
0173 dev_err(&pdev->dev, "failed to get mode[1] gpio\n");
0174 return PTR_ERR(lcd->lr_gpio);
0175 }
0176
0177 lcd->ud_gpio = devm_gpiod_get_index(&pdev->dev, "mode", 2,
0178 GPIOD_OUT_LOW);
0179 if (IS_ERR(lcd->ud_gpio)) {
0180 dev_err(&pdev->dev, "failed to get mode[2] gpio\n");
0181 return PTR_ERR(lcd->ud_gpio);
0182 }
0183
0184 drm_panel_init(&lcd->panel, &pdev->dev, &ls037v7dw01_funcs,
0185 DRM_MODE_CONNECTOR_DPI);
0186
0187 drm_panel_add(&lcd->panel);
0188
0189 return 0;
0190 }
0191
0192 static int ls037v7dw01_remove(struct platform_device *pdev)
0193 {
0194 struct ls037v7dw01_panel *lcd = platform_get_drvdata(pdev);
0195
0196 drm_panel_remove(&lcd->panel);
0197 drm_panel_disable(&lcd->panel);
0198 drm_panel_unprepare(&lcd->panel);
0199
0200 return 0;
0201 }
0202
0203 static const struct of_device_id ls037v7dw01_of_match[] = {
0204 { .compatible = "sharp,ls037v7dw01", },
0205 { },
0206 };
0207
0208 MODULE_DEVICE_TABLE(of, ls037v7dw01_of_match);
0209
0210 static struct platform_driver ls037v7dw01_driver = {
0211 .probe = ls037v7dw01_probe,
0212 .remove = ls037v7dw01_remove,
0213 .driver = {
0214 .name = "panel-sharp-ls037v7dw01",
0215 .of_match_table = ls037v7dw01_of_match,
0216 },
0217 };
0218
0219 module_platform_driver(ls037v7dw01_driver);
0220
0221 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
0222 MODULE_DESCRIPTION("Sharp LS037V7DW01 Panel Driver");
0223 MODULE_LICENSE("GPL");