0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030 #include <linux/clk.h>
0031 #include <linux/dma-buf.h>
0032 #include <linux/irq.h>
0033 #include <linux/io.h>
0034 #include <linux/module.h>
0035 #include <linux/platform_device.h>
0036 #include <linux/shmem_fs.h>
0037 #include <linux/slab.h>
0038
0039 #include <drm/drm_atomic_helper.h>
0040 #include <drm/drm_bridge.h>
0041 #include <drm/drm_drv.h>
0042 #include <drm/drm_fb_cma_helper.h>
0043 #include <drm/drm_fb_helper.h>
0044 #include <drm/drm_gem_cma_helper.h>
0045 #include <drm/drm_gem_framebuffer_helper.h>
0046 #include <drm/drm_module.h>
0047 #include <drm/drm_of.h>
0048 #include <drm/drm_panel.h>
0049 #include <drm/drm_probe_helper.h>
0050 #include <drm/drm_vblank.h>
0051
0052 #include "tve200_drm.h"
0053
0054 #define DRIVER_DESC "DRM module for Faraday TVE200"
0055
0056 static const struct drm_mode_config_funcs mode_config_funcs = {
0057 .fb_create = drm_gem_fb_create,
0058 .atomic_check = drm_atomic_helper_check,
0059 .atomic_commit = drm_atomic_helper_commit,
0060 };
0061
0062 static int tve200_modeset_init(struct drm_device *dev)
0063 {
0064 struct drm_mode_config *mode_config;
0065 struct tve200_drm_dev_private *priv = dev->dev_private;
0066 struct drm_panel *panel;
0067 struct drm_bridge *bridge;
0068 int ret = 0;
0069
0070 drm_mode_config_init(dev);
0071 mode_config = &dev->mode_config;
0072 mode_config->funcs = &mode_config_funcs;
0073 mode_config->min_width = 352;
0074 mode_config->max_width = 720;
0075 mode_config->min_height = 240;
0076 mode_config->max_height = 576;
0077
0078 ret = drm_of_find_panel_or_bridge(dev->dev->of_node,
0079 0, 0, &panel, &bridge);
0080 if (ret && ret != -ENODEV)
0081 return ret;
0082 if (panel) {
0083 bridge = drm_panel_bridge_add_typed(panel,
0084 DRM_MODE_CONNECTOR_Unknown);
0085 if (IS_ERR(bridge)) {
0086 ret = PTR_ERR(bridge);
0087 goto out_bridge;
0088 }
0089 } else {
0090
0091
0092
0093
0094
0095 dev_err(dev->dev, "the bridge is not a panel\n");
0096 goto out_bridge;
0097 }
0098
0099 ret = tve200_display_init(dev);
0100 if (ret) {
0101 dev_err(dev->dev, "failed to init display\n");
0102 goto out_bridge;
0103 }
0104
0105 ret = drm_simple_display_pipe_attach_bridge(&priv->pipe,
0106 bridge);
0107 if (ret) {
0108 dev_err(dev->dev, "failed to attach bridge\n");
0109 goto out_bridge;
0110 }
0111
0112 priv->panel = panel;
0113 priv->connector = drm_panel_bridge_connector(bridge);
0114 priv->bridge = bridge;
0115
0116 dev_info(dev->dev, "attached to panel %s\n",
0117 dev_name(panel->dev));
0118
0119 ret = drm_vblank_init(dev, 1);
0120 if (ret) {
0121 dev_err(dev->dev, "failed to init vblank\n");
0122 goto out_bridge;
0123 }
0124
0125 drm_mode_config_reset(dev);
0126 drm_kms_helper_poll_init(dev);
0127
0128 goto finish;
0129
0130 out_bridge:
0131 if (panel)
0132 drm_panel_bridge_remove(bridge);
0133 drm_mode_config_cleanup(dev);
0134 finish:
0135 return ret;
0136 }
0137
0138 DEFINE_DRM_GEM_CMA_FOPS(drm_fops);
0139
0140 static const struct drm_driver tve200_drm_driver = {
0141 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_ATOMIC,
0142 .ioctls = NULL,
0143 .fops = &drm_fops,
0144 .name = "tve200",
0145 .desc = DRIVER_DESC,
0146 .date = "20170703",
0147 .major = 1,
0148 .minor = 0,
0149 .patchlevel = 0,
0150 DRM_GEM_CMA_DRIVER_OPS,
0151 };
0152
0153 static int tve200_probe(struct platform_device *pdev)
0154 {
0155 struct device *dev = &pdev->dev;
0156 struct tve200_drm_dev_private *priv;
0157 struct drm_device *drm;
0158 struct resource *res;
0159 int irq;
0160 int ret;
0161
0162 priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
0163 if (!priv)
0164 return -ENOMEM;
0165
0166 drm = drm_dev_alloc(&tve200_drm_driver, dev);
0167 if (IS_ERR(drm))
0168 return PTR_ERR(drm);
0169 platform_set_drvdata(pdev, drm);
0170 priv->drm = drm;
0171 drm->dev_private = priv;
0172
0173
0174 priv->pclk = devm_clk_get(dev, "PCLK");
0175 if (IS_ERR(priv->pclk)) {
0176 dev_err(dev, "unable to get PCLK\n");
0177 ret = PTR_ERR(priv->pclk);
0178 goto dev_unref;
0179 }
0180 ret = clk_prepare_enable(priv->pclk);
0181 if (ret) {
0182 dev_err(dev, "failed to enable PCLK\n");
0183 goto dev_unref;
0184 }
0185
0186
0187 priv->clk = devm_clk_get(dev, "TVE");
0188 if (IS_ERR(priv->clk)) {
0189 dev_err(dev, "unable to get TVE clock\n");
0190 ret = PTR_ERR(priv->clk);
0191 goto clk_disable;
0192 }
0193
0194 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
0195 priv->regs = devm_ioremap_resource(dev, res);
0196 if (IS_ERR(priv->regs)) {
0197 dev_err(dev, "%s failed mmio\n", __func__);
0198 ret = -EINVAL;
0199 goto clk_disable;
0200 }
0201
0202 irq = platform_get_irq(pdev, 0);
0203 if (irq < 0) {
0204 ret = irq;
0205 goto clk_disable;
0206 }
0207
0208
0209 writel(0, priv->regs + TVE200_INT_EN);
0210
0211 ret = devm_request_irq(dev, irq, tve200_irq, 0, "tve200", priv);
0212 if (ret) {
0213 dev_err(dev, "failed to request irq %d\n", ret);
0214 goto clk_disable;
0215 }
0216
0217 ret = tve200_modeset_init(drm);
0218 if (ret)
0219 goto clk_disable;
0220
0221 ret = drm_dev_register(drm, 0);
0222 if (ret < 0)
0223 goto clk_disable;
0224
0225
0226
0227
0228
0229 drm_fbdev_generic_setup(drm, 16);
0230
0231 return 0;
0232
0233 clk_disable:
0234 clk_disable_unprepare(priv->pclk);
0235 dev_unref:
0236 drm_dev_put(drm);
0237 return ret;
0238 }
0239
0240 static int tve200_remove(struct platform_device *pdev)
0241 {
0242 struct drm_device *drm = platform_get_drvdata(pdev);
0243 struct tve200_drm_dev_private *priv = drm->dev_private;
0244
0245 drm_dev_unregister(drm);
0246 if (priv->panel)
0247 drm_panel_bridge_remove(priv->bridge);
0248 drm_mode_config_cleanup(drm);
0249 clk_disable_unprepare(priv->pclk);
0250 drm_dev_put(drm);
0251
0252 return 0;
0253 }
0254
0255 static const struct of_device_id tve200_of_match[] = {
0256 {
0257 .compatible = "faraday,tve200",
0258 },
0259 {},
0260 };
0261
0262 static struct platform_driver tve200_driver = {
0263 .driver = {
0264 .name = "tve200",
0265 .of_match_table = of_match_ptr(tve200_of_match),
0266 },
0267 .probe = tve200_probe,
0268 .remove = tve200_remove,
0269 };
0270 drm_module_platform_driver(tve200_driver);
0271
0272 MODULE_DESCRIPTION(DRIVER_DESC);
0273 MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
0274 MODULE_LICENSE("GPL");